diff --git a/game/engines/default/engine/Game.lua b/game/engines/default/engine/Game.lua index 00212fd887d389e214044501b24e36818499e820..c4994cd561c613540b2ed869505d8d159a666649 100644 --- a/game/engines/default/engine/Game.lua +++ b/game/engines/default/engine/Game.lua @@ -366,9 +366,11 @@ end available_resolutions = { - ["800x600 Windowed"] = {800, 600, false}, - ["1024x768 Windowed"] = {1024, 768, false}, - ["1200x1024 Windowed"] = {1200, 1024, false}, + ["800x600 Windowed"] = {800, 600, false}, + ["1024x768 Windowed"] = {1024, 768, false}, + ["1200x1024 Windowed"] = {1200, 1024, false}, + ["1280x720 Windowed"] = {1280, 720, false}, + ["1600x900 Windowed"] = {1600, 900, false}, ["1600x1200 Windowed"] = {1600, 1200, false}, -- ["800x600 Fullscreen"] = {800, 600, true}, -- ["1024x768 Fullscreen"] = {1024, 768, true}, @@ -403,55 +405,85 @@ function _M:setResolution(res, force) end if not r then return false, "unknown resolution" end - print("Switching resolution to", res, r[1], r[2], r[3]) + -- Change the window size + print("setResolution: switching resolution to", res, r[1], r[2], r[3], force and "(forced)") local old_w, old_h, old_f = self.w, self.h, self.fullscreen core.display.setWindowSize(r[1], r[2], r[3]) - self.w, self.h, self.fullscreen = core.display.size() + + -- Don't write self.w/h/fullscreen yet + local new_w, new_h, new_f = core.display.size() - -- Save settings if need be - if self.w ~= old_w or self.h ~= old_h or self.fullscreen ~= old_f then + -- Check if a resolution change actually happened + if new_w ~= old_w or new_h ~= old_h or new_f ~= old_f then + print("setResolution: performing onResolutionChange...\n") self:onResolutionChange() - self:saveSettings("resolution", ("window.size = %q\n"):format(res)) + -- onResolutionChange saves settings... + -- self:saveSettings("resolution", ("window.size = %q\n"):format(res)) + else + print("setResolution: resolution change requested from same resolution!\n") end end --- Called when screen resolution changes function _M:onResolutionChange() + local ow, oh, of = self.w, self.h, self.fullscreen + + -- Save old values for a potential revert if game and not self.change_res_dialog_oldw then - self.change_res_dialog_oldw, self.change_res_dialog_oldh, self.change_res_dialog_oldf = self.w, self.h, self.fullscreen + print("onResolutionChange: saving current resolution for potential revert.") + self.change_res_dialog_oldw, self.change_res_dialog_oldh, self.change_res_dialog_oldf = ow, oh, of end - - local ow, oh, of = self.w, self.h, self.fullscreen + -- Get new resolution and save self.w, self.h, self.fullscreen = core.display.size() config.settings.window.size = ("%dx%d%s"):format(self.w, self.h, self.fullscreen and " Fullscreen" or " Windowed") self:saveSettings("resolution", ("window.size = '%s'\n"):format(config.settings.window.size)) - print("[RESOLUTION] changed to ", self.w, self.h, "from", ow, oh) + print("onResolutionChange: resolution changed to ", self.w, self.h, "from", ow, oh) -- We do not even have a game yet - if not game then return end + if not game then + print("onResolutionChange: no game yet!") + return + end -- No actual resize - if ow == self.w and oh == self.h then return end + if ow == self.w and oh == self.h then + print("onResolutionChange: no actual resize, no confirm dialog.") + return + end - if self:checkResolutionChange(self.w, self.h, ow, oh) then return end + -- Extra game logic to be updated on a resize + if not self:checkResolutionChange(self.w, self.h, ow, oh) then + print("onResolutionChange: checkResolutionChange returned false, no confirm dialog.") + return + end -- Do not repop if we just revert back - if self.change_res_dialog and type(self.change_res_dialog) == "string" and self.change_res_dialog == "revert" then return end + if self.change_res_dialog and type(self.change_res_dialog) == "string" and self.change_res_dialog == "revert" then + print("onResolutionChange: Reverting, no popup.") + return + end + -- Unregister old dialog if there was one - if self.change_res_dialog and type(self.change_res_dialog) == "table" then self:unregisterDialog(self.change_res_dialog) end - -- Ask if we want to switch - self.change_res_dialog = require("engine.ui.Dialog"):yesnoPopup("Resolution changed", "Accept the new resolution?", function(ret) - if ret then - if not self.creating_player then self:saveGame() end - util.showMainMenu(false, nil, nil, self.__mod_info.short_name, self.save_name, false) - else - self.change_res_dialog = "revert" - self:setResolution(("%dx%d%s"):format(self.change_res_dialog_oldw, self.change_res_dialog_oldh, self.change_res_dialog_oldf and " Fullscreen" or " Windowed"), true) - self.change_res_dialog = nil - self.change_res_dialog_oldw, self.change_res_dialog_oldh, self.change_res_dialog_oldf = nil, nil, nil - end - end, "Accept", "Revert") + if self.change_res_dialog and type(self.change_res_dialog) == "table" then + print("onResolutionChange: Unregistering dialog") + self:unregisterDialog(self.change_res_dialog) + end + + -- Are you sure you want to save these settings? Somewhat obnoxious... +-- self.change_res_dialog = require("engine.ui.Dialog"):yesnoPopup("Resolution changed", "Accept the new resolution?", function(ret) +-- if ret then +-- if not self.creating_player then self:saveGame() end +-- util.showMainMenu(false, nil, nil, self.__mod_info.short_name, self.save_name, false) +-- else +-- self.change_res_dialog = "revert" +-- self:setResolution(("%dx%d%s"):format(self.change_res_dialog_oldw, self.change_res_dialog_oldh, self.change_res_dialog_oldf and " Fullscreen" or " Windowed"), true) +-- self.change_res_dialog = nil +-- self.change_res_dialog_oldw, self.change_res_dialog_oldh, self.change_res_dialog_oldf = nil, nil, nil +-- end +-- end, "Accept", "Revert") + print("onResolutionChange: (Would have) created popup.") + end --- Checks if we must reload to change resolution diff --git a/game/modules/tome/class/uiset/Minimalist.lua b/game/modules/tome/class/uiset/Minimalist.lua index 69a40a543bbd0014bfb5844e5e62a55cd32513d7..12f23788a3946aeb34df3c0c8abadd73265c67fe 100644 --- a/game/modules/tome/class/uiset/Minimalist.lua +++ b/game/modules/tome/class/uiset/Minimalist.lua @@ -405,11 +405,10 @@ function _M:resizeIconsHotkeysToolbar() end function _M:handleResolutionChange(w, h, ow, oh) - local w, h = core.display.size() - game:setResolution(w.."x"..h, true) - - self.no_ui = not self.no_ui - self:toggleUI() + print("minimalist:handleResolutionChange: adjusting UI") + -- what was the point of this recursive call? +-- local w, h = core.display.size() +-- game:setResolution(w.."x"..h, true) -- Adjust UI local w2, h2 = math.floor(ow / 2), math.floor(oh / 2) @@ -418,8 +417,14 @@ function _M:handleResolutionChange(w, h, ow, oh) if d.y > h2 then d.y = d.y + h - oh end end + print("minimalist:handleResolutionChange: toggling UI to refresh") + -- Toggle the UI to refresh the changes + self:toggleUI() + self:toggleUI() + self:boundPlaces() self:saveSettings() + print("minimalist:handleResolutionChange: saved settings") return true end diff --git a/src/core_lua.c b/src/core_lua.c index f04133b12219dc8f67c5980ac09b7e6bc52cb676..0dc766c3b9346e0537194d19791bda45904778b9 100644 --- a/src/core_lua.c +++ b/src/core_lua.c @@ -1322,6 +1322,23 @@ static int sdl_load_image(lua_State *L) return 3; } +static int sdl_load_image_mem(lua_State *L) +{ + size_t len; + const char *data = luaL_checklstring(L, 1, &len); + + SDL_Surface **s = (SDL_Surface**)lua_newuserdata(L, sizeof(SDL_Surface*)); + auxiliar_setclass(L, "sdl{surface}", -1); + + *s = IMG_Load_RW(SDL_RWFromConstMem(data, len), TRUE); + if (!*s) return 0; + + lua_pushnumber(L, (*s)->w); + lua_pushnumber(L, (*s)->h); + + return 3; +} + static int sdl_free_surface(lua_State *L) { SDL_Surface **s = (SDL_Surface**)auxiliar_checkclass(L, "sdl{surface}", 1); @@ -2557,6 +2574,7 @@ static const struct luaL_reg displaylib[] = {"drawStringNewSurface", sdl_surface_drawstring_newsurface}, {"drawStringBlendedNewSurface", sdl_surface_drawstring_newsurface_aa}, {"loadImage", sdl_load_image}, + {"loadImageMemory", sdl_load_image_mem}, {"setWindowTitle", sdl_set_window_title}, {"setWindowSize", sdl_set_window_size}, {"setWindowPos", sdl_set_window_pos}, diff --git a/src/main.c b/src/main.c index df4fd484cda9a20d07ac1135c83979b2c2a431f2..c18a4fc7384ff1e04a0b837502e6214dfe0744a4 100644 --- a/src/main.c +++ b/src/main.c @@ -771,30 +771,90 @@ int resizeWindow(int width, int height) void do_resize(int w, int h, bool fullscreen) { - if (!window) - { - window = SDL_CreateWindow("TE4", (start_xpos == -1) ? SDL_WINDOWPOS_CENTERED : start_xpos, (start_ypos == -1) ? SDL_WINDOWPOS_CENTERED : start_ypos, w, h, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | (fullscreen ? SDL_WINDOW_FULLSCREEN : 0)); + /* Temporary width, height (since SDL might reject our resize) */ + int aw, ah; + int mustPushEvent = 0; + SDL_Event fsEvent; + + printf("[DO RESIZE] Requested: %dx%d (%d)\n", w, h, fullscreen); + + /* If there is no current window, we have to make one and initialize */ + if (!window) { + window = SDL_CreateWindow("TE4", + (start_xpos == -1) ? SDL_WINDOWPOS_CENTERED : start_xpos, + (start_ypos == -1) ? SDL_WINDOWPOS_CENTERED : start_ypos, w, h, + SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE + | (fullscreen ? SDL_WINDOW_FULLSCREEN : 0)); if (window==NULL) { printf("error opening screen: %s\n", SDL_GetError()); exit(1); } + is_fullscreen = fullscreen; screen = SDL_GetWindowSurface(window); maincontext = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, maincontext); glewInit(); - } - else - { + + } else { + /* SDL won't allow a fullscreen resolution change in one go. Check. */ + if (is_fullscreen) { + /* Drop out of fullscreen so we can change resolution. */ + SDL_SetWindowFullscreen(window, SDL_FALSE); + is_fullscreen = 0; + mustPushEvent = 1; /* Actually just a maybe for now, confirmed later */ + + } + + /* Update window size */ SDL_SetWindowSize(window, w, h); + + /* Jump [back] into fullscreen if requested */ + if (fullscreen) { + if (!SDL_SetWindowFullscreen(window, SDL_TRUE)) { + /* Fullscreen change successful */ + is_fullscreen = SDL_TRUE; + + } else { + /* Error switching fullscreen mode */ + printf("[DO RESIZE] Unable to switch window" + " to fullscreen mode: %s\n", SDL_GetError()); + SDL_ClearError(); + } + + } else if (mustPushEvent) { + /* + * Our changes will get clobbered by an automatic event from + * setWindowFullscreen. Push an event to the event loop to make + * sure these changes are applied after whatever that other event + * throws. + */ + /* Create an event to push */ + fsEvent.type = SDL_WINDOWEVENT; + fsEvent.window.timestamp = SDL_GetTicks(); + fsEvent.window.windowID = SDL_GetWindowID(window); + // windowId + fsEvent.window.event = SDL_WINDOWEVENT_RESIZED; + fsEvent.window.data1 = w; + fsEvent.window.data2 = h; + + /* Push the event, but don't bother waiting */ + SDL_PushEvent(&fsEvent); + printf("[DO RESIZE]: pushed fullscreen compensation event\n"); + + } + + /* Finally, update the screen info */ screen = SDL_GetWindowSurface(window); + + } - printf("[DO RESIZE] %dx%d (%d)\n", w, h, fullscreen); - is_fullscreen = fullscreen; - SDL_SetWindowFullscreen(window, fullscreen); - SDL_GetWindowSize(window, &w, &h); + /* Check and see if SDL honored our resize request */ + SDL_GetWindowSize(window, &aw, &ah); + printf("[DO RESIZE] Got: %dx%d (%d)\n", aw, ah, is_fullscreen); SDL_GL_MakeCurrent(window, maincontext); - resizeWindow(w, h); + resizeWindow(aw, ah); + } void boot_lua(int state, bool rebooting, int argc, char *argv[]) @@ -1087,17 +1147,22 @@ int main(int argc, char *argv[]) switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: - printf("resize %d x %d\n", event.window.data1, event.window.data2); - do_resize(event.window.data1, event.window.data2, is_fullscreen); + /* Note: SDL can't resize a fullscreen window, so don't bother! */ + if (!is_fullscreen) { + printf("SDL_WINDOWEVENT_RESIZED: %d x %d\n", event.window.data1, event.window.data2); + do_resize(event.window.data1, event.window.data2, is_fullscreen); + if (current_game != LUA_NOREF) + { + lua_rawgeti(L, LUA_REGISTRYINDEX, current_game); + lua_pushstring(L, "onResolutionChange"); + lua_gettable(L, -2); + lua_remove(L, -2); + lua_rawgeti(L, LUA_REGISTRYINDEX, current_game); + docall(L, 1, 0); + } + } else { + printf("SDL_WINDOWEVENT_RESIZED: ignored due to fullscreen\n"); - if (current_game != LUA_NOREF) - { - lua_rawgeti(L, LUA_REGISTRYINDEX, current_game); - lua_pushstring(L, "onResolutionChange"); - lua_gettable(L, -2); - lua_remove(L, -2); - lua_rawgeti(L, LUA_REGISTRYINDEX, current_game); - docall(L, 1, 0); } break; case SDL_WINDOWEVENT_MOVED: { @@ -1146,22 +1211,33 @@ int main(int argc, char *argv[]) exit_engine = TRUE; break; case SDL_USEREVENT: - if (event.user.code == 0 && isActive) { - on_redraw(); - SDL_mutexP(renderingLock); - redraw_pending = 0; - SDL_mutexV(renderingLock); + /* TODO: Enumerate user event codes */ + switch(event.user.code) + { + case 0: + if (isActive) { + on_redraw(); + SDL_mutexP(renderingLock); + redraw_pending = 0; + SDL_mutexV(renderingLock); + } + break; - } - else if (event.user.code == 2 && isActive) { - on_tick(); - SDL_mutexP(realtimeLock); - realtime_pending = 0; - SDL_mutexV(realtimeLock); - - } - else if (event.user.code == 1) { + case 1: on_music_stop(); + break; + + case 2: + if (isActive) { + on_tick(); + SDL_mutexP(realtimeLock); + realtime_pending = 0; + SDL_mutexV(realtimeLock); + } + break; + + default: + break; } break; default: