diff --git a/docs/changelog.txt b/docs/changelog.txt index 7aad40128..7f15d5279 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -70,6 +70,8 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - `spectate`: improved documentation of features and functionality ## API +- ``Lua::PushInterfaceKeys()``: transforms viewscreen ``feed()`` keys into something that can be interpreted by lua-based widgets +- ``Lua::Push()``: now handles maps with otherwise supported keys and values - Constructions module: added ``insert()`` to insert constructions into the game's sorted list. ## Lua diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 4a97a0502..9f713244d 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -68,6 +68,7 @@ distribution. #include "df/activity_entry.h" #include "df/activity_event.h" +#include "df/enabler.h" #include "df/job.h" #include "df/job_item.h" #include "df/building.h" @@ -78,9 +79,6 @@ distribution. #include "df/identity.h" #include "df/nemesis_record.h" #include "df/historical_figure.h" -#include "df/historical_entity.h" -#include "df/entity_position.h" -#include "df/entity_position_assignment.h" #include "df/histfig_entity_link_positionst.h" #include "df/plant_raw.h" #include "df/creature_raw.h" @@ -95,7 +93,6 @@ distribution. #include "df/unit_misc_trait.h" #include "df/proj_itemst.h" #include "df/itemdef.h" -#include "df/enabler.h" #include "df/feature_init.h" #include "df/plant.h" #include "df/specific_ref.h" @@ -117,78 +114,6 @@ using Random::PerlinNoise3D; void dfhack_printerr(lua_State *S, const std::string &str); -void Lua::Push(lua_State *state, const Units::NoblePosition &pos) -{ - lua_createtable(state, 0, 3); - Lua::PushDFObject(state, pos.entity); - lua_setfield(state, -2, "entity"); - Lua::PushDFObject(state, pos.assignment); - lua_setfield(state, -2, "assignment"); - Lua::PushDFObject(state, pos.position); - lua_setfield(state, -2, "position"); -} - -void Lua::Push(lua_State *state, df::coord pos) -{ - lua_createtable(state, 0, 3); - lua_pushinteger(state, pos.x); - lua_setfield(state, -2, "x"); - lua_pushinteger(state, pos.y); - lua_setfield(state, -2, "y"); - lua_pushinteger(state, pos.z); - lua_setfield(state, -2, "z"); -} - -void Lua::Push(lua_State *state, df::coord2d pos) -{ - lua_createtable(state, 0, 2); - lua_pushinteger(state, pos.x); - lua_setfield(state, -2, "x"); - lua_pushinteger(state, pos.y); - lua_setfield(state, -2, "y"); -} - -void Lua::GetVector(lua_State *state, std::vector &pvec) -{ - lua_pushnil(state); // first key - while (lua_next(state, 1) != 0) - { - pvec.push_back(lua_tostring(state, -1)); - lua_pop(state, 1); // remove value, leave key - } -} - -int Lua::PushPosXYZ(lua_State *state, df::coord pos) -{ - if (!pos.isValid()) - { - lua_pushnil(state); - return 1; - } - else - { - lua_pushinteger(state, pos.x); - lua_pushinteger(state, pos.y); - lua_pushinteger(state, pos.z); - return 3; - } -} - -int Lua::PushPosXY(lua_State *state, df::coord2d pos) -{ - if (!pos.isValid()) - { - lua_pushnil(state); - return 1; - } - else - { - lua_pushinteger(state, pos.x); - lua_pushinteger(state, pos.y); - return 2; - } -} - static df::coord2d CheckCoordXY(lua_State *state, int base, bool vararg = false) { df::coord2d p; diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp index fea90b394..3cd6a1f7d 100644 --- a/library/LuaTools.cpp +++ b/library/LuaTools.cpp @@ -41,6 +41,7 @@ distribution. #include "modules/World.h" #include "modules/Gui.h" #include "modules/Job.h" +#include "modules/Screen.h" #include "modules/Translation.h" #include "modules/Units.h" @@ -51,11 +52,15 @@ distribution. #include "DFHackVersion.h" #include "PluginManager.h" +#include "df/building.h" +#include "df/enabler.h" +#include "df/entity_position.h" +#include "df/entity_position_assignment.h" +#include "df/historical_entity.h" +#include "df/item.h" #include "df/job.h" #include "df/job_item.h" -#include "df/building.h" #include "df/unit.h" -#include "df/item.h" #include "df/world.h" #include @@ -81,6 +86,126 @@ inline void AssertCoreSuspend(lua_State *state) assert(!Lua::IsCoreContext(state) || DFHack::Core::getInstance().isSuspended()); } +/* + * Lua Push methods + */ + +void DFHack::Lua::Push(lua_State *state, const Units::NoblePosition &pos) +{ + lua_createtable(state, 0, 3); + Lua::PushDFObject(state, pos.entity); + lua_setfield(state, -2, "entity"); + Lua::PushDFObject(state, pos.assignment); + lua_setfield(state, -2, "assignment"); + Lua::PushDFObject(state, pos.position); + lua_setfield(state, -2, "position"); +} + +void DFHack::Lua::Push(lua_State *state, df::coord pos) +{ + lua_createtable(state, 0, 3); + lua_pushinteger(state, pos.x); + lua_setfield(state, -2, "x"); + lua_pushinteger(state, pos.y); + lua_setfield(state, -2, "y"); + lua_pushinteger(state, pos.z); + lua_setfield(state, -2, "z"); +} + +void DFHack::Lua::Push(lua_State *state, df::coord2d pos) +{ + lua_createtable(state, 0, 2); + lua_pushinteger(state, pos.x); + lua_setfield(state, -2, "x"); + lua_pushinteger(state, pos.y); + lua_setfield(state, -2, "y"); +} + +void DFHack::Lua::GetVector(lua_State *state, std::vector &pvec) +{ + lua_pushnil(state); // first key + while (lua_next(state, 1) != 0) + { + pvec.push_back(lua_tostring(state, -1)); + lua_pop(state, 1); // remove value, leave key + } +} + +void DFHack::Lua::PushInterfaceKeys(lua_State *L, + const std::set &keys) { + lua_createtable(L, 0, keys.size() + 5); + + for (auto &key : keys) + { + if (auto name = enum_item_raw_key(key)) + lua_pushstring(L, name); + else + lua_pushinteger(L, key); + + lua_pushboolean(L, true); + lua_rawset(L, -3); + + int charval = Screen::keyToChar(key); + if (charval >= 0) + { + lua_pushinteger(L, charval); + lua_setfield(L, -2, "_STRING"); + } + } + + if (df::global::enabler) { + if (df::global::enabler->mouse_lbut_down) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "_MOUSE_L"); + } + if (df::global::enabler->mouse_rbut_down) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "_MOUSE_R"); + } + if (df::global::enabler->mouse_lbut) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "_MOUSE_L_DOWN"); + df::global::enabler->mouse_lbut = 0; + } + if (df::global::enabler->mouse_rbut) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "_MOUSE_R_DOWN"); + df::global::enabler->mouse_rbut = 0; + } + } +} + +int DFHack::Lua::PushPosXYZ(lua_State *state, df::coord pos) +{ + if (!pos.isValid()) + { + lua_pushnil(state); + return 1; + } + else + { + lua_pushinteger(state, pos.x); + lua_pushinteger(state, pos.y); + lua_pushinteger(state, pos.z); + return 3; + } +} + +int DFHack::Lua::PushPosXY(lua_State *state, df::coord2d pos) +{ + if (!pos.isValid()) + { + lua_pushnil(state); + return 1; + } + else + { + lua_pushinteger(state, pos.x); + lua_pushinteger(state, pos.y); + return 2; + } +} + /* * Public DF object reference handling API */ diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h index 6dc5ae0bd..e4245f09a 100644 --- a/library/include/LuaTools.h +++ b/library/include/LuaTools.h @@ -30,6 +30,8 @@ distribution. #include #include +#include "df/interfacest.h" + #include "ColorText.h" #include "DataDefs.h" @@ -321,6 +323,8 @@ namespace DFHack {namespace Lua { Push(L, val); lua_setfield(L, idx, name); } + DFHACK_EXPORT void PushInterfaceKeys(lua_State *L, const std::set &keys); + template void PushVector(lua_State *state, const T &pvec, bool addn = false) { @@ -352,6 +356,13 @@ namespace DFHack {namespace Lua { lua_settable(state, -3); } + template + void Push(lua_State *L, const std::map &pmap) { + lua_createtable(L, 0, pmap.size()); + for (auto &entry : pmap) + TableInsert(L, entry.first, entry.second); + } + DFHACK_EXPORT void CheckPen(lua_State *L, Screen::Pen *pen, int index, bool allow_nil = false, bool allow_color = true); DFHACK_EXPORT bool IsCoreContext(lua_State *state); diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index bff14a380..ebcc3f229 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -749,50 +749,7 @@ int dfhack_lua_viewscreen::do_input(lua_State *L) } lua_pushvalue(L, -2); - - lua_createtable(L, 0, keys->size()+3); - - for (auto it = keys->begin(); it != keys->end(); ++it) - { - auto key = *it; - - if (auto name = enum_item_raw_key(key)) - lua_pushstring(L, name); - else - lua_pushinteger(L, key); - - lua_pushboolean(L, true); - lua_rawset(L, -3); - - int charval = Screen::keyToChar(key); - if (charval >= 0) - { - lua_pushinteger(L, charval); - lua_setfield(L, -2, "_STRING"); - } - } - - if (enabler) - { - if (enabler->mouse_lbut_down) { - lua_pushboolean(L, true); - lua_setfield(L, -2, "_MOUSE_L"); - } - if (enabler->mouse_rbut_down) { - lua_pushboolean(L, true); - lua_setfield(L, -2, "_MOUSE_R"); - } - if (enabler->mouse_lbut) { - lua_pushboolean(L, true); - lua_setfield(L, -2, "_MOUSE_L_DOWN"); - enabler->mouse_lbut = 0; - } - if (enabler->mouse_rbut) { - lua_pushboolean(L, true); - lua_setfield(L, -2, "_MOUSE_R_DOWN"); - enabler->mouse_rbut = 0; - } - } + Lua::PushInterfaceKeys(L, *keys); lua_call(L, 2, 0); self->update_focus(L, -1);