201 lines
6.6 KiB
C++
201 lines
6.6 KiB
C++
#include "df/enabler.h"
|
|
#include "df/viewscreen_adopt_regionst.h"
|
|
#include "df/viewscreen_choose_game_typest.h"
|
|
#include "df/viewscreen_choose_start_sitest.h"
|
|
#include "df/viewscreen_dwarfmodest.h"
|
|
#include "df/viewscreen_export_regionst.h"
|
|
#include "df/viewscreen_game_cleanerst.h"
|
|
#include "df/viewscreen_initial_prepst.h"
|
|
#include "df/viewscreen_legendsst.h"
|
|
#include "df/viewscreen_loadgamest.h"
|
|
#include "df/viewscreen_new_arenast.h"
|
|
#include "df/viewscreen_new_regionst.h"
|
|
#include "df/viewscreen_savegamest.h"
|
|
#include "df/viewscreen_setupdwarfgamest.h"
|
|
#include "df/viewscreen_titlest.h"
|
|
#include "df/viewscreen_update_regionst.h"
|
|
#include "df/viewscreen_worldst.h"
|
|
#include "df/world.h"
|
|
|
|
#include "Debug.h"
|
|
#include "LuaTools.h"
|
|
#include "PluginManager.h"
|
|
#include "VTableInterpose.h"
|
|
|
|
#include "modules/Gui.h"
|
|
#include "modules/Screen.h"
|
|
|
|
using namespace DFHack;
|
|
|
|
DFHACK_PLUGIN("overlay");
|
|
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
|
|
|
|
REQUIRE_GLOBAL(world);
|
|
REQUIRE_GLOBAL(enabler);
|
|
|
|
namespace DFHack {
|
|
DBG_DECLARE(overlay, control, DebugCategory::LINFO);
|
|
DBG_DECLARE(overlay, event, DebugCategory::LINFO);
|
|
}
|
|
|
|
static df::coord2d screenSize;
|
|
|
|
static void call_overlay_lua(color_ostream *out, const char *fn_name,
|
|
int nargs = 0, int nres = 0,
|
|
Lua::LuaLambda && args_lambda = Lua::DEFAULT_LUA_LAMBDA,
|
|
Lua::LuaLambda && res_lambda = Lua::DEFAULT_LUA_LAMBDA) {
|
|
DEBUG(event).print("calling overlay lua function: '%s'\n", fn_name);
|
|
|
|
CoreSuspender guard;
|
|
|
|
auto L = Lua::Core::State;
|
|
Lua::StackUnwinder top(L);
|
|
|
|
if (!out)
|
|
out = &Core::getInstance().getConsole();
|
|
|
|
Lua::CallLuaModuleFunction(*out, L, "plugins.overlay", fn_name, nargs, nres,
|
|
std::forward<Lua::LuaLambda&&>(args_lambda),
|
|
std::forward<Lua::LuaLambda&&>(res_lambda));
|
|
}
|
|
|
|
template<class T>
|
|
struct viewscreen_overlay : T {
|
|
typedef T interpose_base;
|
|
|
|
DEFINE_VMETHOD_INTERPOSE(void, logic, ()) {
|
|
INTERPOSE_NEXT(logic)();
|
|
call_overlay_lua(NULL, "update_viewscreen_widgets", 2, 0,
|
|
[&](lua_State *L) {
|
|
Lua::Push(L, T::_identity.getName());
|
|
Lua::Push(L, this);
|
|
});
|
|
}
|
|
DEFINE_VMETHOD_INTERPOSE(void, feed, (std::set<df::interface_key> *input)) {
|
|
bool input_is_handled = false;
|
|
// don't send input to the overlays if there is a modal dialog up
|
|
if (!world->status.popups.size())
|
|
call_overlay_lua(NULL, "feed_viewscreen_widgets", 3, 1,
|
|
[&](lua_State *L) {
|
|
Lua::Push(L, T::_identity.getName());
|
|
Lua::Push(L, this);
|
|
Lua::PushInterfaceKeys(L, Screen::normalize_text_keys(*input));
|
|
}, [&](lua_State *L) {
|
|
input_is_handled = lua_toboolean(L, -1);
|
|
});
|
|
if (!input_is_handled)
|
|
INTERPOSE_NEXT(feed)(input);
|
|
else
|
|
enabler->last_text_input[0] = '\0';
|
|
}
|
|
DEFINE_VMETHOD_INTERPOSE(void, render, ()) {
|
|
INTERPOSE_NEXT(render)();
|
|
call_overlay_lua(NULL, "render_viewscreen_widgets", 2, 0,
|
|
[&](lua_State *L) {
|
|
Lua::Push(L, T::_identity.getName());
|
|
Lua::Push(L, this);
|
|
});
|
|
}
|
|
};
|
|
|
|
#define IMPLEMENT_HOOKS(screen) \
|
|
typedef viewscreen_overlay<df::viewscreen_##screen##st> screen##_overlay; \
|
|
template<> IMPLEMENT_VMETHOD_INTERPOSE_PRIO(screen##_overlay, logic, 100); \
|
|
template<> IMPLEMENT_VMETHOD_INTERPOSE_PRIO(screen##_overlay, feed, 100); \
|
|
template<> IMPLEMENT_VMETHOD_INTERPOSE_PRIO(screen##_overlay, render, 100);
|
|
|
|
IMPLEMENT_HOOKS(adopt_region)
|
|
IMPLEMENT_HOOKS(choose_game_type)
|
|
IMPLEMENT_HOOKS(choose_start_site)
|
|
IMPLEMENT_HOOKS(dwarfmode)
|
|
IMPLEMENT_HOOKS(export_region)
|
|
IMPLEMENT_HOOKS(game_cleaner)
|
|
IMPLEMENT_HOOKS(initial_prep)
|
|
IMPLEMENT_HOOKS(legends)
|
|
IMPLEMENT_HOOKS(loadgame)
|
|
IMPLEMENT_HOOKS(new_arena)
|
|
IMPLEMENT_HOOKS(new_region)
|
|
IMPLEMENT_HOOKS(savegame)
|
|
IMPLEMENT_HOOKS(setupdwarfgame)
|
|
IMPLEMENT_HOOKS(title)
|
|
IMPLEMENT_HOOKS(update_region)
|
|
IMPLEMENT_HOOKS(world)
|
|
|
|
#undef IMPLEMENT_HOOKS
|
|
|
|
#define INTERPOSE_HOOKS_FAILED(screen) \
|
|
!INTERPOSE_HOOK(screen##_overlay, logic).apply(enable) || \
|
|
!INTERPOSE_HOOK(screen##_overlay, feed).apply(enable) || \
|
|
!INTERPOSE_HOOK(screen##_overlay, render).apply(enable)
|
|
|
|
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) {
|
|
if (is_enabled == enable)
|
|
return CR_OK;
|
|
|
|
if (enable) {
|
|
screenSize = Screen::getWindowSize();
|
|
call_overlay_lua(&out, "rescan");
|
|
}
|
|
|
|
DEBUG(control).print("%sing interpose hooks\n", enable ? "enabl" : "disabl");
|
|
|
|
if (INTERPOSE_HOOKS_FAILED(adopt_region) ||
|
|
INTERPOSE_HOOKS_FAILED(choose_start_site) ||
|
|
INTERPOSE_HOOKS_FAILED(choose_game_type) ||
|
|
INTERPOSE_HOOKS_FAILED(dwarfmode) ||
|
|
INTERPOSE_HOOKS_FAILED(export_region) ||
|
|
INTERPOSE_HOOKS_FAILED(game_cleaner) ||
|
|
INTERPOSE_HOOKS_FAILED(initial_prep) ||
|
|
INTERPOSE_HOOKS_FAILED(legends) ||
|
|
INTERPOSE_HOOKS_FAILED(loadgame) ||
|
|
INTERPOSE_HOOKS_FAILED(new_arena) ||
|
|
INTERPOSE_HOOKS_FAILED(new_region) ||
|
|
INTERPOSE_HOOKS_FAILED(savegame) ||
|
|
INTERPOSE_HOOKS_FAILED(setupdwarfgame) ||
|
|
INTERPOSE_HOOKS_FAILED(title) ||
|
|
INTERPOSE_HOOKS_FAILED(update_region) ||
|
|
INTERPOSE_HOOKS_FAILED(world))
|
|
return CR_FAILURE;
|
|
|
|
is_enabled = enable;
|
|
return CR_OK;
|
|
}
|
|
|
|
#undef INTERPOSE_HOOKS_FAILED
|
|
|
|
static command_result overlay_cmd(color_ostream &out, std::vector <std::string> & parameters) {
|
|
bool show_help = false;
|
|
call_overlay_lua(&out, "overlay_command", 1, 1, [&](lua_State *L) {
|
|
Lua::PushVector(L, parameters);
|
|
}, [&](lua_State *L) {
|
|
show_help = !lua_toboolean(L, -1);
|
|
});
|
|
|
|
return show_help ? CR_WRONG_USAGE : CR_OK;
|
|
}
|
|
|
|
DFhackCExport command_result plugin_init(color_ostream &out, std::vector <PluginCommand> &commands) {
|
|
commands.push_back(
|
|
PluginCommand(
|
|
"overlay",
|
|
"Manage onscreen widgets.",
|
|
overlay_cmd,
|
|
Gui::anywhere_hotkey));
|
|
|
|
return CR_OK;
|
|
}
|
|
|
|
DFhackCExport command_result plugin_shutdown(color_ostream &out) {
|
|
return plugin_enable(out, false);
|
|
}
|
|
|
|
DFhackCExport command_result plugin_onupdate (color_ostream &out) {
|
|
df::coord2d newScreenSize = Screen::getWindowSize();
|
|
if (newScreenSize != screenSize) {
|
|
call_overlay_lua(&out, "reposition_widgets");
|
|
screenSize = newScreenSize;
|
|
}
|
|
call_overlay_lua(&out, "update_hotspot_widgets");
|
|
return CR_OK;
|
|
}
|