Merge pull request #746 from lethosor/gui-hooks
Support for hooking into GUI-related functionsdevelop
commit
140da9ff37
@ -0,0 +1,71 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
namespace DFHack {
|
||||||
|
#define GUI_HOOK_DECLARE(name, rtype, args) DFHACK_EXPORT extern DFHack::GuiHooks::Hook<rtype args> name
|
||||||
|
#define GUI_HOOK_DEFINE(name, base_func) DFHack::GuiHooks::Hook<decltype(base_func)> name(base_func)
|
||||||
|
#define GUI_HOOK_TOP(name) name.top()
|
||||||
|
#define GUI_HOOK_CALLBACK(hook, name, callback) DFHack::GuiHooks::Hook<decltype(callback)>::Callback name(&hook, callback)
|
||||||
|
namespace GuiHooks {
|
||||||
|
template <typename T_func>
|
||||||
|
class Hook {
|
||||||
|
typedef Hook<T_func> T_hook;
|
||||||
|
friend class Callback;
|
||||||
|
T_func *base_func;
|
||||||
|
std::vector<T_func*> funcs;
|
||||||
|
void add(T_func *func)
|
||||||
|
{
|
||||||
|
if (std::find(funcs.begin(), funcs.end(), func) == funcs.end())
|
||||||
|
funcs.push_back(func);
|
||||||
|
}
|
||||||
|
void remove(T_func *func)
|
||||||
|
{
|
||||||
|
auto it = std::find(funcs.begin(), funcs.end(), func);
|
||||||
|
if (it != funcs.end())
|
||||||
|
funcs.erase(it);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
Hook(T_func* base) : base_func(base)
|
||||||
|
{ }
|
||||||
|
T_func* top()
|
||||||
|
{
|
||||||
|
return funcs.empty() ? base_func : funcs[funcs.size() - 1];
|
||||||
|
}
|
||||||
|
T_func* next(T_func* cur)
|
||||||
|
{
|
||||||
|
if (funcs.size())
|
||||||
|
{
|
||||||
|
auto it = std::find(funcs.begin(), funcs.end(), cur);
|
||||||
|
if (it != funcs.end() && it != funcs.begin())
|
||||||
|
return *(it - 1);
|
||||||
|
}
|
||||||
|
return base_func;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Callback {
|
||||||
|
T_func *func;
|
||||||
|
T_hook *hook;
|
||||||
|
bool enabled;
|
||||||
|
public:
|
||||||
|
Callback(T_hook *hook, T_func *func) : hook(hook), func(func)
|
||||||
|
{ }
|
||||||
|
~Callback()
|
||||||
|
{
|
||||||
|
disable();
|
||||||
|
}
|
||||||
|
inline T_func *next() { return hook->next(func); }
|
||||||
|
void apply (bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
hook->add(func);
|
||||||
|
else
|
||||||
|
hook->remove(func);
|
||||||
|
enabled = enable;
|
||||||
|
}
|
||||||
|
inline void enable() { apply(true); }
|
||||||
|
inline void disable() { apply(false); }
|
||||||
|
inline bool is_enabled() { return enabled; }
|
||||||
|
inline void toggle() { apply(!enabled); }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,136 @@
|
|||||||
|
#include "Console.h"
|
||||||
|
#include "Core.h"
|
||||||
|
#include "DataDefs.h"
|
||||||
|
#include "Export.h"
|
||||||
|
#include "PluginManager.h"
|
||||||
|
|
||||||
|
#include "modules/Gui.h"
|
||||||
|
#include "modules/Screen.h"
|
||||||
|
|
||||||
|
using namespace DFHack;
|
||||||
|
|
||||||
|
DFHACK_PLUGIN("color-dfhack-text");
|
||||||
|
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
|
||||||
|
REQUIRE_GLOBAL(gps);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool flicker;
|
||||||
|
uint8_t color;
|
||||||
|
short tick;
|
||||||
|
} config;
|
||||||
|
|
||||||
|
void color_text_tile(const Screen::Pen &pen, int x, int y, bool map);
|
||||||
|
GUI_HOOK_CALLBACK(Screen::Hooks::set_tile, color_text_hook, color_text_tile);
|
||||||
|
void color_text_tile(const Screen::Pen &pen, int x, int y, bool map)
|
||||||
|
{
|
||||||
|
Screen::Pen pen2 = pen;
|
||||||
|
uint8_t color = config.flicker ? config.tick % 8 : config.color;
|
||||||
|
pen2.fg = color;
|
||||||
|
pen2.bg = color;
|
||||||
|
pen2.bold = true;
|
||||||
|
return color_text_hook.next()(pen2, x, y, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
void aaaaa_set_tile(const Screen::Pen &pen, int x, int y, bool map);
|
||||||
|
GUI_HOOK_CALLBACK(Screen::Hooks::set_tile, aaaaa_set_tile_hook, aaaaa_set_tile);
|
||||||
|
void aaaaa_set_tile(const Screen::Pen &pen, int x, int y, bool map)
|
||||||
|
{
|
||||||
|
Screen::Pen pen2 = pen;
|
||||||
|
if ((pen.ch >= 'A' && pen.ch <= 'Z') || (pen.ch >= '0' && pen.ch <= '9'))
|
||||||
|
pen2.ch = 'A';
|
||||||
|
else if (pen.ch >= 'a' && pen.ch <= 'z')
|
||||||
|
pen2.ch = 'a';
|
||||||
|
aaaaa_set_tile_hook.next()(pen2, x, y, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shift_set_tile(const Screen::Pen &pen, int x, int y, bool map);
|
||||||
|
GUI_HOOK_CALLBACK(Screen::Hooks::set_tile, shift_set_tile_hook, shift_set_tile);
|
||||||
|
void shift_set_tile(const Screen::Pen &pen, int x, int y, bool map)
|
||||||
|
{
|
||||||
|
x = (x + 1) % gps->dimx;
|
||||||
|
shift_set_tile_hook.next()(pen, x, y, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_enable (color_ostream &out, bool enable)
|
||||||
|
{
|
||||||
|
color_text_hook.apply(enable);
|
||||||
|
if (!enable)
|
||||||
|
{
|
||||||
|
shift_set_tile_hook.disable();
|
||||||
|
aaaaa_set_tile_hook.disable();
|
||||||
|
}
|
||||||
|
is_enabled = enable;
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result color(color_ostream &out, std::vector<std::string> ¶ms)
|
||||||
|
{
|
||||||
|
if (params.empty())
|
||||||
|
return plugin_enable(out, true);
|
||||||
|
for (auto it = params.begin(); it != params.end(); ++it)
|
||||||
|
{
|
||||||
|
std::string p = toLower(*it);
|
||||||
|
if (!p.size())
|
||||||
|
continue;
|
||||||
|
#define CHECK_COLOR(color_name) else if (p == toLower(std::string(#color_name))) \
|
||||||
|
{ config.flicker = false; config.color = COLOR_##color_name % 8; plugin_enable(out, true); }
|
||||||
|
CHECK_COLOR(RED)
|
||||||
|
CHECK_COLOR(GREEN)
|
||||||
|
CHECK_COLOR(BLUE)
|
||||||
|
CHECK_COLOR(YELLOW)
|
||||||
|
CHECK_COLOR(BROWN)
|
||||||
|
CHECK_COLOR(CYAN)
|
||||||
|
CHECK_COLOR(MAGENTA)
|
||||||
|
CHECK_COLOR(WHITE)
|
||||||
|
CHECK_COLOR(GREY)
|
||||||
|
CHECK_COLOR(BLACK)
|
||||||
|
#undef CHECK_COLOR
|
||||||
|
else if (p == "flicker")
|
||||||
|
{
|
||||||
|
config.flicker = true;
|
||||||
|
plugin_enable(out, true);
|
||||||
|
}
|
||||||
|
else if (p.size() >= 3 && p.substr(0, 3) == "aaa")
|
||||||
|
{
|
||||||
|
aaaaa_set_tile_hook.toggle();
|
||||||
|
}
|
||||||
|
else if (p == "shift")
|
||||||
|
{
|
||||||
|
shift_set_tile_hook.toggle();
|
||||||
|
}
|
||||||
|
else if (p == "disable")
|
||||||
|
{
|
||||||
|
plugin_enable(out, false);
|
||||||
|
}
|
||||||
|
else if (p != "enable")
|
||||||
|
{
|
||||||
|
out.printerr("Unrecognized option: %s\n", p.c_str());
|
||||||
|
return CR_WRONG_USAGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
|
||||||
|
{
|
||||||
|
commands.push_back(PluginCommand(
|
||||||
|
"color-dfhack-text",
|
||||||
|
"color <color>|flicker|enable|disable|shift|aaaaa",
|
||||||
|
color,
|
||||||
|
false
|
||||||
|
));
|
||||||
|
config.flicker = false;
|
||||||
|
config.color = COLOR_RED;
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_shutdown (color_ostream &out)
|
||||||
|
{
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_onupdate (color_ostream &out)
|
||||||
|
{
|
||||||
|
++config.tick;
|
||||||
|
return CR_OK;
|
||||||
|
}
|
Loading…
Reference in New Issue