From 99f4ea4d2bdb10d805a0e3749fd392ac010d7381 Mon Sep 17 00:00:00 2001 From: lethosor Date: Fri, 27 Mar 2015 22:56:20 -0400 Subject: [PATCH 1/3] Implement a PenArray class for caching parts of rendered screens --- library/LuaApi.cpp | 83 ++++++++++++++++++++++++++++++++ library/include/LuaTools.h | 1 + library/include/modules/Screen.h | 13 +++++ library/lua/dfhack.lua | 6 +++ library/modules/Screen.cpp | 53 ++++++++++++++++++++ 5 files changed, 156 insertions(+) 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. */ From e2b6ae9beb5dcfa6c470ff567ddcf191bdab76a4 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 28 Mar 2015 11:27:47 -0400 Subject: [PATCH 2/3] Allocate Lua PenArray objects using an existing buffer --- library/LuaApi.cpp | 3 ++- library/include/LuaTools.h | 1 - library/include/modules/Screen.h | 2 ++ library/modules/Screen.cpp | 12 ++++++++++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index ff444013c..cccd8d88c 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1064,7 +1064,8 @@ 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); + void *buf = lua_newuserdata(L, sizeof(PenArray) + (sizeof(Pen) * bufwidth * bufheight)); + new (buf) PenArray(bufwidth, bufheight, buf); lua_rawgetp(L, LUA_REGISTRYINDEX, &DFHACK_PENARRAY_TOKEN); lua_setmetatable(L, -2); diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h index cbcad7ccf..042870273 100644 --- a/library/include/LuaTools.h +++ b/library/include/LuaTools.h @@ -48,7 +48,6 @@ namespace DFHack { } namespace Screen { struct Pen; - struct PenArray; }; } diff --git a/library/include/modules/Screen.h b/library/include/modules/Screen.h index bd87d416b..47bcdd0a6 100644 --- a/library/include/modules/Screen.h +++ b/library/include/modules/Screen.h @@ -118,8 +118,10 @@ namespace DFHack Pen *buffer; unsigned int dimx; unsigned int dimy; + bool static_alloc; public: PenArray(unsigned int bufwidth, unsigned int bufheight); + PenArray(unsigned int bufwidth, unsigned int bufheight, void *buf); ~PenArray(); void clear(); void set_tile(unsigned int x, unsigned int y, Screen::Pen pen); diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index f14068c47..e7fd2df04 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -442,15 +442,23 @@ df::interface_key Screen::charToKey(char code) */ PenArray::PenArray(unsigned int bufwidth, unsigned int bufheight) - :dimx(bufwidth), dimy(bufheight) + :dimx(bufwidth), dimy(bufheight), static_alloc(false) { buffer = new Pen[bufwidth * bufheight]; clear(); } +PenArray::PenArray(unsigned int bufwidth, unsigned int bufheight, void *buf) + :dimx(bufwidth), dimy(bufheight), static_alloc(true) +{ + buffer = (Pen*)((uint8_t*)buf + sizeof(PenArray)); + clear(); +} + PenArray::~PenArray() { - delete[] buffer; + if (!static_alloc) + delete[] buffer; } void PenArray::clear() From bbb41078e7a8b78d7047591e86263e4f3de5e75e Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 28 Mar 2015 18:35:07 -0400 Subject: [PATCH 3/3] Expose PenArray dimensions and tiles to Lua --- library/LuaApi.cpp | 27 +++++++++++++++++++++++++++ library/include/modules/Screen.h | 3 +++ library/modules/Screen.cpp | 9 ++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index cccd8d88c..f7de14876 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1080,6 +1080,31 @@ static int dfhack_penarray_clear(lua_State *L) return 0; } +static int dfhack_penarray_get_dims(lua_State *L) +{ + PenArray *parr = check_penarray_native(L, 1); + lua_pushinteger(L, parr->get_dimx()); + lua_pushinteger(L, parr->get_dimy()); + return 2; +} + +static int dfhack_penarray_get_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); + if (x < parr->get_dimx() && y < parr->get_dimy()) + { + Pen pen = parr->get_tile(x, y); + Lua::Push(L, pen); + } + else + { + lua_pushnil(L); + } + return 1; +} + static int dfhack_penarray_set_tile(lua_State *L) { PenArray *parr = check_penarray_native(L, 1); @@ -1107,6 +1132,8 @@ static int dfhack_penarray_draw(lua_State *L) static const luaL_Reg dfhack_penarray_funcs[] = { { "new", dfhack_penarray_new }, { "clear", dfhack_penarray_clear }, + { "get_dims", dfhack_penarray_get_dims }, + { "get_tile", dfhack_penarray_get_tile }, { "set_tile", dfhack_penarray_set_tile }, { "draw", dfhack_penarray_draw }, { NULL, NULL } diff --git a/library/include/modules/Screen.h b/library/include/modules/Screen.h index 47bcdd0a6..3e9097c54 100644 --- a/library/include/modules/Screen.h +++ b/library/include/modules/Screen.h @@ -124,6 +124,9 @@ namespace DFHack PenArray(unsigned int bufwidth, unsigned int bufheight, void *buf); ~PenArray(); void clear(); + unsigned int get_dimx() { return dimx; } + unsigned int get_dimy() { return dimy; } + Pen get_tile(unsigned int x, unsigned int y); 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); diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index e7fd2df04..4866c80c1 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -451,7 +451,7 @@ PenArray::PenArray(unsigned int bufwidth, unsigned int bufheight) PenArray::PenArray(unsigned int bufwidth, unsigned int bufheight, void *buf) :dimx(bufwidth), dimy(bufheight), static_alloc(true) { - buffer = (Pen*)((uint8_t*)buf + sizeof(PenArray)); + buffer = (Pen*)((PenArray*)buf + 1); clear(); } @@ -472,6 +472,13 @@ void PenArray::clear() } } +Pen PenArray::get_tile(unsigned int x, unsigned int y) +{ + if (x < dimx && y < dimy) + return buffer[(y * dimx) + x]; + return Pen(0, 0, 0, 0, false); +} + void PenArray::set_tile(unsigned int x, unsigned int y, Screen::Pen pen) { if (x < dimx && y < dimy)