def test_dict_export(test_map_data): filename, has_gzip, output_filename = test_map_data xml = file_contents(get_test_filename(filename)) map = tmxlib.Map.load(xml, base_path=base_path) dct = json.load(open(get_test_filename(filename.replace('.tmx', '.json')))) result = map.to_dict() assert_json_safe_almost_equal(result, dct)
def test_dict_import(filename, has_gzip, out_filename): dct = json.load(open(get_test_filename(filename.replace('.tmx', '.json')))) map = tmxlib.Map.from_dict(dct, base_path=base_path) # Check JSON roundtrip result_dct = map.to_dict() assert_json_safe_almost_equal(result_dct, dct) # Check XML roundtrip if has_gzip and sys.version_info < (2, 7): raise pytest.skip('Cannot test gzip on Python 2.6: missing mtime arg') xml = file_contents(get_test_filename(filename)) xml_map = tmxlib.Map.load(xml, base_path=base_path) xml = file_contents(get_test_filename(out_filename)) # Have to copy presentation attrs, since those aren't in the JSON # Also, load images for layer, xml_layer in zip(map.layers, xml_map.layers): layer.compression = getattr(xml_layer, 'compression', None) layer.mtime = 0 if map_loadable(filename) and layer.type == 'image': layer.image.load_image() for tileset, xml_tileset in zip(map.tilesets, xml_map.tilesets): tileset.source = xml_tileset.source if map_loadable( filename) and tileset.type == 'image' and tileset.image: tileset.image.load_image() dumped = map.dump() assert_xml_compare(xml, dumped)
def test_dict_import(filename, has_gzip, out_filename, map_loadable): dct = json.load(open(get_test_filename(filename.replace('.tmx', '.json')))) map = tmxlib.Map.from_dict(dct, base_path=base_path) # Check JSON roundtrip result_dct = map.to_dict() assert_json_safe_almost_equal(result_dct, dct) # Check XML roundtrip if has_gzip and sys.version_info < (2, 7): raise pytest.skip('Cannot test gzip on Python 2.6: missing mtime arg') xml = file_contents(get_test_filename(filename)) xml_map = tmxlib.Map.load(xml, base_path=base_path) xml = file_contents(get_test_filename(out_filename)) # Have to copy presentation attrs, since those aren't in the JSON # Also, load images for layer, xml_layer in zip(map.layers, xml_map.layers): layer.compression = getattr(xml_layer, 'compression', None) layer.mtime = 0 if map_loadable and layer.type == 'image': layer.image.load_image() for tileset, xml_tileset in zip(map.tilesets, xml_map.tilesets): tileset.source = xml_tileset.source if map_loadable and tileset.type == 'image' and tileset.image: tileset.image.load_image() dumped = map.dump() assert_xml_compare(xml, dumped)
def test_roundtrip_readwrite(filename, has_gzip, out_filename): if has_gzip and sys.version_info < (2, 7): raise pytest.skip('Cannot test gzip on Python 2.6: missing mtime arg') xml = file_contents(get_test_filename(filename)) map = tmxlib.Map.load(xml, base_path=base_path) for layer in map.layers: # normalize mtime, for Gzip layer.mtime = 0 dumped = map.dump() if out_filename != filename: xml = file_contents(get_test_filename(out_filename)) assert_xml_compare(xml, dumped)
def test_flipping(): testmap = tmxlib.Map.open(get_test_filename('flip-test.tmx')) layer = testmap.layers[0] colors = { (1, 0, 0, 1): 'red', (1, 1, 0, 1): 'ylw', (0, 1, 0, 1): 'grn', (0, 0, 1, 1): 'blu', } def assert_corners(tile_x, tile_y, *expected): # "expected" are colors clockwise from top left, and the 3 flags tile = layer[tile_x, tile_y] g = colors.get actual = ( g(tile.get_pixel(0, 0)), g(tile.get_pixel(15, 0)), g(tile.get_pixel(15, 15)), g(tile.get_pixel(0, 15)), int(tile.flipped_horizontally), int(tile.flipped_vertically), int(tile.flipped_diagonally), ) assert actual == expected # Test all combinations of flags, as Tiled saved them # (tiles are tested clockwise from top left, again) assert_corners(0, 0, 'red', 'ylw', 'grn', 'blu', 0, 0, 0) assert_corners(1, 0, 'blu', 'red', 'ylw', 'grn', 1, 0, 1) assert_corners(2, 0, 'grn', 'blu', 'red', 'ylw', 1, 1, 0) assert_corners(2, 1, 'ylw', 'grn', 'blu', 'red', 0, 1, 1) assert_corners(2, 2, 'red', 'blu', 'grn', 'ylw', 0, 0, 1) assert_corners(1, 2, 'ylw', 'red', 'blu', 'grn', 1, 0, 0) assert_corners(0, 2, 'grn', 'ylw', 'red', 'blu', 1, 1, 1) assert_corners(0, 1, 'blu', 'grn', 'ylw', 'red', 0, 1, 0)
def test_layer_list(desert): different_map = tmxlib.Map.open(get_test_filename('desert.tmx')) desert.add_layer('Sky') desert.add_tile_layer('Underground', before='Ground') desert.add_object_layer('Grass', after='Ground') def check_names(names_string): names = names_string.split() assert [l.name for l in desert.layers] == names check_names('Underground Ground Grass Sky') assert [l.name for l in desert.layers[2:]] == 'Grass Sky'.split() assert [l.name for l in desert.layers[:2]] == 'Underground Ground'.split() assert [l.name for l in desert.layers[::2]] == 'Underground Grass'.split() assert [l.name for l in desert.layers[1::2]] == 'Ground Sky'.split() assert [l.name for l in desert.layers[:2:2]] == 'Underground'.split() assert [l.name for l in desert.layers[1:3]] == 'Ground Grass'.split() assert [l.name for l in desert.layers[-2:]] == 'Grass Sky'.split() assert [l.name for l in desert.layers[:-2]] == 'Underground Ground'.split() assert [l.name for l in desert.layers[::-2]] == 'Sky Ground'.split() assert [l.name for l in desert.layers[-2::-2]] == 'Grass Underground'.split() assert [l.name for l in desert.layers[:-2:-2]] == 'Sky'.split() assert [l.name for l in desert.layers[-3:-1]] == 'Ground Grass'.split() ground = desert.layers[1] assert ground.name == 'Ground' del desert.layers[1::2] check_names('Underground Grass') two_layers = list(desert.layers) del desert.layers[1] check_names('Underground') desert.layers[0] = ground check_names('Ground') desert.layers[1:] = two_layers check_names('Ground Underground Grass') del desert.layers[:1] desert.layers[1:1] = [ground] check_names('Underground Ground Grass') with pytest.raises(ValueError): desert.layers[0] = different_map.layers[0] desert.layers.move('Grass', -2) check_names('Grass Underground Ground') desert.layers.move('Ground', -20) check_names('Ground Grass Underground') desert.layers.move('Underground', -1) check_names('Ground Underground Grass') desert.layers.move('Underground', 1) check_names('Ground Grass Underground') desert.layers.move('Ground', 20) check_names('Grass Underground Ground') desert.layers.move('Grass', 2) check_names('Underground Ground Grass')
def test_map_repr_png(canvas_mod, filename, rendered_filename): map = tmxlib.Map.open(get_test_filename(filename)) for obj in map.all_objects(): if not obj.value: raise pytest.skip('Plain objects not renderable yet') # TODO assert_png_repr_equal(map, rendered_filename, epsilon=2, crop_first=[425, 228, 80, 80])
def test_map_get_pixel(): map = tmxlib.Map.open(get_test_filename('desert_and_walls.tmx')) pixel_value = 255 / 255, 208 / 255, 148 / 255, 1 assert map.layers['Ground'][0, 0].get_pixel(0, 0) == pixel_value assert map.tilesets['Desert'][0].get_pixel(0, 0) == pixel_value assert map.layers['Ground'][0, 0].image[0, 0] == pixel_value assert map.tilesets['Desert'][0].image[0, 0] == pixel_value assert map.tilesets[0].image.data empty_tile = map.layers['Building'][0, 0] assert not empty_tile assert empty_tile.get_pixel(0, 0) == (0, 0, 0, 0) tile = map.layers['Ground'][0, 0] top_left = 98 / 255, 88 / 255, 56 / 255, 1 top_right = 98 / 255, 88 / 255, 56 / 255, 1 bottom_left = 209 / 255, 189 / 255, 158 / 255, 1 bottom_right = 162 / 255, 152 / 255, 98 / 255, 1 tile.value = map.tilesets['Desert'][9] assert_color_tuple_eq(tile.get_pixel(0, 0), top_left) assert_color_tuple_eq(tile.get_pixel(0, -1), bottom_left) assert_color_tuple_eq(tile.get_pixel(-1, 0), top_right) assert_color_tuple_eq(tile.get_pixel(-1, -1), bottom_right) tile.value = map.tilesets['Desert'][9] tile.flipped_horizontally = True assert_color_tuple_eq(tile.get_pixel(0, 0), top_right) assert_color_tuple_eq(tile.get_pixel(0, -1), bottom_right) assert_color_tuple_eq(tile.get_pixel(-1, 0), top_left) assert_color_tuple_eq(tile.get_pixel(-1, -1), bottom_left) tile.value = map.tilesets['Desert'][9] tile.flipped_vertically = True assert_color_tuple_eq(tile.get_pixel(0, 0), bottom_left) assert_color_tuple_eq(tile.get_pixel(0, -1), top_left) assert_color_tuple_eq(tile.get_pixel(-1, 0), bottom_right) assert_color_tuple_eq(tile.get_pixel(-1, -1), top_right) tile.value = map.tilesets['Desert'][9] tile.flipped_diagonally = True assert_color_tuple_eq(tile.get_pixel(0, 0), top_left) assert_color_tuple_eq(tile.get_pixel(0, -1), top_right) assert_color_tuple_eq(tile.get_pixel(-1, 0), bottom_left) assert_color_tuple_eq(tile.get_pixel(-1, -1), bottom_right) tile.value = map.tilesets['Desert'][9] tile.flipped_horizontally = True tile.flipped_vertically = True tile.flipped_diagonally = True assert_color_tuple_eq(tile.get_pixel(0, 0), bottom_right) assert_color_tuple_eq(tile.get_pixel(0, -1), bottom_left) assert_color_tuple_eq(tile.get_pixel(-1, 0), top_right) assert_color_tuple_eq(tile.get_pixel(-1, -1), top_left)
def test_map_tiles(desert): assert len(list(desert.get_tiles(0, 0))) == 1 map = tmxlib.Map.open(get_test_filename('desert_and_walls.tmx')) tile_list = list(map.get_tiles(0, 0)) assert len(tile_list) == 3 assert tile_list[0] == map.layers[0][0, 0] assert tile_list[1] == map.layers[1][0, 0]
def test_render_layer(canvas_mod): commands = [] desert = tmxlib.Map.open(get_test_filename('desert.tmx')) for layer in desert.layers: commands.extend(layer.generate_draw_commands()) canvas = canvas_mod.Canvas(desert.pixel_size, commands=commands) assert_png_repr_equal(canvas, 'desert.rendered.png')
def test_autoadd_tileset(desert): tileset = tmxlib.ImageTileset.open( get_test_filename('perspective_walls.tsx')) assert tileset not in desert.tilesets desert.layers[0][0, 0] = tileset[0] assert tileset in desert.tilesets
def test_roundtrip_opensave(filename, has_gzip, out_filename): if has_gzip and sys.version_info < (2, 7): raise pytest.skip('Cannot test gzip on Python 2.6: missing mtime arg') filename = get_test_filename(filename) out_filename = get_test_filename(out_filename) map = tmxlib.Map.open(filename) for layer in map.layers: # normalize mtime, for Gzip layer.mtime = 0 temporary_file = tempfile.NamedTemporaryFile(delete=False) map.check_consistency() try: temporary_file.close() map.save(temporary_file.name) assert_xml_compare(file_contents(out_filename), file_contents(temporary_file.name)) finally: os.unlink(temporary_file.name)
def assert_png_repr_equal(image, filename, epsilon=0, crop_first=None): data = image._repr_png_() a = pil_image_open(get_test_filename(filename)) b = pil_image_open(BytesIO(data)) assert b.format == 'PNG' if crop_first: left, top, width, height = crop_first ac = a.crop((left, top, left + width, top + height)) bc = b.crop((left, top, left + width, top + height)) assert_pil_images_equal(ac, bc, epsilon=epsilon) assert_pil_images_equal(a, b, epsilon=epsilon)
def test_del_tileset(): filename = get_test_filename('walls_and_desert.tmx') testmap = tmxlib.Map.open(filename) with pytest.raises(tmxlib.UsedTilesetError): del testmap.tilesets['Walls'] # Ensure deleting did not mess up anything dumped = testmap.dump() xml = file_contents(filename) assert_xml_compare(xml, dumped)
def test_multiple_tilesets(): map = tmxlib.Map.open(get_test_filename('desert_and_walls.tmx')) def check_names(names_string): names = names_string.split() assert [l.name for l in map.tilesets] == names check_names('Desert Walls') walls = map.tilesets[1] walls2 = tmxlib.ImageTileset('Walls2', tile_size=(20, 20), image=map.tilesets[0].image) map.tilesets.append(walls2) check_names('Desert Walls Walls2') assert walls2.first_gid(map) == walls.first_gid(map) + len(walls) == 65 assert any(t.tileset is walls for t in map.all_tiles()) assert not any(t.tileset is walls2 for t in map.all_tiles()) building = map.layers['Building'] tile = building[1, 1] assert tile.tileset is walls assert tile.gid == walls.first_gid(map) + tile.number assert walls.first_gid(map) < building[1, 1].gid < walls2.first_gid(map) assert map.end_gid == 182 map.tilesets.move('Walls2', -1) check_names('Desert Walls2 Walls') print(tile.gid, walls.first_gid(map)) print(tile.tileset_tile) assert tile.tileset is walls assert tile.gid == walls.first_gid(map) + tile.number assert walls2.first_gid(map) < walls.first_gid(map) < building[1, 1].gid assert map.end_gid == 182 assert any(t.tileset is walls for t in map.all_tiles()) assert not any(t.tileset is walls2 for t in map.all_tiles()) assert map.end_gid == 182 map.tilesets.move('Walls2', 1) assert tile.tileset is walls assert tile.gid == walls.first_gid(map) + tile.number assert walls.first_gid(map) < building[1, 1].gid < walls2.first_gid(map) assert map.end_gid == 182 del map.tilesets['Walls2'] assert tile.tileset is walls assert tile.gid == walls.first_gid(map) + tile.number assert map.end_gid == 65 del map.layers[:] del map.tilesets[:] assert map.end_gid == 0
def test_rotation(): testmap = tmxlib.Map.open(get_test_filename('flip-test.tmx')) layer = testmap.layers[0] tile = layer[1, 1] tile.gid = layer[0, 0].gid assert tile.value == layer[0, 0].value tile.rotate() assert tile.value == layer[1, 0].value tile.rotate() assert tile.value == layer[2, 0].value tile.rotate() assert tile.value == layer[2, 1].value tile.rotate() assert tile.value == layer[0, 0].value tile.rotate(-90) assert tile.value == layer[2, 1].value tile.rotate(-180) assert tile.value == layer[1, 0].value tile.rotate(270) assert tile.value == layer[0, 0].value tile.flipped_diagonally = True assert tile.value == layer[2, 2].value tile.rotate() assert tile.value == layer[1, 2].value tile.rotate() assert tile.value == layer[0, 2].value tile.rotate() assert tile.value == layer[0, 1].value tile.rotate() tile.flipped_diagonally = False assert tile.value == layer[0, 0].value tile.hflip() assert tile.value == layer[1, 2].value tile.vflip() assert tile.value == layer[2, 0].value tile.hflip() assert tile.value == layer[0, 1].value tile.rotate() assert tile.value == layer[2, 2].value
def test_tile_and_object_attr_equivalence(): map = tmxlib.Map.open(get_test_filename('equivcheck.tmx')) def assert_equal_attr(attr_name, tile, obj): print(attr_name, getattr(tile, attr_name), getattr(obj, attr_name)) assert getattr(tile, attr_name) == getattr(obj, attr_name) for tile, tileobj, plainobj in ( ( map.layers['Tile Layer'][1, 1], map.layers['Tileobject Layer'][0], map.layers['Plain Object Layer'][0], ), ( map.layers['Tile Layer'][4, 2], map.layers['Tileobject Layer'][1], map.layers['Plain Object Layer'][1], ), ): for attr_name in ( 'size', 'width', 'height', 'pixel_size', 'pixel_width', 'pixel_height', 'pos', 'x', 'y', 'pixel_pos', 'pixel_x', 'pixel_y', ): assert_equal_attr(attr_name, tile, tileobj) assert_equal_attr(attr_name, tile, plainobj) for attr_name in ('value', 'gid', 'flipped_horizontally', 'flipped_vertically', 'flipped_diagonally', 'tileset_tile'): assert_equal_attr(attr_name, tile, tileobj) with pytest.raises(AssertionError): assert_equal_attr('layer', tile, tileobj)
def assert_png_repr_equal(image, filename, epsilon=0): data = image._repr_png_() a = pil_image_open(get_test_filename(filename)) b = pil_image_open(BytesIO(data)) assert b.format == 'PNG' abytes = a.convert('RGBA').tobytes() bbytes = b.convert('RGBA').tobytes() if abytes != bbytes: from tmxlib_test.image_to_term import image_to_term256 from PIL import ImageChops, ImageOps print("Expected: ({im.size[0]}x{im.size[1]})".format(im=a)) print(image_to_term256(a)) print("Got: ({im.size[0]}x{im.size[1]})".format(im=b)) print(image_to_term256(b)) diff = ImageChops.difference(a, b).convert('RGB') diff = ImageOps.autocontrast(diff) print('Difference:') print(image_to_term256(diff)) assert len(abytes) == len(bbytes), 'unequal image size' max_pixel_delta = 0 try: Counter = collections.Counter except AttributeError: # pragma: no cover -- Python 2.6 counters = None else: counters = [Counter() for i in range(4)] for i, (ba, bb) in enumerate(zip(abytes, bbytes)): pixel_delta = ord_(ba) - ord_(bb) max_pixel_delta = max(abs(pixel_delta), max_pixel_delta) if counters: counters[i % 4][pixel_delta] += 1 if counters: print("Pixel deltas:") for band_index, counter in enumerate(counters): print(' {0}:'.format('RGBA'[band_index])) for delta, count in sorted(counter.items()): print(' {0:4}: {1}x'.format(delta, count)) print('Max |pixel delta|:', max_pixel_delta) assert max_pixel_delta <= epsilon
def test_objects(): map = tmxlib.Map.open(get_test_filename('desert_and_walls.tmx')) objects = map.layers['Objects'] sign = objects['Sign'] assert sign.size == (1, 1) sign.size = 1, 1 with pytest.raises(TypeError): sign.size = 10, 10 assert sign.pixel_size == (32, 32) sign.pixel_size = 32, 32 with pytest.raises(TypeError): sign.pixel_size = 3, 3 hole = objects['Hole A'] assert hole.pos == (hole.x, hole.y) assert hole.pos == (hole.x, hole.y) == (438 / 32, 299 / 32) assert hole.pixel_size == (53, 85) hole.pixel_size = 32, 10 assert hole.width == 1 assert hole.pixel_width == 32 hole.size = 20, 2 assert hole.height == 2 assert hole.pixel_height == 64 assert hole.pos == (hole.x, hole.y) assert hole.pos == (hole.x, hole.y) == (438 / 32, 299 / 32) hole.x = 10 hole.y = 9 assert hole.pos == (10, 9) assert hole.pixel_pos == (hole.pixel_x, hole.pixel_y) == (320, 320) hole.pixel_x = 20 hole.pixel_y = 20 assert hole.pixel_pos == (hole.pixel_x, hole.pixel_y) == (20, 20) assert hole.pos == (20 / 32, 20 / 32 - 1) # This map has all objects in one layer only all_map_objects = list(map.all_objects()) assert all_map_objects == list(objects) == list(objects.all_objects())
def test_tile_and_object_attr_equivalence(): map = tmxlib.Map.open(get_test_filename('equivcheck.tmx')) def assert_equal_attr(attr_name, tile, obj): print(attr_name, getattr(tile, attr_name), getattr(obj, attr_name)) assert getattr(tile, attr_name) == getattr(obj, attr_name) for tile, tileobj, plainobj in ( ( map.layers['Tile Layer'][1, 1], map.layers['Tileobject Layer'][0], map.layers['Plain Object Layer'][0], ), ( map.layers['Tile Layer'][4, 2], map.layers['Tileobject Layer'][1], map.layers['Plain Object Layer'][1], ), ): for attr_name in ( 'size', 'width', 'height', 'pixel_size', 'pixel_width', 'pixel_height', 'pos', 'x', 'y', 'pixel_pos', 'pixel_x', 'pixel_y', ): assert_equal_attr(attr_name, tile, tileobj) assert_equal_attr(attr_name, tile, plainobj) for attr_name in ( 'value', 'gid', 'flipped_horizontally', 'flipped_vertically', 'flipped_diagonally', 'tileset_tile'): assert_equal_attr(attr_name, tile, tileobj) with pytest.raises(AssertionError): assert_equal_attr('layer', tile, tileobj)
def test_add_image_layer(desert): image = tmxlib.image.open(get_test_filename('colorcorners.png')) desert.add_image_layer('image', image) assert desert.layers['image'].image.source.endswith('colorcorners.png') assert desert.layers['image']
def test_properties(): map = tmxlib.Map.open(get_test_filename('tilebmp-test.tmx')) assert map.properties['test'] == 'value' assert map.tilesets['Sewers'][0].properties['obstacle'] == '1'
def test_map_background_color(): map = tmxlib.Map.open(get_test_filename('desert_and_walls.tmx')) assert map.background_color is None map = tmxlib.Map.open(get_test_filename('walls_and_desert.tmx')) assert map.background_color == (1, 220 / 255, 168 / 255)
def test_object_layer_color(): map = tmxlib.Map.open(get_test_filename('desert_and_walls.tmx')) assert map.layers['Objects'].color is None map = tmxlib.Map.open(get_test_filename('objects.tmx')) assert map.layers['Objects'].color == (1, 0, 0)
def load_image(image_class, name): filename = get_test_filename(name) data = file_contents(filename) return image_class(data=data, source=filename)
def test_trans_property(image_class, basic_color): filename = get_test_filename('colorcorners.png') image = image_class(source=filename, trans=basic_color) assert image.trans == basic_color assert image[:5, :5].trans == basic_color
def test_image_layer(desert): layer = tmxlib.layer.ImageLayer(desert, 'image') assert not layer layer.image = tmxlib.image.open(get_test_filename('colorcorners.png')) assert layer
def test_shared_tilesets(): map1 = tmxlib.Map.open(get_test_filename('perspective_walls.tmx')) map2 = tmxlib.Map.open(get_test_filename('perspective_walls.tmx')) assert map1.tilesets[0] is map2.tilesets[0]
def test_layer_repr_png(canvas_mod): desert = tmxlib.Map.open(get_test_filename('desert.tmx')) assert_png_repr_equal(desert.layers[0], 'desert.rendered.png')
def colorcorners_image(image_class): filename = get_test_filename('colorcorners.png') data = file_contents(filename) return image_class(data=data, source=filename)