Allow player to pause the confirmation dialog without disabling (#2164)

* basic pause functionality for confirm

* update changelog

* wrap the pause message and output in white

* unpause on viewscreen transition when we can

but still use esc detection when we won't get a viewscreen transition
(like when we're intercepting input on viewscreen_dwarfmodest

* add more code docs about unpause detection
develop
Myk 2022-06-02 06:24:13 -07:00 committed by GitHub
parent f5d3b9f699
commit 27bf4c758b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 2 deletions

@ -42,6 +42,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## Misc Improvements
- `confirm`: added a confirmation dialog for removing manager orders
- `confirm`: allow players to pause the confirmation dialog until they exit the current screen
- `dfhack-examples-guide`: refine food preparation orders and fix conditions for making jugs and pots in the ``basic`` manager orders
## Documentation

@ -17,6 +17,7 @@
#include "df/building_tradedepotst.h"
#include "df/general_ref.h"
#include "df/general_ref_contained_in_itemst.h"
#include "df/interfacest.h"
#include "df/viewscreen_dwarfmodest.h"
#include "df/viewscreen_jobmanagementst.h"
#include "df/viewscreen_justicest.h"
@ -44,6 +45,12 @@ static map<string, conf_wrapper*> confirmations;
string active_id;
queue<string> cmds;
// true when confirm is paused
bool paused = false;
// if set, confirm will unpause when this screen is no longer on the stack
df::viewscreen *paused_screen = NULL;
template <typename VT, typename FT>
inline bool in_vector (std::vector<VT> &vec, FT item)
{
@ -229,6 +236,18 @@ namespace conf_lua {
lua_pushnil(L);
return 1;
}
int unpause(lua_State *)
{
Core::getInstance().print("unpausing\n");
paused = false;
paused_screen = NULL;
return 0;
}
int get_paused (lua_State *L)
{
Lua::Push(L, paused);
return 1;
}
}
}
@ -247,6 +266,8 @@ DFHACK_PLUGIN_LUA_COMMANDS {
CONF_LUA_CMD(get_ids),
CONF_LUA_CMD(get_conf_data),
CONF_LUA_CMD(get_active_id),
CONF_LUA_CMD(unpause),
CONF_LUA_CMD(get_paused),
DFHACK_LUA_END
};
@ -281,7 +302,15 @@ public:
return true;
}
bool feed (ikey_set *input) {
if (state == INACTIVE)
if (paused)
{
// we can only detect that we've left the screen by intercepting the
// ESC key
if (!paused_screen && input->count(df::interface_key::LEAVESCREEN))
conf_lua::api::unpause(NULL);
return false;
}
else if (state == INACTIVE)
{
for (df::interface_key key : *input)
{
@ -302,6 +331,18 @@ public:
set_state(INACTIVE);
else if (input->count(df::interface_key::SELECT))
set_state(SELECTED);
else if (input->count(df::interface_key::CUSTOM_P))
{
Core::getInstance().print("pausing\n");
paused = true;
// only record the screen when we're not at the top viewscreen
// since this screen will *always* be on the stack. for
// dwarfmode screens, use ESC detection to discover when to
// unpause
if (!df::viewscreen_dwarfmodest::_identity.is_instance(screen))
paused_screen = screen;
set_state(INACTIVE);
}
else if (input->count(df::interface_key::CUSTOM_S))
show_options();
return true;
@ -316,6 +357,8 @@ public:
}
void render() {
static vector<string> lines;
static const std::string pause_message =
"Pause confirmations until you exit this screen";
Screen::Pen corner_ul = Screen::Pen((char)201, COLOR_GREY, COLOR_BLACK);
Screen::Pen corner_ur = Screen::Pen((char)187, COLOR_GREY, COLOR_BLACK);
Screen::Pen corner_dl = Screen::Pen((char)200, COLOR_GREY, COLOR_BLACK);
@ -329,7 +372,9 @@ public:
for (string line : lines)
max_length = std::max(max_length, line.size());
int width = max_length + 4;
int height = lines.size() + 4;
vector<string> pause_message_lines;
word_wrap(&pause_message_lines, pause_message, max_length - 3);
int height = lines.size() + pause_message_lines.size() + 5;
int x1 = (gps->dimx / 2) - (width / 2);
int x2 = x1 + width - 1;
int y1 = (gps->dimy / 2) - (height / 2);
@ -368,6 +413,14 @@ public:
{
Screen::paintString(Screen::Pen(' ', get_color(), COLOR_BLACK), x1 + 2, y1 + 2 + i, lines[i]);
}
y = y1 + 3 + lines.size();
for (size_t i = 0; i < pause_message_lines.size(); i++)
{
Screen::paintString(Screen::Pen(' ', COLOR_WHITE, COLOR_BLACK), x1 + 5, y + i, pause_message_lines[i]);
}
x = x1 + 2;
OutputString(COLOR_LIGHTRED, x, y, Screen::getKeyDisplay(df::interface_key::CUSTOM_P));
OutputString(COLOR_WHITE, x, y, ":");
}
else if (state == SELECTED)
{
@ -533,6 +586,22 @@ DFhackCExport command_result plugin_shutdown (color_ostream &out)
return CR_OK;
}
static bool screen_found(df::viewscreen *target_screen)
{
if (!df::global::gview)
return false;
df::viewscreen *screen = &df::global::gview->view;
while (screen)
{
if (screen == target_screen)
return true;
screen = screen->child;
}
return false;
}
DFhackCExport command_result plugin_onupdate (color_ostream &out)
{
while (!cmds.empty())
@ -540,6 +609,11 @@ DFhackCExport command_result plugin_onupdate (color_ostream &out)
Core::getInstance().runCommand(out, cmds.front());
cmds.pop();
}
// if the screen that we paused on is no longer on the stack, unpause
if (paused_screen && !screen_found(paused_screen))
conf_lua::api::unpause(NULL);
return CR_OK;
}