1 module Dgame.Graphics.TiledMap;
2 
3 private {
4 	import std.xml : Document, Element;
5 	import std.file : read;
6 	import std.conv : to;
7 
8 	import Dgame.Internal.Log;
9 
10 	import Dgame.Math.Vector2;
11 	import Dgame.Math.Vector3;
12 
13 	import Dgame.Graphics.TileMap;
14 	import Dgame.System.VertexRenderer : Target;
15 }
16 
17 class TiledMap : TileMap {
18 protected:
19 	override void _readTileMap() {
20 		Document doc = new Document(cast(string) .read(super._filename));
21 		
22 		scope Vector3f[] vertices;
23 		
24 		foreach (const Element elem; doc.elements) {
25 			if (elem.tag.name == "tileset") {
26 				super._tmi.source = elem.elements[0].tag.attr["source"];
27 				
28 				super._tmi.tileWidth = to!ubyte(elem.tag.attr["tilewidth"]);
29 				super._tmi.tileHeight = to!ubyte(elem.tag.attr["tileheight"]);
30 			}
31 			
32 			if (elem.tag.name == "layer") {
33 				if (!super._tmi.width) {
34 					super._tmi.width  = to!ushort(elem.tag.attr["width"]);
35 					super._tmi.height = to!ushort(elem.tag.attr["height"]);
36 					
37 					if (vertices.length != 0)
38 						Log.error("Wrong vertice format.");
39 					
40 					const size_t cap = super._tmi.width * super._tmi.height;
41 
42 					vertices.reserve(cap * 4);
43 					super._tiles.reserve(cap);
44 
45 					debug Log.info("TiledMap: Reserve %d vertices. Get %d.", cap * 4, vertices.capacity);
46 					debug Log.info("TiledMap: Reserve %d Tiles. Get %d.", cap, super._tiles.capacity);
47 				}
48 				
49 				ushort row, col;
50 				foreach (const Element child; elem.elements[0].elements) {
51 					const ushort gid = to!ushort(child.tag.attr["gid"]);
52 					
53 					const ushort vx = cast(ushort)(col * super._tmi.tileWidth);
54 					const ushort vy = cast(ushort)(row * super._tmi.tileHeight);
55 					
56 					super._tiles ~= Tile(gid, [vx, vy], [col, row], elem.tag.attr["name"], );
57 					
58 					const float vw = super._tmi.tileWidth;
59 					const float vh = super._tmi.tileHeight;
60 					
61 					vertices ~= Vector3f(vx, vy); /// #1
62 					vertices ~= Vector3f(vx + vw, vy); /// #2
63 					vertices ~= Vector3f(vx, vy + vh); /// #3
64 					vertices ~= Vector3f(vx + vw, vy + vh); /// #4
65 					
66 					col++;
67 					if (col >= super._tmi.width) {
68 						col = 0;
69 						row++;
70 					}
71 				}
72 			}
73 		}
74 		
75 		debug Log.info("TiledMap: Needed %d vertices.", vertices.length);
76 		debug Log.info("TiledMap: Needed %d Tiles.", super._tiles.length);
77 		
78 		/// Store the map size
79 		super._tmi.mapSize[0] = super._tmi.width;
80 		super._tmi.mapSize[1] = super._tmi.height;
81 		
82 		/// Adjust to real size in pixel
83 		super._tmi.width *= super._tmi.tileWidth;
84 		super._tmi.height *= super._tmi.tileHeight;
85 		
86 		super._vbo.bind(Target.Vertex);
87 		
88 		if (!super._vbo.isCurrentEmpty())
89 			super._vbo.modify(&vertices[0], vertices.length * Vector3f.sizeof);
90 		else
91 			super._vbo.cache(&vertices[0], vertices.length * Vector3f.sizeof);
92 		
93 		super._vbo.unbind();
94 		
95 		super._loadTileset();
96 	}
97 	
98 public:
99 	/**
100 	 * CTor
101 	 * 
102 	 * If compress is true, only the needed Tiles are stored
103 	 * (which means that are new tileset is created which contains only the needed tiles)
104 	 * otherwise the whole tileset is taken.
105 	 */
106 	this(string filename, bool compress = true) {
107 		super(filename, compress);
108 	}
109 }
110