Allow Lua scripts to handle input actions when UI is opened. Also fixes #6456.

pull/3225/head
Petr Mikheev 3 years ago
parent 7549496162
commit db72380ba9

@ -296,7 +296,7 @@ bool OMW::Engine::frame(float frametime)
// Should be called after input manager update and before any change to the game world.
// It applies to the game world queued changes from the previous frame.
mLuaManager->synchronizedUpdate(mEnvironment.getWindowManager()->isGuiMode(), frametime);
mLuaManager->synchronizedUpdate();
// update game state
{
@ -873,10 +873,8 @@ public:
mThread = std::thread([this]{ threadBody(); });
};
void allowUpdate(double dt)
void allowUpdate()
{
mDt = dt;
mIsGuiMode = mEngine->mEnvironment.getWindowManager()->isGuiMode();
if (!mThread)
return;
{
@ -918,7 +916,7 @@ private:
const unsigned int frameNumber = viewer->getFrameStamp()->getFrameNumber();
ScopedProfile<UserStatsType::Lua> profile(frameStart, frameNumber, *osg::Timer::instance(), *viewer->getViewerStats());
mEngine->mLuaManager->update(mIsGuiMode, mDt);
mEngine->mLuaManager->update();
}
void threadBody()
@ -943,8 +941,6 @@ private:
std::condition_variable mCV;
bool mUpdateRequest = false;
bool mJoinRequest = false;
double mDt = 0;
bool mIsGuiMode = false;
std::optional<std::thread> mThread;
};
@ -1057,7 +1053,7 @@ void OMW::Engine::go()
mEnvironment.getWorld()->updateWindowManager();
luaWorker.allowUpdate(dt); // if there is a separate Lua thread, it starts the update now
luaWorker.allowUpdate(); // if there is a separate Lua thread, it starts the update now
mViewer->renderingTraversals();

@ -25,7 +25,7 @@ namespace MWLua
{
auto* lua = context.mLua;
sol::table api(lua->sol(), sol::create);
api["API_REVISION"] = 10;
api["API_REVISION"] = 11;
api["quit"] = [lua]()
{
Log(Debug::Warning) << "Quit requested by a Lua script.\n" << lua->debugTraceback();
@ -37,6 +37,7 @@ namespace MWLua
};
api["getGameTimeInSeconds"] = [world=context.mWorldView]() { return world->getGameTimeInSeconds(); };
api["getGameTimeInHours"] = [world=context.mWorldView]() { return world->getGameTimeInHours(); };
api["isWorldPaused"] = [world=context.mWorldView]() { return world->isPaused(); };
api["OBJECT_TYPE"] = definitionList(*lua,
{
"Activator", "Armor", "Book", "Clothing", "Creature", "Door", "Ingredient",

@ -78,11 +78,12 @@ namespace MWLua
mInitialized = true;
}
void LuaManager::update(bool paused, float dt)
void LuaManager::update()
{
if (mPlayer.isEmpty())
return; // The game is not started yet.
float frameDuration = MWBase::Environment::get().getFrameDuration();
ObjectRegistry* objectRegistry = mWorldView.getObjectRegistry();
MWWorld::Ptr newPlayerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr();
@ -101,9 +102,9 @@ namespace MWLua
mGlobalEvents = std::vector<GlobalEvent>();
mLocalEvents = std::vector<LocalEvent>();
if (!paused)
if (!mWorldView.isPaused())
{ // Update time and process timers
double seconds = mWorldView.getGameTimeInSeconds() + dt;
double seconds = mWorldView.getGameTimeInSeconds() + frameDuration;
mWorldView.setGameTimeInSeconds(seconds);
double hours = mWorldView.getGameTimeInHours();
@ -146,10 +147,10 @@ namespace MWLua
}
mLocalEngineEvents.clear();
if (!paused)
if (!mWorldView.isPaused())
{
for (LocalScripts* scripts : mActiveLocalScripts)
scripts->update(dt);
scripts->update(frameDuration);
}
// Engine handlers in global scripts
@ -168,24 +169,25 @@ namespace MWLua
mGlobalScripts.actorActive(GObject(id, objectRegistry));
mActorAddedEvents.clear();
if (!paused)
mGlobalScripts.update(dt);
if (!mWorldView.isPaused())
mGlobalScripts.update(frameDuration);
}
void LuaManager::synchronizedUpdate(bool paused, float dt)
void LuaManager::synchronizedUpdate()
{
if (mPlayer.isEmpty())
return; // The game is not started yet.
// We apply input events in `synchronizedUpdate` rather than in `update` in order to reduce input latency.
PlayerScripts* playerScripts = dynamic_cast<PlayerScripts*>(mPlayer.getRefData().getLuaScripts());
if (playerScripts && !paused)
if (playerScripts && !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
{
for (const auto& event : mInputEvents)
playerScripts->processInputEvent(event);
playerScripts->inputUpdate(dt);
}
mInputEvents.clear();
if (playerScripts && !mWorldView.isPaused())
playerScripts->inputUpdate(MWBase::Environment::get().getFrameDuration());
MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager();
for (const std::string& message : mUIMessages)

@ -29,10 +29,10 @@ namespace MWLua
// Called by engine.cpp every frame. For performance reasons it works in a separate
// thread (in parallel with osg Cull). Can not use scene graph.
void update(bool paused, float dt);
void update();
// Called by engine.cpp from the main thread. Can use scene graph.
void synchronizedUpdate(bool paused, float dt);
void synchronizedUpdate();
// Available everywhere through the MWBase::LuaManager interface.
// LuaManager queues these events and propagates to scripts on the next `update` call.

@ -4,6 +4,8 @@
#include <components/esm/esmwriter.hpp>
#include <components/esm/loadcell.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwclass/container.hpp"
#include "../mwworld/class.hpp"
@ -20,6 +22,7 @@ namespace MWLua
mContainersInScene.updateList();
mDoorsInScene.updateList();
mItemsInScene.updateList();
mPaused = MWBase::Environment::get().getWindowManager()->isGuiMode();
}
void WorldView::clear()

@ -19,6 +19,9 @@ namespace MWLua
void update(); // Should be called every frame.
void clear(); // Should be called every time before starting or loading a new game.
// Whether the world is paused (i.e. game time is not changing and actors don't move).
bool isPaused() const { return mPaused; }
// Returns the number of seconds passed from the beginning of the game.
double getGameTimeInSeconds() const { return mGameSeconds; }
void setGameTimeInSeconds(double t) { mGameSeconds = t; }
@ -74,6 +77,7 @@ namespace MWLua
ObjectGroup mItemsInScene;
double mGameSeconds = 0;
bool mPaused = false;
};
}

@ -1,4 +1,5 @@
local camera = require('openmw.camera')
local core = require('openmw.core')
local input = require('openmw.input')
local settings = require('openmw.settings')
local util = require('openmw.util')
@ -225,6 +226,7 @@ return {
onUpdate = onUpdate,
onInputUpdate = onInputUpdate,
onInputAction = function(action)
if core.isWorldPaused() then return end
if action == input.ACTION.ZoomIn then
zoom(10)
elseif action == input.ACTION.ZoomOut then

@ -22,7 +22,7 @@
-------------------------------------------------------------------------------
-- Game time in seconds.
-- The number of seconds in the game world, passed from starting a new game.
-- The number of seconds passed in the game world since starting a new game.
-- @function [parent=#core] getGameTimeInSeconds
-- @return #number
@ -32,6 +32,11 @@
-- @function [parent=#core] getGameTimeInHours
-- @return #number
-------------------------------------------------------------------------------
-- Whether the world is paused (onUpdate doesn't work when the world is paused).
-- @function [parent=#core] isWorldPaused
-- @return #boolean
-------------------------------------------------------------------------------
-- @type OBJECT_TYPE

Loading…
Cancel
Save