Merge pull request #2745 from myk002/myk_no_stuck_df_viewscreens

Prevent DF screens from getting stuck and corrupting the stack on transitions
develop
Myk 2023-01-29 16:58:36 -08:00 committed by GitHub
commit f4c4d4dcdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 4 deletions

@ -36,6 +36,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## New Plugins
## Fixes
-@ DF screens can no longer get "stuck" on transitions when DFHack tool windows are visible. Instead, those DF screens are force-paused while DFHack windows are visible so the player can close them first and not corrupt the screen sequence. The "force pause" indicator will appear on these DFHack windows to indicate what is happening.
-@ ``Screen``: allow `gui/launcher` and `gui/quickcmd` to launch themselves without hanging the game
-@ Fix issues with clicks "passing through" some DFHack window elements, like scrollbars
- `getplants`: tree are now designated correctly

@ -714,7 +714,7 @@ end
function ZScreen:init()
self.saved_pause_state = df.global.pause_state
if self.initial_pause then
if self.initial_pause and dfhack.isMapLoaded() then
df.global.pause_state = true
end
self.defocused = false
@ -722,19 +722,39 @@ end
function ZScreen:dismiss()
ZScreen.super.dismiss(self)
if self.force_pause or self.initial_pause then
if (self.force_pause or self.initial_pause) and dfhack.isMapLoaded() then
-- never go from unpaused to paused, just from paused to unpaused
df.global.pause_state = df.global.pause_state and self.saved_pause_state
end
end
local NO_LOGIC_SCREENS = {
'viewscreen_loadgamest',
'viewscreen_export_regionst',
'viewscreen_choose_game_typest',
'viewscreen_worldst',
}
for _,v in ipairs(NO_LOGIC_SCREENS) do
if not df[v] then
error('invalid class name: ' .. v)
end
NO_LOGIC_SCREENS[df[v]] = true
end
-- this is necessary for middle-click map scrolling to function
function ZScreen:onIdle()
if self.force_pause then
if self.force_pause and dfhack.isMapLoaded() then
df.global.pause_state = true
end
if self._native and self._native.parent then
self._native.parent:logic()
local vs_type = dfhack.gui.getDFViewscreen(true)._type
if NO_LOGIC_SCREENS[vs_type] then
self.force_pause = true
self.pass_movement_keys = false
self.pass_mouse_clicks = false
else
self._native.parent:logic()
end
end
end

@ -716,6 +716,21 @@ void dfhack_viewscreen::logic()
// Various stuff works poorly unless always repainting
Screen::invalidate();
// if the DF screen immediately beneath the DFHack viewscreens is waiting to
// be dismissed, raise it to the top so DF never gets stuck
auto *p = parent;
while (p) {
bool is_df_screen = !is_instance(p);
auto *next_p = p->parent;
if (is_df_screen && Screen::isDismissed(p)) {
DEBUG(screen).print("raising dismissed DF viewscreen %p\n", p);
Screen::raise(p);
}
if (is_df_screen)
break;
p = next_p;
}
}
void dfhack_viewscreen::render()
@ -806,6 +821,13 @@ int dfhack_lua_viewscreen::do_destroy(lua_State *L)
auto self = get_self(L);
if (!self) return 0;
if (!Screen::isDismissed(self)) {
WARN(screen).print("DFHack screen was destroyed before it was dismissed\n");
WARN(screen).print("Please tell the DFHack team which DF screen you were just viewing\n");
// run skipped onDismiss cleanup logic
Screen::dismiss(self);
}
lua_pushnil(L);
lua_rawsetp(L, LUA_REGISTRYINDEX, self);