tmx/
parse.rs

1use std::hash::{Hash, Hasher};
2use std::io::{BufReader, Read};
3use std::path::Path;
4
5use anyhow::*;
6use glam::{vec2, IVec2, UVec2, Vec4};
7use xml::attribute::OwnedAttribute;
8use xml::reader::{EventReader, XmlEvent};
9
10use crate::loader::TmxLoadContext;
11use crate::map::Map;
12
13use super::*;
14
15enum Data {
16    U8(Vec<u8>),
17    U32(Vec<u32>),
18}
19
20impl Data {
21    fn into_vec_u8(self) -> Vec<u8> {
22        match self {
23            Data::U8(v) => v,
24            Data::U32(_) => unimplemented!("u8 to u32 conversion is not needed"),
25        }
26    }
27
28    fn into_vec_u32(self) -> Vec<u32> {
29        match self {
30            Data::U8(v) => v
31                .chunks_exact(4)
32                .map(|chunk| {
33                    (chunk[0] as u32)
34                        | (chunk[1] as u32) << 8
35                        | (chunk[2] as u32) << 16
36                        | (chunk[3] as u32) << 24
37                })
38                .collect(),
39            Data::U32(v) => v,
40        }
41    }
42}
43
44impl Map {
45    pub(crate) fn load_from_xml_reader<R: Read + Send>(
46        env: TmxLoadContext<'_>,
47        mut reader: EventReader<R>,
48    ) -> Result<Self> {
49        loop {
50            if let XmlEvent::StartElement {
51                name, attributes, ..
52            } = reader.next()?
53            {
54                if name.local_name == "map" {
55                    return Map::parse(env, attributes, &mut reader);
56                } else {
57                    parse_empty(&mut reader)?;
58                }
59            }
60        }
61    }
62
63    fn parse<R: Read + Send>(
64        env: TmxLoadContext<'_>,
65        attributes: Vec<OwnedAttribute>,
66        reader: &mut EventReader<R>,
67    ) -> Result<Self> {
68        let mut result = Map {
69            properties: HashMap::new(),
70            tilesets: Vec::new(),
71            layers: Vec::new(),
72
73            width: 0,
74            height: 0,
75            tile_type: TileType::Ortho {
76                width: 0,
77                height: 0,
78                render_order: RenderOrder::RightDown,
79            },
80
81            background: [0; 4],
82        };
83
84        let mut render_order = RenderOrder::RightDown;
85        let mut tile_type = 0;
86        let mut tile_width = 0;
87        let mut tile_height = 0;
88        let mut stagger_y = false;
89        let mut stagger_i = true;
90        let mut hex_side_length = 0;
91
92        for a in attributes {
93            match a.name.local_name.as_ref() {
94                "width" => result.width = a.value.parse()?,
95                "height" => result.height = a.value.parse()?,
96                "tilewidth" => tile_width = a.value.parse()?,
97                "tileheight" => tile_height = a.value.parse()?,
98                "renderorder" => {
99                    render_order = match a.value.as_ref() {
100                        "right-down" => RenderOrder::RightDown,
101                        "right-up" => RenderOrder::RightUp,
102                        "left-down" => RenderOrder::LeftDown,
103                        "left-up" => RenderOrder::LeftUp,
104                        _ => bail!("invalid renderorder"),
105                    }
106                }
107                "orientation" => {
108                    tile_type = match a.value.as_ref() {
109                        "orthogonal" => 0,
110                        "isometric" => 1,
111                        "staggered" => 2,
112                        "hexagonal" => 3,
113                        _ => bail!("invalid orientation"),
114                    }
115                }
116                "backgroundcolor" => {
117                    result.background = [1; 4];
118                }
119                "staggeraxis" => {
120                    stagger_y = match a.value.as_ref() {
121                        "x" => false,
122                        "y" => true,
123                        _ => bail!("invalid staggeraxis"),
124                    }
125                }
126                "staggerindex" => {
127                    stagger_i = match a.value.as_ref() {
128                        "odd" => true,
129                        "even" => false,
130                        _ => bail!("invalid staggerindex"),
131                    }
132                }
133                "hexsidelength" => hex_side_length = a.value.parse()?,
134                _ => (), // skip
135            }
136        }
137
138        result.tile_type = match tile_type {
139            0 => TileType::Ortho {
140                width: tile_width,
141                height: tile_height,
142                render_order,
143            },
144            1 => TileType::Isometric {
145                width: tile_width,
146                height: tile_height,
147                stagger: false,
148                stagger_odd: stagger_i,
149                stagger_y,
150                render_order,
151            },
152            2 => TileType::Isometric {
153                width: tile_width,
154                height: tile_height,
155                stagger: true,
156                stagger_odd: stagger_i,
157                stagger_y,
158                render_order,
159            },
160            3 => TileType::Hexagonal {
161                width: tile_width,
162                height: tile_width,
163                stagger_odd: stagger_i,
164                stagger_y,
165                side_length: hex_side_length,
166                render_order,
167            },
168            _ => unreachable!(),
169        };
170
171        while match reader.next()? {
172            XmlEvent::StartElement {
173                name, attributes, ..
174            } => {
175                match name.local_name.as_ref() {
176                    "properties" => {
177                        result.properties = parse_properties(reader)?;
178                    }
179                    "tileset" => {
180                        result.tilesets.push(Arc::new(Tileset::parse(
181                            env.clone(),
182                            attributes,
183                            reader,
184                        )?));
185                    }
186                    "layer" => {
187                        result.layers.push(Layer::parse_tiles(attributes, reader)?);
188                    }
189                    "objectgroup" => {
190                        result = Layer::parse_objects(env.clone(), attributes, reader)?
191                            .process(result)?;
192                    }
193                    "imagelayer" => {
194                        result
195                            .layers
196                            .push(Layer::parse_image(env.clone(), attributes, reader)?);
197                    }
198                    "group" => {
199                        result
200                            .layers
201                            .push(Layer::parse_group(env.clone(), attributes, reader)?);
202                    }
203                    _ => parse_empty(reader)?, // skip
204                }
205
206                true
207            }
208            XmlEvent::EndElement { .. } => false,
209            _ => true,
210        } {
211            continue;
212        }
213
214        Ok(result)
215    }
216}
217
218impl Tileset {
219    /// Parse a tileset element. This can be either an external reference or an actual tileset.
220    fn parse<R: Read + Send>(
221        env: TmxLoadContext<'_>,
222        attributes: Vec<OwnedAttribute>,
223        reader: &mut EventReader<R>,
224    ) -> Result<Self> {
225        let mut result = Tileset {
226            first_gid: 0,
227            source: "embedded#".to_string(),
228            tiles: Vec::new(),
229            image: None,
230            tile_size: Vec2::ZERO,
231        };
232
233        let mut found_source = false;
234
235        for a in attributes.iter() {
236            match a.name.local_name.as_ref() {
237                "firstgid" => {
238                    result.first_gid = a.value.parse()?;
239                }
240                "name" => {
241                    result.source = format!("embedded#{}", a.value.clone());
242                }
243                "source" => {
244                    found_source = true;
245                    let source_path = Path::new(a.value.as_str());
246                    let file_name = env.file_path(source_path);
247                    let sub_env = env.file_directory(source_path);
248                    let file = env.load_file(source_path)?;
249                    let file = BufReader::new(file.as_slice());
250                    let mut reader = EventReader::new(file);
251                    loop {
252                        if let XmlEvent::StartElement {
253                            name, attributes, ..
254                        } = reader.next()?
255                        {
256                            if name.local_name == "tileset" {
257                                result =
258                                    Tileset::parse_tsx(result, sub_env, attributes, &mut reader)?;
259                                result.source = format!("{}", file_name.display());
260                                break;
261                            } else {
262                                parse_empty(&mut reader)?;
263                            }
264                        }
265                    }
266                }
267                _ => (),
268            }
269        }
270
271        if found_source {
272            // The actual XML element will be parsed in Tileset::parse_tmx(..).
273            // If we parse the TMX from an external file, this means the element is not handled. To correct for
274            //  this we call parse_empty(..) if an external file was found.
275            parse_empty(reader)?;
276            Ok(result)
277        } else {
278            Tileset::parse_tsx(result, env, attributes, reader)
279        }
280    }
281
282    /// Parse the actual tileset content
283    fn parse_tsx<R: Read + Send>(
284        mut tileset: Tileset,
285        env: TmxLoadContext<'_>,
286        attributes: Vec<OwnedAttribute>,
287        reader: &mut EventReader<R>,
288    ) -> Result<Tileset> {
289        let mut tile_width = 0;
290        let mut tile_height = 0;
291        let mut spacing = 0;
292        let mut margin = 0;
293        let mut tile_count: Option<u32> = None;
294        let mut columns: Option<i32> = None;
295
296        for a in attributes.iter() {
297            match a.name.local_name.as_ref() {
298                "tilewidth" => tile_width = a.value.parse()?,
299                "tileheight" => tile_height = a.value.parse()?,
300                "spacing" => spacing = a.value.parse()?,
301                "margin" => margin = a.value.parse()?,
302                "tilecount" => tile_count = Some(a.value.parse()?),
303                "columns" => columns = Some(a.value.parse()?),
304                _ => (),
305            }
306        }
307
308        tileset.tile_size.x = tile_width as f32;
309        tileset.tile_size.y = tile_height as f32;
310
311        while match reader.next()? {
312            XmlEvent::StartElement {
313                name, attributes, ..
314            } => {
315                match name.local_name.as_ref() {
316                    "image" => {
317                        let columns = columns;
318                        let spacing = spacing;
319                        let margin = margin;
320                        let tile_width = tile_width;
321                        let mut tiles_added = 0;
322                        let image = parse_image(env.clone(), attributes, reader)?;
323                        tileset.image = Some(image.clone());
324
325                        let (width, height) = (image.width(), image.height());
326                        let (width, height) = (width as i32, height as i32);
327                        let columns = columns.unwrap_or_else(|| {
328                            let mut space = width - margin * 2;
329                            let mut cols = 0;
330                            while space >= tile_width {
331                                space -= tile_width + spacing;
332                                space -= spacing;
333                                cols += 1;
334                            }
335                            cols
336                        });
337                        let rows = {
338                            let mut space = height - margin * 2;
339                            let mut rows = 0;
340                            while space >= tile_height {
341                                space -= tile_height + spacing;
342                                rows += 1;
343                            }
344                            rows
345                        };
346
347                        for y in 0..rows {
348                            for x in 0..columns {
349                                if tile_count.map_or(true, |tc| tiles_added < tc) {
350                                    let u = (margin + x * tile_width + x * spacing) as f32
351                                        / width as f32;
352                                    let v = (margin + y * tile_height + y * spacing) as f32
353                                        / height as f32;
354                                    let w = tile_width as f32 / width as f32;
355                                    let h = tile_height as f32 / height as f32;
356
357                                    tileset.tiles.push(Some(Tile {
358                                        image: Some(image.clone()),
359                                        top_left: Vec2::new(u, v),
360                                        bottom_right: Vec2::new(u + w, v + h),
361                                        width: tile_width,
362                                        height: tile_height,
363                                        animation: Vec::new(),
364                                        properties: HashMap::new(),
365                                        object_group: Vec::new(),
366                                    }));
367
368                                    tiles_added += 1;
369                                } else {
370                                    break;
371                                }
372                            }
373                        }
374                    }
375                    "tile" => {
376                        let (id, tile) = Tile::parse(env.clone(), attributes, reader)?;
377
378                        if id < tileset.tiles.len() {
379                            if tileset.tiles[id].is_none() {
380                                tileset.tiles[id].replace(tile);
381                            } else {
382                                // we already checked if the tile exists, unwrap is safe.
383                                tileset.tiles[id].as_mut().unwrap().join(tile);
384                            }
385                        } else {
386                            while id > tileset.tiles.len() {
387                                tileset.tiles.push(None);
388                            }
389                            tileset.tiles.push(Some(tile));
390                        }
391                    }
392                    _ => parse_empty(reader)?, // skip
393                }
394
395                true
396            }
397            XmlEvent::EndElement { .. } => false,
398            _ => true,
399        } {
400            continue;
401        }
402
403        Ok(tileset)
404    }
405}
406
407impl Tile {
408    fn join(&mut self, mut new_data: Tile) {
409        self.properties = new_data.properties;
410        self.animation = new_data.animation;
411        if new_data.image.is_some() {
412            self.top_left = new_data.top_left;
413            self.bottom_right = new_data.bottom_right;
414            self.image = new_data.image;
415        }
416        self.object_group.append(&mut new_data.object_group);
417    }
418
419    fn parse<R: Read + Send>(
420        env: TmxLoadContext<'_>,
421        attributes: Vec<OwnedAttribute>,
422        reader: &mut EventReader<R>,
423    ) -> Result<(usize, Tile)> {
424        let mut id = 0;
425
426        for a in attributes.iter() {
427            if a.name.local_name == "id" {
428                id = a.value.parse()?
429            }
430        }
431
432        let mut result = Tile {
433            image: None,
434            top_left: Vec2::new(0.0, 0.0),
435            bottom_right: Vec2::new(1.0, 1.0),
436            width: 0,
437            height: 0,
438            animation: Vec::new(),
439            properties: HashMap::new(),
440            object_group: Vec::new(),
441        };
442
443        while match reader.next()? {
444            XmlEvent::StartElement {
445                name, attributes, ..
446            } => {
447                match name.local_name.as_ref() {
448                    "properties" => {
449                        result.properties = parse_properties(reader)?;
450                    }
451                    "image" => {
452                        let image = parse_image(env.clone(), attributes, reader)?;
453                        result.width = image.width() as i32;
454                        result.height = image.height() as i32;
455                        result.image = Some(image);
456                    }
457                    "animation" => {
458                        result.animation = parse_animation(reader)?;
459                    }
460                    "objectgroup" => {
461                        let group = Layer::parse_objects(env.clone(), attributes, reader)?;
462                        if let Layer::ObjectLayer {
463                            mut objects,
464                            offset,
465                            ..
466                        } = group
467                        {
468                            assert_eq!(offset, IVec2::ZERO);
469                            result.object_group.append(&mut objects);
470                        }
471                    }
472                    _ => parse_empty(reader)?, // skip
473                }
474
475                true
476            }
477            XmlEvent::EndElement { .. } => false,
478            _ => true,
479        } {
480            continue;
481        }
482
483        Ok((id, result))
484    }
485}
486
487impl Layer {
488    fn parse_tiles<R: Read + Send>(
489        attributes: Vec<OwnedAttribute>,
490        reader: &mut EventReader<R>,
491    ) -> Result<Self> {
492        let mut position = IVec2::ZERO;
493        let mut size = UVec2::ZERO;
494        let mut color = Vec4::new(1.0, 1.0, 1.0, 1.0);
495        let mut visible = true;
496        let mut offset = IVec2::ZERO;
497        let mut parallax = Vec2::new(1.0, 1.0);
498        let mut data = Vec::new();
499
500        for a in attributes {
501            match a.name.local_name.as_ref() {
502                "x" => position.x = a.value.parse()?,
503                "y" => position.y = a.value.parse()?,
504                "width" => size.x = a.value.parse()?,
505                "height" => size.y = a.value.parse()?,
506                "offsetx" => offset.x = a.value.parse()?,
507                "offsety" => offset.y = a.value.parse()?,
508                "parallaxx" => parallax.x = a.value.parse()?,
509                "parallaxy" => parallax.y = a.value.parse()?,
510                "opacity" => color.w *= a.value.parse::<f32>()?,
511                "tintcolor" => color *= parse_color_vec4(a.value.as_str())?,
512                "visible" => visible = a.value == "true",
513                _ => (), // skip
514            }
515        }
516
517        while match reader.next()? {
518            XmlEvent::StartElement {
519                name, attributes, ..
520            } => {
521                match name.local_name.as_ref() {
522                    "data" => data = parse_data(attributes, reader)?.into_vec_u32(),
523                    _ => parse_empty(reader)?, // skip
524                }
525
526                true
527            }
528            XmlEvent::EndElement { .. } => false,
529            _ => true,
530        } {}
531
532        Ok(Layer::TileLayer {
533            position,
534            size,
535            color,
536            visible,
537            offset,
538            parallax,
539            data,
540        })
541    }
542
543    fn parse_objects<R: Read + Send>(
544        env: TmxLoadContext<'_>,
545        attributes: Vec<OwnedAttribute>,
546        reader: &mut EventReader<R>,
547    ) -> Result<Self> {
548        let mut offset = IVec2::ZERO;
549        let mut parallax = Vec2::new(1.0, 1.0);
550        let mut color = Vec4::new(1.0, 1.0, 1.0, 1.0);
551        let mut visible = true;
552        let mut draworder_index = false;
553        let mut objects = Vec::new();
554
555        for a in attributes {
556            match a.name.local_name.as_ref() {
557                "offsetx" => offset.x = a.value.parse()?,
558                "offsety" => offset.y = a.value.parse()?,
559                "parallaxx" => parallax.x = a.value.parse()?,
560                "parallaxy" => parallax.y = a.value.parse()?,
561                "opacity" => color.w *= a.value.parse::<f32>()?,
562                "tintcolor" => color *= parse_color_vec4(a.value.as_str())?,
563                "visible" => visible = a.value == "true",
564                "draworder" => draworder_index = a.value == "index",
565                _ => (), // skip
566            }
567        }
568
569        while match reader.next()? {
570            XmlEvent::StartElement {
571                name, attributes, ..
572            } => {
573                match name.local_name.as_ref() {
574                    "object" => {
575                        objects.push(Object::parse(env.clone(), attributes, reader)?);
576                    }
577                    _ => parse_empty(reader)?, // skip
578                }
579
580                true
581            }
582            XmlEvent::EndElement { .. } => false,
583            _ => true,
584        } {
585            continue;
586        }
587
588        Ok(Layer::ObjectLayer {
589            offset,
590            parallax,
591            color,
592            visible,
593            draworder_index,
594            objects,
595        })
596    }
597
598    fn process(mut self, mut map: Map) -> Result<Map> {
599        //let mut new_tilesets = Vec::new();
600        //let mut next_first_gid = map.tilesets
601        //	.last()
602        //	.map(|ts| ts.first_gid + ts.tiles.len() as u32)
603        //	.unwrap_or(1);
604
605        match &mut self {
606            Layer::ObjectLayer { objects, .. } => {
607                for object in objects.iter_mut() {
608                    if let Some(&Property::File(ref tileset_source)) =
609                        object.properties.get("__include_tileset__")
610                    {
611                        let mut found = false;
612                        for tileset in map.tilesets.iter() {
613                            if tileset.source == tileset_source.as_ref() {
614                                object.tile = object.tile.map(|t| tileset.first_gid + t);
615                                found = true;
616                            }
617                        }
618
619                        if !found {
620                            // tileset needs to be added to the map
621                            //object.tile = object.tile.map(|t| tileset.)
622
623                            println!("Can't find the tileset back in the map!!");
624                            println!(
625                                "Tilesets in map: {:#?}",
626                                map.tilesets
627                                    .iter()
628                                    .map(|ts| ts.source.as_str())
629                                    .collect::<Vec<_>>()
630                            );
631                            println!("Tileset in template: {}", tileset_source);
632
633                            todo!("Tilesets referenced in templates must also exist in the map for now.");
634
635                            //
636                        }
637                    }
638                }
639            }
640            &mut _ => unreachable!(),
641        }
642
643        map.layers.push(self);
644
645        Ok(map)
646    }
647
648    fn parse_image<R: Read + Send>(
649        env: TmxLoadContext<'_>,
650        attributes: Vec<OwnedAttribute>,
651        reader: &mut EventReader<R>,
652    ) -> Result<Self> {
653        let mut image = Err(anyhow!("no image found"));
654
655        let mut offset = IVec2::ZERO;
656        let mut parallax = Vec2::new(1.0, 1.0);
657        let mut color = Vec4::new(1.0, 1.0, 1.0, 1.0);
658        let mut visible: bool = true;
659
660        for a in attributes {
661            match a.name.local_name.as_ref() {
662                "offsetx" => offset.x = a.value.parse()?,
663                "offsety" => offset.y = a.value.parse()?,
664                "parallaxx" => parallax.x = a.value.parse()?,
665                "parallaxy" => parallax.y = a.value.parse()?,
666                "opacity" => color.w *= a.value.parse::<f32>()?,
667                "tintcolor" => color *= parse_color_vec4(a.value.as_str())?,
668                "visible" => visible = a.value == "true",
669                _ => (), // skip
670            }
671        }
672
673        while match reader.next()? {
674            XmlEvent::StartElement {
675                name, attributes, ..
676            } => {
677                match name.local_name.as_ref() {
678                    "image" => {
679                        image = parse_image(env.clone(), attributes, reader);
680                    }
681                    _ => parse_empty(reader)?, // skip
682                }
683
684                true
685            }
686            XmlEvent::EndElement { .. } => false,
687            _ => true,
688        } {
689            continue;
690        }
691
692        image.map(|image| Layer::ImageLayer {
693            image,
694            color,
695            visible,
696            offset,
697            parallax,
698        })
699    }
700
701    fn parse_group<'a, R: Read + Send>(
702        env: TmxLoadContext<'a>,
703        attributes: Vec<OwnedAttribute>,
704        reader: &'a mut EventReader<R>,
705    ) -> Result<Self> {
706        let mut offset = IVec2::ZERO;
707        let mut parallax = Vec2::new(1.0, 1.0);
708        let mut color = Vec4::new(1.0, 1.0, 1.0, 1.0);
709        //let mut visible: Option<bool> = None;
710
711        for a in attributes {
712            match a.name.local_name.as_ref() {
713                "offsetx" => offset.x = a.value.parse()?,
714                "offsety" => offset.y = a.value.parse()?,
715                "parallaxx" => parallax.x = a.value.parse()?,
716                "parallaxy" => parallax.y = a.value.parse()?,
717                "opacity" => color.w *= a.value.parse::<f32>()?,
718                "tintcolor" => color *= parse_color_vec4(a.value.as_str())?,
719                //"visible" => visible = Some(a.value == "true"),
720                _ => (), // skip
721            }
722        }
723
724        let mut layers = Vec::new();
725
726        while match reader.next()? {
727            XmlEvent::StartElement {
728                name, attributes, ..
729            } => {
730                match name.local_name.as_ref() {
731                    "layer" => {
732                        layers.push(Layer::parse_tiles(attributes, reader)?);
733                    }
734                    "objectgroup" => {
735                        layers.push(Layer::parse_objects(env.clone(), attributes, reader)?);
736                    }
737                    "imagelayer" => {
738                        layers.push(Layer::parse_image(env.clone(), attributes, reader)?);
739                    }
740                    "group" => {
741                        layers.push(Layer::parse_group(env.clone(), attributes, reader)?);
742                    }
743                    _ => parse_empty(reader)?, // skip
744                }
745
746                true
747            }
748            XmlEvent::EndElement { .. } => false,
749            _ => true,
750        } {
751            continue;
752        }
753
754        for l in layers.iter_mut() {
755            l.add_offset(offset.x, offset.y);
756            l.mul_parallax(parallax.x, parallax.y);
757            l.mul_color(color);
758        }
759        Ok(Layer::Group { layers })
760    }
761}
762
763impl Object {
764    fn parse<'a, R: Read + Send>(
765        env: TmxLoadContext<'a>,
766        attributes: Vec<OwnedAttribute>,
767        reader: &'a mut EventReader<R>,
768    ) -> Result<Object> {
769        let mut result = Object {
770            id: 0,
771            properties: HashMap::new(),
772            tile: None,
773            shape: Shape {
774                points: Vec::new(),
775                closed: false,
776            },
777            name: String::from(""),
778            ty: String::from(""),
779            x: 0.0,
780            y: 0.0,
781            width: 0.0,
782            height: 0.0,
783            rotation: 0.0,
784            visible: true,
785        };
786
787        // see if there is a template
788        for a in attributes.iter() {
789            if a.name.local_name == "template" {
790                let sub_env = env.file_directory(Path::new(a.value.as_str()));
791
792                let file = env.load_file(Path::new(a.value.as_str()).to_path_buf())?;
793                let file = BufReader::new(file.as_slice());
794                let mut reader = EventReader::new(file);
795
796                loop {
797                    if let XmlEvent::StartElement { name, .. } = reader.next()? {
798                        if name.local_name == "template" {
799                            result = Object::parse_template(sub_env.clone(), &mut reader)?;
800                            break;
801                        } else {
802                            parse_empty(&mut reader)?;
803                        }
804                    }
805                }
806            }
807        }
808
809        // apply properties
810        for a in attributes.iter() {
811            match a.name.local_name.as_ref() {
812                "id" => result.id = a.value.parse()?,
813                "gid" => result.tile = Some(a.value.parse()?),
814                "name" => result.name = a.value.clone(),
815                "type" => result.ty = a.value.clone(),
816                "x" => result.x = a.value.parse()?,
817                "y" => result.y = a.value.parse()?,
818                "width" => result.width = a.value.parse()?,
819                "height" => result.height = a.value.parse()?,
820                "rotation" => result.rotation = a.value.parse()?,
821                "visible" => result.visible = a.value == "true",
822                _ => (),
823            }
824        }
825
826        result.shape = Shape {
827            points: vec![
828                vec2(0.0, 0.0),
829                vec2(result.width, 0.0),
830                vec2(result.width, result.height),
831                vec2(0.0, result.height),
832            ],
833            closed: true,
834        };
835
836        while match reader.next()? {
837            XmlEvent::StartElement {
838                name, attributes, ..
839            } => {
840                match name.local_name.as_ref() {
841                    "properties" => {
842                        for (k, v) in parse_properties(reader)?.into_iter() {
843                            result.properties.insert(k, v);
844                        }
845                    }
846                    "polyline" | "polygon" => {
847                        let points: Result<Vec<Vec2>> = attributes
848                            .iter()
849                            .filter(|a| a.name.local_name == "points")
850                            .flat_map(|a| a.value.split(' '))
851                            .map(|pt| {
852                                let mut i = pt.split(',').map(|x| x.parse::<f32>());
853                                let x = i.next();
854                                let y = i.next();
855                                match (x, y) {
856                                    (Some(Ok(x)), Some(Ok(y))) => Ok(Vec2::new(x, y)),
857                                    _ => Err(anyhow!("invalid point")),
858                                }
859                            })
860                            .fold(Ok(Vec::new()), |vec, result| match vec {
861                                Ok(mut vec) => {
862                                    vec.push(result?);
863                                    Ok(vec)
864                                }
865                                Err(e) => Err(e),
866                            });
867
868                        result.shape = Shape {
869                            points: points?,
870                            closed: name.local_name == "polygon",
871                        };
872                        parse_empty(reader)?;
873                    }
874                    "ellipse" => {
875                        let offset = vec2(result.width * 0.5, result.height * 0.5);
876                        result.shape = Shape {
877                            points: (0..16)
878                                .into_iter()
879                                .map(|i| {
880                                    let a = i as f32 * std::f32::consts::PI / 8.0;
881                                    offset
882                                        + vec2(
883                                            a.cos() * result.width * 0.5,
884                                            a.sin() * result.height * 0.5,
885                                        )
886                                })
887                                .collect(),
888                            closed: true,
889                        };
890                        parse_empty(reader)?;
891                    }
892                    "point" => {
893                        result.shape = Shape {
894                            points: vec![vec2(0.0, 0.0)],
895                            closed: false,
896                        };
897                        parse_empty(reader)?;
898                    }
899                    _ => parse_empty(reader)?, // skip
900                }
901
902                true
903            }
904            XmlEvent::EndElement { .. } => false,
905            _ => true,
906        } {}
907
908        Ok(result)
909    }
910
911    fn parse_template<R: Read + Send>(
912        env: TmxLoadContext<'_>,
913        reader: &mut EventReader<R>,
914    ) -> Result<Object> {
915        let mut tileset = Err(anyhow!("tileset not found"));
916        let mut object = Err(anyhow!("object not found"));
917
918        while match reader.next()? {
919            XmlEvent::StartElement {
920                name, attributes, ..
921            } => {
922                match name.local_name.as_ref() {
923                    "tileset" => {
924                        let mut first_gid = 0;
925                        let mut source = "".to_string();
926                        for a in attributes.iter() {
927                            match a.name.local_name.as_ref() {
928                                "firstgid" => first_gid = a.value.parse()?,
929                                "source" => {
930                                    source = format!(
931                                        "{}",
932                                        env.file_path(Path::new(a.value.as_str())).display()
933                                    );
934                                }
935                                _ => (),
936                            }
937                        }
938
939                        tileset = Ok((first_gid, source));
940                        parse_empty(reader)?;
941                    }
942                    "object" => {
943                        object = Object::parse(env.clone(), attributes, reader);
944                    }
945                    _ => parse_empty(reader)?, // skip
946                }
947
948                true
949            }
950            XmlEvent::EndElement { .. } => false,
951            _ => true,
952        } {
953            continue;
954        }
955
956        let mut object = object?;
957        if object.tile.is_some() {
958            let (first_gid, source) = tileset?;
959            object.tile = object.tile.map(|t| t - first_gid);
960            object
961                .properties
962                .insert("__include_tileset__".to_string(), Property::File(source));
963        }
964        Ok(object)
965    }
966}
967
968fn parse_image<R: Read + Send>(
969    env: TmxLoadContext<'_>,
970    attributes: Vec<OwnedAttribute>,
971    reader: &mut EventReader<R>,
972) -> Result<texture::Texture> {
973    let mut source: Option<String> = None;
974    //let mut trans: Option<[u8; 4]> = None;
975    let mut width: Option<u32> = None;
976    let mut height: Option<u32> = None;
977    let mut data: Option<Vec<u8>> = None;
978    //let mut format: Option<String> = None;
979
980    for a in attributes.iter() {
981        match a.name.local_name.as_ref() {
982            "source" => source = Some(a.value.clone()),
983            //"trans" => trans = Some(parse_color(a.value.as_str())),
984            "width" => width = Some(a.value.parse()?),
985            "height" => height = Some(a.value.parse()?),
986            //"format" => format = Some(a.value.clone()),
987            _ => (),
988        }
989    }
990
991    while match reader.next()? {
992        XmlEvent::StartElement {
993            name, attributes, ..
994        } => {
995            match name.local_name.as_ref() {
996                "data" => data = Some(parse_data(attributes, reader)?.into_vec_u8()),
997                _ => parse_empty(reader)?, // skip
998            }
999
1000            true
1001        }
1002        XmlEvent::EndElement { .. } => false,
1003        _ => true,
1004    } {
1005        continue;
1006    }
1007
1008    let mut image = if let Some(source) = source.as_ref() {
1009        Texture::from_path(env.file_path(Path::new(source)))
1010    } else if let Some(data) = data {
1011        let mut h = std::collections::hash_map::DefaultHasher::default();
1012        data.hash(&mut h);
1013        Texture::from_bytes(data.as_slice(), format!("embedded#{}", h.finish()))?
1014    } else {
1015        bail!("invalid image")
1016    };
1017
1018    if let (Some(width), Some(height)) = (width, height) {
1019        image = image.resize(width, height)?;
1020    }
1021    Ok(image)
1022}
1023
1024fn parse_data<R: Read + Send>(
1025    attributes: Vec<OwnedAttribute>,
1026    reader: &mut EventReader<R>,
1027) -> Result<Data> {
1028    let mut decode_csv = false;
1029    let mut decode_base64 = false;
1030    let mut decompress_z = false;
1031    let mut decompress_g = false;
1032
1033    for a in attributes.iter() {
1034        match a.name.local_name.as_ref() {
1035            "encoding" => match a.value.as_ref() {
1036                "csv" => decode_csv = true,
1037                "base64" => decode_base64 = true,
1038                _ => (),
1039            },
1040            "compression" => match a.value.as_ref() {
1041                "zlib" => decompress_z = true,
1042                "glib" => decompress_g = true,
1043                _ => (),
1044            },
1045            _ => (),
1046        }
1047    }
1048
1049    let mut result = Data::U32(Vec::new());
1050
1051    while match reader.next()? {
1052        XmlEvent::StartElement { .. } => {
1053            parse_empty(reader)?;
1054            true
1055        }
1056        XmlEvent::Characters(s) => {
1057            if decode_csv {
1058                result = Data::U32(
1059                    s.split(',')
1060                        .filter(|v| v.trim() != "")
1061                        .map(|v| v.replace('\r', "").parse().unwrap_or(0))
1062                        .collect(),
1063                );
1064            } else if decode_base64 {
1065                let bytes = base64::decode(s.trim().as_bytes())?;
1066
1067                let bytes = if decompress_z {
1068                    let mut zd = libflate::zlib::Decoder::new(BufReader::new(&bytes[..]))?;
1069                    let mut bytes = Vec::new();
1070                    zd.read_to_end(&mut bytes)?;
1071
1072                    bytes
1073                } else if decompress_g {
1074                    let mut zd = libflate::gzip::Decoder::new(BufReader::new(&bytes[..]))?;
1075                    let mut bytes = Vec::new();
1076                    zd.read_to_end(&mut bytes)?;
1077
1078                    bytes
1079                } else {
1080                    bytes
1081                };
1082
1083                result = Data::U8(bytes)
1084            } else {
1085                bail!("<tile> based data is not supported");
1086            }
1087
1088            true
1089        }
1090        XmlEvent::EndElement { .. } => false,
1091        _ => true,
1092    } {
1093        continue;
1094    }
1095
1096    Ok(result)
1097}
1098
1099fn parse_properties<R: Read + Send>(
1100    reader: &mut EventReader<R>,
1101) -> Result<HashMap<String, Property>> {
1102    let mut result = HashMap::new();
1103
1104    while match reader.next()? {
1105        XmlEvent::StartElement {
1106            name, attributes, ..
1107        } => {
1108            match name.local_name.as_ref() {
1109                "property" => {
1110                    let (k, v) = parse_property(attributes, reader)?;
1111                    result.insert(k, v);
1112                }
1113                _ => parse_empty(reader)?, // skip
1114            }
1115
1116            true
1117        }
1118        XmlEvent::EndElement { .. } => false,
1119        _ => true,
1120    } {
1121        continue;
1122    }
1123
1124    Ok(result)
1125}
1126
1127fn parse_property<R: Read + Send>(
1128    attributes: Vec<OwnedAttribute>,
1129    reader: &mut EventReader<R>,
1130) -> Result<(String, Property)> {
1131    let mut key = String::from("");
1132    let mut value = Property::Int(0);
1133    let mut ty = 0;
1134
1135    for a in attributes {
1136        match a.name.local_name.as_ref() {
1137            "name" => key = a.value.clone(),
1138            "type" => {
1139                ty = match a.value.as_ref() {
1140                    "string" => 0,
1141                    "int" => 1,
1142                    "float" => 2,
1143                    "bool" => 3,
1144                    "color" => 4,
1145                    "file" => 5,
1146                    _ => bail!("invalid property type"),
1147                }
1148            }
1149            "value" => {
1150                value = match ty {
1151                    0 => Property::String(a.value.clone()),
1152                    1 => Property::Int(a.value.parse()?),
1153                    2 => Property::Float(a.value.parse()?),
1154                    3 => Property::Bool(a.value == "true"),
1155                    4 => Property::Color(parse_color(a.value.as_str())?),
1156                    5 => Property::File(a.value.clone()),
1157                    _ => unreachable!(),
1158                }
1159            }
1160            _ => (), // skip
1161        }
1162    }
1163
1164    parse_empty(reader)?;
1165
1166    Ok((key, value))
1167}
1168
1169fn parse_animation<R: Read + Send>(reader: &mut EventReader<R>) -> Result<Vec<Frame>> {
1170    let mut result = Vec::new();
1171
1172    while match reader.next()? {
1173        XmlEvent::StartElement {
1174            name, attributes, ..
1175        } => {
1176            match name.local_name.as_ref() {
1177                "frame" => result.push(parse_frame(attributes, reader)?),
1178                _ => parse_empty(reader)?, // skip
1179            }
1180
1181            true
1182        }
1183        XmlEvent::EndElement { .. } => false,
1184        _ => true,
1185    } {
1186        continue;
1187    }
1188
1189    Ok(result)
1190}
1191
1192fn parse_frame<R: Read + Send>(
1193    attributes: Vec<OwnedAttribute>,
1194    reader: &mut EventReader<R>,
1195) -> Result<Frame> {
1196    let mut frame = Frame {
1197        tile: 0,
1198        duration: 0,
1199    };
1200
1201    for a in attributes {
1202        match a.name.local_name.as_ref() {
1203            "tileid" => frame.tile = a.value.parse()?,
1204            "duration" => frame.duration = a.value.parse()?,
1205            _ => (), // skip
1206        }
1207    }
1208
1209    parse_empty(reader)?;
1210
1211    Ok(frame)
1212}
1213
1214fn parse_empty<R: Read + Send>(reader: &mut EventReader<R>) -> Result<()> {
1215    while match reader.next()? {
1216        XmlEvent::StartElement { .. } => {
1217            parse_empty(reader)?;
1218            true
1219        }
1220        XmlEvent::EndElement { .. } => false,
1221        _ => true,
1222    } {
1223        continue;
1224    }
1225    Ok(())
1226}
1227
1228fn parse_color(text: &str) -> Result<[u8; 4]> {
1229    let lowercase: Vec<char> = text
1230        .chars()
1231        .filter(|&c| c != '#')
1232        .map(|c| c.to_ascii_lowercase())
1233        .collect();
1234    let mut result = [255u8; 4];
1235
1236    let nibble = |c| match c {
1237        '0' => 0,
1238        '1' => 1,
1239        '2' => 2,
1240        '3' => 3,
1241        '4' => 4,
1242        '5' => 5,
1243        '6' => 6,
1244        '7' => 7,
1245        '8' => 8,
1246        '9' => 9,
1247        'a' => 10,
1248        'b' => 11,
1249        'c' => 12,
1250        'd' => 13,
1251        'e' => 14,
1252        'f' => 15,
1253        _ => 0,
1254    };
1255
1256    match lowercase.len() {
1257        6 => {
1258            for (i, e) in lowercase.chunks_exact(2).enumerate() {
1259                result[i + 1] = nibble(e[0]) << 4 | nibble(e[1]);
1260            }
1261            Ok(result)
1262        }
1263
1264        8 => {
1265            for (i, e) in lowercase.chunks_exact(2).enumerate() {
1266                result[i] = nibble(e[0]) << 4 | nibble(e[1]);
1267            }
1268            Ok(result)
1269        }
1270
1271        _ => bail!("invalid color"),
1272    }
1273}
1274
1275fn parse_color_vec4(text: &str) -> Result<Vec4> {
1276    let [a, r, g, b] = parse_color(text)?;
1277    Ok(Vec4::new(r as f32, g as f32, b as f32, a as f32) * (1.0 / 255.0))
1278}