1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-03 17:39:42 +00:00

Apply lua handlers for user input in the main thread in order to reduce latency.

This commit is contained in:
Petr Mikheev 2021-11-17 03:05:50 +01:00
parent 47cbdcba15
commit e56ee2c735
5 changed files with 27 additions and 13 deletions

View file

@ -293,6 +293,10 @@ bool OMW::Engine::frame(float frametime)
// Main menu opened? Then scripts are also paused.
bool paused = mEnvironment.getWindowManager()->containsMode(MWGui::GM_MainMenu);
// 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(paused, frametime);
// update game state
{
ScopedProfile<UserStatsType::State> profile(frameStart, frameNumber, *timer, *stats);
@ -874,7 +878,6 @@ public:
}
else
update();
mEngine->mLuaManager->applyQueuedChanges();
};
void join()

View file

@ -132,14 +132,6 @@ namespace MWLua
mQueuedCallbacks.clear();
// Engine handlers in local scripts
PlayerScripts* playerScripts = dynamic_cast<PlayerScripts*>(mPlayer.getRefData().getLuaScripts());
if (playerScripts && !paused)
{
for (const auto& event : mInputEvents)
playerScripts->processInputEvent(event);
}
mInputEvents.clear();
for (const LocalEngineEvent& e : mLocalEngineEvents)
{
LObject obj(e.mDest, objectRegistry);
@ -180,8 +172,21 @@ namespace MWLua
mGlobalScripts.update(dt);
}
void LuaManager::applyQueuedChanges()
void LuaManager::synchronizedUpdate(bool paused, float dt)
{
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)
{
for (const auto& event : mInputEvents)
playerScripts->processInputEvent(event);
playerScripts->inputUpdate(dt);
}
mInputEvents.clear();
MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager();
for (const std::string& message : mUIMessages)
windowManager->messageBox(message);

View file

@ -32,7 +32,7 @@ namespace MWLua
void update(bool paused, float dt);
// Called by engine.cpp from the main thread. Can use scene graph.
void applyQueuedChanges();
void synchronizedUpdate(bool paused, float dt);
// Available everywhere through the MWBase::LuaManager interface.
// LuaManager queues these events and propagates to scripts on the next `update` call.

View file

@ -17,7 +17,7 @@ namespace MWLua
{
registerEngineHandlers({&mKeyPressHandlers, &mKeyReleaseHandlers,
&mControllerButtonPressHandlers, &mControllerButtonReleaseHandlers,
&mActionHandlers});
&mActionHandlers, &mInputUpdateHandlers});
}
void processInputEvent(const MWBase::LuaManager::InputEvent& event)
@ -43,12 +43,15 @@ namespace MWLua
}
}
void inputUpdate(float dt) { callEngineHandlers(mInputUpdateHandlers, dt); }
private:
EngineHandlerList mKeyPressHandlers{"onKeyPress"};
EngineHandlerList mKeyReleaseHandlers{"onKeyRelease"};
EngineHandlerList mControllerButtonPressHandlers{"onControllerButtonPress"};
EngineHandlerList mControllerButtonReleaseHandlers{"onControllerButtonRelease"};
EngineHandlerList mActionHandlers{"onInputAction"};
EngineHandlerList mInputUpdateHandlers{"onInputUpdate"};
};
}

View file

@ -10,7 +10,7 @@ Engine handler is a function defined by a script, that can be called by the engi
| | | `be assigned to a script in openmw-cs (not yet implemented)`. |
| | | ``onInterfaceOverride`` can be called before ``onInit``. |
+----------------------------------+----------------------------------------------------------------------+
| onUpdate(dt) | | Called every frame if game not paused. `dt` is the time |
| onUpdate(dt) | | Called every frame if the game is not paused. `dt` is the time |
| | | from the last update in seconds. |
+----------------------------------+----------------------------------------------------------------------+
| onSave() -> savedData | | Called when the game is saving. May be called in inactive |
@ -44,6 +44,9 @@ Engine handler is a function defined by a script, that can be called by the engi
+----------------------------------+----------------------------------------------------------------------+
| **Only for local scripts attached to a player** |
+----------------------------------+----------------------------------------------------------------------+
| onInputUpdate(dt) | | Called every frame (if the game is not paused) right after |
| | | processing user input. Use it only for latency-critical stuff. |
+----------------------------------+----------------------------------------------------------------------+
| onKeyPress(key) | | `Key <openmw_input.html##(KeyboardEvent)>`_ is pressed. |
| | | Usage example: ``if key.symbol == 'z' and key.withShift then ...`` |
+----------------------------------+----------------------------------------------------------------------+