From 448eced17cf8963434ebfe2711d7a046c22354f2 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 18 Sep 2022 08:07:08 -0700 Subject: [PATCH 01/10] make Screen::getMousePos always return scr coords --- library/modules/Screen.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index 5001a34c0..bff14a380 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -31,6 +31,7 @@ distribution. #include using namespace std; +#include "modules/Renderer.h" #include "modules/Screen.h" #include "modules/GuiHooks.h" #include "MemAccess.h" @@ -75,12 +76,14 @@ using std::string; * Screen painting API. */ +// returns text grid coordinates, even if the game map is scaled differently df::coord2d Screen::getMousePos() { - if (!gps || (enabler && !enabler->tracking_on)) + int32_t x = Renderer::GET_MOUSE_COORDS_SENTINEL, y = (int32_t)true; + if (!enabler || !enabler->renderer->get_mouse_coords(&x, &y)) { return df::coord2d(-1, -1); - - return df::coord2d(gps->mouse_x, gps->mouse_y); + } + return df::coord2d(x, y); } df::coord2d Screen::getWindowSize() @@ -769,7 +772,7 @@ int dfhack_lua_viewscreen::do_input(lua_State *L) } } - if (enabler && enabler->tracking_on) + if (enabler) { if (enabler->mouse_lbut_down) { lua_pushboolean(L, true); From 3b89f482d11e448cb70f5f4247413d990aef47d6 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 18 Sep 2022 08:18:08 -0700 Subject: [PATCH 02/10] use the new Screen::getMousePos() implementation --- plugins/overlay.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/plugins/overlay.cpp b/plugins/overlay.cpp index 1e66814a0..30a5546a4 100644 --- a/plugins/overlay.cpp +++ b/plugins/overlay.cpp @@ -87,7 +87,7 @@ #include "VTableInterpose.h" #include "uicommon.h" -#include "modules/Renderer.h" +#include "modules/Screen.h" using namespace DFHack; @@ -104,16 +104,12 @@ static const std::string button_text = "[ DFHack Launcher ]"; static bool clicked = false; static bool handle_click() { - int32_t x = Renderer::GET_MOUSE_COORDS_SENTINEL, y = (int32_t)true; - if (!enabler->mouse_lbut_down || clicked || - !enabler->renderer->get_mouse_coords(&x, &y)) { - DEBUG(log).print( - "lbut_down=%s; clicked=%s; mouse_x=%d; mouse_y=%d\n", - enabler->mouse_lbut_down ? "true" : "false", - clicked ? "true" : "false", x, y); + if (!enabler->mouse_lbut_down || clicked) { return false; } - if (y == gps->dimy - 1 && x >= 1 && (size_t)x <= button_text.size()) { + df::coord2d pos = Screen::getMousePos(); + DEBUG(log).print("clicked at screen coordinates (%d, %d)\n", pos.x, pos.y); + if (pos.y == gps->dimy - 1 && pos.x >= 1 && (size_t)pos.x <= button_text.size()) { clicked = true; Core::getInstance().setHotkeyCmd("gui/launcher"); return true; From 215a5b0a24be00d91dcf9376680e6311cf3df574 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 18 Sep 2022 08:19:02 -0700 Subject: [PATCH 03/10] add Gui::getMousePos() that always gets map coords --- library/include/modules/Gui.h | 5 ++--- library/modules/Gui.cpp | 17 ++++++++--------- plugins/devel/kittens.cpp | 11 +++++------ plugins/mousequery.cpp | 20 ++++---------------- 4 files changed, 19 insertions(+), 34 deletions(-) diff --git a/library/include/modules/Gui.h b/library/include/modules/Gui.h index 455032fea..a0ae27889 100644 --- a/library/include/modules/Gui.h +++ b/library/include/modules/Gui.h @@ -126,10 +126,11 @@ namespace DFHack DFHACK_EXPORT void showAutoAnnouncement(df::announcement_type type, df::coord pos, std::string message, int color = 7, bool bright = true, df::unit *unit1 = NULL, df::unit *unit2 = NULL); /* - * Cursor and window coords + * Cursor and window map coords */ DFHACK_EXPORT df::coord getViewportPos(); DFHACK_EXPORT df::coord getCursorPos(); + DFHACK_EXPORT df::coord getMousePos(); static const int AREA_MAP_WIDTH = 23; static const int MENU_WIDTH = 30; @@ -162,8 +163,6 @@ namespace DFHack DFHACK_EXPORT bool getDesignationCoords (int32_t &x, int32_t &y, int32_t &z); DFHACK_EXPORT bool setDesignationCoords (const int32_t x, const int32_t y, const int32_t z); - DFHACK_EXPORT bool getMousePos (int32_t & x, int32_t & y); - // The distance from the z-level of the tile at map coordinates (x, y) to the closest ground z-level below // Defaults to 0, unless overriden by plugins DFHACK_EXPORT int getDepthAt (int32_t x, int32_t y); diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index fc78bb57d..f9e15aac4 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -1831,17 +1831,16 @@ bool Gui::setDesignationCoords (const int32_t x, const int32_t y, const int32_t return true; } -bool Gui::getMousePos (int32_t & x, int32_t & y) +// returns the map coordinates that the mouse cursor is over +df::coord Gui::getMousePos() { - if (gps) { - x = gps->mouse_x; - y = gps->mouse_y; - } - else { - x = -1; - y = -1; + df::coord pos; + if (gps && gps->mouse_x > -1) { + pos = getViewportPos(); + pos.x += gps->mouse_x - 1; + pos.y += gps->mouse_y - 1; } - return (x == -1) ? false : true; + return pos; } int getDepthAt_default (int32_t x, int32_t y) diff --git a/plugins/devel/kittens.cpp b/plugins/devel/kittens.cpp index fce924aff..56ca813ae 100644 --- a/plugins/devel/kittens.cpp +++ b/plugins/devel/kittens.cpp @@ -135,13 +135,12 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) last_designation[2] = desig_z; out.print("Designation: %d %d %d\n",desig_x, desig_y, desig_z); } - int mouse_x, mouse_y; - Gui::getMousePos(mouse_x,mouse_y); - if(mouse_x != last_mouse[0] || mouse_y != last_mouse[1]) + df:coord mousePos = Gui::getMousePos(); + if(mousePos.x != last_mouse[0] || mousePos.y != last_mouse[1]) { - last_mouse[0] = mouse_x; - last_mouse[1] = mouse_y; - out.print("Mouse: %d %d\n",mouse_x, mouse_y); + last_mouse[0] = mousePos.x; + last_mouse[1] = mousePos.y; + out.print("Mouse: %d %d\n",mousePos.x, mousePos.y); } } return CR_OK; diff --git a/plugins/mousequery.cpp b/plugins/mousequery.cpp index cd85de2bc..2bfa08470 100644 --- a/plugins/mousequery.cpp +++ b/plugins/mousequery.cpp @@ -53,23 +53,11 @@ static enum { None, Left, Right } drag_mode; static df::coord get_mouse_pos(int32_t &mx, int32_t &my) { - df::coord pos; - pos.x = -30000; - - if (!enabler->tracking_on) - return pos; - - if (!Gui::getMousePos(mx, my)) - return pos; - - int32_t vx, vy, vz; - if (!Gui::getViewCoords(vx, vy, vz)) - return pos; - - pos.x = vx + mx - 1; - pos.y = vy + my - 1; - pos.z = vz - Gui::getDepthAt(mx, my); + df::coord pos = Gui::getMousePos(); + pos.z -= Gui::getDepthAt(pos.x, pos.y); + mx = pos.x; + my = pos.y; return pos; } From 1f15e4d47ec593cc5bc803d6e5bdec720c48b07b Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 18 Sep 2022 08:19:56 -0700 Subject: [PATCH 04/10] expose Gui::getMousePos() to Lua --- library/LuaApi.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 70cb01dfc..b556e5737 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1523,6 +1523,12 @@ static int gui_getDwarfmodeViewDims(lua_State *state) return 1; } +static int gui_getMousePos(lua_State *L) +{ + Lua::PushPosXYZ(L, Gui::getMousePos()); + return 3; +} + static const LuaWrapper::FunctionReg dfhack_gui_module[] = { WRAPM(Gui, getCurViewscreen), WRAPM(Gui, getFocusString), @@ -1555,6 +1561,7 @@ static const LuaWrapper::FunctionReg dfhack_gui_module[] = { static const luaL_Reg dfhack_gui_funcs[] = { { "getDwarfmodeViewDims", gui_getDwarfmodeViewDims }, + { "getMousePos", gui_getMousePos }, { NULL, NULL } }; @@ -2282,9 +2289,7 @@ static const LuaWrapper::FunctionReg dfhack_screen_module[] = { static int screen_getMousePos(lua_State *L) { - auto pos = Screen::getMousePos(); - lua_pushinteger(L, pos.x); - lua_pushinteger(L, pos.y); + Lua::PushPosXY(L, Screen::getMousePos()); return 2; } From 3b650c8d0bb5cd31be1bbffcab7bef34ac4452dc Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 18 Sep 2022 08:20:33 -0700 Subject: [PATCH 05/10] don't let changes to the lua cursor bleed through before, we could end up changing the state of whoever last called guidm.setCursorPos() --- library/lua/gui/dwarfmode.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lua/gui/dwarfmode.lua b/library/lua/gui/dwarfmode.lua index e56211233..db80554cd 100644 --- a/library/lua/gui/dwarfmode.lua +++ b/library/lua/gui/dwarfmode.lua @@ -104,7 +104,7 @@ function getCursorPos() end function setCursorPos(cursor) - df.global.cursor = cursor + df.global.cursor = copyall(cursor) end function clearCursorPos() From 8fd86f6e566d6fa855650d49ac489e815ca6cd71 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 18 Sep 2022 08:40:22 -0700 Subject: [PATCH 06/10] fix typo in kittens.cpp --- plugins/devel/kittens.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/devel/kittens.cpp b/plugins/devel/kittens.cpp index 56ca813ae..156686a1e 100644 --- a/plugins/devel/kittens.cpp +++ b/plugins/devel/kittens.cpp @@ -135,7 +135,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) last_designation[2] = desig_z; out.print("Designation: %d %d %d\n",desig_x, desig_y, desig_z); } - df:coord mousePos = Gui::getMousePos(); + df::coord mousePos = Gui::getMousePos(); if(mousePos.x != last_mouse[0] || mousePos.y != last_mouse[1]) { last_mouse[0] = mousePos.x; From dbc5001bd8947731b676742f1329830eba1a6db0 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 18 Sep 2022 13:27:13 -0700 Subject: [PATCH 07/10] fail if mouse cursor isn't over the map area --- library/modules/Gui.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index f9e15aac4..56aa09b7f 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -1836,6 +1836,12 @@ df::coord Gui::getMousePos() { df::coord pos; if (gps && gps->mouse_x > -1) { + // return invalid coords if the cursor is not over the map + DwarfmodeDims dims = getDwarfmodeViewDims(); + if (gps->mouse_x < dims.map_x1 || gps->mouse_x > dims.map_x2 || + gps->mouse_y < dims.map_y1 || gps->mouse_y > dims.map_y2) { + return pos; + } pos = getViewportPos(); pos.x += gps->mouse_x - 1; pos.y += gps->mouse_y - 1; From 28b70eaee9d2d1b2b9d78ecd4d19bac13c8ba01b Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 18 Sep 2022 13:27:33 -0700 Subject: [PATCH 08/10] return map coords as a coord, not x, y, z --- library/LuaApi.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index b556e5737..3a83f7aef 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1525,8 +1525,12 @@ static int gui_getDwarfmodeViewDims(lua_State *state) static int gui_getMousePos(lua_State *L) { - Lua::PushPosXYZ(L, Gui::getMousePos()); - return 3; + auto pos = Gui::getMousePos(); + if (pos.isValid()) + Lua::Push(L, pos); + else + lua_pushnil(L); + return 1; } static const LuaWrapper::FunctionReg dfhack_gui_module[] = { @@ -2289,16 +2293,12 @@ static const LuaWrapper::FunctionReg dfhack_screen_module[] = { static int screen_getMousePos(lua_State *L) { - Lua::PushPosXY(L, Screen::getMousePos()); - return 2; + return Lua::PushPosXY(L, Screen::getMousePos()); } static int screen_getWindowSize(lua_State *L) { - auto pos = Screen::getWindowSize(); - lua_pushinteger(L, pos.x); - lua_pushinteger(L, pos.y); - return 2; + return Lua::PushPosXY(L, Screen::getWindowSize()); } static int screen_paintTile(lua_State *L) From 8e718d9851600c7247b6e1c8f95db39e6f59b3b6 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 18 Sep 2022 13:31:20 -0700 Subject: [PATCH 09/10] add docs for dfhack.gui.getMousePos() --- docs/Lua API.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index ba63030b5..64ccdd595 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -1088,6 +1088,11 @@ Announcements Uses the type to look up options from announcements.txt, and calls the above operations accordingly. The units are used to call ``addCombatReportAuto``. +* ``dfhack.gui.getMousePos()`` + + Returns the map coordinates of the map tile the mouse is over as a table of + ``{x, y, z}``. If the cursor is not over the map, returns ``nil``. + Other ~~~~~ From 24816763703f9179bf481602fbf7afc1962463a0 Mon Sep 17 00:00:00 2001 From: myk002 Date: Mon, 19 Sep 2022 11:13:47 -0700 Subject: [PATCH 10/10] fix mouse pos offset and output 'X' at screen edge --- plugins/mousequery.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/plugins/mousequery.cpp b/plugins/mousequery.cpp index 2bfa08470..6358262f4 100644 --- a/plugins/mousequery.cpp +++ b/plugins/mousequery.cpp @@ -20,6 +20,7 @@ #include "uicommon.h" #include "TileTypes.h" #include "DataFuncs.h" +#include "Debug.h" DFHACK_PLUGIN("mousequery"); REQUIRE_GLOBAL(enabler); @@ -32,6 +33,10 @@ using namespace df::enums::ui_sidebar_mode; #define PLUGIN_VERSION 0.18 +namespace DFHack { + DBG_DECLARE(mousequery,log,DebugCategory::LINFO); +} + static int32_t last_clicked_x, last_clicked_y, last_clicked_z; static int32_t last_pos_x, last_pos_y, last_pos_z; static df::coord last_move_pos; @@ -56,8 +61,10 @@ static df::coord get_mouse_pos(int32_t &mx, int32_t &my) df::coord pos = Gui::getMousePos(); pos.z -= Gui::getDepthAt(pos.x, pos.y); - mx = pos.x; - my = pos.y; + df::coord vpos = Gui::getViewportPos(); + mx = pos.x - vpos.x + 1; + my = pos.y - vpos.y + 1; + return pos; } @@ -524,6 +531,7 @@ struct mousequery_hook : public df::viewscreen_dwarfmodest if (mpos.x == x && mpos.y == y && mpos.z == z) return; + DEBUG(log).print("moving cursor to %d, %d, %d\n", x, y, z); Gui::setCursorCoords(mpos.x, mpos.y, mpos.z); Gui::refreshSidebar(); } @@ -563,8 +571,6 @@ struct mousequery_hook : public df::viewscreen_dwarfmodest int32_t mx, my; auto mpos = get_mouse_pos(mx, my); bool mpos_valid = mpos.x != -30000 && mpos.y != -30000 && mpos.z != -30000; - if (mx < 1 || mx > dims.map_x2 || my < 1 || my > dims.map_y2) - mpos_valid = false; // Check if in lever binding mode if (Gui::getFocusString(Core::getTopViewscreen()) == @@ -711,7 +717,7 @@ struct mousequery_hook : public df::viewscreen_dwarfmodest } } - OutputString(color, mx, my, "X", false, 0, 0, true); + Screen::paintTile(Screen::Pen('X', color), mx, my, true); return; }