diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 9af7ed563..ff444013c 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1041,6 +1041,88 @@ static void OpenPen(lua_State *state) lua_pop(state, 1); } +/****************** +* PenArray object * +******************/ + +static int DFHACK_PENARRAY_TOKEN = 0; +using Screen::PenArray; + +static PenArray *check_penarray_native(lua_State *L, int index) +{ + lua_rawgetp(L, LUA_REGISTRYINDEX, &DFHACK_PENARRAY_TOKEN); + + if (!lua_getmetatable(L, index) || !lua_rawequal(L, -1, -2)) + luaL_argerror(L, index, "not a penarray object"); + + lua_pop(L, 2); + + return (PenArray*)lua_touserdata(L, index); +} + +static int dfhack_penarray_new(lua_State *L) +{ + int bufwidth = luaL_checkint(L, 1); + int bufheight = luaL_checkint(L, 2); + new (L) PenArray(bufwidth, bufheight); + + lua_rawgetp(L, LUA_REGISTRYINDEX, &DFHACK_PENARRAY_TOKEN); + lua_setmetatable(L, -2); + + return 1; +} + +static int dfhack_penarray_clear(lua_State *L) +{ + PenArray *parr = check_penarray_native(L, 1); + parr->clear(); + return 0; +} + +static int dfhack_penarray_set_tile(lua_State *L) +{ + PenArray *parr = check_penarray_native(L, 1); + unsigned int x = luaL_checkint(L, 2); + unsigned int y = luaL_checkint(L, 3); + Pen pen; + Lua::CheckPen(L, &pen, 4); + parr->set_tile(x, y, pen); + return 0; +} + +static int dfhack_penarray_draw(lua_State *L) +{ + PenArray *parr = check_penarray_native(L, 1); + unsigned int x = (unsigned int)luaL_checkint(L, 2); + unsigned int y = (unsigned int)luaL_checkint(L, 3); + unsigned int w = (unsigned int)luaL_checkint(L, 4); + unsigned int h = (unsigned int)luaL_checkint(L, 5); + unsigned int bufx = (unsigned int)luaL_optint(L, 6, 0); + unsigned int bufy = (unsigned int)luaL_optint(L, 7, 0); + parr->draw(x, y, w, h, bufx, bufy); + return 0; +} + +static const luaL_Reg dfhack_penarray_funcs[] = { + { "new", dfhack_penarray_new }, + { "clear", dfhack_penarray_clear }, + { "set_tile", dfhack_penarray_set_tile }, + { "draw", dfhack_penarray_draw }, + { NULL, NULL } +}; + +static void OpenPenArray(lua_State *state) +{ + luaL_getsubtable(state, lua_gettop(state), "penarray"); + + lua_dup(state); + lua_rawsetp(state, LUA_REGISTRYINDEX, &DFHACK_PENARRAY_TOKEN); + + luaL_setfuncs(state, dfhack_penarray_funcs, 0); + + lua_pop(state, 1); +} + /******************** * Random generator * ********************/ @@ -2516,6 +2598,7 @@ void OpenDFHackApi(lua_State *state) OpenPersistent(state); OpenMatinfo(state); OpenPen(state); + OpenPenArray(state); OpenRandom(state); LuaWrapper::SetFunctionWrappers(state, dfhack_module); diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h index 042870273..cbcad7ccf 100644 --- a/library/include/LuaTools.h +++ b/library/include/LuaTools.h @@ -48,6 +48,7 @@ namespace DFHack { } namespace Screen { struct Pen; + struct PenArray; }; } diff --git a/library/include/modules/Screen.h b/library/include/modules/Screen.h index 205a0ed3f..bd87d416b 100644 --- a/library/include/modules/Screen.h +++ b/library/include/modules/Screen.h @@ -114,6 +114,19 @@ namespace DFHack Pen chtile(char ch, int tile) { Pen cp(*this); cp.ch = ch; cp.tile = tile; return cp; } }; + class DFHACK_EXPORT PenArray { + Pen *buffer; + unsigned int dimx; + unsigned int dimy; + public: + PenArray(unsigned int bufwidth, unsigned int bufheight); + ~PenArray(); + void clear(); + void set_tile(unsigned int x, unsigned int y, Screen::Pen pen); + void draw(unsigned int x, unsigned int y, unsigned int width, unsigned int height, + unsigned int bufx = 0, unsigned int bufy = 0); + }; + struct DFHACK_EXPORT ViewRect { rect2d view, clip; diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index 1cc9c5552..a40ae552b 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -264,6 +264,12 @@ function dfhack.random:__tostring() return "" end +dfhack.penarray.__index = dfhack.penarray + +function dfhack.penarray.__tostring() + return "" +end + function dfhack.maps.getSize() local map = df.global.world.map return map.x_count_block, map.y_count_block, map.z_count_block diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index c0e857922..f14068c47 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -65,6 +65,7 @@ using df::global::gview; using df::global::enabler; using Screen::Pen; +using Screen::PenArray; using std::string; @@ -436,6 +437,58 @@ df::interface_key Screen::charToKey(char code) return df::interface_key(interface_key::STRING_A128 + (val-128)); } +/* + * Pen array + */ + +PenArray::PenArray(unsigned int bufwidth, unsigned int bufheight) + :dimx(bufwidth), dimy(bufheight) +{ + buffer = new Pen[bufwidth * bufheight]; + clear(); +} + +PenArray::~PenArray() +{ + delete[] buffer; +} + +void PenArray::clear() +{ + for (unsigned int x = 0; x < dimx; x++) + { + for (unsigned int y = 0; y < dimy; y++) + { + set_tile(x, y, Screen::Pen(0, 0, 0, 0, false)); + } + } +} + +void PenArray::set_tile(unsigned int x, unsigned int y, Screen::Pen pen) +{ + if (x < dimx && y < dimy) + buffer[(y * dimx) + x] = pen; +} + +void PenArray::draw(unsigned int x, unsigned int y, unsigned int width, unsigned int height, + unsigned int bufx, unsigned int bufy) +{ + if (!gps) + return; + for (unsigned int gridx = x; gridx < x + width; gridx++) + { + for (unsigned int gridy = y; gridy < y + height; gridy++) + { + if (gridx >= gps->dimx || + gridy >= gps->dimy || + gridx - x + bufx >= dimx || + gridy - y + bufy >= dimy) + continue; + Screen::paintTile(buffer[((gridy - y + bufy) * dimx) + (gridx - x + bufx)], gridx, gridy); + } + } +} + /* * Base DFHack viewscreen. */