Merge pull request #591 from lethosor/penarray

Expose a faster screen drawing/caching API to Lua
develop
Lethosor 2015-03-31 16:11:28 -04:00
commit e71c55865d
4 changed files with 203 additions and 0 deletions

@ -1041,6 +1041,116 @@ static void OpenPen(lua_State *state)
lua_pop(state, 1); 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);
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);
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_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);
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 },
{ "get_dims", dfhack_penarray_get_dims },
{ "get_tile", dfhack_penarray_get_tile },
{ "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 * * Random generator *
********************/ ********************/
@ -2516,6 +2626,7 @@ void OpenDFHackApi(lua_State *state)
OpenPersistent(state); OpenPersistent(state);
OpenMatinfo(state); OpenMatinfo(state);
OpenPen(state); OpenPen(state);
OpenPenArray(state);
OpenRandom(state); OpenRandom(state);
LuaWrapper::SetFunctionWrappers(state, dfhack_module); LuaWrapper::SetFunctionWrappers(state, dfhack_module);

@ -114,6 +114,24 @@ namespace DFHack
Pen chtile(char ch, int tile) { Pen cp(*this); cp.ch = ch; cp.tile = tile; return cp; } 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;
bool static_alloc;
public:
PenArray(unsigned int bufwidth, unsigned int bufheight);
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);
};
struct DFHACK_EXPORT ViewRect { struct DFHACK_EXPORT ViewRect {
rect2d view, clip; rect2d view, clip;

@ -264,6 +264,12 @@ function dfhack.random:__tostring()
return "<random generator>" return "<random generator>"
end end
dfhack.penarray.__index = dfhack.penarray
function dfhack.penarray.__tostring()
return "<penarray>"
end
function dfhack.maps.getSize() function dfhack.maps.getSize()
local map = df.global.world.map local map = df.global.world.map
return map.x_count_block, map.y_count_block, map.z_count_block return map.x_count_block, map.y_count_block, map.z_count_block

@ -65,6 +65,7 @@ using df::global::gview;
using df::global::enabler; using df::global::enabler;
using Screen::Pen; using Screen::Pen;
using Screen::PenArray;
using std::string; using std::string;
@ -436,6 +437,73 @@ df::interface_key Screen::charToKey(char code)
return df::interface_key(interface_key::STRING_A128 + (val-128)); return df::interface_key(interface_key::STRING_A128 + (val-128));
} }
/*
* Pen array
*/
PenArray::PenArray(unsigned int bufwidth, unsigned int 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*)((PenArray*)buf + 1);
clear();
}
PenArray::~PenArray()
{
if (!static_alloc)
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));
}
}
}
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)
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. * Base DFHack viewscreen.
*/ */