diff --git a/dfhack.init-example b/dfhack.init-example index 552b2b3a1..380bdd04f 100644 --- a/dfhack.init-example +++ b/dfhack.init-example @@ -51,3 +51,10 @@ keybinding add Alt-R@dwarfmode/QueryBuilding/Some gui/room-list.work # interface for the liquids plugin keybinding add Alt-L@dwarfmode/LookAround gui/liquids + +################### +# UI logic tweaks # +################### + +# stabilize the cursor of dwarfmode when switching menus +tweak stable-cursor diff --git a/plugins/tweak.cpp b/plugins/tweak.cpp index 2daa9063b..70acf7607 100644 --- a/plugins/tweak.cpp +++ b/plugins/tweak.cpp @@ -13,6 +13,7 @@ #include "MiscUtils.h" #include "DataDefs.h" +#include #include "df/ui.h" #include "df/world.h" #include "df/squad.h" @@ -26,6 +27,7 @@ #include "df/death_info.h" #include "df/criminal_case.h" #include "df/unit_inventory_item.h" +#include "df/viewscreen_dwarfmodest.h" #include @@ -67,6 +69,9 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector & params); - - // to be called by tweak-fixmigrant // units forced into the fort by removing the flags do not own their clothes // which has the result that they drop all their clothes and become unhappy because they are naked @@ -136,6 +138,54 @@ command_result fix_clothing_ownership(color_ostream &out, df::unit* unit) return CR_OK; } +/* + * Save or restore cursor position on change to/from main dwarfmode menu. + */ + +static df::coord last_view, last_cursor; + +struct stable_cursor_hook : df::viewscreen_dwarfmodest +{ + typedef df::viewscreen_dwarfmodest interpose_base; + + DEFINE_VMETHOD_INTERPOSE(void, feed, (set *input)) + { + bool was_default = (ui->main.mode == df::ui_sidebar_mode::Default); + df::coord view = Gui::getViewportPos(); + df::coord cursor = Gui::getCursorPos(); + + INTERPOSE_NEXT(feed)(input); + + bool is_default = (ui->main.mode == df::ui_sidebar_mode::Default); + df::coord cur_cursor = Gui::getCursorPos(); + + if (is_default && !was_default) + { + last_view = view; last_cursor = cursor; + } + else if (!is_default && was_default && + Gui::getViewportPos() == last_view && + last_cursor.isValid() && cur_cursor.isValid()) + { + Gui::setCursorCoords(last_cursor.x, last_cursor.y, last_cursor.z); + + // Force update of ui state + set tmp; + tmp.insert(interface_key::CURSOR_DOWN_Z); + INTERPOSE_NEXT(feed)(&tmp); + tmp.clear(); + tmp.insert(interface_key::CURSOR_UP_Z); + INTERPOSE_NEXT(feed)(&tmp); + } + else if (cur_cursor.isValid()) + { + last_cursor = df::coord(); + } + } +}; + +IMPLEMENT_VMETHOD_INTERPOSE(stable_cursor_hook, feed); + static command_result tweak(color_ostream &out, vector ¶meters) { CoreSuspender suspend; @@ -234,6 +284,14 @@ static command_result tweak(color_ostream &out, vector ¶meters) unit->profession2 = df::profession::TRADER; return fix_clothing_ownership(out, unit); } + else if (cmd == "stable-cursor") + { + auto &hook = INTERPOSE_HOOK(stable_cursor_hook, feed); + if (vector_get(parameters, 1) == "disable") + hook.remove(); + else + hook.apply(); + } else return CR_WRONG_USAGE;