diff --git a/src/app/script/engine.h b/src/app/script/engine.h index d4b2d5957..a4936ff5d 100644 --- a/src/app/script/engine.h +++ b/src/app/script/engine.h @@ -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); diff --git a/src/app/script/image_class.cpp b/src/app/script/image_class.cpp index 0319cc095..7c241564b 100644 --- a/src/app/script/image_class.cpp +++ b/src/app/script/image_class.cpp @@ -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(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(L, tileset, image); + doc::ImageRef image = tileset->get(ti); + if (image) + push_new(L, tileset, ti, image.get()); + else + lua_pushnil(L); } doc::Image* may_get_image_from_arg(lua_State* L, int index) diff --git a/src/app/script/luacpp.h b/src/app/script/luacpp.h index cd01576fa..8ead070e4 100644 --- a/src/app/script/luacpp.h +++ b/src/app/script/luacpp.h @@ -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 +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()); \ lua_getglobal(L, "__generic_mt_index"); \ diff --git a/src/app/script/pixel_color_object.cpp b/src/app/script/pixel_color_object.cpp index 63d01c192..9fa96aba5 100644 --- a/src/app/script/pixel_color_object.cpp +++ b/src/app/script/pixel_color_object.cpp @@ -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 } diff --git a/src/app/script/tile_class.cpp b/src/app/script/tile_class.cpp index 7db7f5660..d4ff27225 100644 --- a/src/app/script/tile_class.cpp +++ b/src/app/script/tile_class.cpp @@ -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; } diff --git a/src/app/script/tileset_class.cpp b/src/app/script/tileset_class.cpp index 2d008b7e8..d0c8965ab 100644 --- a/src/app/script/tileset_class.cpp +++ b/src/app/script/tileset_class.cpp @@ -41,12 +41,8 @@ int Tileset_len(lua_State* L) int Tileset_getTile(lua_State* L) { auto tileset = get_docobj(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; } diff --git a/tests/scripts/tilemap.lua b/tests/scripts/tilemap.lua index af1acec37..37efe6706 100644 --- a/tests/scripts/tilemap.lua +++ b/tests/scripts/tilemap.lua @@ -1226,4 +1226,103 @@ do assert(spr.tilesets[1] == tilemapLay1.tileset) assert(spr.tilesets[2] == tilemapLay2.tileset) assert(spr.tilesets[3] == tilemapLay3.tileset) -end \ No newline at end of file +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