diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 727aee4abc..df6893c1ba 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -134,8 +134,8 @@ namespace MWBase virtual bool isGuiMode() const = 0; virtual bool isConsoleMode() const = 0; - virtual bool isPostProcessorHudVisible() const = 0; + virtual bool isInteractiveMessageBoxActive() const = 0; virtual void toggleVisible(MWGui::GuiWindow wnd) = 0; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index b9c52136c1..9bcfb3e158 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1539,8 +1539,7 @@ namespace MWGui bool WindowManager::isGuiMode() const { - return !mGuiModes.empty() || isConsoleMode() || (mPostProcessorHud && mPostProcessorHud->isVisible()) - || (mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox()); + return !mGuiModes.empty() || isConsoleMode() || isPostProcessorHudVisible() || isInteractiveMessageBoxActive(); } bool WindowManager::isConsoleMode() const @@ -1550,7 +1549,12 @@ namespace MWGui bool WindowManager::isPostProcessorHudVisible() const { - return mPostProcessorHud->isVisible(); + return mPostProcessorHud && mPostProcessorHud->isVisible(); + } + + bool WindowManager::isInteractiveMessageBoxActive() const + { + return mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox(); } MWGui::GuiMode WindowManager::getMode() const diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 9d79e0a0d7..fae3bb1ec9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -160,8 +160,8 @@ namespace MWGui bool isGuiMode() const override; bool isConsoleMode() const override; - bool isPostProcessorHudVisible() const override; + bool isInteractiveMessageBoxActive() const override; void toggleVisible(GuiWindow wnd) override; diff --git a/apps/openmw/mwrender/camera.cpp b/apps/openmw/mwrender/camera.cpp index fbe5c6b4c7..86d5699d75 100644 --- a/apps/openmw/mwrender/camera.cpp +++ b/apps/openmw/mwrender/camera.cpp @@ -138,14 +138,12 @@ namespace MWRender if (mProcessViewChange) processViewChange(); - if (paused) - return; - // only show the crosshair in game mode MWBase::WindowManager* wm = MWBase::Environment::get().getWindowManager(); wm->showCrosshair(!wm->isGuiMode() && mShowCrosshair); - updateFocalPointOffset(duration); + if (!paused) + updateFocalPointOffset(duration); updatePosition(); } diff --git a/apps/openmw/mwworld/datetimemanager.cpp b/apps/openmw/mwworld/datetimemanager.cpp index 7559242bef..78565cef60 100644 --- a/apps/openmw/mwworld/datetimemanager.cpp +++ b/apps/openmw/mwworld/datetimemanager.cpp @@ -263,6 +263,8 @@ namespace MWWorld void DateTimeManager::updateIsPaused() { - mPaused = !mPausedTags.empty() || MWBase::Environment::get().getWindowManager()->isGuiMode(); + auto wm = MWBase::Environment::get().getWindowManager(); + mPaused = !mPausedTags.empty() || wm->isConsoleMode() || wm->isPostProcessorHudVisible() + || wm->isInteractiveMessageBoxActive(); } } diff --git a/docs/source/reference/lua-scripting/events.rst b/docs/source/reference/lua-scripting/events.rst index 22cf4710d4..3e689078d0 100644 --- a/docs/source/reference/lua-scripting/events.rst +++ b/docs/source/reference/lua-scripting/events.rst @@ -42,3 +42,22 @@ and ``arg`` (for example in the mode ``Book`` the argument is the book the playe print('UiModeChanged from', data.oldMode , 'to', data.newMode, '('..tostring(data.arg)..')') end } + +World events +------------ + +Global events that just call the corresponding function in `openmw.world`. + +.. code-block:: Lua + + -- world.pause(tag) + core.sendGlobalEvent('Pause', tag) + + -- world.unpause(tag) + core.sendGlobalEvent('Unpause', tag) + + -- world.setGameTimeScale(scale) + core.sendGlobalEvent('SetGameTimeScale', scale) + + -- world.setSimulationTimeScale(scale) + core.sendGlobalEvent('SetSimulationTimeScale', scale) diff --git a/files/data/CMakeLists.txt b/files/data/CMakeLists.txt index afab9b4c79..dbf86cc44d 100644 --- a/files/data/CMakeLists.txt +++ b/files/data/CMakeLists.txt @@ -91,6 +91,7 @@ set(BUILTIN_DATA_FILES scripts/omw/mwui/init.lua scripts/omw/ui.lua scripts/omw/usehandlers.lua + scripts/omw/worldeventhandlers.lua shaders/adjustments.omwfx shaders/bloomlinear.omwfx diff --git a/files/data/builtin.omwscripts b/files/data/builtin.omwscripts index b86bedc509..ec08c5299d 100644 --- a/files/data/builtin.omwscripts +++ b/files/data/builtin.omwscripts @@ -9,6 +9,7 @@ PLAYER: scripts/omw/settings/player.lua GLOBAL: scripts/omw/activationhandlers.lua GLOBAL: scripts/omw/cellhandlers.lua GLOBAL: scripts/omw/usehandlers.lua +GLOBAL: scripts/omw/worldeventhandlers.lua PLAYER: scripts/omw/mechanics/playercontroller.lua PLAYER: scripts/omw/playercontrols.lua PLAYER: scripts/omw/camera/camera.lua diff --git a/files/data/scripts/omw/activationhandlers.lua b/files/data/scripts/omw/activationhandlers.lua index 7d185cf9da..2f63f59e92 100644 --- a/files/data/scripts/omw/activationhandlers.lua +++ b/files/data/scripts/omw/activationhandlers.lua @@ -23,6 +23,9 @@ local handlersPerType = {} handlersPerType[types.ESM4Door] = { ESM4DoorActivation } local function onActivate(obj, actor) + if world.isWorldPaused() then + return + end local handlers = handlersPerObject[obj.id] if handlers then for i = #handlers, 1, -1 do diff --git a/files/data/scripts/omw/camera/camera.lua b/files/data/scripts/omw/camera/camera.lua index 6fcb46bb2f..a3d2ae7b3f 100644 --- a/files/data/scripts/omw/camera/camera.lua +++ b/files/data/scripts/omw/camera/camera.lua @@ -5,6 +5,7 @@ local util = require('openmw.util') local self = require('openmw.self') local nearby = require('openmw.nearby') local async = require('openmw.async') +local I = require('openmw.interfaces') local Actor = require('openmw.types').Actor @@ -189,7 +190,7 @@ local function updateIdleTimer(dt) end local function onFrame(dt) - if core.isWorldPaused() then return end + if core.isWorldPaused() or I.UI.getMode() then return end updateIdleTimer(dt) local mode = camera.getMode() if (mode == MODE.FirstPerson or mode == MODE.ThirdPerson) and not camera.getQueuedMode() then @@ -273,7 +274,7 @@ return { onUpdate = onUpdate, onFrame = onFrame, onInputAction = function(action) - if core.isWorldPaused() then return end + if core.isWorldPaused() or I.UI.getMode() then return end if action == input.ACTION.ZoomIn then zoom(10) elseif action == input.ACTION.ZoomOut then diff --git a/files/data/scripts/omw/playercontrols.lua b/files/data/scripts/omw/playercontrols.lua index 56a0b962e6..bea7e5392f 100644 --- a/files/data/scripts/omw/playercontrols.lua +++ b/files/data/scripts/omw/playercontrols.lua @@ -107,7 +107,8 @@ local function processAttacking() end local function onFrame(dt) - local controlsAllowed = input.getControlSwitch(input.CONTROL_SWITCH.Controls) and not core.isWorldPaused() + local controlsAllowed = input.getControlSwitch(input.CONTROL_SWITCH.Controls) + and not core.isWorldPaused() and not I.UI.getMode() if not movementControlsOverridden then if controlsAllowed then processMovement() @@ -165,7 +166,7 @@ local function onInputAction(action) end end - if core.isWorldPaused() then + if core.isWorldPaused() or I.UI.getMode() then return end diff --git a/files/data/scripts/omw/ui.lua b/files/data/scripts/omw/ui.lua index 0c15e53bc3..8199aec8f0 100644 --- a/files/data/scripts/omw/ui.lua +++ b/files/data/scripts/omw/ui.lua @@ -1,6 +1,7 @@ local ui = require('openmw.ui') local util = require('openmw.util') local self = require('openmw.self') +local core = require('openmw.core') local ambient = require('openmw.ambient') local MODE = ui._getAllUiModes() @@ -10,6 +11,11 @@ local replacedWindows = {} local hiddenWindows = {} local modeStack = {} +local modePause = {} +for _, mode in pairs(MODE) do + modePause[mode] = true +end + local function registerWindow(window, showFn, hideFn) if not WINDOW[window] then error('At the moment it is only possible to override existing windows. Window "'.. @@ -114,6 +120,15 @@ local function onUiModeChanged(arg) end end end + local shouldPause = false + for _, m in pairs(modeStack) do + shouldPause = shouldPause or modePause[m] + end + if shouldPause then + core.sendGlobalEvent('Pause', 'ui') + else + core.sendGlobalEvent('Unpause', 'ui') + end self:sendEvent('UiModeChanged', {oldMode = oldMode, newMode = mode, arg = arg}) oldMode = mode end @@ -145,7 +160,7 @@ return { interface = { --- Interface version -- @field [parent=#UI] #number version - version = 0, + version = 1, --- All available UI modes. -- Use `view(I.UI.MODE)` in `luap` console mode to see the list. @@ -204,6 +219,12 @@ return { -- @param #string mode Mode to drop removeMode = removeMode, + --- Set whether the mode should pause the game. + -- @function [parent=#UI] setPauseOnMode + -- @param #string mode Mode to configure + -- @param #boolean shouldPause + setPauseOnMode = function(mode, shouldPause) modePause[mode] = shouldPause end + -- TODO -- registerHudElement = function(name, showFn, hideFn) end, -- showHud = function(bool) end, diff --git a/files/data/scripts/omw/worldeventhandlers.lua b/files/data/scripts/omw/worldeventhandlers.lua new file mode 100644 index 0000000000..4bf6044178 --- /dev/null +++ b/files/data/scripts/omw/worldeventhandlers.lua @@ -0,0 +1,10 @@ +local world = require('openmw.world') + +return { + eventHandlers = { + Pause = function(tag) world.pause(tag) end, + Unpause = function(tag) world.unpause(tag) end, + SetGameTimeScale = function(scale) world.setGameTimeScale(scale) end, + SetSimulationTimeScale = function(scale) world.setSimulationTimeScale(scale) end, + }, +}