Remove recenterViewscreen, update revealInDwarfmodeMap

develop
Ryan Williams 2022-06-04 11:59:04 -07:00 committed by GitHub
parent 574728ac5c
commit b0b601cf0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 116 additions and 145 deletions

@ -1007,31 +1007,23 @@ Fortress mode
* ``dfhack.gui.pauseRecenter(pos[,pause])`` * ``dfhack.gui.pauseRecenter(pos[,pause])``
``dfhack.gui.pauseRecenter(x,y,z[,pause])`` ``dfhack.gui.pauseRecenter(x,y,z[,pause])``
Same as ``resetDwarfmodeView``, but also recenter if ``x`` isn't ``-30000``. Respects Same as ``resetDwarfmodeView``, but also recenter if position is valid. If ``pause`` is false, skip pausing. Respects
``RECENTER_INTERFACE_SHUTDOWN_MS`` in DF's ``init.txt`` (the delay before input is recognized when a recenter occurs.) ``RECENTER_INTERFACE_SHUTDOWN_MS`` in DF's ``init.txt`` (the delay before input is recognized when a recenter occurs.)
* ``dfhack.gui.recenterViewscreen(pos[,zoom])`` * ``dfhack.gui.revealInDwarfmodeMap(pos[,center])``
``dfhack.gui.recenterViewscreen(x,y,z[,zoom])`` ``dfhack.gui.revealInDwarfmodeMap(x,y,z[,center])``
``dfhack.gui.recenterViewscreen([zoom])``
Recenter the view on a position using a specific zoom type. If no position is given, Centers the view on the given coordinates. If ``center`` is true, make sure the
recenter on ``df.global.cursor``. Zoom types are ``df.report_zoom_type`` position is in the exact center of the view, else just bring it on screen.
(see: `enum definition <https://github.com/DFHack/df-structures/blob/master/df.announcements.xml>`_),
where ``df.report_zoom_type.Generic`` skips recentering and enforces valid view bounds (the same as x = -30000,)
``df.report_zoom_type.Item`` brings the position onscreen without centering, and
``df.report_zoom_type.Unit`` centers the screen on the position. Default zoom type is ``df.report_zoom_type.Item``.
* ``dfhack.gui.revealInDwarfmodeMap(pos)`` ``pos`` can be a ``df.coord`` instance or a table assignable to a ``df.coord`` (see `lua-api-table-assignment`),
Centers the view on the given position, which can be a ``df.coord`` instance
or a table assignable to a ``df.coord`` (see `lua-api-table-assignment`),
e.g.:: e.g.::
{x = 5, y = 7, z = 11} {x = 5, y = 7, z = 11}
getSelectedUnit().pos getSelectedUnit().pos
copyall(df.global.cursor) copyall(df.global.cursor)
Returns false if unsuccessful. If the position is invalid, the function will simply ensure the current window position is clamped between valid values.
* ``dfhack.gui.refreshSidebar()`` * ``dfhack.gui.refreshSidebar()``

@ -45,9 +45,11 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- `dfhack-examples-guide`: refine food preparation orders and fix conditions for making jugs and pots in the ``basic`` manager orders - `dfhack-examples-guide`: refine food preparation orders and fix conditions for making jugs and pots in the ``basic`` manager orders
## Documentation ## Documentation
- ``dfhack.gui.revealInDwarfmodeMap``: document ``center`` bool for lua API
## API ## API
- add functions reverse-engineered from announcement code: ``Gui::autoDFAnnouncement``, ``Gui::pauseRecenter``, ``Gui::recenterViewscreen`` - add functions reverse-engineered from announcement code: ``Gui::autoDFAnnouncement``, ``Gui::pauseRecenter``
- ``Gui::revealInDwarfmodeMap``: Now enforce valid view bounds when pos invalid, add variant accepting x, y, z
## Lua ## Lua
- ``widgets.HotkeyLabel``: the ``key_sep`` string is now configurable - ``widgets.HotkeyLabel``: the ``key_sep`` string is now configurable

@ -1457,26 +1457,6 @@ static const LuaWrapper::FunctionReg dfhack_module[] = {
/***** Gui module *****/ /***** Gui module *****/
static int gui_getDwarfmodeViewDims(lua_State *state)
{
auto dims = Gui::getDwarfmodeViewDims();
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;
}
static const LuaWrapper::FunctionReg dfhack_gui_module[] = { static const LuaWrapper::FunctionReg dfhack_gui_module[] = {
WRAPM(Gui, getCurViewscreen), WRAPM(Gui, getCurViewscreen),
WRAPM(Gui, getFocusString), WRAPM(Gui, getFocusString),
@ -1500,7 +1480,6 @@ static const LuaWrapper::FunctionReg dfhack_gui_module[] = {
WRAPM(Gui, showPopupAnnouncement), WRAPM(Gui, showPopupAnnouncement),
WRAPM(Gui, showAutoAnnouncement), WRAPM(Gui, showAutoAnnouncement),
WRAPM(Gui, resetDwarfmodeView), WRAPM(Gui, resetDwarfmodeView),
WRAPM(Gui, revealInDwarfmodeMap),
WRAPM(Gui, refreshSidebar), WRAPM(Gui, refreshSidebar),
WRAPM(Gui, inRenameBuilding), WRAPM(Gui, inRenameBuilding),
WRAPM(Gui, getDepthAt), WRAPM(Gui, getDepthAt),
@ -1520,7 +1499,7 @@ static int gui_autoDFAnnouncement(lua_State *state)
else else
{ {
df::coord pos; df::coord pos;
int color = 0; //initialize these to prevent warning int color = 0; // initialize these to prevent warning
bool bright = false, is_sparring = false; bool bright = false, is_sparring = false;
df::unit *unit1 = NULL, *unit2 = NULL; df::unit *unit1 = NULL, *unit2 = NULL;
@ -1572,54 +1551,85 @@ static int gui_autoDFAnnouncement(lua_State *state)
return 1; return 1;
} }
static int gui_getDwarfmodeViewDims(lua_State *state)
{
auto dims = Gui::getDwarfmodeViewDims();
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;
}
static int gui_pauseRecenter(lua_State *state) static int gui_pauseRecenter(lua_State *state)
{ {
if (lua_gettop(state) == 2) bool rv;
df::coord p;
switch (lua_gettop(state))
{ {
df::coord p; default:
Lua::CheckDFAssign(state, &p, 1); case 4:
Gui::pauseRecenter(p, lua_toboolean(state, 2)); rv = Gui::pauseRecenter(CheckCoordXYZ(state, 1, false), lua_toboolean(state, 4));
break;
case 3:
rv = Gui::pauseRecenter(CheckCoordXYZ(state, 1, false));
break;
case 2:
Lua::CheckDFAssign(state, &p, 1);
rv = Gui::pauseRecenter(p, lua_toboolean(state, 2));
break;
case 1:
Lua::CheckDFAssign(state, &p, 1);
rv = Gui::pauseRecenter(p);
} }
else
Gui::pauseRecenter(CheckCoordXYZ(state, 1, false), lua_toboolean(state, 4));
lua_pushboolean(state, rv);
return 1; return 1;
} }
static int gui_recenterViewscreen(lua_State *state) static int gui_revealInDwarfmodeMap(lua_State *state)
{ {
bool rv;
df::coord p; df::coord p;
switch (lua_gettop(state)) switch (lua_gettop(state))
{ {
default: default:
case 4: case 4:
Gui::recenterViewscreen(CheckCoordXYZ(state, 1, false), (df::report_zoom_type)lua_tointeger(state, 4)); rv = Gui::revealInDwarfmodeMap(CheckCoordXYZ(state, 1, false), lua_toboolean(state, 4));
break; break;
case 3: case 3:
Gui::recenterViewscreen(CheckCoordXYZ(state, 1, false)); rv = Gui::revealInDwarfmodeMap(CheckCoordXYZ(state, 1, false));
break; break;
case 2: case 2:
Lua::CheckDFAssign(state, &p, 1); Lua::CheckDFAssign(state, &p, 1);
Gui::recenterViewscreen(p, (df::report_zoom_type)lua_tointeger(state, 2)); rv = Gui::revealInDwarfmodeMap(p, lua_toboolean(state, 2));
break; break;
case 1: case 1:
if (lua_type(state, 1) == LUA_TNUMBER) Lua::CheckDFAssign(state, &p, 1);
Gui::recenterViewscreen((df::report_zoom_type)lua_tointeger(state, 1)); rv = Gui::revealInDwarfmodeMap(p);
else
Gui::recenterViewscreen(CheckCoordXYZ(state, 1, true));
break;
case 0:
Gui::recenterViewscreen();
} }
lua_pushboolean(state, rv);
return 1; return 1;
} }
static const luaL_Reg dfhack_gui_funcs[] = { static const luaL_Reg dfhack_gui_funcs[] = {
{ "autoDFAnnouncement", gui_autoDFAnnouncement }, { "autoDFAnnouncement", gui_autoDFAnnouncement },
{ "pauseRecenter", gui_pauseRecenter },
{ "recenterViewscreen", gui_recenterViewscreen },
{ "getDwarfmodeViewDims", gui_getDwarfmodeViewDims }, { "getDwarfmodeViewDims", gui_getDwarfmodeViewDims },
{ "pauseRecenter", gui_pauseRecenter },
{ "revealInDwarfmodeMap", gui_revealInDwarfmodeMap },
{ NULL, NULL } { NULL, NULL }
}; };

@ -138,13 +138,6 @@ namespace DFHack
DFHACK_EXPORT df::coord getViewportPos(); DFHACK_EXPORT df::coord getViewportPos();
DFHACK_EXPORT df::coord getCursorPos(); DFHACK_EXPORT df::coord getCursorPos();
// Recenter the viewscreen, based on DF code for announcements and scrolling
DFHACK_EXPORT void pauseRecenter(int32_t x, int32_t y, int32_t z, bool pause);
DFHACK_EXPORT inline void pauseRecenter(df::coord pos, bool pause) { pauseRecenter(pos.x, pos.y, pos.z, pause); }
DFHACK_EXPORT void recenterViewscreen(int32_t x, int32_t y, int32_t z, df::report_zoom_type zoom = df::enums::report_zoom_type::Item);
DFHACK_EXPORT inline void recenterViewscreen(df::coord pos, df::report_zoom_type zoom = df::enums::report_zoom_type::Item) { recenterViewscreen(pos.x, pos.y, pos.z, zoom); };
DFHACK_EXPORT inline void recenterViewscreen(df::report_zoom_type zoom = df::enums::report_zoom_type::Item) { recenterViewscreen(getCursorPos(), zoom); };
static const int AREA_MAP_WIDTH = 23; static const int AREA_MAP_WIDTH = 23;
static const int MENU_WIDTH = 30; static const int MENU_WIDTH = 30;
@ -161,7 +154,10 @@ namespace DFHack
DFHACK_EXPORT DwarfmodeDims getDwarfmodeViewDims(); DFHACK_EXPORT DwarfmodeDims getDwarfmodeViewDims();
DFHACK_EXPORT void resetDwarfmodeView(bool pause = false); DFHACK_EXPORT void resetDwarfmodeView(bool pause = false);
DFHACK_EXPORT bool revealInDwarfmodeMap(df::coord pos, bool center = false); DFHACK_EXPORT bool revealInDwarfmodeMap(int32_t x, int32_t y, int32_t z, bool center = false);
DFHACK_EXPORT inline bool revealInDwarfmodeMap(df::coord pos, bool center = false) { return revealInDwarfmodeMap(pos.x, pos.y, pos.z, center); };
DFHACK_EXPORT bool pauseRecenter(int32_t x, int32_t y, int32_t z, bool pause = true);
DFHACK_EXPORT inline bool pauseRecenter(df::coord pos, bool pause = true) { return pauseRecenter(pos.x, pos.y, pos.z, pause); };
DFHACK_EXPORT bool refreshSidebar(); DFHACK_EXPORT bool refreshSidebar();
DFHACK_EXPORT bool inRenameBuilding(); DFHACK_EXPORT bool inRenameBuilding();

@ -1387,7 +1387,7 @@ static bool parseReportString(std::vector<std::string> *out, const std::string &
if (str[i] == 'r') // "&r" adds a blank line if (str[i] == 'r') // "&r" adds a blank line
{ {
word_wrap(out, parsed, line_length/*, WSMODE_TRIM_LEADING*/); word_wrap(out, parsed, line_length, WSMODE_TRIM_LEADING);
out->push_back(" "); // DF adds a line with a space for some reason out->push_back(" "); // DF adds a line with a space for some reason
parsed.clear(); parsed.clear();
} }
@ -1401,7 +1401,7 @@ static bool parseReportString(std::vector<std::string> *out, const std::string &
while (++i < str.length()); while (++i < str.length());
if (parsed.length()) if (parsed.length())
word_wrap(out, parsed, line_length/*, WSMODE_TRIM_LEADING*/); word_wrap(out, parsed, line_length, WSMODE_TRIM_LEADING);
return true; return true;
} }
@ -1921,65 +1921,6 @@ df::coord Gui::getCursorPos()
return df::coord(cursor->x, cursor->y, cursor->z); return df::coord(cursor->x, cursor->y, cursor->z);
} }
void Gui::recenterViewscreen(int32_t x, int32_t y, int32_t z, df::report_zoom_type zoom)
{ // Reverse-engineered from DF announcement code, also used when scrolling
auto dims = getDwarfmodeViewDims();
int32_t w = dims.map_x2 - dims.map_x1 + 1;
int32_t h = dims.map_y2 - dims.map_y1 + 1;
int32_t new_win_x, new_win_y, new_win_z;
getViewCoords(new_win_x, new_win_y, new_win_z);
if (zoom != report_zoom_type::Generic && x != -30000)
{
if (zoom == report_zoom_type::Unit)
{
new_win_x = x - w / 2;
new_win_y = y - h / 2;
}
else // report_zoom_type::Item
{
if (new_win_x > (x - 5)) // equivalent to: "while (new_win_x > x - 5) new_win_x -= 10;"
new_win_x -= (new_win_x - (x - 5) - 1) / 10 * 10 + 10;
if (new_win_y > (y - 5))
new_win_y -= (new_win_y - (y - 5) - 1) / 10 * 10 + 10;
if (new_win_x < (x + 5 - w))
new_win_x += ((x + 5 - w) - new_win_x - 1) / 10 * 10 + 10;
if (new_win_y < (y + 5 - h))
new_win_y += ((y + 5 - h) - new_win_y - 1) / 10 * 10 + 10;
}
new_win_z = z;
}
*df::global::window_x = clip_range(new_win_x, 0, (world->map.x_count - w));
*df::global::window_y = clip_range(new_win_y, 0, (world->map.y_count - h));
*df::global::window_z = clip_range(new_win_z, 0, (world->map.z_count - 1));
ui_sidebar_menus->minimap.need_render = true;
ui_sidebar_menus->minimap.need_scan = true;
return;
}
void Gui::pauseRecenter(int32_t x, int32_t y, int32_t z, bool pause)
{ // Reverse-engineered from DF announcement code
if (*gamemode != game_mode::DWARF)
return;
resetDwarfmodeView(pause);
if (x != -30000)
recenterViewscreen(x, y, z, report_zoom_type::Item);
if (init->input.pause_zoom_no_interface_ms > 0)
{
gview->shutdown_interface_tickcount = Core::getInstance().p->getTickCount();
gview->shutdown_interface_for_ms = init->input.pause_zoom_no_interface_ms;
}
return;
}
Gui::DwarfmodeDims getDwarfmodeViewDims_default() Gui::DwarfmodeDims getDwarfmodeViewDims_default()
{ {
Gui::DwarfmodeDims dims; Gui::DwarfmodeDims dims;
@ -2059,38 +2000,68 @@ void Gui::resetDwarfmodeView(bool pause)
*df::global::pause_state = true; *df::global::pause_state = true;
} }
bool Gui::revealInDwarfmodeMap(df::coord pos, bool center) bool Gui::revealInDwarfmodeMap(int32_t x, int32_t y, int32_t z, bool center)
{ { // Reverse-engineered from DF announcement and scrolling code
using df::global::window_x; using df::global::window_x;
using df::global::window_y; using df::global::window_y;
using df::global::window_z; using df::global::window_z;
if (!window_x || !window_y || !window_z || !world) if (!window_x || !window_y || !window_z || !world)
return false; return false;
if (!Maps::isValidTilePos(pos))
return false;
auto dims = getDwarfmodeViewDims(); auto dims = getDwarfmodeViewDims();
int w = dims.map_x2 - dims.map_x1 + 1; int32_t w = dims.map_x2 - dims.map_x1 + 1;
int h = dims.map_y2 - dims.map_y1 + 1; int32_t h = dims.map_y2 - dims.map_y1 + 1;
int32_t new_win_x, new_win_y, new_win_z;
*window_z = pos.z; getViewCoords(new_win_x, new_win_y, new_win_z);
if (center) if (Maps::isValidTilePos(x, y, z))
{ {
*window_x = pos.x - w/2; if (center)
*window_y = pos.y - h/2; {
new_win_x = x - w / 2;
new_win_y = y - h / 2;
}
else // just bring it on screen
{
if (new_win_x > (x - 5)) // equivalent to: "while (new_win_x > x - 5) new_win_x -= 10;"
new_win_x -= (new_win_x - (x - 5) - 1) / 10 * 10 + 10;
if (new_win_y > (y - 5))
new_win_y -= (new_win_y - (y - 5) - 1) / 10 * 10 + 10;
if (new_win_x < (x + 5 - w))
new_win_x += ((x + 5 - w) - new_win_x - 1) / 10 * 10 + 10;
if (new_win_y < (y + 5 - h))
new_win_y += ((y + 5 - h) - new_win_y - 1) / 10 * 10 + 10;
}
new_win_z = z;
} }
else
*window_x = clip_range(new_win_x, 0, (world->map.x_count - w));
*window_y = clip_range(new_win_y, 0, (world->map.y_count - h));
*window_z = clip_range(new_win_z, 0, (world->map.z_count - 1));
ui_sidebar_menus->minimap.need_render = true;
ui_sidebar_menus->minimap.need_scan = true;
return true;
}
bool Gui::pauseRecenter(int32_t x, int32_t y, int32_t z, bool pause)
{ // Reverse-engineered from DF announcement code
if (*gamemode != game_mode::DWARF)
return false;
resetDwarfmodeView(pause);
if (Maps::isValidTilePos(x, y, z))
revealInDwarfmodeMap(x, y, z, false);
if (init->input.pause_zoom_no_interface_ms > 0)
{ {
while (*window_x + w < pos.x+5) *window_x += 10; gview->shutdown_interface_tickcount = Core::getInstance().p->getTickCount();
while (*window_y + h < pos.y+5) *window_y += 10; gview->shutdown_interface_for_ms = init->input.pause_zoom_no_interface_ms;
while (*window_x + 5 > pos.x) *window_x -= 10;
while (*window_y + 5 > pos.y) *window_y -= 10;
} }
*window_x = std::max(0, std::min(*window_x, world->map.x_count-w));
*window_y = std::max(0, std::min(*window_y, world->map.y_count-h));
return true; return true;
} }