From 27bf4c758beaa1d4b47832a2e090fdf3db5393ac Mon Sep 17 00:00:00 2001 From: Myk Date: Thu, 2 Jun 2022 06:24:13 -0700 Subject: [PATCH] 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 --- docs/changelog.txt | 1 + plugins/confirm.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index a777b60c4..4dd8404ac 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -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 diff --git a/plugins/confirm.cpp b/plugins/confirm.cpp index 6a2798cb4..60735ef94 100644 --- a/plugins/confirm.cpp +++ b/plugins/confirm.cpp @@ -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 confirmations; string active_id; queue 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 inline bool in_vector (std::vector &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 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 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; }