mirror of https://github.com/aseprite/aseprite.git
				
				
				
			[lua] Add test about saving/loading/modifying tilemap w/flags
Something interesting is that Image:drawPixel() must ask for a rehash to the tileset when the tile is modified, maybe we can find a better way to handle this in the future.
This commit is contained in:
		
							parent
							
								
									b43fbe2249
								
							
						
					
					
						commit
						d3a8a10517
					
				|  | @ -178,7 +178,7 @@ namespace app { | |||
|   void push_tile(lua_State* L, const doc::Tileset* tileset, doc::tile_index ti); | ||||
|   void push_tile_properties(lua_State* L, const doc::Tileset* tileset, doc::tile_index ti, const std::string& extID); | ||||
|   void push_tileset(lua_State* L, const doc::Tileset* tileset); | ||||
|   void push_tileset_image(lua_State* L, doc::Tileset* tileset, doc::Image* image); | ||||
|   void push_tileset_image(lua_State* L, doc::Tileset* tileset, doc::tile_index ti); | ||||
|   void push_tilesets(lua_State* L, doc::Tilesets* tilesets); | ||||
|   void push_tool(lua_State* L, app::tools::Tool* tool); | ||||
|   void push_version(lua_State* L, const base::Version& ver); | ||||
|  |  | |||
|  | @ -51,6 +51,7 @@ struct ImageObj { | |||
|   doc::ObjectId imageId = 0; | ||||
|   doc::ObjectId celId = 0; | ||||
|   doc::ObjectId tilesetId = 0; | ||||
|   doc::tile_index ti = 0; | ||||
|   ImageObj(doc::Image* image) | ||||
|     : imageId(image->id()) { | ||||
|   } | ||||
|  | @ -58,9 +59,12 @@ struct ImageObj { | |||
|     : imageId(cel->image()->id()) | ||||
|     , celId(cel->id()) { | ||||
|   } | ||||
|   ImageObj(doc::Tileset* tileset, doc::Image* image) | ||||
|   ImageObj(doc::Tileset* tileset, | ||||
|            doc::tile_index ti, | ||||
|            doc::Image* image) | ||||
|     : imageId(image->id()) | ||||
|     , tilesetId(tileset->id()) { | ||||
|     , tilesetId(tileset->id()) | ||||
|     , ti(ti) { | ||||
|   } | ||||
|   ImageObj(const ImageObj&) = delete; | ||||
|   ImageObj& operator=(const ImageObj&) = delete; | ||||
|  | @ -264,6 +268,14 @@ int Image_drawPixel(lua_State* L) | |||
|   else | ||||
|     color = convert_args_into_pixel_color(L, 4, img->pixelFormat()); | ||||
|   doc::put_pixel(img, x, y, color); | ||||
| 
 | ||||
|   // Rehash tileset
 | ||||
|   if (obj->tilesetId) { | ||||
|     if (doc::Tileset* ts = obj->tileset(L)) { | ||||
|       ts->incrementVersion(); | ||||
|       ts->notifyTileContentChange(obj->ti); | ||||
|     } | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -779,9 +791,13 @@ void push_image(lua_State* L, doc::Image* image) | |||
|   push_new<ImageObj>(L, image); | ||||
| } | ||||
| 
 | ||||
| void push_tileset_image(lua_State* L, doc::Tileset* tileset, doc::Image* image) | ||||
| void push_tileset_image(lua_State* L, doc::Tileset* tileset, doc::tile_index ti) | ||||
| { | ||||
|   push_new<ImageObj>(L, tileset, image); | ||||
|   doc::ImageRef image = tileset->get(ti); | ||||
|   if (image) | ||||
|     push_new<ImageObj>(L, tileset, ti, image.get()); | ||||
|   else | ||||
|     lua_pushnil(L); | ||||
| } | ||||
| 
 | ||||
| doc::Image* may_get_image_from_arg(lua_State* L, int index) | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| // Aseprite
 | ||||
| // Copyright (C) 2018-2019  Igara Studio S.A.
 | ||||
| // Copyright (C) 2018-2023  Igara Studio S.A.
 | ||||
| // Copyright (C) 2018  David Capello
 | ||||
| //
 | ||||
| // This program is distributed under the terms of
 | ||||
|  | @ -102,6 +102,12 @@ inline void setfield_integer(lua_State* L, const char* key, const T& value) { | |||
|   lua_setfield(L, -2, key); | ||||
| } | ||||
| 
 | ||||
| template<typename T> | ||||
| inline void setfield_uinteger(lua_State* L, const char* key, const T& value) { | ||||
|   lua_pushinteger(L, value); | ||||
|   lua_setfield(L, -2, key); | ||||
| } | ||||
| 
 | ||||
| #define REG_CLASS(L, T) {                        \ | ||||
|     luaL_newmetatable(L, get_mtname<T>());       \ | ||||
|     lua_getglobal(L, "__generic_mt_index");      \ | ||||
|  |  | |||
|  | @ -116,6 +116,12 @@ void register_app_pixel_color_object(lua_State* L) | |||
|   lua_pushvalue(L, -2);         // Copy table
 | ||||
|   lua_rawset(L, -4); | ||||
|   luaL_setfuncs(L, PixelColor_methods, 0); | ||||
| 
 | ||||
|   // Masks for tile flags
 | ||||
|   setfield_uinteger(L, "TILE_XFLIP", doc::tile_f_xflip); | ||||
|   setfield_uinteger(L, "TILE_YFLIP", doc::tile_f_yflip); | ||||
|   setfield_uinteger(L, "TILE_DFLIP", doc::tile_f_dflip); | ||||
| 
 | ||||
|   lua_pop(L, 2);                // Pop table & app global
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -48,11 +48,7 @@ int Tile_get_image(lua_State* L) | |||
|   if (!ts) | ||||
|     return 0; | ||||
| 
 | ||||
|   ImageRef image = ts->get(tile->ti); | ||||
|   if (image) | ||||
|     push_tileset_image(L, ts, image.get()); | ||||
|   else | ||||
|     lua_pushnil(L); | ||||
|   push_tileset_image(L, ts, tile->ti); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,12 +41,8 @@ int Tileset_len(lua_State* L) | |||
| int Tileset_getTile(lua_State* L) | ||||
| { | ||||
|   auto tileset = get_docobj<Tileset>(L, 1); | ||||
|   tile_index i = lua_tointeger(L, 2); | ||||
|   ImageRef image = tileset->get(i); | ||||
|   if (image) | ||||
|     push_tileset_image(L, tileset, image.get()); | ||||
|   else | ||||
|     lua_pushnil(L); | ||||
|   tile_index ti = lua_tointeger(L, 2); | ||||
|   push_tileset_image(L, tileset, ti); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1226,4 +1226,103 @@ do | |||
|   assert(spr.tilesets[1] == tilemapLay1.tileset) | ||||
|   assert(spr.tilesets[2] == tilemapLay2.tileset) | ||||
|   assert(spr.tilesets[3] == tilemapLay3.tileset) | ||||
| end | ||||
| end | ||||
| 
 | ||||
| ----------------------------------------------------------------------- | ||||
| -- Test tilemaps with flags (flips) | ||||
| ----------------------------------------------------------------------- | ||||
| 
 | ||||
| do | ||||
|   local spr = Sprite(8, 8, ColorMode.INDEXED) | ||||
| 
 | ||||
|   -- Create a new tilemap (delete the default regular layer) | ||||
|   app.command.NewLayer{ tilemap=true, gridBounds=Rectangle{ 0, 0, 2, 2 } } | ||||
|   local mapLay = app.layer | ||||
|   spr:deleteLayer(spr.layers[1]) | ||||
|   assert(#mapLay.cels == 0) | ||||
| 
 | ||||
|   -- Set a palette just for testing/preview the result | ||||
|   spr:setPalette(Palette{ fromResource="Teletext" }) | ||||
| 
 | ||||
|   -- Create one tile with these pixels (indexes): | ||||
|   -- 12 | ||||
|   -- 34 | ||||
|   local tile = spr:newTile(mapLay.tileset, 1) | ||||
|   array_to_pixels({ 1, 2, | ||||
|                     3, 4 }, tile.image) | ||||
| 
 | ||||
|   -- Fill the tilemap with this only tile | ||||
|   app.useTool{ tool='paint_bucket', color=1, layer=mapLay, | ||||
|                tilemapMode=TilemapMode.TILES, | ||||
|                points={ Point(0, 0) }} | ||||
| 
 | ||||
|   assert(#mapLay.cels == 1) | ||||
|   local map = mapLay.cels[1].image | ||||
|   assert(map.width == 4) | ||||
|   assert(map.height == 4) | ||||
| 
 | ||||
|   -- Constants | ||||
|   local x = app.pixelColor.TILE_XFLIP | ||||
|   local y = app.pixelColor.TILE_YFLIP | ||||
|   local d = app.pixelColor.TILE_DFLIP | ||||
| 
 | ||||
|   -- Normal (tile without flags) | ||||
|   -- 12 | ||||
|   -- 34 | ||||
|   map:drawPixel(0, 0, 1) | ||||
| 
 | ||||
|   -- Flip X | ||||
|   -- 21 | ||||
|   -- 43 | ||||
|   map:drawPixel(1, 0, 1|x) | ||||
| 
 | ||||
|   -- Flip Y | ||||
|   -- 34 | ||||
|   -- 12 | ||||
|   map:drawPixel(0, 1, 1|y) | ||||
| 
 | ||||
|   -- Flip X+Y | ||||
|   -- 43 | ||||
|   -- 21 | ||||
|   map:drawPixel(1, 1, 1|x|y) | ||||
| 
 | ||||
|   -- Flip D | ||||
|   -- 31 | ||||
|   -- 42 | ||||
|   map:drawPixel(2, 2, 1|d) | ||||
| 
 | ||||
|   -- Flip X+D | ||||
|   -- 42 | ||||
|   -- 31 | ||||
|   map:drawPixel(3, 2, 1|x|d) | ||||
| 
 | ||||
|   -- Flip Y+D | ||||
|   -- 13 | ||||
|   -- 24 | ||||
|   map:drawPixel(2, 3, 1|y|d) | ||||
| 
 | ||||
|   -- Flip X+Y+D | ||||
|   -- 24 | ||||
|   -- 13 | ||||
|   map:drawPixel(3, 3, 1|x|y|d) | ||||
| 
 | ||||
|   -- Clear areas | ||||
|   app.useTool{ tool='filled_rectangle', color=0, layer=mapLay, | ||||
|                tilemapMode=TilemapMode.TILES, | ||||
|                points={ Point(0, 4), Point(3, 7) }} | ||||
|   app.useTool{ tool='filled_rectangle', color=0, layer=mapLay, | ||||
|                tilemapMode=TilemapMode.TILES, | ||||
|                points={ Point(4, 0), Point(7, 3) }} | ||||
| 
 | ||||
|   -- Save, load, and test if the tilemap were saved correctly with the | ||||
|   -- given flags | ||||
|   spr:saveAs('_test_tile_flags.aseprite') | ||||
|   spr:close() | ||||
| 
 | ||||
|   local spr2 = app.open('_test_tile_flags.aseprite') | ||||
|   local map2 = spr2.layers[1].cels[1].image | ||||
|   expect_img(map2, { 1,   (1|x),   0,     0, | ||||
|                      1|y, (1|x|y), 0,     0, | ||||
|                      0,   0,     1|d,   (1|x|d), | ||||
|                      0,   0,     1|y|d, (1|x|y|d) }) | ||||
| end | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue