1 module tests.data; 2 3 import std.conv; 4 import std.range; 5 import std.algorithm; 6 import std.path : buildPath, setExtension; 7 import std.exception : assertThrown; 8 import dtiled.data; 9 10 enum testPath(string name) = "tests".buildPath("resources", name).setExtension("json"); 11 12 // expected gids for the test terrain layer 13 enum terrainGids = [1, 2, 1, 2, 3, 1, 3, 1, 2, 2, 3, 3, 4, 4, 4, 1]; 14 enum flippedTerrainGids = [1, 2, 2, 1, 3, 1, 1, 3, 4, 4, 1, 4, 2, 2, 3, 3]; 15 16 /// Load a map containing a single tile layer 17 unittest { 18 // load map 19 auto map = MapData.load(testPath!"tiles"); 20 21 // general fields 22 assert(map.numRows == 4); 23 assert(map.numCols == 4); 24 assert(map.tileWidth == 32); 25 assert(map.tileHeight == 32); 26 assert(map.renderOrder == MapData.RenderOrder.rightDown); 27 assert(map.orientation == MapData.Orientation.orthogonal); 28 assert(map.backgroundColor == "#656667"); 29 30 // user defined properties 31 assert(map.properties["mapProperty1"] == "one"); 32 assert(map.properties["mapProperty2"] == "two"); 33 34 // this map should have a single tile layer 35 assert(map.layers.length == 1); 36 37 auto tiles = map.layers[0]; 38 assert(tiles.name == "terrain"); 39 assert(tiles.data == terrainGids); 40 assert(tiles.numRows == 4); 41 assert(tiles.numCols == 4); 42 assert(tiles.opacity == 1f); 43 assert(tiles.type == LayerData.Type.tilelayer); 44 assert(tiles.visible); 45 assert(tiles.x == 0); 46 assert(tiles.y == 0); 47 48 // getLayer should return layers[0] 49 assert(map.getLayer("terrain") == tiles); 50 51 // this map should have a single tile set 52 assert(map.tilesets.length == 1); auto tileset = map.tilesets[0]; 53 // fields 54 assert(tileset.name == "terrain"); 55 assert(tileset.firstGid == 1); 56 assert(tileset.imageHeight == 64); 57 assert(tileset.imageWidth == 64); 58 assert(tileset.margin == 0); 59 assert(tileset.tileHeight == 32); 60 assert(tileset.tileWidth == 32); 61 assert(tileset.spacing == 0); 62 // properties 63 assert(tileset.numRows == 2); 64 assert(tileset.numCols == 2); 65 assert(tileset.numTiles == 4); 66 67 // getTileset should return tilesets[0] 68 assert(map.getTileset("terrain") == tileset); 69 } 70 71 /// Load a map containing an object layer 72 unittest { 73 import std.string : format; 74 75 // load map 76 auto map = MapData.load(testPath!"objects"); 77 78 // Layer 1 is an object layer in the test map 79 auto layer = map.layers[1]; 80 assert(layer.name == "things"); 81 assert(layer.type == LayerData.Type.objectgroup); 82 assert(layer.drawOrder == "topdown"); 83 84 // Tileset 1 is the tileset used for the objects 85 auto tileset = map.tilesets[1]; 86 assert(tileset.name == "numbers"); 87 auto objects = layer.objects; 88 89 // helper to check an object in the test data 90 void checkObject(int num) { 91 string name = "number%d".format(num); 92 auto found = objects.find!(x => x.name == name); 93 assert(!found.empty, "no object with name " ~ name); 94 auto obj = found.front; 95 96 assert(obj.gid == tileset.firstGid + num - 1); // number1 is the zeroth tile, ect. 97 assert(obj.type == (num % 2 == 0 ? "even" : "odd")); // just an arbitrarily picked type 98 //assert(obj.properties["half"].to!int == num / 2 )); 99 assert(obj.rotation == 0); 100 assert(obj.visible); 101 } 102 103 checkObject(1); 104 checkObject(2); 105 checkObject(3); 106 checkObject(4); 107 } 108 109 /// Load a map containing flipped (mirrored) tiles. 110 unittest { 111 import std.algorithm : map, equal; 112 113 // load map 114 auto tileMap = MapData.load(testPath!"flipped_tiles"); 115 116 // this map should have a single tile layer 117 assert(tileMap.layers.length == 1); 118 auto layer = tileMap.layers[0]; 119 120 // clear special bits to get actual gid 121 auto gids = layer.data.map!(gid => gid & ~TiledFlag.all); 122 // with the special bits cleared, the gids should be the same as in the original map 123 assert(gids.equal(flippedTerrainGids)); 124 125 // isolate special bits to get flipped state 126 auto flags = layer.data.map!(gid => gid & TiledFlag.all); 127 128 with(TiledFlag) { 129 enum N = none; 130 enum H = flipHorizontal; 131 enum V = flipVertical; 132 enum D = H | V; 133 134 enum flippedState = [ 135 N, N, H, H, 136 N, N, H, H, 137 V, V, D, D, 138 V, V, D, D, 139 ]; 140 141 assert(flags.equal(flippedState)); 142 } 143 } 144 145 /// Load a map containing flipped (mirrored) objects. 146 unittest { 147 import std.conv; 148 import std.string : format; 149 150 // load map 151 auto map = MapData.load(testPath!"flipped_objects"); 152 153 // Layer 1 is an object layer in the test map 154 auto layer = map.layers[1]; 155 156 // Tileset 1 is the tileset used for the objects 157 auto tileset = map.tilesets[1]; 158 assert(tileset.name == "numbers"); 159 auto objects = layer.objects; 160 161 // helper to check an object in the test data 162 void checkObject(int num, TiledFlag expectedFlags) { 163 string name = "number%d".format(num); 164 auto found = objects.find!(x => x.name == name); 165 assert(!found.empty, "no object with name " ~ name); 166 auto obj = found.front; 167 168 auto gid = obj.gid & ~TiledFlag.all; 169 auto flags = obj.gid & TiledFlag.all; 170 assert(gid == tileset.firstGid + num - 1); // number1 is the zeroth tile, ect. 171 assert(flags == expectedFlags, 172 "tile %d: expected flag %s, got %s".format(num, expectedFlags, cast(TiledFlag) flags)); 173 } 174 175 checkObject(1, TiledFlag.none); 176 checkObject(2, TiledFlag.flipVertical); 177 checkObject(3, TiledFlag.flipHorizontal); 178 checkObject(4, TiledFlag.flipHorizontal | TiledFlag.flipVertical); 179 }