From 07f8fad7876047aeec46b1d6ba61565a236772fa Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Wed, 28 Dec 2022 16:00:10 -0800 Subject: [PATCH 01/51] implement Gui::getMousePos and Gui::getDepthAt --- library/modules/Gui.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index 4b600a661..71a166b89 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -61,6 +61,7 @@ using namespace DFHack; #include "df/general_ref.h" #include "df/global_objects.h" #include "df/graphic.h" +#include "df/graphic_viewportst.h" #include "df/historical_figure.h" #include "df/interfacest.h" #include "df/item_corpsepiecest.h" @@ -2151,16 +2152,24 @@ df::coord Gui::getMousePos() df::coord pos; if (gps && gps->precise_mouse_x > -1) { pos = getViewportPos(); -/* TODO: understand how this changes for v50 - pos.x += gps->mouse_x_pixel / tile_width; - pos.y += gps->mouse_y_pixel / tile_height; -*/ + int32_t map_tile_pixels = gps->viewport_zoom_factor >> 2; + pos.x += gps->precise_mouse_x / map_tile_pixels; + pos.y += gps->precise_mouse_y / map_tile_pixels; } return pos; } int getDepthAt_default (int32_t x, int32_t y) { + auto &main_vp = gps->main_viewport; + if (x < 0 || x >= main_vp->dim_x || y < 0 || y >= main_vp->dim_y) + return 0; + const size_t num_viewports = gps->viewport.size(); + const size_t index = (x * main_vp->dim_y) + y; + for (int depth = 0; depth < num_viewports; ++depth) { + if (gps->viewport[depth]->screentexpos_background[index]) + return depth; + } return 0; } From fc523f12fecf2e1cdb42f7f4328d61799f295952 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Wed, 28 Dec 2022 16:05:27 -0800 Subject: [PATCH 02/51] expose and document dfhack.screen.getMousePixels() --- docs/dev/Lua API.rst | 12 ++++++++++-- library/LuaApi.cpp | 6 ++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 0fa95dd03..4b9e2e972 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -1121,7 +1121,8 @@ Other * ``dfhack.gui.getDepthAt(x, y)`` Returns 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 overridden by plugins. + the closest rendered ground z-level below. Defaults to 0, unless overridden by + plugins. Job module ---------- @@ -2161,7 +2162,14 @@ Functions: * ``dfhack.screen.getMousePos()`` - Returns *x,y* of the tile the mouse is over. + Returns *x,y* of the UI interface tile the mouse is over, with the upper left + corner being ``0,0``. To get the map tile coordinate that the mouse is over, + see ``dfhack.gui.getMousePos()``. + +* ``dfhack.screen.getMousePixels()`` + + Returns *x,y* of the screen coordinates the mouse is over in pixels, with the + upper left corner being ``0,0``. * ``dfhack.screen.inGraphicsMode()`` diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index ef0b5c3dd..31a6ee753 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2373,6 +2373,11 @@ static int screen_getMousePos(lua_State *L) return Lua::PushPosXY(L, Screen::getMousePos()); } +static int screen_getMousePixels(lua_State *L) +{ + return Lua::PushPosXY(L, Screen::getMousePixels()); +} + static int screen_getWindowSize(lua_State *L) { return Lua::PushPosXY(L, Screen::getWindowSize()); @@ -2563,6 +2568,7 @@ static int screen_zoom(lua_State *L) static const luaL_Reg dfhack_screen_funcs[] = { { "getMousePos", screen_getMousePos }, + { "getMousePixels", screen_getMousePixels }, { "getWindowSize", screen_getWindowSize }, { "paintTile", screen_paintTile }, { "readTile", screen_readTile }, From d7b67e9528b1e5296ee959eb564304e6ab631af8 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Wed, 28 Dec 2022 16:27:44 -0800 Subject: [PATCH 03/51] remove cached USE_GRAPHICS from gui.lua it's no longer constant --- docs/dev/Lua API.rst | 5 ----- library/lua/gui.lua | 2 -- 2 files changed, 7 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 4b9e2e972..7c6e72f19 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -3640,11 +3640,6 @@ considered stable. Misc ---- -* ``USE_GRAPHICS`` - - Contains the value of ``dfhack.screen.inGraphicsMode()``, which cannot be - changed without restarting the game and thus is constant during the session. - * ``CLEAR_PEN`` The black pen used to clear the screen. diff --git a/library/lua/gui.lua b/library/lua/gui.lua index 709ff65f9..1eaa9861a 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -7,8 +7,6 @@ local utils = require('utils') local dscreen = dfhack.screen local getval = utils.getval -USE_GRAPHICS = dscreen.inGraphicsMode() - local to_pen = dfhack.pen.parse CLEAR_PEN = to_pen{tile=909, ch=32, fg=0, bg=0} From cff603e2433fea4b2a698bb0e8b900135cbbfd68 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Wed, 28 Dec 2022 23:16:13 -0800 Subject: [PATCH 04/51] allow Labels to write tile textures --- library/lua/gui/widgets.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 9ce42f2b2..55d8facf9 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -988,7 +988,7 @@ function render_text(obj,dc,x0,y0,pen,dpen,disabled) if token.tile then x = x + 1 if dc then - dc:char(nil, token.tile) + dc:tile(nil, token.tile) end end From 371f5be050bd38be40592b73abe95a23f4c9385e Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Wed, 28 Dec 2022 23:31:06 -0800 Subject: [PATCH 05/51] fix signedness of comparison var --- library/modules/Gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index 71a166b89..7283b6774 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -2166,7 +2166,7 @@ int getDepthAt_default (int32_t x, int32_t y) return 0; const size_t num_viewports = gps->viewport.size(); const size_t index = (x * main_vp->dim_y) + y; - for (int depth = 0; depth < num_viewports; ++depth) { + for (size_t depth = 0; depth < num_viewports; ++depth) { if (gps->viewport[depth]->screentexpos_background[index]) return depth; } From a4c11de4fbb2c43cb441545664cfa1705d218074 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Thu, 29 Dec 2022 00:01:40 -0800 Subject: [PATCH 06/51] returns correct mouse pos when in ascii --- library/modules/Gui.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index 7283b6774..83ca8c2e9 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -2152,10 +2152,17 @@ df::coord Gui::getMousePos() df::coord pos; if (gps && gps->precise_mouse_x > -1) { pos = getViewportPos(); - int32_t map_tile_pixels = gps->viewport_zoom_factor >> 2; - pos.x += gps->precise_mouse_x / map_tile_pixels; - pos.y += gps->precise_mouse_y / map_tile_pixels; + if (Screen::inGraphicsMode()) { + int32_t map_tile_pixels = gps->viewport_zoom_factor >> 2; + pos.x += gps->precise_mouse_x / map_tile_pixels; + pos.y += gps->precise_mouse_y / map_tile_pixels; + } else { + pos.x += gps->mouse_x; + pos.y += gps->mouse_y; + } } + if (!Maps::isValidTilePos(pos.x, pos.y, pos.z)) + return df::coord(); return pos; } From f45eac993a2031f998f93a3db4b4b769cb7230eb Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Thu, 29 Dec 2022 22:18:35 -0800 Subject: [PATCH 07/51] use semantically clearer div rather than bit shift --- library/modules/Gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index 83ca8c2e9..c436a0ca5 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -2153,7 +2153,7 @@ df::coord Gui::getMousePos() if (gps && gps->precise_mouse_x > -1) { pos = getViewportPos(); if (Screen::inGraphicsMode()) { - int32_t map_tile_pixels = gps->viewport_zoom_factor >> 2; + int32_t map_tile_pixels = gps->viewport_zoom_factor / 4; pos.x += gps->precise_mouse_x / map_tile_pixels; pos.y += gps->precise_mouse_y / map_tile_pixels; } else { From 1265d531d58387c8721b1e79de9b3f82a9607566 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 00:53:44 -0800 Subject: [PATCH 08/51] only keep the anchor flag if it's already there --- library/modules/Screen.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index 653ab0bd3..c068ab42a 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -145,7 +145,9 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map) *screen = 0; *texpos = 0; *texpos_lower = 0; - *flag = 4; // remove SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE + // keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE so occluded anchored textures + // don't appear corrupted + *flag &= 4; if (gps->top_in_use) { screen = &gps->screen_top[index * 8]; @@ -156,7 +158,7 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map) *screen = 0; *texpos = 0; *texpos_lower = 0; - *flag = 4; // remove SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE + *flag &= 4; // keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE } if (pen.tile_mode == Screen::Pen::CharColor) From 83a8e9a45aec4157a14cbb07ac700b5061b2e3a8 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 03:30:01 -0800 Subject: [PATCH 09/51] render bright colors correctly --- library/modules/Screen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index c068ab42a..9c4f8303f 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -173,8 +173,8 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map) *texpos_lower = 909; } - // note that pen.bold currently (50.04) has no representation in the DF data - auto fg = &gps->uccolor[pen.fg][0]; + uint8_t fullfg = pen.fg | (pen.bold << 3); + auto fg = &gps->uccolor[fullfg][0]; auto bg = &gps->uccolor[pen.bg][0]; screen[1] = fg[0]; screen[2] = fg[1]; From 3aac79fe4ff55c86f6e2a506b0abf215a99946e3 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 03:28:59 -0800 Subject: [PATCH 10/51] skin our scrollbars to look and hover like DF's --- library/lua/gui/widgets.lua | 98 +++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 20 deletions(-) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 55d8facf9..73add1a9d 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -8,6 +8,7 @@ local utils = require('utils') local dscreen = dfhack.screen local getval = utils.getval +local to_pen = dfhack.pen.parse local function show_view(view,vis) if view then @@ -465,7 +466,7 @@ function Panel:onRenderFrame(dc, rect) gui.paint_frame(dc, rect, self.frame_style, self.frame_title) if self.kbd_get_pos then local pos = self.kbd_get_pos() - local pen = dfhack.pen.parse{fg=COLOR_GREEN, bg=COLOR_BLACK} + local pen = to_pen{fg=COLOR_GREEN, bg=COLOR_BLACK} dc:seek(pos.x, pos.y):pen(pen):char(string.char(0xDB)) end if self.drag_offset and not self.kbd_get_pos @@ -759,14 +760,12 @@ SCROLL_DELAY_MS = 20 Scrollbar = defclass(Scrollbar, Widget) Scrollbar.ATTRS{ - fg = COLOR_LIGHTGREEN, - bg = COLOR_CYAN, on_scroll = DEFAULT_NIL, } function Scrollbar:preinit(init_table) init_table.frame = init_table.frame or {} - init_table.frame.w = init_table.frame.w or 1 + init_table.frame.w = init_table.frame.w or 2 end function Scrollbar:init() @@ -824,36 +823,95 @@ local function scrollbar_is_visible(scrollbar) return scrollbar.elems_per_page < scrollbar.num_elems end -local UP_ARROW_CHAR = string.char(24) -local DOWN_ARROW_CHAR = string.char(25) -local NO_ARROW_CHAR = string.char(32) -local BAR_CHAR = string.char(7) -local BAR_BG_CHAR = string.char(179) +local SCROLLBAR_UP_LEFT_PEN = to_pen{tile=922, ch=47, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_UP_RIGHT_PEN = to_pen{tile=923, ch=92, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_DOWN_LEFT_PEN = to_pen{tile=946, ch=92, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_DOWN_RIGHT_PEN = to_pen{tile=947, ch=47, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_UP_LEFT_PEN = to_pen{tile=930, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_UP_RIGHT_PEN = to_pen{tile=931, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_LEFT_PEN = to_pen{tile=954, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_RIGHT_PEN = to_pen{tile=955, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_UP_LEFT_PEN = to_pen{tile=932, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_UP_RIGHT_PEN = to_pen{tile=933, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_DOWN_LEFT_PEN = to_pen{tile=960, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_DOWN_RIGHT_PEN = to_pen{tile=961, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_LEFT_PEN = to_pen{tile=940, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_RIGHT_PEN = to_pen{tile=941, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_DOWN_LEFT_PEN = to_pen{tile=966, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_DOWN_RIGHT_PEN = to_pen{tile=967, ch=219, fg=COLOR_CYAN, bg=COLOR_BLACK} +local SCROLLBAR_UP_LEFT_HOVER_PEN = to_pen{tile=924, ch=47, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_UP_RIGHT_HOVER_PEN = to_pen{tile=925, ch=92, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_DOWN_LEFT_HOVER_PEN = to_pen{tile=936, ch=92, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_DOWN_RIGHT_HOVER_PEN = to_pen{tile=937, ch=47, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_UP_LEFT_HOVER_PEN = to_pen{tile=930, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_UP_RIGHT_HOVER_PEN = to_pen{tile=931, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_LEFT_HOVER_PEN = to_pen{tile=954, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_RIGHT_HOVER_PEN = to_pen{tile=955, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_UP_LEFT_HOVER_PEN = to_pen{tile=956, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_UP_RIGHT_HOVER_PEN = to_pen{tile=957, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_DOWN_LEFT_HOVER_PEN = to_pen{tile=968, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_DOWN_RIGHT_HOVER_PEN = to_pen{tile=969, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_LEFT_HOVER_PEN = to_pen{tile=942, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_CENTER_RIGHT_HOVER_PEN = to_pen{tile=943, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_DOWN_LEFT_HOVER_PEN = to_pen{tile=966, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_DOWN_RIGHT_HOVER_PEN = to_pen{tile=967, ch=219, fg=COLOR_LIGHTCYAN, bg=COLOR_BLACK} +local SCROLLBAR_BAR_BG_LEFT_PEN = to_pen{tile=934, ch=176, fg=COLOR_DARKGREY, bg=COLOR_BLACK} +local SCROLLBAR_BAR_BG_RIGHT_PEN = to_pen{tile=935, ch=176, fg=COLOR_DARKGREY, bg=COLOR_BLACK} function Scrollbar:onRenderBody(dc) -- don't draw if all elements are visible if not scrollbar_is_visible(self) then return end - -- render up arrow if we're not at the top - dc:seek(0, 0):char( - self.top_elem == 1 and NO_ARROW_CHAR or UP_ARROW_CHAR, self.fg, self.bg) + -- determine which elements should be highlighted + local _,hover_y = self:getMousePos() + local hover_up, hover_down, hover_bar = false, false, false + if hover_y == 0 then + hover_up = true + elseif hover_y == dc.height-1 then + hover_down = true + elseif hover_y then + hover_bar = true + end + -- render up arrow + dc:seek(0, 0) + dc:char(nil, hover_up and SCROLLBAR_UP_LEFT_HOVER_PEN or SCROLLBAR_UP_LEFT_PEN) + dc:char(nil, hover_up and SCROLLBAR_UP_RIGHT_HOVER_PEN or SCROLLBAR_UP_RIGHT_PEN) -- render scrollbar body local starty = self.bar_offset + 1 local endy = self.bar_offset + self.bar_height + local midy = (starty + endy)/2 for y=1,dc.height-2 do dc:seek(0, y) if y >= starty and y <= endy then - dc:char(BAR_CHAR, self.fg) + if y == starty then + dc:char(nil, hover_bar and SCROLLBAR_BAR_UP_LEFT_HOVER_PEN or SCROLLBAR_BAR_UP_LEFT_PEN) + dc:char(nil, hover_bar and SCROLLBAR_BAR_UP_RIGHT_HOVER_PEN or SCROLLBAR_BAR_UP_RIGHT_PEN) + elseif y == midy - 0.5 then + dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_UP_LEFT_HOVER_PEN or SCROLLBAR_BAR_CENTER_UP_LEFT_PEN) + dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_UP_RIGHT_HOVER_PEN or SCROLLBAR_BAR_CENTER_UP_RIGHT_PEN) + elseif y == midy + 0.5 then + dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_DOWN_LEFT_HOVER_PEN or SCROLLBAR_BAR_CENTER_DOWN_LEFT_PEN) + dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_DOWN_RIGHT_HOVER_PEN or SCROLLBAR_BAR_CENTER_DOWN_RIGHT_PEN) + elseif y == midy then + dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_LEFT_HOVER_PEN or SCROLLBAR_BAR_CENTER_LEFT_PEN) + dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_RIGHT_HOVER_PEN or SCROLLBAR_BAR_CENTER_RIGHT_PEN) + elseif y == endy then + dc:char(nil, hover_bar and SCROLLBAR_BAR_DOWN_LEFT_HOVER_PEN or SCROLLBAR_BAR_DOWN_LEFT_PEN) + dc:char(nil, hover_bar and SCROLLBAR_BAR_DOWN_RIGHT_HOVER_PEN or SCROLLBAR_BAR_DOWN_RIGHT_PEN) + else + dc:char(nil, hover_bar and SCROLLBAR_BAR_LEFT_HOVER_PEN or SCROLLBAR_BAR_LEFT_PEN) + dc:char(nil, hover_bar and SCROLLBAR_BAR_RIGHT_HOVER_PEN or SCROLLBAR_BAR_RIGHT_PEN) + end else - dc:char(BAR_BG_CHAR, self.bg) + dc:char(nil, SCROLLBAR_BAR_BG_LEFT_PEN) + dc:char(nil, SCROLLBAR_BAR_BG_RIGHT_PEN) end end - -- render down arrow if we're not at the bottom - local last_visible_el = self.top_elem + self.elems_per_page - 1 - dc:seek(0, dc.height-1):char( - last_visible_el >= self.num_elems and NO_ARROW_CHAR or DOWN_ARROW_CHAR, - self.fg, self.bg) + -- render down arrow + dc:seek(0, dc.height-1) + dc:char(nil, hover_down and SCROLLBAR_DOWN_LEFT_HOVER_PEN or SCROLLBAR_DOWN_LEFT_PEN) + dc:char(nil, hover_down and SCROLLBAR_DOWN_RIGHT_HOVER_PEN or SCROLLBAR_DOWN_RIGHT_PEN) if not self.on_scroll then return end -- manage state for dragging and continuous scrolling if self.is_dragging then @@ -994,7 +1052,7 @@ function render_text(obj,dc,x0,y0,pen,dpen,disabled) if token.text or token.key then local text = ''..(getval(token.text) or '') - local keypen = dfhack.pen.parse(token.key_pen or COLOR_LIGHTGREEN) + local keypen = to_pen(token.key_pen or COLOR_LIGHTGREEN) if dc then local tpen = getval(token.pen) From 4c2842a8542db63ea3087ae7939aa72c1f9298ce Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 03:31:58 -0800 Subject: [PATCH 11/51] update docs --- docs/dev/Lua API.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 7c6e72f19..7f6c61c65 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -4347,13 +4347,11 @@ Scrollbar class This Widget subclass implements mouse-interactive scrollbars whose bar sizes represent the amount of content currently visible in an associated display -widget (like a `Label class`_ or a `List class`_). By default they are styled -like scrollbars used in the vanilla DF help screens, but they are configurable. +widget (like a `Label class`_ or a `List class`_). They are styled like scrollbars +used in vanilla DF. Scrollbars have the following attributes: -:fg: Specifies the pen for the scroll icons and the active part of the bar. Default is ``COLOR_LIGHTGREEN``. -:bg: Specifies the pen for the background part of the scrollbar. Default is ``COLOR_CYAN``. :on_scroll: A callback called when the scrollbar is scrolled. If the scrollbar is clicked, the callback will be called with one of the following string parameters: "up_large", "down_large", "up_small", or "down_small". If the scrollbar is dragged, the callback will From 7d91f9262dc951da59313c41bb2ee833c179da50 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 05:35:04 -0800 Subject: [PATCH 12/51] respect tile colors in pens --- library/modules/Screen.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index 9c4f8303f..685802019 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -161,10 +161,18 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map) *flag &= 4; // keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE } + uint8_t fg = pen.fg | (pen.bold << 3); + uint8_t bg = pen.bg; + if (pen.tile_mode == Screen::Pen::CharColor) *flag |= 2; // SCREENTEXPOS_FLAG_ADDCOLOR - else if (pen.tile_mode == Screen::Pen::TileColor) + else if (pen.tile_mode == Screen::Pen::TileColor) { *flag |= 1; // SCREENTEXPOS_FLAG_GRAYSCALE + if (pen.tile_fg) + fg = pen.tile_fg; + if (pen.tile_bg) + bg = pen.tile_bg; + } if (pen.tile && use_graphics) { *texpos = pen.tile; @@ -173,15 +181,14 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map) *texpos_lower = 909; } - uint8_t fullfg = pen.fg | (pen.bold << 3); - auto fg = &gps->uccolor[fullfg][0]; - auto bg = &gps->uccolor[pen.bg][0]; - screen[1] = fg[0]; - screen[2] = fg[1]; - screen[3] = fg[2]; - screen[4] = bg[0]; - screen[5] = bg[1]; - screen[6] = bg[2]; + auto rgb_fg = &gps->uccolor[fg][0]; + auto rgb_bg = &gps->uccolor[bg][0]; + screen[1] = rgb_fg[0]; + screen[2] = rgb_fg[1]; + screen[3] = rgb_fg[2]; + screen[4] = rgb_bg[0]; + screen[5] = rgb_bg[1]; + screen[6] = rgb_bg[2]; return true; } From 70a0f4a71894c3c2bb2a0588e4d546767ade1c03 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 16:58:40 -0800 Subject: [PATCH 13/51] only do a full refresh when needed this significantly reduces CPU utilization when DFHack-owned screens are visible. --- docs/dev/Lua API.rst | 9 ++++++++- library/lua/gui.lua | 6 +++++- library/lua/gui/widgets.lua | 4 ++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 7c6e72f19..683bb9d29 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -2363,7 +2363,14 @@ Supported callbacks and fields are: where the above painting functions work correctly. If omitted, the screen is cleared; otherwise it should do that itself. - In order to make a see-through dialog, call ``self._native.parent:render()``. + In order to make a dialog where portions of the parent viewscreen are still + visible in the background, call ``screen:renderParent()``. + + If artifacts are left on the parent even after this function is called, such + as when the window is dragged or is resized, any code can set + ``gui.Screen.request_full_screen_refresh`` to ``true``. Then when + ``screen.renderParent()`` is next called, it will do a full flush of the + graphics and clear the screen of artifacts. * ``function screen:onIdle()`` diff --git a/library/lua/gui.lua b/library/lua/gui.lua index 1eaa9861a..ba15e32aa 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -597,6 +597,7 @@ end Screen = defclass(Screen, View) Screen.text_input_mode = false +Screen.request_full_screen_refresh = false function Screen:postinit() self:onResize(dscreen.getWindowSize()) @@ -622,7 +623,10 @@ function Screen:renderParent() else dscreen.clear() end - df.global.gps.force_full_display_count = 1 + if Screen.request_full_screen_refresh then + df.global.gps.force_full_display_count = 1 + Screen.request_full_screen_refresh = false + end end function Screen:sendInputToParent(...) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 55d8facf9..18d61c6b3 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -487,6 +487,10 @@ Window.ATTRS { draggable = true, } +function Window:postUpdateLayout() + gui.Screen.request_full_screen_refresh = true +end + ------------------- -- ResizingPanel -- ------------------- From 88dcdfd158a44e0ca4c061d1e549d8fe028915c7 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 20:01:09 -0800 Subject: [PATCH 14/51] move trigger code from Window to Panel where the drag/resize code actually is. Panels can be dragged around the parent screen without them being a Window --- library/lua/gui/widgets.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 18d61c6b3..19b898446 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -441,6 +441,9 @@ end -- if self.autoarrange_subviews is true, lay out visible subviews vertically, -- adding gaps between widgets according to self.autoarrange_gap. function Panel:postUpdateLayout() + -- don't leave artifacts behind on the parent screen when we move + gui.Screen.request_full_screen_refresh = true + if not self.autoarrange_subviews then return end local gap = self.autoarrange_gap @@ -487,10 +490,6 @@ Window.ATTRS { draggable = true, } -function Window:postUpdateLayout() - gui.Screen.request_full_screen_refresh = true -end - ------------------- -- ResizingPanel -- ------------------- From 33787473f0b058df5032b4cee82d0b4acd802f12 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 20:44:15 -0800 Subject: [PATCH 15/51] consolidate full refresh logic in widgets.Panel --- docs/dev/Lua API.rst | 6 ------ library/lua/gui.lua | 5 ----- library/lua/gui/widgets.lua | 6 +++++- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 683bb9d29..93a3ea160 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -2366,12 +2366,6 @@ Supported callbacks and fields are: In order to make a dialog where portions of the parent viewscreen are still visible in the background, call ``screen:renderParent()``. - If artifacts are left on the parent even after this function is called, such - as when the window is dragged or is resized, any code can set - ``gui.Screen.request_full_screen_refresh`` to ``true``. Then when - ``screen.renderParent()`` is next called, it will do a full flush of the - graphics and clear the screen of artifacts. - * ``function screen:onIdle()`` Called every frame when the screen is on top of the stack. diff --git a/library/lua/gui.lua b/library/lua/gui.lua index ba15e32aa..1bb9bae6b 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -597,7 +597,6 @@ end Screen = defclass(Screen, View) Screen.text_input_mode = false -Screen.request_full_screen_refresh = false function Screen:postinit() self:onResize(dscreen.getWindowSize()) @@ -623,10 +622,6 @@ function Screen:renderParent() else dscreen.clear() end - if Screen.request_full_screen_refresh then - df.global.gps.force_full_display_count = 1 - Screen.request_full_screen_refresh = false - end end function Screen:sendInputToParent(...) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 19b898446..01e1de89d 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -442,7 +442,7 @@ end -- adding gaps between widgets according to self.autoarrange_gap. function Panel:postUpdateLayout() -- don't leave artifacts behind on the parent screen when we move - gui.Screen.request_full_screen_refresh = true + self.request_full_screen_refresh = true if not self.autoarrange_subviews then return end @@ -464,6 +464,10 @@ end function Panel:onRenderFrame(dc, rect) Panel.super.onRenderFrame(self, dc, rect) + if self.request_full_screen_refresh then + df.global.gps.force_full_display_count = 1 + self.request_full_screen_refresh = false + end if not self.frame_style then return end gui.paint_frame(dc, rect, self.frame_style, self.frame_title) if self.kbd_get_pos then From dd0cc087d5d32f96dcee428b37f5003e68327e03 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 22:13:53 -0800 Subject: [PATCH 16/51] Revert "consolidate full refresh logic in widgets.Panel" This reverts commit 33787473f0b058df5032b4cee82d0b4acd802f12. I've already found another use case where we need a more general implementation -- modal dialogs that inherit from FramedScreen that appear and disappear --- docs/dev/Lua API.rst | 6 ++++++ library/lua/gui.lua | 5 +++++ library/lua/gui/widgets.lua | 6 +----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 93a3ea160..683bb9d29 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -2366,6 +2366,12 @@ Supported callbacks and fields are: In order to make a dialog where portions of the parent viewscreen are still visible in the background, call ``screen:renderParent()``. + If artifacts are left on the parent even after this function is called, such + as when the window is dragged or is resized, any code can set + ``gui.Screen.request_full_screen_refresh`` to ``true``. Then when + ``screen.renderParent()`` is next called, it will do a full flush of the + graphics and clear the screen of artifacts. + * ``function screen:onIdle()`` Called every frame when the screen is on top of the stack. diff --git a/library/lua/gui.lua b/library/lua/gui.lua index 1bb9bae6b..ba15e32aa 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -597,6 +597,7 @@ end Screen = defclass(Screen, View) Screen.text_input_mode = false +Screen.request_full_screen_refresh = false function Screen:postinit() self:onResize(dscreen.getWindowSize()) @@ -622,6 +623,10 @@ function Screen:renderParent() else dscreen.clear() end + if Screen.request_full_screen_refresh then + df.global.gps.force_full_display_count = 1 + Screen.request_full_screen_refresh = false + end end function Screen:sendInputToParent(...) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 01e1de89d..19b898446 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -442,7 +442,7 @@ end -- adding gaps between widgets according to self.autoarrange_gap. function Panel:postUpdateLayout() -- don't leave artifacts behind on the parent screen when we move - self.request_full_screen_refresh = true + gui.Screen.request_full_screen_refresh = true if not self.autoarrange_subviews then return end @@ -464,10 +464,6 @@ end function Panel:onRenderFrame(dc, rect) Panel.super.onRenderFrame(self, dc, rect) - if self.request_full_screen_refresh then - df.global.gps.force_full_display_count = 1 - self.request_full_screen_refresh = false - end if not self.frame_style then return end gui.paint_frame(dc, rect, self.frame_style, self.frame_title) if self.kbd_get_pos then From 1d7a7c8a49f2fc3bcc4030eacfe1735808e1d972 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 22:20:50 -0800 Subject: [PATCH 17/51] Don't leave artifats behind when dimissing mboxes --- library/lua/gui.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/lua/gui.lua b/library/lua/gui.lua index ba15e32aa..31631b469 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -661,6 +661,8 @@ function Screen:dismiss() if self._native then dscreen.dismiss(self) end + -- don't leave artifacts behind on the parent screen when we disappear + Screen.request_full_screen_refresh = true end function Screen:onDismiss() From 38b525bdb57f58a10de79eff2dc152432b8b2177 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 01:13:13 -0800 Subject: [PATCH 18/51] adapt lua library widgets to new keyboard keybindings --- docs/dev/Lua API.rst | 9 +++-- library/lua/gui/buildings.lua | 8 ++--- library/lua/gui/dialogs.lua | 22 ++++++------ library/lua/gui/dwarfmode.lua | 62 --------------------------------- library/lua/gui/materials.lua | 8 ++--- library/lua/gui/widgets.lua | 65 +++++++++++++++++------------------ 6 files changed, 54 insertions(+), 120 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 7f6c61c65..c7994a001 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -4309,7 +4309,6 @@ Attributes: If it returns false, the character is ignored. :on_change: Change notification callback; used as ``on_change(new_text,old_text)``. :on_submit: Enter key callback; if set the field will handle the key and call ``on_submit(text)``. -:on_submit2: Shift-Enter key callback; if set the field will handle the key and call ``on_submit2(text)``. :key: If specified, the field is disabled until this key is pressed. Must be given as a string. :key_sep: If specified, will be used to customize how the activation key is displayed. See ``token.key_sep`` in the ``Label`` documentation below. @@ -4339,8 +4338,8 @@ You can click where you want the cursor to move or you can use any of the following keyboard hotkeys: - Left/Right arrow: move the cursor one character to the left or right. -- Ctrl-Left/Right arrow: move the cursor one word to the left or right. -- Alt-Left/Right arrow: move the cursor to the beginning/end of the text. +- Ctrl-B/Ctrl-F: move the cursor one word back or forward. +- Ctrl-A/Ctrl-E: move the cursor to the beginning/end of the text. Scrollbar class --------------- @@ -4622,8 +4621,8 @@ It has the following attributes: with an empty list. :on_submit: Enter key or mouse click callback; if specified, the list reacts to the key/click and calls the callback as ``on_submit(index,choice)``. -:on_submit2: Shift-Enter key or shift-mouse click callback; if specified, the list - reacts to the key/click and calls it as ``on_submit2(index,choice)``. +:on_submit2: Shift-click callback; if specified, the list reacts to the click and + calls the callback as ``on_submit2(index,choice)``. :row_height: Height of every row in text lines. :icon_width: If not *nil*, the specified number of character columns are reserved to the left of the list item for the icons. diff --git a/library/lua/gui/buildings.lua b/library/lua/gui/buildings.lua index ae9219171..8871346f2 100644 --- a/library/lua/gui/buildings.lua +++ b/library/lua/gui/buildings.lua @@ -258,8 +258,8 @@ function BuildingDialog:onSubmitItem(idx, item) end function BuildingDialog:onInput(keys) - if keys.LEAVESCREEN or keys.LEAVESCREEN_ALL then - if self.subviews.back.visible and not keys.LEAVESCREEN_ALL then + if keys.LEAVESCREEN then + if self.subviews.back.visible then self:onGoBack() else self:dismiss() @@ -267,9 +267,9 @@ function BuildingDialog:onInput(keys) self.on_cancel() end end - else - self:inputToSubviews(keys) + return true end + self:inputToSubviews(keys) end function showBuildingPrompt(title, prompt, on_select, on_cancel, build_filter) diff --git a/library/lua/gui/dialogs.lua b/library/lua/gui/dialogs.lua index 952e8f734..0421ff365 100644 --- a/library/lua/gui/dialogs.lua +++ b/library/lua/gui/dialogs.lua @@ -59,19 +59,16 @@ function MessageBox:onDestroy() end function MessageBox:onInput(keys) - if keys.MENU_CONFIRM then + if keys.SELECT or keys.LEAVESCREEN then self:dismiss() - if self.on_accept then + if keys.SELECT and self.on_accept then self.on_accept() - end - elseif keys.LEAVESCREEN or (keys.SELECT and not self.on_accept) then - self:dismiss() - if self.on_cancel then + elseif keys.LEAVESCREEN and self.on_cancel then self.on_cancel() end - else - self:inputToSubviews(keys) + return true end + return self:inputToSubviews(keys) end function showMessage(title, text, tcolor, on_close) @@ -132,14 +129,15 @@ function InputBox:onInput(keys) if self.on_input then self.on_input(self.subviews.edit.text) end + return true elseif keys.LEAVESCREEN then self:dismiss() if self.on_cancel then self.on_cancel() end - else - self:inputToSubviews(keys) + return true end + return self:inputToSubviews(keys) end function showInputPrompt(title, text, tcolor, input, on_input, on_cancel, min_width) @@ -238,9 +236,9 @@ function ListBox:onInput(keys) if self.on_cancel then self.on_cancel() end - else - self:inputToSubviews(keys) + return true end + return self:inputToSubviews(keys) end function showListPrompt(title, text, tcolor, choices, on_select, on_cancel, min_width, filter) diff --git a/library/lua/gui/dwarfmode.lua b/library/lua/gui/dwarfmode.lua index db80554cd..78b84f441 100644 --- a/library/lua/gui/dwarfmode.lua +++ b/library/lua/gui/dwarfmode.lua @@ -553,66 +553,4 @@ function MenuOverlay:renderMapOverlay(get_overlay_char_fn, bounds_rect) end end ---fakes a "real" workshop sidebar menu, but on exactly selected workshop -WorkshopOverlay = defclass(WorkshopOverlay, MenuOverlay) -WorkshopOverlay.focus_path="WorkshopOverlay" -WorkshopOverlay.ATTRS={ - workshop=DEFAULT_NIL, -} -function WorkshopOverlay:onAboutToShow(below) - WorkshopOverlay.super.onAboutToShow(self,below) - - if df.global.world.selected_building ~= self.workshop then - error("The workshop overlay tried to show up for incorrect workshop") - end -end -function WorkshopOverlay:onInput(keys) - local allowedKeys={ --TODO add options: job management, profile, etc... - "CURSOR_RIGHT","CURSOR_RIGHT_FAST","CURSOR_LEFT","CURSOR_LEFT_FAST","CURSOR_UP","CURSOR_UP_FAST","CURSOR_DOWN","CURSOR_DOWN_FAST", - "CURSOR_UPRIGHT","CURSOR_UPRIGHT_FAST","CURSOR_UPLEFT","CURSOR_UPLEFT_FAST","CURSOR_DOWNRIGHT","CURSOR_DOWNRIGHT_FAST","CURSOR_DOWNLEFT","CURSOR_DOWNLEFT_FAST", - "CURSOR_UP_Z","CURSOR_DOWN_Z","DESTROYBUILDING","CHANGETAB","SUSPENDBUILDING"} - - if keys.LEAVESCREEN then - self:dismiss() - self:sendInputToParent('LEAVESCREEN') - elseif keys.CHANGETAB then - self:sendInputToParent("CHANGETAB") - self:inputToSubviews(keys) - self:updateLayout() - else - for _,name in ipairs(allowedKeys) do - if keys[name] then - self:sendInputToParent(name) - break - end - end - self:inputToSubviews(keys) - end - if df.global.world.selected_building ~= self.workshop then - self:dismiss() - return - end -end -function WorkshopOverlay:onGetSelectedBuilding() - return self.workshop -end -local function is_slated_for_remove( bld ) - for i,v in ipairs(bld.jobs) do - if v.job_type==df.job_type.DestroyBuilding then - return true - end - end - return false -end -function WorkshopOverlay:render(dc) - self:renderParent() - if df.global.world.selected_building ~= self.workshop then - return - end - if is_slated_for_remove(self.workshop) then - return - end - - WorkshopOverlay.super.render(self, dc) -end return _ENV diff --git a/library/lua/gui/materials.lua b/library/lua/gui/materials.lua index 1fbce4377..eea881768 100644 --- a/library/lua/gui/materials.lua +++ b/library/lua/gui/materials.lua @@ -255,8 +255,8 @@ function MaterialDialog:onSubmitItem(idx, item) end function MaterialDialog:onInput(keys) - if keys.LEAVESCREEN or keys.LEAVESCREEN_ALL then - if self.subviews.back.visible and not keys.LEAVESCREEN_ALL then + if keys.LEAVESCREEN then + if self.subviews.back.visible then self:onGoBack() else self:dismiss() @@ -264,9 +264,9 @@ function MaterialDialog:onInput(keys) self.on_cancel() end end - else - self:inputToSubviews(keys) + return true end + return self:inputToSubviews(keys) end function showMaterialPrompt(title, prompt, on_select, on_cancel, mat_filter) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 73add1a9d..222ee2167 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -26,16 +26,17 @@ end STANDARDSCROLL = { STANDARDSCROLL_UP = -1, + KEYBOARD_CURSOR_UP = -1, + CONTEXT_SCROLL_UP = -1, STANDARDSCROLL_DOWN = 1, + KEYBOARD_CURSOR_DOWN = 1, + CONTEXT_SCROLL_DOWN = 1, STANDARDSCROLL_PAGEUP = '-page', + KEYBOARD_CURSOR_UP_FAST = '-page', + CONTEXT_SCROLL_PAGEUP = '-page', STANDARDSCROLL_PAGEDOWN = '+page', -} - -SECONDSCROLL = { - SECONDSCROLL_UP = -1, - SECONDSCROLL_DOWN = 1, - SECONDSCROLL_PAGEUP = '-page', - SECONDSCROLL_PAGEDOWN = '+page', + KEYBOARD_CURSOR_DOWN_FAST = '+page', + CONTEXT_SCROLL_PAGEDOWN = '+page', } ------------ @@ -677,22 +678,20 @@ function EditField:onInput(keys) return true end - if keys.SELECT then - if self.key then - self:setFocus(false) - end - if self.on_submit then - self.on_submit(self.text) - return true - end - return not not self.key - elseif keys.SEC_SELECT then + if keys.SELECT or keys.CUSTOM_SHIFT_ENTER then if self.key then self:setFocus(false) end - if self.on_submit2 then - self.on_submit2(self.text) - return true + if keys.CUSTOM_SHIFT_ENTER then + if self.on_submit2 then + self.on_submit2(self.text) + return true + end + else + if self.on_submit then + self.on_submit(self.text) + return true + end end return not not self.key elseif keys._MOUSE_L then @@ -723,25 +722,25 @@ function EditField:onInput(keys) self.on_change(self.text, old) end return true - elseif keys.CURSOR_LEFT then + elseif keys.KEYBOARD_CURSOR_LEFT then self:setCursor(self.cursor - 1) return true - elseif keys.A_MOVE_W_DOWN then -- Ctrl-Left (end of prev word) + elseif keys.CUSTOM_CTRL_B then -- back one word local _, prev_word_end = self.text:sub(1, self.cursor-1): - find('.*[%w_%-][^%w_%-]') + find('.*[%w_%-][^%w_%-]') self:setCursor(prev_word_end or 1) return true - elseif keys.A_CARE_MOVE_W then -- Alt-Left (home) + elseif keys.CUSTOM_CTRL_A then -- home self:setCursor(1) return true - elseif keys.CURSOR_RIGHT then + elseif keys.KEYBOARD_CURSOR_RIGHT then self:setCursor(self.cursor + 1) return true - elseif keys.A_MOVE_E_DOWN then -- Ctrl-Right (beginning of next word) + elseif keys.CUSTOM_CTRL_F then -- forward one word local _,next_word_start = self.text:find('[^%w_%-][%w_%-]', self.cursor) self:setCursor(next_word_start) return true - elseif keys.A_CARE_MOVE_E then -- Alt-Right (end) + elseif keys.CUSTOM_CTRL_E then -- end self:setCursor() return true end @@ -1680,12 +1679,14 @@ end function List:submit() if self.on_submit and #self.choices > 0 then self.on_submit(self:getSelected()) + return true end end function List:submit2() if self.on_submit2 and #self.choices > 0 then self.on_submit2(self:getSelected()) + return true end end @@ -1693,12 +1694,10 @@ function List:onInput(keys) if self:inputToSubviews(keys) then return true end - if self.on_submit and keys.SELECT then - self:submit() - return true - elseif self.on_submit2 and keys.SEC_SELECT then - self:submit2() - return true + if keys.SELECT then + return self:submit() + elseif keys.CUSTOM_SHIFT_ENTER then + return self:submit2() elseif keys._MOUSE_L_DOWN then local idx = self:getIdxUnderMouse() if idx then From 04f2d555c67ca08e9328ba063faf91e87afdb018 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 01:37:22 -0800 Subject: [PATCH 19/51] implement context-aware mouse wheel scrolling --- docs/dev/Lua API.rst | 4 ++++ library/lua/gui/widgets.lua | 24 ++++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index c7994a001..f25eb0f56 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -4377,6 +4377,10 @@ direction. The amount of scrolling done in each case in determined by the associated widget, and after scrolling is complete, the associated widget must call ``scrollbar:update()`` with updated new display info. +If the mouse wheel is scrolled while the mouse is over the Scrollbar widget's +parent view, then the parent is scrolled accordingly. Holding :kbd:`Shift` +while scrolling will result in faster movement. + You can click and drag the scrollbar to scroll to a specific spot, or you can click and hold on the end arrows or in the unfilled portion of the scrollbar to scroll multiple times, just like in a normal browser scrollbar. The speed of diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 222ee2167..f77c31063 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -27,16 +27,12 @@ end STANDARDSCROLL = { STANDARDSCROLL_UP = -1, KEYBOARD_CURSOR_UP = -1, - CONTEXT_SCROLL_UP = -1, STANDARDSCROLL_DOWN = 1, KEYBOARD_CURSOR_DOWN = 1, - CONTEXT_SCROLL_DOWN = 1, STANDARDSCROLL_PAGEUP = '-page', KEYBOARD_CURSOR_UP_FAST = '-page', - CONTEXT_SCROLL_PAGEUP = '-page', STANDARDSCROLL_PAGEDOWN = '+page', KEYBOARD_CURSOR_DOWN_FAST = '+page', - CONTEXT_SCROLL_PAGEDOWN = '+page', } ------------ @@ -934,10 +930,26 @@ function Scrollbar:onRenderBody(dc) end function Scrollbar:onInput(keys) - if not keys._MOUSE_L_DOWN or not self.on_scroll - or not scrollbar_is_visible(self) then + if not self.on_scroll or not scrollbar_is_visible(self) then return false end + + if self.parent_view:getMousePos() then + if keys.CONTEXT_SCROLL_UP then + self.on_scroll('up_small') + return true + elseif keys.CONTEXT_SCROLL_DOWN then + self.on_scroll('down_small') + return true + elseif keys.CONTEXT_SCROLL_PAGEUP then + self.on_scroll('up_large') + return true + elseif keys.CONTEXT_SCROLL_PAGEDOWN then + self.on_scroll('down_large') + return true + end + end + if not keys._MOUSE_L_DOWN then return false end local _,y = self:getMousePos() if not y then return false end local scroll_spec = nil From cb6b595affdd28d1e26900210b7e2bbe0e10c19a Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 01:39:04 -0800 Subject: [PATCH 20/51] update changelog --- docs/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index 2c000262b..eed11d6d6 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -38,6 +38,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Fixes ## Misc Improvements +- Scrollable widgets now react to mouse wheel events when the mouse is over the widget ## Documentation - `overlay-dev-guide`: added troubleshooting tips and common development workflows From 6871bc20c4c821439956366b1d08838ad30401db Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 04:40:10 -0800 Subject: [PATCH 21/51] use new KEYBOARD interface keys in move delta --- library/lua/gui/dwarfmode.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/lua/gui/dwarfmode.lua b/library/lua/gui/dwarfmode.lua index 78b84f441..2686b597e 100644 --- a/library/lua/gui/dwarfmode.lua +++ b/library/lua/gui/dwarfmode.lua @@ -267,6 +267,10 @@ function Viewport:reveal(target,gap,max_scroll,scroll_gap,scroll_z) end MOVEMENT_KEYS = { + KEYBOARD_CURSOR_UP = { 0, -1, 0 }, KEYBOARD_CURSOR_DOWN = { 0, 1, 0 }, + KEYBOARD_CURSOR_LEFT = { -1, 0, 0 }, KEYBOARD_CURSOR_RIGHT = { 1, 0, 0 }, + KEYBOARD_CURSOR_UP_FAST = { 0, -1, 0, true }, KEYBOARD_CURSOR_DOWN_FAST = { 0, 1, 0, true }, + KEYBOARD_CURSOR_LEFT_FAST = { -1, 0, 0, true }, KEYBOARD_CURSOR_RIGHT_FAST = { 1, 0, 0, true }, CURSOR_UP = { 0, -1, 0 }, CURSOR_DOWN = { 0, 1, 0 }, CURSOR_LEFT = { -1, 0, 0 }, CURSOR_RIGHT = { 1, 0, 0 }, CURSOR_UPLEFT = { -1, -1, 0 }, CURSOR_UPRIGHT = { 1, -1, 0 }, From 3a76fc086fe527d31a5e6b686a457079082e26cc Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 04:40:50 -0800 Subject: [PATCH 22/51] fix keyboard movement of Panel widgets --- library/lua/gui/widgets.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index f77c31063..4af3cf9ad 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -363,8 +363,10 @@ function Panel:setKeyboardDragEnabled(enabled) return end if enabled then - local kbd_get_pos = function() return {x=0, y=0} end - Panel_begin_drag(self, kbd_get_pos()) + local kbd_get_pos = function() + return {x=self.frame_rect.x1, y=self.frame_rect.y1} + end + Panel_begin_drag(self) self.kbd_get_pos = kbd_get_pos else Panel_end_drag(self) From 21f137644f47d0c8550268f86cc8e23de2ff7bd0 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 05:40:57 -0800 Subject: [PATCH 23/51] remove trailing whitespace --- library/lua/gui/widgets.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 4af3cf9ad..592efca74 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -935,7 +935,7 @@ function Scrollbar:onInput(keys) if not self.on_scroll or not scrollbar_is_visible(self) then return false end - + if self.parent_view:getMousePos() then if keys.CONTEXT_SCROLL_UP then self.on_scroll('up_small') From cf65f48aa08db776deeb5c90ef4e0fed2813662f Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 22:34:19 -0800 Subject: [PATCH 24/51] don't use defunct MENU_CONFIRM keybinding --- library/lua/gui/dialogs.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lua/gui/dialogs.lua b/library/lua/gui/dialogs.lua index 0421ff365..e5448986f 100644 --- a/library/lua/gui/dialogs.lua +++ b/library/lua/gui/dialogs.lua @@ -48,7 +48,7 @@ end function MessageBox:onRenderFrame(dc,rect) MessageBox.super.onRenderFrame(self,dc,rect) if self.on_accept then - dc:seek(rect.x1+2,rect.y2):key('LEAVESCREEN'):string('/'):key('MENU_CONFIRM') + dc:seek(rect.x1+2,rect.y2):key('LEAVESCREEN'):string('/'):key('SELECT') end end From a53e94379659f432c512ef11db1cf5cff12e09da Mon Sep 17 00:00:00 2001 From: DFHack-Urist via GitHub Actions <63161697+DFHack-Urist@users.noreply.github.com> Date: Sat, 31 Dec 2022 07:13:14 +0000 Subject: [PATCH 25/51] Auto-update submodules scripts: master --- scripts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts b/scripts index e64d86728..75bb06c7f 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit e64d86728f25f22871e47beb52ad1177aef5e043 +Subproject commit 75bb06c7f70adc415125013ec05b42b4e28efdfa From 5232e2b04ed04ca1d1f5eee94bb1fe1f351be8de Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 23:30:11 -0800 Subject: [PATCH 26/51] add dfhack-config/scripts to default script paths --- docs/Core.rst | 22 +++++++++++++--------- docs/changelog.txt | 1 + docs/dev/Lua API.rst | 24 +++++++++--------------- docs/guides/modding-guide.rst | 7 ++++--- library/Core.cpp | 1 + 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/docs/Core.rst b/docs/Core.rst index 2296d1ab7..4fb1fdb71 100644 --- a/docs/Core.rst +++ b/docs/Core.rst @@ -21,10 +21,11 @@ DFHack commands can be implemented in any of three ways: same version of DFHack. They are less flexible than scripts, but used for complex or ongoing tasks because they run faster. -:scripts: are Ruby or Lua scripts stored in ``hack/scripts/``. - Because they don't need to be compiled, scripts are - more flexible about versions, and easier to distribute. - Most third-party DFHack addons are scripts. +:scripts: are Ruby or Lua scripts stored in ``hack/scripts/`` or other + directories in the `script-paths`. Because they don't need to + be compiled, scripts are more flexible about versions, and + they are easier to distribute. Most third-party DFHack addons + are scripts. All tools distributed with DFHack are documented `here `. @@ -37,6 +38,8 @@ DFHack commands can be executed in a number of ways: #. Pressing a key combination set up with `keybinding` #. From one of several `init-files`, automatically #. Using `script` to run a batch of commands from a file +#. From an in-game command launcher interface like `gui/launcher`, the + `hotkeys` overlay widget, or `gui/quickcmd`. The DFHack console ------------------ @@ -144,7 +147,7 @@ save-specific init files in the save folders. DFHack looks for init files in three places each time they could be run: #. The :file:`dfhack-config/init` subdirectory in the main DF directory -#. :file:`data/save/{world}/raw`, where ``world`` is the current save, and +#. :file:`data/save/{world}/raw`, where ``{world}`` is the current save, and #. :file:`data/save/{world}/raw/objects` For each of those directories, all matching init files will be executed in @@ -171,7 +174,7 @@ dfhack\*.init On startup, DFHack looks for files of the form ``dfhack*.init`` (where ``*`` is a placeholder for any string, including the empty string). -These files are best used for keybindings and enabling persistent plugins +These files are best used for keybindings and enabling persistent tools which do not require a world to be loaded. @@ -230,9 +233,10 @@ Script paths are folders that DFHack searches to find a script when a command is run. By default, the following folders are searched, in order (relative to the root DF folder): -1. :file:`data/save/{}/raw/scripts` (only if a save is loaded) -2. :file:`raw/scripts` -3. :file:`hack/scripts` +#. :file:`dfhack-config/scripts` +#. :file:`data/save/{}/raw/scripts` (only if a save is loaded) +#. :file:`raw/scripts` +#. :file:`hack/scripts` For example, if ``teleport`` is run, these folders are searched in order for ``teleport.lua`` or ``teleport.rb``, and the first matching file is run. diff --git a/docs/changelog.txt b/docs/changelog.txt index eed11d6d6..19f548f30 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -39,6 +39,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Misc Improvements - Scrollable widgets now react to mouse wheel events when the mouse is over the widget +- the ``dfhack-config/scripts/`` folder is now searched for scripts by default ## Documentation - `overlay-dev-guide`: added troubleshooting tips and common development workflows diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 5a9784d24..d1833f600 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -2629,8 +2629,8 @@ and are only documented here for completeness: Registers ``path`` as a `script path `. If ``search_before`` is passed and ``true``, the path will be searched before - the default paths (e.g. ``raw/scripts``, ``hack/scripts``); otherwise, it will - be searched after. + the default paths (e.g. ``dfhack-config/scripts``, ``hack/scripts``); otherwise, + it will be searched after. Returns ``true`` if successful or ``false`` otherwise (e.g. if the path does not exist or has already been registered). @@ -5466,11 +5466,11 @@ Scripts :local: Any files with the ``.lua`` extension placed into the :file:`hack/scripts` folder -are automatically made available as DFHack commands. The command corresponding to -a script is simply the script's filename, relative to the scripts folder, with -the extension omitted. For example: +(or any other folder in your `script-paths`) are automatically made available as +DFHack commands. The command corresponding to a script is simply the script's +filename, relative to the scripts folder, with the extension omitted. For example: -* :file:`hack/scripts/add-thought.lua` is invoked as ``add-thought`` +* :file:`dfhack-config/scripts/startup.lua` is invoked as ``startup`` * :file:`hack/scripts/gui/teleport.lua` is invoked as ``gui/teleport`` .. note:: @@ -5487,12 +5487,6 @@ the extension omitted. For example: a mod developer would want to run a script from the console, it should not be placed in this folder) -Scripts can also be placed in other folders - by default, these include -:file:`raw/scripts` and :file:`data/save/{region}/raw/scripts`, but additional -folders can be added (for example, a copy of the -:source-scripts:`scripts repository <>` for local development). See -`script-paths` for more information on how to configure this behavior. - Scripts are read from disk when run for the first time, or if they have changed since the last time they were run. @@ -5520,7 +5514,7 @@ General script API * ``dfhack.run_script(name[,args...])`` - Run a Lua script in :file:`hack/scripts/`, as if it were started from the + Run a Lua script in your `script-paths`, as if it were started from the DFHack command-line. The ``name`` argument should be the name of the script without its extension, as it would be used on the command line. @@ -5562,8 +5556,8 @@ Importing scripts Loads a Lua script and returns its environment (i.e. a table of all global functions and variables). This is similar to the built-in ``require()``, but - searches all script paths for the first matching ``name.lua`` file instead - of searching the Lua library paths (like ``hack/lua``). + searches all `script-paths` for the first matching ``name.lua`` file instead + of searching the Lua library paths (like ``hack/lua/``). Most scripts can be made to support ``reqscript()`` without significant changes (in contrast, ``require()`` requires the use of ``mkmodule()`` and diff --git a/docs/guides/modding-guide.rst b/docs/guides/modding-guide.rst index e602e632d..9fe62bf6a 100644 --- a/docs/guides/modding-guide.rst +++ b/docs/guides/modding-guide.rst @@ -60,9 +60,10 @@ For scripts with the same name, the `order of precedence ` will be: 1. ``own-scripts/`` -2. ``data/save/*/raw/scripts/`` -3. ``raw/scripts/`` -4. ``hack/scripts/`` +2. ``dfhack-config/scripts/`` +3. ``data/save/*/raw/scripts/`` +4. ``raw/scripts/`` +5. ``hack/scripts/`` The structure of the game ------------------------- diff --git a/library/Core.cpp b/library/Core.cpp index 5b53db98f..bf16d4a7e 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -487,6 +487,7 @@ void Core::getScriptPaths(std::vector *dest) string df_path = this->p->getPath(); for (auto it = script_paths[0].begin(); it != script_paths[0].end(); ++it) dest->push_back(*it); + dest->push_back(df_path + "/dfhack-config/scripts"); if (df::global::world && isWorldLoaded()) { string save = World::ReadWorldFolder(); if (save.size()) From f509173a70eda718307698fcb26edeff4db58bc9 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Fri, 30 Dec 2022 23:39:10 -0800 Subject: [PATCH 27/51] create dfhack-config/scripts dir and add README.md --- dfhack-config/scripts/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 dfhack-config/scripts/README.md diff --git a/dfhack-config/scripts/README.md b/dfhack-config/scripts/README.md new file mode 100644 index 000000000..95b67b058 --- /dev/null +++ b/dfhack-config/scripts/README.md @@ -0,0 +1,7 @@ +You can put scripts you write or download in this folder and DFHack will find +them. + +If a script in this directory has the same name as a default DFHack script, the + script in this directory will take precedence. + +Everything you add to this folder will be kept safe when you upgrade DFHack. From c401154393062d40007d9473c261905b00697b49 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 31 Dec 2022 21:02:00 -0800 Subject: [PATCH 28/51] widgets inherit from Panel and can be perma-enabled --- docs/dev/Lua API.rst | 2 ++ docs/dev/overlay-dev-guide.rst | 6 +++++- plugins/lua/overlay.lua | 6 ++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 5a9784d24..417fffbf0 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -4154,6 +4154,8 @@ Base of all the widgets. Inherits from View and has the following attributes: The pen to fill the outer frame with. Defaults to no fill. +.. _panel: + Panel class ----------- diff --git a/docs/dev/overlay-dev-guide.rst b/docs/dev/overlay-dev-guide.rst index e6147f8c3..bce623180 100644 --- a/docs/dev/overlay-dev-guide.rst +++ b/docs/dev/overlay-dev-guide.rst @@ -38,7 +38,7 @@ Overlay widget API ------------------ Overlay widgets are Lua classes that inherit from ``overlay.OverlayWidget`` -(which itself inherits from `widgets.Widget `). The regular +(which itself inherits from `widgets.Panel `). The regular ``onInput(keys)``, ``onRenderFrame(dc, frame_rect)``, and ``onRenderBody(dc)`` functions work as normal, and they are called when the viewscreen that the widget is associated with does its usual input and render processing. The widget @@ -125,6 +125,10 @@ The ``overlay.OverlayWidget`` superclass defines the following class attributes: not annoy the player. Set to 0 to be called at the maximum rate. Be aware that running more often than you really need to will impact game FPS, especially if your widget can run while the game is unpaused. +- ``always_enabled`` (default: ``false``) + Set this to ``true`` if you don't want to let the user disable the widget. + This is useful for widgets that are controlled purely through their + triggers. See `gui/pathable` for an example. Registering a widget with the overlay framework *********************************************** diff --git a/plugins/lua/overlay.lua b/plugins/lua/overlay.lua index 9f2c9029b..57100b85b 100644 --- a/plugins/lua/overlay.lua +++ b/plugins/lua/overlay.lua @@ -177,6 +177,7 @@ end local function do_disable(args, quiet) local disable_fn = function(name, db_entry) + if db_entry.widget.always_enabled then return end overlay_config[name].enabled = false if db_entry.widget.hotspot then active_hotspot_widgets[name] = nil @@ -244,7 +245,7 @@ local function load_widget(name, widget_class) local config = overlay_config[name] config.pos = sanitize_pos(config.pos or widget.default_pos) widget.frame = make_frame(config.pos, widget.frame) - if config.enabled then + if config.enabled or widget.always_enabled then do_enable(name, true, true) else config.enabled = false @@ -461,7 +462,7 @@ end -- OverlayWidget (base class of all overlay widgets) -- -- ------------------------------------------------- -- -OverlayWidget = defclass(OverlayWidget, widgets.Widget) +OverlayWidget = defclass(OverlayWidget, widgets.Panel) OverlayWidget.ATTRS{ name=DEFAULT_NIL, -- this is set by the framework to the widget name default_pos={x=DEFAULT_X_POS, y=DEFAULT_Y_POS}, -- 1-based widget screen pos @@ -469,6 +470,7 @@ OverlayWidget.ATTRS{ hotspot=false, -- whether to call overlay_onupdate on all screens viewscreens={}, -- override with associated viewscreen or list of viewscrens overlay_onupdate_max_freq_seconds=5, -- throttle calls to overlay_onupdate + always_enabled=false, -- for overlays that should never be disabled } function OverlayWidget:init() From 481bbb9df4a36e41513679eeb4749af3acc78fd1 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 31 Dec 2022 21:04:19 -0800 Subject: [PATCH 29/51] update changelog --- docs/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.txt b/docs/changelog.txt index eed11d6d6..442476f09 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -50,6 +50,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - ``gui.View``: ``visible`` and ``active`` can now be functions that return a boolean - ``widgets.Panel``: new attributes to control window dragging and resizing with mouse or keyboard - ``widgets.Window``: Panel subclass with attributes preset for top-level windows +- `overlay`: ``OverlayWidget`` now inherits from ``Panel`` instead of ``Widget`` to get all the frame and mouse integration goodies ## Internals From 11333e3872442810fd5b61eb23d39cfe8cd74bf5 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 31 Dec 2022 21:05:03 -0800 Subject: [PATCH 30/51] update pathable plugin to support v50 maps --- plugins/CMakeLists.txt | 2 +- plugins/lua/pathable.lua | 2 +- plugins/pathable.cpp | 114 ++++++++++++++++++++++----------------- 3 files changed, 66 insertions(+), 52 deletions(-) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index dd5000ab5..1d51dc354 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -141,7 +141,7 @@ dfhack_plugin(hotkeys hotkeys.cpp LINK_LIBRARIES lua) #dfhack_plugin(nestboxes nestboxes.cpp) #dfhack_plugin(orders orders.cpp LINK_LIBRARIES jsoncpp_static) dfhack_plugin(overlay overlay.cpp LINK_LIBRARIES lua) -#dfhack_plugin(pathable pathable.cpp LINK_LIBRARIES lua) +dfhack_plugin(pathable pathable.cpp LINK_LIBRARIES lua) #dfhack_plugin(petcapRemover petcapRemover.cpp) #dfhack_plugin(plants plants.cpp) #dfhack_plugin(probe probe.cpp) diff --git a/plugins/lua/pathable.lua b/plugins/lua/pathable.lua index b5f5addfc..f3247cffe 100644 --- a/plugins/lua/pathable.lua +++ b/plugins/lua/pathable.lua @@ -2,7 +2,7 @@ local _ENV = mkmodule('plugins.pathable') --[[ -Native functions: (see Plugins.rst for details) +Native functions: (see docs/dev/Lua API.rst for details) - paintScreen(cursor[,skip_unrevealed]) diff --git a/plugins/pathable.cpp b/plugins/pathable.cpp index e5a9bebcc..9d5ae8bef 100644 --- a/plugins/pathable.cpp +++ b/plugins/pathable.cpp @@ -1,82 +1,96 @@ -#include "Console.h" -#include "Core.h" -#include "DataDefs.h" -#include "DataFuncs.h" -#include "DataIdentity.h" -#include "Export.h" -#include "LuaTools.h" -#include "PluginManager.h" -#include "modules/Gui.h" +#include "df/graphic_viewportst.h" + #include "modules/Maps.h" #include "modules/Screen.h" -#include "df/world.h" + +#include "Debug.h" +#include "LuaTools.h" +#include "PluginManager.h" using namespace DFHack; DFHACK_PLUGIN("pathable"); -REQUIRE_GLOBAL(world); + +REQUIRE_GLOBAL(gps); REQUIRE_GLOBAL(window_x); REQUIRE_GLOBAL(window_y); REQUIRE_GLOBAL(window_z); +REQUIRE_GLOBAL(world); + +namespace DFHack { + DBG_DECLARE(pathable, log, DebugCategory::LINFO); +} -DFhackCExport command_result plugin_init(color_ostream &out, std::vector &commands) -{ +DFhackCExport command_result plugin_init(color_ostream &out, std::vector &commands) { return CR_OK; } -DFhackCExport command_result plugin_shutdown(color_ostream &out) -{ +DFhackCExport command_result plugin_shutdown(color_ostream &out) { return CR_OK; } -static void paintScreen(df::coord cursor, bool skip_unrevealed = false) -{ - auto dims = Gui::getDwarfmodeViewDims(); - for (int y = dims.map_y1; y <= dims.map_y2; y++) - { - for (int x = dims.map_x1; x <= dims.map_x2; x++) - { - Screen::Pen cur_tile = Screen::readTile(x, y, true); - if (!cur_tile.valid()) - continue; +static void paintScreen(df::coord target, bool skip_unrevealed = false) { + DEBUG(log).print("entering paintScreen\n"); + + bool use_graphics = Screen::inGraphicsMode(); - df::coord map_pos( - *window_x + x - dims.map_x1, - *window_y + y - dims.map_y1, - *window_z - ); + auto dimx = use_graphics ? gps->main_viewport->dim_x : gps->dimx; + auto dimy = use_graphics ? gps->main_viewport->dim_y : gps->dimy; + for (int y = 0; y < dimy; ++y) { + for (int x = 0; x < dimx; ++x) { + df::coord map_pos(*window_x + x, *window_y + y, *window_z); - // Keep yellow cursor - if (map_pos == cursor) + if (!Maps::isValidTilePos(map_pos)) continue; - if (map_pos.x < 0 || map_pos.x >= world->map.x_count || - map_pos.y < 0 || map_pos.y >= world->map.y_count || - map_pos.z < 0 || map_pos.z >= world->map.z_count) - { + // don't overwrite the target tile + if (!use_graphics && map_pos == target) { + TRACE(log).print("skipping target tile\n"); continue; } - if (skip_unrevealed && !Maps::isTileVisible(map_pos)) + if (skip_unrevealed && !Maps::isTileVisible(map_pos)) { + TRACE(log).print("skipping hidden tile\n"); continue; + } - int color = Maps::canWalkBetween(cursor, map_pos) ? COLOR_GREEN : COLOR_RED; + DEBUG(log).print("scanning map tile at offset %d, %d\n", x, y); + Screen::Pen cur_tile = Screen::readTile(x, y, true); + DEBUG(log).print("tile data: ch=%d, fg=%d, bg=%d, bold=%s\n", + cur_tile.ch, cur_tile.fg, cur_tile.bg, cur_tile.bold ? "true" : "false"); + DEBUG(log).print("tile data: tile=%d, tile_mode=%d, tile_fg=%d, tile_bg=%d\n", + cur_tile.tile, cur_tile.tile_mode, cur_tile.tile_fg, cur_tile.tile_bg); - if (cur_tile.fg && cur_tile.ch != ' ') - { - cur_tile.fg = color; - cur_tile.bg = 0; - } - else - { - cur_tile.fg = 0; - cur_tile.bg = color; + if (!cur_tile.valid()) { + DEBUG(log).print("cannot read tile at offset %d, %d\n", x, y); + continue; } - cur_tile.bold = false; + bool can_walk = Maps::canWalkBetween(target, map_pos); + DEBUG(log).print("tile is %swalkable at offset %d, %d\n", + can_walk ? "" : "not ", x, y); + + if (use_graphics) { + if (map_pos == target) { + cur_tile.tile = 100711; // highlighted selection + } else{ + cur_tile.tile = can_walk ? 779 : 782; + } + } else { + int color = can_walk ? COLOR_GREEN : COLOR_RED; + if (cur_tile.fg && cur_tile.ch != ' ') { + cur_tile.fg = color; + cur_tile.bg = 0; + } else { + cur_tile.fg = 0; + cur_tile.bg = color; + } - if (cur_tile.tile) - cur_tile.tile_mode = Screen::Pen::CharColor; + cur_tile.bold = false; + + if (cur_tile.tile) + cur_tile.tile_mode = Screen::Pen::CharColor; + } Screen::paintTile(cur_tile, x, y, true); } From a6294c24fb4419679ac350052c0742f7f521b6c9 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 31 Dec 2022 21:00:44 -0800 Subject: [PATCH 31/51] implement Screen::paintTile and readTile --- library/modules/Screen.cpp | 105 +++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 28 deletions(-) diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index 685802019..b77de0d2a 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -116,7 +116,12 @@ bool Screen::inGraphicsMode() } static bool doSetTile_map(const Pen &pen, int x, int y) { + size_t max_index = gps->main_viewport->dim_x * gps->main_viewport->dim_y - 1; size_t index = (x * gps->main_viewport->dim_y) + y; + + if (index < 0 || index > max_index) + return false; + long texpos = pen.tile; if (texpos == 0) { texpos = init->font.large_font_texpos[(uint8_t)pen.ch]; @@ -207,39 +212,83 @@ bool Screen::paintTile(const Pen &pen, int x, int y, bool map) return true; } -static Pen doGetTile_default(int x, int y, bool map) -{ - auto dim = Screen::getWindowSize(); - if (x < 0 || x >= dim.x || y < 0 || y >= dim.y) - return Pen(0,0,0,-1); +static Pen doGetTile_map(int x, int y) { + size_t max_index = gps->main_viewport->dim_x * gps->main_viewport->dim_y - 1; + size_t index = (x * gps->main_viewport->dim_y) + y; -/* TODO: understand how this changes for v50 - int index = x*dim.y + y; - auto screen = gps->screen + index*4; - if (screen[3] & 0x80) - return Pen(0,0,0,-1); + if (index < 0 || index > max_index) + return Pen(0, 0, 0, -1); + + int tile = gps->main_viewport->screentexpos[index]; + if (tile == 0) + tile = gps->main_viewport->screentexpos_item[index]; + if (tile == 0) + tile = gps->main_viewport->screentexpos_building_one[index]; + if (tile == 0) + tile = gps->main_viewport->screentexpos_background_two[index]; + if (tile == 0) + tile = gps->main_viewport->screentexpos_background[index]; + + char ch = 0; + uint8_t fg = 0; + uint8_t bg = 0; + return Pen(ch, fg, bg, tile, false); +} + +static uint8_t to_16_bit_color(uint8_t *rgb) { + for (uint8_t c = 0; c < 16; ++c) { + if (rgb[0] == gps->uccolor[c][0] && + rgb[1] == gps->uccolor[c][1] && + rgb[2] == gps->uccolor[c][2]) { + return c; + } + } + return 0; +} - Pen pen( - screen[0], screen[1], screen[2], screen[3]?true:false, - gps->screentexpos[index] - ); +static Pen doGetTile_default(int x, int y, bool map) { + if (x < 0 || y < 0) + return Pen(0, 0, 0, -1); - if (pen.tile) - { - if (gps->screentexpos_grayscale[index]) - { - pen.tile_mode = Screen::Pen::TileColor; - pen.tile_fg = gps->screentexpos_cf[index]; - pen.tile_bg = gps->screentexpos_cbr[index]; - } - else if (gps->screentexpos_addcolor[index]) - { - pen.tile_mode = Screen::Pen::CharColor; - } + bool use_graphics = Screen::inGraphicsMode(); + + if (map && use_graphics) + return doGetTile_map(x, y); + + size_t index = (x * gps->dimy) + y; + uint8_t *screen = &gps->screen[index * 8]; + + if (screen > gps->screen_limit) + return Pen(0, 0, 0, -1); + + long *texpos = &gps->screentexpos[index]; + uint32_t *flag = &gps->screentexpos_flag[index]; + + if (gps->top_in_use && + (gps->screen_top[index * 8] || + (use_graphics && gps->screentexpos_top[index]))) { + screen = &gps->screen_top[index * 8]; + texpos = &gps->screentexpos_top[index]; + flag = &gps->screentexpos_top_flag[index]; + } + + char ch = *screen; + uint8_t fg = to_16_bit_color(&screen[1]); + uint8_t bg = to_16_bit_color(&screen[4]); + int tile = 0; + if (use_graphics) + tile = *texpos; + + if (*flag & 1) { + // TileColor + return Pen(ch, fg&7, bg, !!(fg&8), tile, fg, bg); + } else if (*flag & 2) { + // CharColor + return Pen(ch, fg, bg, tile, true); } - return pen; -*/ return Pen(0,0,0,-1); + // AsIs + return Pen(ch, fg, bg, tile, false); } GUI_HOOK_DEFINE(Screen::Hooks::get_tile, doGetTile_default); From 7d5d2d0a9bf274e9aca955ef8450a4775c471314 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 31 Dec 2022 22:49:30 -0800 Subject: [PATCH 32/51] clear out obsolete area map and menu logic in particular, return the correct map dimensions in getDwarfmodeDims() --- docs/changelog.txt | 1 + docs/dev/Lua API.rst | 2 +- library/LuaApi.cpp | 9 ------ library/include/modules/Gui.h | 17 +--------- library/lua/gui/dwarfmode.lua | 25 ++------------ library/modules/Gui.cpp | 61 ++++------------------------------- 6 files changed, 12 insertions(+), 103 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index eed11d6d6..967287970 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -45,6 +45,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: - added DFHack architecture diagrams to the dev intro ## API +- ``Gui::getDwarfmodeDims``: now only returns map viewport dimensions; menu dimensions are obsolete ## Lua - ``gui.View``: ``visible`` and ``active`` can now be functions that return a boolean diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 5a9784d24..1b955870a 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -1011,7 +1011,7 @@ Fortress mode * ``dfhack.gui.getDwarfmodeViewDims()`` - Returns dimensions of the main fortress mode screen. See ``getPanelLayout()`` + Returns dimensions of the displayed map viewport. See ``getPanelLayout()`` in the ``gui.dwarfmode`` module for a more Lua-friendly version. * ``dfhack.gui.resetDwarfmodeView([pause])`` diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index 31a6ee753..1352b7f1a 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1436,17 +1436,8 @@ static int gui_getDwarfmodeViewDims(lua_State *state) lua_newtable(state); Lua::TableInsert(state, "map_x1", dims.map_x1); Lua::TableInsert(state, "map_x2", dims.map_x2); - Lua::TableInsert(state, "menu_x1", dims.menu_x1); - Lua::TableInsert(state, "menu_x2", dims.menu_x2); - Lua::TableInsert(state, "area_x1", dims.area_x1); - Lua::TableInsert(state, "area_x2", dims.area_x2); - Lua::TableInsert(state, "y1", dims.y1); - Lua::TableInsert(state, "y2", dims.y2); Lua::TableInsert(state, "map_y1", dims.map_y1); Lua::TableInsert(state, "map_y2", dims.map_y2); - Lua::TableInsert(state, "menu_on", dims.menu_on); - Lua::TableInsert(state, "area_on", dims.area_on); - Lua::TableInsert(state, "menu_forced", dims.menu_forced); return 1; } diff --git a/library/include/modules/Gui.h b/library/include/modules/Gui.h index d0b6f4d15..3ce2df0eb 100644 --- a/library/include/modules/Gui.h +++ b/library/include/modules/Gui.h @@ -143,13 +143,10 @@ namespace DFHack static const int MENU_WIDTH = 30; struct DwarfmodeDims { - int map_x1, map_x2, menu_x1, menu_x2, area_x1, area_x2; - int y1, y2; + int map_x1, map_x2; int map_y1, map_y2; - bool menu_on, area_on, menu_forced; rect2d map() { return mkrect_xy(map_x1, map_y1, map_x2, map_y2); } - rect2d menu() { return mkrect_xy(menu_x1, y1, menu_x2, y2); } }; DFHACK_EXPORT DwarfmodeDims getDwarfmodeViewDims(); @@ -198,18 +195,6 @@ namespace DFHack /// get the size of the window buffer DFHACK_EXPORT bool getWindowSize(int32_t & width, int32_t & height); - /** - *Menu width: - *3:3 - menu and area map closed - *2:3 - menu open single width - *1:3 - menu open double width - *1:2 - menu and area map open - *2:2 - area map open - */ - - DFHACK_EXPORT bool getMenuWidth(uint8_t & menu_width, uint8_t & area_map_width); - DFHACK_EXPORT bool setMenuWidth(const uint8_t menu_width, const uint8_t area_map_width); - namespace Hooks { GUI_HOOK_DECLARE(depth_at, int, (int32_t x, int32_t y)); GUI_HOOK_DECLARE(dwarfmode_view_dims, DwarfmodeDims, ()); diff --git a/library/lua/gui/dwarfmode.lua b/library/lua/gui/dwarfmode.lua index 2686b597e..7ac29e04e 100644 --- a/library/lua/gui/dwarfmode.lua +++ b/library/lua/gui/dwarfmode.lua @@ -71,30 +71,9 @@ end function getPanelLayout() local dims = dfhack.gui.getDwarfmodeViewDims() - local area_pos = df.global.ui_menu_width[1] - local menu_pos = df.global.ui_menu_width[0] - - if dims.menu_forced then - menu_pos = area_pos - 1 - end - - local rv = { - menu_pos = menu_pos, - area_pos = area_pos, - map = gui.mkdims_xy(dims.map_x1, dims.map_y1, dims.map_x2, dims.map_y2), + return { + map=gui.mkdims_xy(dims.map_x1, dims.map_y1, dims.map_x2, dims.map_y2), } - - if dims.menu_forced then - rv.menu_forced = true - end - if dims.menu_on then - rv.menu = gui.mkdims_xy(dims.menu_x1, dims.y1, dims.menu_x2, dims.y2) - end - if dims.area_on then - rv.area_map = gui.mkdims_xy(dims.area_x1, dims.y1, dims.area_x2, dims.y2) - end - - return rv end function getCursorPos() diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index c436a0ca5..46e0a7c22 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -1919,47 +1919,14 @@ Gui::DwarfmodeDims getDwarfmodeViewDims_default() { Gui::DwarfmodeDims dims; - auto ws = Screen::getWindowSize(); - dims.y1 = 1; - dims.y2 = ws.y-2; + bool use_graphics = Screen::inGraphicsMode(); + auto dimx = use_graphics ? gps->main_viewport->dim_x : gps->dimx; + auto dimy = use_graphics ? gps->main_viewport->dim_y : gps->dimy; - dims.map_x1 = 1; - dims.map_x2 = ws.x-2; - dims.map_y1 = dims.y1; - dims.map_y2 = dims.y2; - - dims.area_x1 = dims.area_x2 = dims.menu_x1 = dims.menu_x2 = -1; - dims.menu_forced = false; - - int menu_pos = (ui_menu_width ? (*ui_menu_width)[0] : 2); - int area_pos = (ui_menu_width ? (*ui_menu_width)[1] : 3); - - if (ui && ui->main.mode != ui_sidebar_mode::Default && ui->main.mode != ui_sidebar_mode::ArenaWeather && menu_pos >= area_pos) - { - dims.menu_forced = true; - menu_pos = area_pos-1; - } - - dims.area_on = (area_pos < 3); - dims.menu_on = (menu_pos < area_pos); - - if (dims.menu_on) - { - dims.menu_x2 = ws.x - 2; - dims.menu_x1 = dims.menu_x2 - Gui::MENU_WIDTH + 1; - if (menu_pos == 1) - dims.menu_x1 -= Gui::AREA_MAP_WIDTH + 1; - dims.map_x2 = dims.menu_x1 - 2; - } - if (dims.area_on) - { - dims.area_x2 = ws.x-2; - dims.area_x1 = dims.area_x2 - Gui::AREA_MAP_WIDTH + 1; - if (dims.menu_on) - dims.menu_x2 = dims.area_x1 - 2; - else - dims.map_x2 = dims.area_x1 - 2; - } + dims.map_x1 = 0; + dims.map_x2 = dimx - 1; + dims.map_y1 = 0; + dims.map_y2 = dimy - 1; return dims; } @@ -2199,17 +2166,3 @@ bool Gui::getWindowSize (int32_t &width, int32_t &height) return false; } } - -bool Gui::getMenuWidth(uint8_t &menu_width, uint8_t &area_map_width) -{ - menu_width = (*ui_menu_width)[0]; - area_map_width = (*ui_menu_width)[1]; - return true; -} - -bool Gui::setMenuWidth(const uint8_t menu_width, const uint8_t area_map_width) -{ - (*ui_menu_width)[0] = menu_width; - (*ui_menu_width)[1] = area_map_width; - return true; -} From 44b2515b896b599fefa169d0ae524c00308d838e Mon Sep 17 00:00:00 2001 From: DFHack-Urist via GitHub Actions <63161697+DFHack-Urist@users.noreply.github.com> Date: Sun, 1 Jan 2023 07:13:16 +0000 Subject: [PATCH 33/51] Auto-update submodules scripts: master --- scripts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts b/scripts index 75bb06c7f..4067484ce 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit 75bb06c7f70adc415125013ec05b42b4e28efdfa +Subproject commit 4067484ce9f96c375c6e746706c51c0d64717f0e From a123452eba48033dc4e7d8be5f9e92b783018564 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sat, 31 Dec 2022 23:20:46 -0800 Subject: [PATCH 34/51] use dims from DwarfmodeDims now that they're fixed --- plugins/pathable.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/pathable.cpp b/plugins/pathable.cpp index 9d5ae8bef..344388fae 100644 --- a/plugins/pathable.cpp +++ b/plugins/pathable.cpp @@ -1,5 +1,4 @@ -#include "df/graphic_viewportst.h" - +#include "modules/Gui.h" #include "modules/Maps.h" #include "modules/Screen.h" @@ -34,10 +33,9 @@ static void paintScreen(df::coord target, bool skip_unrevealed = false) { bool use_graphics = Screen::inGraphicsMode(); - auto dimx = use_graphics ? gps->main_viewport->dim_x : gps->dimx; - auto dimy = use_graphics ? gps->main_viewport->dim_y : gps->dimy; - for (int y = 0; y < dimy; ++y) { - for (int x = 0; x < dimx; ++x) { + auto dims = Gui::getDwarfmodeViewDims().map(); + for (int y = dims.first.y; y <= dims.second.y; ++y) { + for (int x = dims.first.x; x <= dims.second.x; ++x) { df::coord map_pos(*window_x + x, *window_y + y, *window_z); if (!Maps::isValidTilePos(map_pos)) From aa091ed37e94d56d58892b0e7edff58741e8cd9a Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 1 Jan 2023 00:45:14 -0800 Subject: [PATCH 35/51] overwrite anchored textures where we actually touch their anchor --- library/modules/Screen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index b77de0d2a..e7f6cea93 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -150,6 +150,7 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map) *screen = 0; *texpos = 0; *texpos_lower = 0; + gps->screentexpos_anchored[index] = 0; // keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE so occluded anchored textures // don't appear corrupted *flag &= 4; @@ -163,6 +164,7 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map) *screen = 0; *texpos = 0; *texpos_lower = 0; + gps->screentexpos_top_anchored[index] = 0; *flag &= 4; // keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE } From 218fbdbd452a8c88636448bc16c0454c3d2906c5 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 1 Jan 2023 01:03:42 -0800 Subject: [PATCH 36/51] prep for Quietust's structure updates --- library/Core.cpp | 4 ++++ library/PlugLoad-windows.cpp | 1 - library/modules/Burrows.cpp | 4 ++++ library/modules/Gui.cpp | 36 +++++++++++++++++++++++------------- library/modules/Items.cpp | 2 ++ 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/library/Core.cpp b/library/Core.cpp index 5b53db98f..1dae68ebb 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -2266,6 +2266,7 @@ bool Core::ncurses_wgetch(int in, int & out) } if(in >= KEY_F(1) && in <= KEY_F(8)) { +/* TODO: understand how this changes for v50 int idx = in - KEY_F(1); // FIXME: copypasta, push into a method! if(df::global::ui && df::global::gview) @@ -2284,6 +2285,7 @@ bool Core::ncurses_wgetch(int in, int & out) return true; } } +*/ } out = in; return true; @@ -2451,6 +2453,7 @@ bool Core::SelectHotkey(int sym, int modifiers) int idx = sym - SDL::K_F1; if(idx >= 0 && idx < 8) { +/* TODO: understand how this changes for v50 if (modifiers & 1) idx += 8; @@ -2460,6 +2463,7 @@ bool Core::SelectHotkey(int sym, int modifiers) { cmd = df::global::ui->main.hotkeys[idx].name; } +*/ } } } diff --git a/library/PlugLoad-windows.cpp b/library/PlugLoad-windows.cpp index 848d25f50..d6ce8cdbf 100644 --- a/library/PlugLoad-windows.cpp +++ b/library/PlugLoad-windows.cpp @@ -35,7 +35,6 @@ distribution. #include #include "tinythread.h" -#include "../plugins/uicommon.h" /* * Plugin loading functions diff --git a/library/modules/Burrows.cpp b/library/modules/Burrows.cpp index 7d62a53db..52e550960 100644 --- a/library/modules/Burrows.cpp +++ b/library/modules/Burrows.cpp @@ -76,6 +76,7 @@ void Burrows::clearUnits(df::burrow *burrow) burrow->units.clear(); +/* TODO: understand how this changes for v50 // Sync ui if active if (ui && ui->main.mode == ui_sidebar_mode::Burrows && ui->burrows.in_add_units_mode && ui->burrows.sel_id == burrow->id) @@ -85,6 +86,7 @@ void Burrows::clearUnits(df::burrow *burrow) for (size_t i = 0; i < sel.size(); i++) sel[i] = false; } +*/ } bool Burrows::isAssignedUnit(df::burrow *burrow, df::unit *unit) @@ -113,6 +115,7 @@ void Burrows::setAssignedUnit(df::burrow *burrow, df::unit *unit, bool enable) erase_from_vector(burrow->units, unit->id); } +/* TODO: understand how this changes for v50 // Sync ui if active if (ui && ui->main.mode == ui_sidebar_mode::Burrows && ui->burrows.in_add_units_mode && ui->burrows.sel_id == burrow->id) @@ -121,6 +124,7 @@ void Burrows::setAssignedUnit(df::burrow *burrow, df::unit *unit, bool enable) if (idx >= 0) ui->burrows.sel_units[idx] = enable; } +*/ } void Burrows::listBlocks(std::vector *pvec, df::burrow *burrow) diff --git a/library/modules/Gui.cpp b/library/modules/Gui.cpp index c436a0ca5..204ce5e60 100644 --- a/library/modules/Gui.cpp +++ b/library/modules/Gui.cpp @@ -143,6 +143,7 @@ static std::map getFocusStringHandlers DEFINE_GET_FOCUS_STRING_HANDLER(dwarfmode) { +/* TODO: understand how this changes for v50 using namespace df::enums::ui_sidebar_mode; using df::global::ui_workshop_in_add; @@ -315,7 +316,6 @@ DEFINE_GET_FOCUS_STRING_HANDLER(dwarfmode) focus += "/List"; break; -/* TODO: understand how this changes for v50 case Hauling: if (ui->hauling.in_assign_vehicle) { @@ -354,11 +354,11 @@ DEFINE_GET_FOCUS_STRING_HANDLER(dwarfmode) focus += "/Select/" + tag; } break; -*/ default: break; } +*/ } /* TODO: understand how this changes for v50 @@ -667,13 +667,14 @@ bool Gui::cursor_hotkey(df::viewscreen *top) bool Gui::workshop_job_hotkey(df::viewscreen *top) { + if (!dwarfmode_hotkey(top)) + return false; + +/* TODO: understand how this changes for v50 using namespace ui_sidebar_mode; using df::global::ui_workshop_in_add; using df::global::ui_workshop_job_cursor; - if (!dwarfmode_hotkey(top)) - return false; - switch (ui->main.mode) { case QueryBuilding: { @@ -699,16 +700,18 @@ bool Gui::workshop_job_hotkey(df::viewscreen *top) default: return false; } +*/ return false; } bool Gui::build_selector_hotkey(df::viewscreen *top) { - using namespace ui_sidebar_mode; - using df::global::ui_build_selector; - if (!dwarfmode_hotkey(top)) return false; +/* TODO: understand how this changes for v50 + using namespace ui_sidebar_mode; + using df::global::ui_build_selector; + switch (ui->main.mode) { case Build: { @@ -726,20 +729,23 @@ bool Gui::build_selector_hotkey(df::viewscreen *top) default: return false; } +*/ return false; } bool Gui::view_unit_hotkey(df::viewscreen *top) { - using df::global::ui_selected_unit; - if (!dwarfmode_hotkey(top)) return false; +/* TODO: understand how this changes for v50 + using df::global::ui_selected_unit; + if (ui->main.mode != ui_sidebar_mode::ViewUnits) return false; if (!ui_selected_unit) // allow missing return false; return vector_get(world->units.active, *ui_selected_unit) != NULL; +*/ return false; } bool Gui::unit_inventory_hotkey(df::viewscreen *top) @@ -826,6 +832,7 @@ df::job *Gui::getSelectedJob(color_ostream &out, bool quiet) df::unit *Gui::getAnyUnit(df::viewscreen *top) { +/* TODO: understand how this changes for v50 using namespace ui_sidebar_mode; using df::global::ui_look_cursor; using df::global::ui_look_list; @@ -834,7 +841,6 @@ df::unit *Gui::getAnyUnit(df::viewscreen *top) using df::global::ui_building_assign_units; using df::global::ui_building_item_cursor; -/* TODO: understand how this changes for v50 if (VIRTUAL_CAST_VAR(screen, df::viewscreen_unitst, top)) { return screen->unit; @@ -1108,13 +1114,13 @@ df::unit *Gui::getSelectedUnit(color_ostream &out, bool quiet) df::item *Gui::getAnyItem(df::viewscreen *top) { +/* TODO: understand how this changes for v50 using namespace ui_sidebar_mode; using df::global::ui_look_cursor; using df::global::ui_look_list; using df::global::ui_unit_view_mode; using df::global::ui_building_item_cursor; -/* TODO: understand how this changes for v50 if (VIRTUAL_CAST_VAR(screen, df::viewscreen_textviewerst, top)) { // return the main item if the parent screen is a viewscreen_itemst @@ -1248,11 +1254,11 @@ df::item *Gui::getSelectedItem(color_ostream &out, bool quiet) df::building *Gui::getAnyBuilding(df::viewscreen *top) { +/* TODO: understand how this changes for v50 using namespace ui_sidebar_mode; using df::global::ui_look_list; using df::global::ui_look_cursor; -/* TODO: understand how this changes for v50 if (VIRTUAL_CAST_VAR(screen, df::viewscreen_buildinglistst, top)) return vector_get(screen->buildings, screen->cursor); @@ -1324,10 +1330,12 @@ df::plant *Gui::getAnyPlant(df::viewscreen *top) if (!cursor || !ui || !world) return nullptr; +/* TODO: understand how this changes for v50 if (ui->main.mode == ui_sidebar_mode::LookAround) { return Maps::getPlantAtTile(cursor->x, cursor->y, cursor->z); } +*/ } return nullptr; @@ -1978,7 +1986,9 @@ void Gui::resetDwarfmodeView(bool pause) { ui->follow_unit = -1; ui->follow_item = -1; +/* TODO: understand how this changes for v50 ui->main.mode = ui_sidebar_mode::Default; +*/ } if (selection_rect) diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index 14c637dc8..ceb0224e8 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -922,11 +922,13 @@ static bool detachItem(MapExtras::MapCache &mc, df::item *item) case general_ref_type::UNIT_HOLDER: if (auto unit = ref->getUnit()) { +/* TODO: understand how this changes for v50 // Unit view sidebar holds inventory item pointers if (ui->main.mode == ui_sidebar_mode::ViewUnits && (!ui_selected_unit || vector_get(world->units.active, *ui_selected_unit) == unit)) return false; +*/ for (int i = unit->inventory.size()-1; i >= 0; i--) { From bebecec1e55db794d2607af90e41de35a665208e Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 1 Jan 2023 16:32:56 -0800 Subject: [PATCH 37/51] update autobutcher to work with new zoo structures --- plugins/CMakeLists.txt | 2 +- plugins/autobutcher.cpp | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index dd5000ab5..6c2071376 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -80,7 +80,7 @@ set_source_files_properties( Brushes.h PROPERTIES HEADER_FILE_ONLY TRUE ) #dfhack_plugin(3dveins 3dveins.cpp) #dfhack_plugin(add-spatter add-spatter.cpp) -#dfhack_plugin(autobutcher autobutcher.cpp LINK_LIBRARIES lua) +dfhack_plugin(autobutcher autobutcher.cpp LINK_LIBRARIES lua) #dfhack_plugin(autochop autochop.cpp) #dfhack_plugin(autoclothing autoclothing.cpp) #dfhack_plugin(autodump autodump.cpp) diff --git a/plugins/autobutcher.cpp b/plugins/autobutcher.cpp index 81ec0c5df..d75108f3f 100644 --- a/plugins/autobutcher.cpp +++ b/plugins/autobutcher.cpp @@ -712,13 +712,20 @@ static bool hasValidMapPos(df::unit *unit) { && unit->pos.z < world->map.z_count; } -// built cage defined as room (supposed to detect zoo cages) +// built cage in a zone (supposed to detect zoo cages) static bool isInBuiltCageRoom(df::unit *unit) { for (auto building : world->buildings.all) { - // !!! building->isRoom() returns true if the building can be made a room but currently isn't - // !!! except for coffins/tombs which always return false - // !!! using the bool is_room however gives the correct state/value - if (!building->is_room || building->getType() != df::building_type::Cage) + if (building->getType() != df::building_type::Cage) + continue; + + bool in_zone = false; + for (auto relation : building->relations) { + if (relation->getType() == df::building_type::Civzone) { + in_zone = true; + break; + } + } + if (!in_zone) continue; df::building_cagest* cage = (df::building_cagest*)building; From ab5c7708d815425ef393a74c2ff2924e39692349 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 1 Jan 2023 16:35:39 -0800 Subject: [PATCH 38/51] update docs --- docs/plugins/autobutcher.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/plugins/autobutcher.rst b/docs/plugins/autobutcher.rst index f288f9073..1a4aa4f91 100644 --- a/docs/plugins/autobutcher.rst +++ b/docs/plugins/autobutcher.rst @@ -12,7 +12,7 @@ watch list. Units will be ignored if they are: * Untamed * Nicknamed (for custom protection; you can use the `rename` ``unit`` tool individually, or `zone` ``nick`` for groups) -* Caged, if and only if the cage is defined as a room (to protect zoos) +* Caged, if and only if the cage is in a zone (to protect zoos) * Trained for war or hunting Creatures who will not reproduce (because they're not interested in the From 4b8a173ec42937a3c8229703ee01585d991ebc12 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 1 Jan 2023 17:18:39 -0800 Subject: [PATCH 39/51] comment out most keybindings until we figure out what we want to set. now that everything is just one viewscreen, we'll have hotkey overload unless we figure something out. --- data/init/dfhack.keybindings.init | 120 +++++++++++++++--------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/data/init/dfhack.keybindings.init b/data/init/dfhack.keybindings.init index 478b78753..c6620f492 100644 --- a/data/init/dfhack.keybindings.init +++ b/data/init/dfhack.keybindings.init @@ -20,7 +20,7 @@ keybinding add Ctrl-Shift-C hotkeys keybinding add Ctrl-Shift-K gui/cp437-table # an in-game init file editor -keybinding add Alt-S@title|dwarfmode/Default|dungeonmode gui/settings-manager +#keybinding add Alt-S@title|dwarfmode/Default|dungeonmode gui/settings-manager ###################### @@ -28,142 +28,142 @@ keybinding add Alt-S@title|dwarfmode/Default|dungeonmode gui/settings-manager ###################### # quicksave, only in main dwarfmode screen and menu page -keybinding add Ctrl-Alt-S@dwarfmode/Default quicksave +#keybinding add Ctrl-Alt-S@dwarfmode/Default quicksave # toggle the display of water level as 1-7 tiles keybinding add Ctrl-W@dwarfmode|dungeonmode twaterlvl # designate the whole vein for digging -keybinding add Ctrl-V@dwarfmode digv -keybinding add Ctrl-Shift-V@dwarfmode "digv x" +#keybinding add Ctrl-V@dwarfmode digv +#keybinding add Ctrl-Shift-V@dwarfmode "digv x" # clean the selected tile of blood etc -keybinding add Ctrl-C spotclean +#keybinding add Ctrl-C spotclean # destroy the selected item -keybinding add Ctrl-K@dwarfmode autodump-destroy-item +#keybinding add Ctrl-K@dwarfmode autodump-destroy-item # destroy items designated for dump in the selected tile -keybinding add Ctrl-Shift-K@dwarfmode autodump-destroy-here +#keybinding add Ctrl-Shift-K@dwarfmode autodump-destroy-here # apply blueprints to the map (Alt-F for compatibility with LNP Quickfort) -keybinding add Ctrl-Shift-Q@dwarfmode gui/quickfort -keybinding add Alt-F@dwarfmode gui/quickfort +#keybinding add Ctrl-Shift-Q@dwarfmode gui/quickfort +#keybinding add Alt-F@dwarfmode gui/quickfort # show information collected by dwarfmonitor -keybinding add Alt-M@dwarfmode/Default "dwarfmonitor prefs" -keybinding add Ctrl-F@dwarfmode/Default "dwarfmonitor stats" +#keybinding add Alt-M@dwarfmode/Default "dwarfmonitor prefs" +#keybinding add Ctrl-F@dwarfmode/Default "dwarfmonitor stats" # set the zone or cage under the cursor as the default -keybinding add Alt-Shift-I@dwarfmode/Zones "zone set" +#keybinding add Alt-Shift-I@dwarfmode/Zones "zone set" # Stocks plugin -keybinding add Ctrl-Shift-Z@dwarfmode/Default "stocks show" +#keybinding add Ctrl-Shift-Z@dwarfmode/Default "stocks show" # open an overview window summarising some stocks (dfstatus) -keybinding add Ctrl-Shift-I@dwarfmode/Default|dfhack/lua/dfstatus gui/dfstatus +#keybinding add Ctrl-Shift-I@dwarfmode/Default|dfhack/lua/dfstatus gui/dfstatus # change quantity of manager orders -keybinding add Alt-Q@jobmanagement/Main gui/manager-quantity +#keybinding add Alt-Q@jobmanagement/Main gui/manager-quantity # re-check manager orders -keybinding add Alt-R@jobmanagement/Main workorder-recheck +#keybinding add Alt-R@jobmanagement/Main workorder-recheck # set workorder item details (on workorder details screen press D again) -keybinding add D@workquota_details gui/workorder-details +#keybinding add D@workquota_details gui/workorder-details # view combat reports for the selected unit/corpse/spatter -keybinding add Ctrl-Shift-R@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist|workshop_profile view-unit-reports +#keybinding add Ctrl-Shift-R@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist|workshop_profile view-unit-reports # view extra unit information -keybinding add Alt-I@dwarfmode/ViewUnits|unitlist gui/unit-info-viewer +#keybinding add Alt-I@dwarfmode/ViewUnits|unitlist gui/unit-info-viewer # boost priority of jobs related to the selected entity -keybinding add Alt-N@dwarfmode|job|joblist|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist|textviewer|item|layer_assigntrade|tradegoods|store|assign_display_item|treasurelist do-job-now +#keybinding add Alt-N@dwarfmode|job|joblist|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist|textviewer|item|layer_assigntrade|tradegoods|store|assign_display_item|treasurelist do-job-now # export a Dwarf's preferences screen in BBCode to post to a forum -keybinding add Ctrl-Shift-F@textviewer forum-dwarves +#keybinding add Ctrl-Shift-F@textviewer forum-dwarves # q->stockpile - copy & paste stockpiles -keybinding add Alt-P@dwarfmode/QueryBuilding/Some/Stockpile copystock +#keybinding add Alt-P@dwarfmode/QueryBuilding/Some/Stockpile copystock # q->stockpile - load and save stockpile settings out of game -keybinding add Alt-L@dwarfmode/QueryBuilding/Some/Stockpile "gui/stockpiles -load" -keybinding add Alt-S@dwarfmode/QueryBuilding/Some/Stockpile "gui/stockpiles -save" +#keybinding add Alt-L@dwarfmode/QueryBuilding/Some/Stockpile "gui/stockpiles -load" +#keybinding add Alt-S@dwarfmode/QueryBuilding/Some/Stockpile "gui/stockpiles -save" # q->workshop - duplicate the selected job -keybinding add Ctrl-D job-duplicate +#keybinding add Ctrl-D job-duplicate # materials: q->workshop; b->select items -keybinding add Shift-A "job-material ALUNITE" -keybinding add Shift-M "job-material MICROCLINE" -keybinding add Shift-D "job-material DACITE" -keybinding add Shift-R "job-material RHYOLITE" -keybinding add Shift-I "job-material CINNABAR" -keybinding add Shift-B "job-material COBALTITE" -keybinding add Shift-O "job-material OBSIDIAN" -keybinding add Shift-T "job-material ORTHOCLASE" -keybinding add Shift-G "job-material GLASS_GREEN" +#keybinding add Shift-A "job-material ALUNITE" +#keybinding add Shift-M "job-material MICROCLINE" +#keybinding add Shift-D "job-material DACITE" +#keybinding add Shift-R "job-material RHYOLITE" +#keybinding add Shift-I "job-material CINNABAR" +#keybinding add Shift-B "job-material COBALTITE" +#keybinding add Shift-O "job-material OBSIDIAN" +#keybinding add Shift-T "job-material ORTHOCLASE" +#keybinding add Shift-G "job-material GLASS_GREEN" # sort units and items in the on-screen list -keybinding add Alt-Shift-N "sort-units name" "sort-items description" -keybinding add Alt-Shift-R "sort-units arrival" -keybinding add Alt-Shift-T "sort-units profession" "sort-items type material" -keybinding add Alt-Shift-Q "sort-units squad_position" "sort-items quality" +#keybinding add Alt-Shift-N "sort-units name" "sort-items description" +#keybinding add Alt-Shift-R "sort-units arrival" +#keybinding add Alt-Shift-T "sort-units profession" "sort-items type material" +#keybinding add Alt-Shift-Q "sort-units squad_position" "sort-items quality" # browse linked mechanisms -keybinding add Ctrl-M@dwarfmode/QueryBuilding/Some gui/mechanisms +#keybinding add Ctrl-M@dwarfmode/QueryBuilding/Some gui/mechanisms # browse rooms of same owner -keybinding add Alt-R@dwarfmode/QueryBuilding/Some gui/room-list +#keybinding add Alt-R@dwarfmode/QueryBuilding/Some gui/room-list # interface for the liquids plugin - spawn water/magma/obsidian -keybinding add Alt-L@dwarfmode/LookAround gui/liquids +#keybinding add Alt-L@dwarfmode/LookAround gui/liquids # machine power sensitive pressure plate construction -keybinding add Ctrl-Shift-M@dwarfmode/Build/Position/Trap gui/power-meter +#keybinding add Ctrl-Shift-M@dwarfmode/Build/Position/Trap gui/power-meter # siege engine control -keybinding add Alt-A@dwarfmode/QueryBuilding/Some/SiegeEngine gui/siege-engine +#keybinding add Alt-A@dwarfmode/QueryBuilding/Some/SiegeEngine gui/siege-engine # military weapon auto-select -keybinding add Ctrl-W@layer_military/Equip/Customize/View gui/choose-weapons +#keybinding add Ctrl-W@layer_military/Equip/Customize/View gui/choose-weapons # military copy uniform -keybinding add Ctrl-C@layer_military/Uniforms gui/clone-uniform +#keybinding add Ctrl-C@layer_military/Uniforms gui/clone-uniform # minecart Guide path -keybinding add Alt-P@dwarfmode/Hauling/DefineStop/Cond/Guide gui/guide-path +#keybinding add Alt-P@dwarfmode/Hauling/DefineStop/Cond/Guide gui/guide-path # workshop job details -keybinding add Alt-A@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workshop-job +#keybinding add Alt-A@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workshop-job # workflow front-end -keybinding add Alt-W@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workflow -keybinding add Alt-W@overallstatus "gui/workflow status" +#keybinding add Alt-W@dwarfmode/QueryBuilding/Some/Workshop/Job gui/workflow +#keybinding add Alt-W@overallstatus "gui/workflow status" # equivalent to the one above when gui/extended-status is enabled -keybinding add Alt-W@dfhack/lua/status_overlay "gui/workflow status" +#keybinding add Alt-W@dfhack/lua/status_overlay "gui/workflow status" # autobutcher front-end -keybinding add Shift-B@pet/List/Unit gui/autobutcher +#keybinding add Shift-B@pet/List/Unit gui/autobutcher # view pathable tiles from active cursor -keybinding add Alt-Shift-P@dwarfmode/LookAround gui/pathable +#keybinding add Alt-Shift-P@dwarfmode/LookAround gui/pathable # gui/rename script - rename units and buildings -keybinding add Ctrl-Shift-N@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist gui/rename -keybinding add Ctrl-Shift-T@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit "gui/rename unit-profession" +#keybinding add Ctrl-Shift-N@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit|buildinglist gui/rename +#keybinding add Ctrl-Shift-T@dwarfmode|unit|unitlist|joblist|dungeon_monsterstatus|layer_unit_relationship|item|workshop_profile|layer_noblelist|locations|pets|layer_overall_health|textviewer|reportlist|announcelist|layer_military|layer_unit_health|customize_unit "gui/rename unit-profession" ##################### # adv mode bindings # ##################### -keybinding add Ctrl-A@dungeonmode/ConversationSpeak adv-rumors -keybinding add Ctrl-B@dungeonmode adv-bodyswap -keybinding add Ctrl-Shift-B@dungeonmode "adv-bodyswap force" -keybinding add Shift-O@dungeonmode gui/companion-order -keybinding add Ctrl-T@dungeonmode gui/advfort +#keybinding add Ctrl-A@dungeonmode/ConversationSpeak adv-rumors +#keybinding add Ctrl-B@dungeonmode adv-bodyswap +#keybinding add Ctrl-Shift-B@dungeonmode "adv-bodyswap force" +#keybinding add Shift-O@dungeonmode gui/companion-order +#keybinding add Ctrl-T@dungeonmode gui/advfort ######################### @@ -171,4 +171,4 @@ keybinding add Ctrl-T@dungeonmode gui/advfort ######################### # export all information, or just the detailed maps (doesn't handle site maps) -keybinding add Ctrl-A@legends "exportlegends all" +#keybinding add Ctrl-A@legends "exportlegends all" From 09e240b41250fa9b6b495330879893208b7dee37 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 1 Jan 2023 17:20:06 -0800 Subject: [PATCH 40/51] allow overlay widgets to 'all' viewscreens --- plugins/lua/overlay.lua | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/plugins/lua/overlay.lua b/plugins/lua/overlay.lua index 9f2c9029b..a61b5d06a 100644 --- a/plugins/lua/overlay.lua +++ b/plugins/lua/overlay.lua @@ -78,7 +78,9 @@ end -- normalize "short form" viewscreen names to "long form" local function normalize_viewscreen_name(vs_name) - if vs_name:match('viewscreen_.*st') then return vs_name end + if vs_name == 'all' or vs_name:match('viewscreen_.*st') then + return vs_name + end return 'viewscreen_' .. vs_name .. 'st' end @@ -416,18 +418,24 @@ function update_hotspot_widgets() end end --- not subject to trigger lock since these widgets are already filtered by --- viewscreen -function update_viewscreen_widgets(vs_name, vs) +local function _update_viewscreen_widgets(vs_name, vs, now_ms) local vs_widgets = active_viewscreen_widgets[vs_name] if not vs_widgets then return end - local now_ms = dfhack.getTickCount() + now_ms = now_ms or dfhack.getTickCount() for name,db_entry in pairs(vs_widgets) do if do_update(name, db_entry, now_ms, vs) then return end end + return now_ms end -function feed_viewscreen_widgets(vs_name, keys) +-- not subject to trigger lock since these widgets are already filtered by +-- viewscreen +function update_viewscreen_widgets(vs_name, vs) + local now_ms = _update_viewscreen_widgets(vs_name, vs, nil) + _update_viewscreen_widgets('all', vs, now_ms) +end + +local function _feed_viewscreen_widgets(vs_name, keys) local vs_widgets = active_viewscreen_widgets[vs_name] if not vs_widgets then return false end for _,db_entry in pairs(vs_widgets) do @@ -439,16 +447,26 @@ function feed_viewscreen_widgets(vs_name, keys) return false end -function render_viewscreen_widgets(vs_name) +function feed_viewscreen_widgets(vs_name, keys) + return _feed_viewscreen_widgets(vs_name, keys) or + _feed_viewscreen_widgets('all', keys) +end + +local function _render_viewscreen_widgets(vs_name, dc) local vs_widgets = active_viewscreen_widgets[vs_name] if not vs_widgets then return false end - local dc = gui.Painter.new() + dc = dc or gui.Painter.new() for _,db_entry in pairs(vs_widgets) do local w = db_entry.widget detect_frame_change(w, function() w:render(dc) end) end end +function render_viewscreen_widgets(vs_name) + local dc = _render_viewscreen_widgets(vs_name, nil) + _render_viewscreen_widgets('all', dc) +end + -- called when the DF window is resized function reposition_widgets() local sr = get_screen_rect() From 2119d4fb2af05a7a6ee5871336158a7f125e3977 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 1 Jan 2023 17:21:35 -0800 Subject: [PATCH 41/51] attach hotkeys widget to all viewscreens and introduce new snazzy logo --- plugins/lua/hotkeys.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/lua/hotkeys.lua b/plugins/lua/hotkeys.lua index 3ad910495..999527d0d 100644 --- a/plugins/lua/hotkeys.lua +++ b/plugins/lua/hotkeys.lua @@ -13,13 +13,13 @@ HotspotMenuWidget = defclass(HotspotMenuWidget, overlay.OverlayWidget) HotspotMenuWidget.ATTRS{ default_pos={x=1,y=2}, hotspot=true, - viewscreens={'dwarfmode'}, + viewscreens='all', overlay_onupdate_max_freq_seconds=0, frame={w=4, h=3} } function HotspotMenuWidget:init() - self:addviews{widgets.Label{text={'!!!!', NEWLINE, '!!!!', NEWLINE, '!!!!'}}} + self:addviews{widgets.Label{text={'!DF!', NEWLINE, '!Ha!', NEWLINE, '!ck!'}}} self.mouseover = false end From da63d6294ba582a0cb621d04a7cabf0714e29ef7 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 1 Jan 2023 17:55:06 -0800 Subject: [PATCH 42/51] ensure the scrollbar midpoint is always rendered this mimics the vanilla scrollbar behavior (and looks better) --- library/lua/gui/widgets.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 7c1c775ee..cfbf48cbd 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -884,7 +884,7 @@ function Scrollbar:onRenderBody(dc) for y=1,dc.height-2 do dc:seek(0, y) if y >= starty and y <= endy then - if y == starty then + if y == starty and y <= midy - 1 then dc:char(nil, hover_bar and SCROLLBAR_BAR_UP_LEFT_HOVER_PEN or SCROLLBAR_BAR_UP_LEFT_PEN) dc:char(nil, hover_bar and SCROLLBAR_BAR_UP_RIGHT_HOVER_PEN or SCROLLBAR_BAR_UP_RIGHT_PEN) elseif y == midy - 0.5 then @@ -896,7 +896,7 @@ function Scrollbar:onRenderBody(dc) elseif y == midy then dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_LEFT_HOVER_PEN or SCROLLBAR_BAR_CENTER_LEFT_PEN) dc:char(nil, hover_bar and SCROLLBAR_BAR_CENTER_RIGHT_HOVER_PEN or SCROLLBAR_BAR_CENTER_RIGHT_PEN) - elseif y == endy then + elseif y == endy and y >= midy + 1 then dc:char(nil, hover_bar and SCROLLBAR_BAR_DOWN_LEFT_HOVER_PEN or SCROLLBAR_BAR_DOWN_LEFT_PEN) dc:char(nil, hover_bar and SCROLLBAR_BAR_DOWN_RIGHT_HOVER_PEN or SCROLLBAR_BAR_DOWN_RIGHT_PEN) else From 0c2908335b1628b06d06c8352a8c6f135d11cad4 Mon Sep 17 00:00:00 2001 From: DFHack-Urist via GitHub Actions <63161697+DFHack-Urist@users.noreply.github.com> Date: Mon, 2 Jan 2023 07:14:31 +0000 Subject: [PATCH 43/51] Auto-update submodules scripts: master --- scripts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts b/scripts index 4067484ce..b79887aed 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit 4067484ce9f96c375c6e746706c51c0d64717f0e +Subproject commit b79887aed0ed9969f0dd38bb0d6b1b6cb6d281fb From fa2da54852f0430360db7905302ca7b241e494c7 Mon Sep 17 00:00:00 2001 From: DFHack-Urist via GitHub Actions <63161697+DFHack-Urist@users.noreply.github.com> Date: Tue, 3 Jan 2023 07:13:58 +0000 Subject: [PATCH 44/51] Auto-update submodules library/xml: master scripts: master --- library/xml | 2 +- scripts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/xml b/library/xml index c4d78c229..1b1ffd406 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit c4d78c229aa0edd68a69cd5b19d5ad35a5b71098 +Subproject commit 1b1ffd4069652bf189ac0bc229ddf027009c110a diff --git a/scripts b/scripts index b79887aed..2618c86b6 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit b79887aed0ed9969f0dd38bb0d6b1b6cb6d281fb +Subproject commit 2618c86b64a744730673ac60bfda5ba3099cecdc From a0343b06a6440e3997d92f23f11c8472f6ecb336 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Tue, 3 Jan 2023 00:56:07 -0800 Subject: [PATCH 45/51] adjust text wrap to new scrollbar width --- library/lua/gui/widgets.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index cfbf48cbd..ba61bab0e 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -1321,7 +1321,7 @@ end -- we can't set the text in init() since we may not yet have a frame that we -- can get wrapping bounds from. function WrappedLabel:postComputeFrame() - local wrapped_text = self:getWrappedText(self.frame_body.width-1) + local wrapped_text = self:getWrappedText(self.frame_body.width-3) if not wrapped_text then return end local text = {} for _,line in ipairs(wrapped_text:split(NEWLINE)) do From 1b1bfc40e79c1cb81a12560ff96f71334b622203 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Tue, 3 Jan 2023 12:07:40 -0800 Subject: [PATCH 46/51] move default hotspot pos one tile to the right so it doesn't overlap with screen borders --- plugins/lua/hotkeys.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/lua/hotkeys.lua b/plugins/lua/hotkeys.lua index 999527d0d..c5e36293f 100644 --- a/plugins/lua/hotkeys.lua +++ b/plugins/lua/hotkeys.lua @@ -11,7 +11,7 @@ local widgets = require('gui.widgets') HotspotMenuWidget = defclass(HotspotMenuWidget, overlay.OverlayWidget) HotspotMenuWidget.ATTRS{ - default_pos={x=1,y=2}, + default_pos={x=2,y=2}, hotspot=true, viewscreens='all', overlay_onupdate_max_freq_seconds=0, From 898e23d6a5bcaf2c5077336c1b2fd69772e494e8 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Tue, 3 Jan 2023 12:08:09 -0800 Subject: [PATCH 47/51] use lookup instead of hardcoding texpos --- plugins/pathable.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/pathable.cpp b/plugins/pathable.cpp index 344388fae..7ed7fffd0 100644 --- a/plugins/pathable.cpp +++ b/plugins/pathable.cpp @@ -33,6 +33,9 @@ static void paintScreen(df::coord target, bool skip_unrevealed = false) { bool use_graphics = Screen::inGraphicsMode(); + int selected_tile_texpos = 0; + Screen::findGraphicsTile("CURSORS", 4, 3, &selected_tile_texpos); + auto dims = Gui::getDwarfmodeViewDims().map(); for (int y = dims.first.y; y <= dims.second.y; ++y) { for (int x = dims.first.x; x <= dims.second.x; ++x) { @@ -70,7 +73,7 @@ static void paintScreen(df::coord target, bool skip_unrevealed = false) { if (use_graphics) { if (map_pos == target) { - cur_tile.tile = 100711; // highlighted selection + cur_tile.tile = selected_tile_texpos; } else{ cur_tile.tile = can_walk ? 779 : 782; } From 55cdaea63698c3d2af99f8d43e1470fdc30cb325 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Tue, 3 Jan 2023 12:57:02 -0800 Subject: [PATCH 48/51] refactor EditField text insertion --- library/lua/gui/widgets.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index ba61bab0e..c3d89c49b 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -657,6 +657,12 @@ function EditField:onRenderBody(dc) dc:string((' '):rep(dc.clip_x2 - dc.x)) end +function EditField:insert(text) + local old = self.text + self:setText(old:sub(1,self.cursor-1)..text..old:sub(self.cursor), + self.cursor + #text) +end + function EditField:onInput(keys) if not self.focus then -- only react to our hotkey @@ -713,8 +719,7 @@ function EditField:onInput(keys) else local cv = string.char(keys._STRING) if not self.on_char or self.on_char(cv, old) then - self:setText(old:sub(1,self.cursor-1)..cv..old:sub(self.cursor), - self.cursor + 1) + self:insert(cv) elseif self.on_char then return self.modal end From b766b727845beb9a62df1b190c68882fc02b4401 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Tue, 3 Jan 2023 13:06:57 -0800 Subject: [PATCH 49/51] update docs for widgets.EditField --- docs/dev/Lua API.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index e6cd2f9e8..83a99e5e6 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -4350,6 +4350,23 @@ following keyboard hotkeys: - Ctrl-B/Ctrl-F: move the cursor one word back or forward. - Ctrl-A/Ctrl-E: move the cursor to the beginning/end of the text. +The ``EditField`` class also provides the following functions: + +* ``editfield:setCursor([cursor_pos])`` + + Sets the text insert cursor to the specified position. If ``cursor_pos`` is + not specified or is past the end of the current text string, the cursor will + be set to the end of the current input (that is, ``#editfield.text + 1``). + +* ``editfield:setText(text[, cursor_pos])`` + + Sets the input text string and, optionally, the cursor position. If the + cursor position is not specified, it sets it to the end of the string. + +* ``editfield:insert(text)`` + + Inserts the given text at the current cursor position. + Scrollbar class --------------- From 2dbc5c2413aa93e87037407cdacb1a5bf00aa068 Mon Sep 17 00:00:00 2001 From: DFHack-Urist via GitHub Actions <63161697+DFHack-Urist@users.noreply.github.com> Date: Wed, 4 Jan 2023 07:14:13 +0000 Subject: [PATCH 50/51] Auto-update submodules scripts: master --- scripts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts b/scripts index 2618c86b6..5ec3a484e 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit 2618c86b64a744730673ac60bfda5ba3099cecdc +Subproject commit 5ec3a484e243954151cf21fd288311667bf15b61 From cbcb8b5f8840c6e0aa039714ba7302af6dd8ee8c Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Wed, 4 Jan 2023 13:27:03 -0800 Subject: [PATCH 51/51] fix up overlay config and pathable docs --- dfhack-config/overlay.json | 9 --------- docs/plugins/pathable.rst | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/dfhack-config/overlay.json b/dfhack-config/overlay.json index 8b90fc4a4..7ebae0948 100644 --- a/dfhack-config/overlay.json +++ b/dfhack-config/overlay.json @@ -1,13 +1,4 @@ { - "dwarfmonitor.date": { - "enabled": true - }, - "dwarfmonitor.misery": { - "enabled": true - }, - "dwarfmonitor.weather": { - "enabled": true - }, "hotkeys.menu": { "enabled": true }, diff --git a/docs/plugins/pathable.rst b/docs/plugins/pathable.rst index f4b89683b..c27172843 100644 --- a/docs/plugins/pathable.rst +++ b/docs/plugins/pathable.rst @@ -7,4 +7,4 @@ pathable :no-command: This plugin provides a Lua API, but no direct commands. See `pathable-api` for -details. +details and `gui/pathable` for the user interface.