diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 645e1ba8f3..184c461cb3 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -64,7 +64,7 @@ add_openmw_dir (mwlua context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings postprocessingbindings stats debugbindings corebindings worldbindings worker magicbindings factionbindings - classbindings itemdata + classbindings itemdata inputprocessor types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc types/creature types/player types/activator types/book types/lockpick types/probe types/apparatus types/potion types/ingredient types/misc types/repair types/armor types/light types/static diff --git a/apps/openmw/mwlua/inputprocessor.hpp b/apps/openmw/mwlua/inputprocessor.hpp new file mode 100644 index 0000000000..112d10c750 --- /dev/null +++ b/apps/openmw/mwlua/inputprocessor.hpp @@ -0,0 +1,73 @@ +#ifndef MWLUA_INPUTPROCESSOR_H +#define MWLUA_INPUTPROCESSOR_H + +#include + +#include +#include +#include + +#include "../mwbase/luamanager.hpp" + +namespace MWLua +{ + class InputProcessor + { + public: + InputProcessor(LuaUtil::ScriptsContainer* scriptsContainer) + : mScriptsContainer(scriptsContainer) + { + mScriptsContainer->registerEngineHandlers({ &mKeyPressHandlers, &mKeyReleaseHandlers, + &mControllerButtonPressHandlers, &mControllerButtonReleaseHandlers, &mActionHandlers, &mTouchpadPressed, + &mTouchpadReleased, &mTouchpadMoved }); + } + + void processInputEvent(const MWBase::LuaManager::InputEvent& event) + { + using InputEvent = MWBase::LuaManager::InputEvent; + switch (event.mType) + { + case InputEvent::KeyPressed: + mScriptsContainer->callEngineHandlers(mKeyPressHandlers, std::get(event.mValue)); + break; + case InputEvent::KeyReleased: + mScriptsContainer->callEngineHandlers(mKeyReleaseHandlers, std::get(event.mValue)); + break; + case InputEvent::ControllerPressed: + mScriptsContainer->callEngineHandlers(mControllerButtonPressHandlers, std::get(event.mValue)); + break; + case InputEvent::ControllerReleased: + mScriptsContainer->callEngineHandlers( + mControllerButtonReleaseHandlers, std::get(event.mValue)); + break; + case InputEvent::Action: + mScriptsContainer->callEngineHandlers(mActionHandlers, std::get(event.mValue)); + break; + case InputEvent::TouchPressed: + mScriptsContainer->callEngineHandlers( + mTouchpadPressed, std::get(event.mValue)); + break; + case InputEvent::TouchReleased: + mScriptsContainer->callEngineHandlers( + mTouchpadReleased, std::get(event.mValue)); + break; + case InputEvent::TouchMoved: + mScriptsContainer->callEngineHandlers(mTouchpadMoved, std::get(event.mValue)); + break; + } + } + + private: + LuaUtil::ScriptsContainer* mScriptsContainer; + LuaUtil::ScriptsContainer::EngineHandlerList mKeyPressHandlers{ "onKeyPress" }; + LuaUtil::ScriptsContainer::EngineHandlerList mKeyReleaseHandlers{ "onKeyRelease" }; + LuaUtil::ScriptsContainer::EngineHandlerList mControllerButtonPressHandlers{ "onControllerButtonPress" }; + LuaUtil::ScriptsContainer::EngineHandlerList mControllerButtonReleaseHandlers{ "onControllerButtonRelease" }; + LuaUtil::ScriptsContainer::EngineHandlerList mActionHandlers{ "onInputAction" }; + LuaUtil::ScriptsContainer::EngineHandlerList mTouchpadPressed{ "onTouchPress" }; + LuaUtil::ScriptsContainer::EngineHandlerList mTouchpadReleased{ "onTouchRelease" }; + LuaUtil::ScriptsContainer::EngineHandlerList mTouchpadMoved{ "onTouchMove" }; + }; +} + +#endif // MWLUA_INPUTPROCESSOR_H diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index 2da2afac5d..5b5a1b7d0d 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -229,7 +229,9 @@ namespace MWLua PlayerScripts* playerScripts = mPlayer.isEmpty() ? nullptr : dynamic_cast(mPlayer.getRefData().getLuaScripts()); MWBase::WindowManager* windowManager = MWBase::Environment::get().getWindowManager(); - // TODO: handle main menu input events + + for (const auto& event : mInputEvents) + mMenuScripts.processInputEvent(event); if (playerScripts && !windowManager->containsMode(MWGui::GM_MainMenu)) { for (const auto& event : mInputEvents) diff --git a/apps/openmw/mwlua/menuscripts.hpp b/apps/openmw/mwlua/menuscripts.hpp index 3fd1bce186..3bd55952ad 100644 --- a/apps/openmw/mwlua/menuscripts.hpp +++ b/apps/openmw/mwlua/menuscripts.hpp @@ -10,6 +10,7 @@ #include "../mwbase/luamanager.hpp" #include "context.hpp" +#include "inputprocessor.hpp" namespace MWLua { @@ -21,10 +22,16 @@ namespace MWLua public: MenuScripts(LuaUtil::LuaState* lua) : LuaUtil::ScriptsContainer(lua, "Menu") + , mInputProcessor(this) { registerEngineHandlers({ &mStateChanged, &mConsoleCommandHandlers, &mUiModeChanged }); } + void processInputEvent(const MWBase::LuaManager::InputEvent& event) + { + mInputProcessor.processInputEvent(event); + } + void stateChanged() { callEngineHandlers(mStateChanged); } bool consoleCommand(const std::string& consoleMode, const std::string& command) @@ -36,6 +43,7 @@ namespace MWLua void uiModeChanged() { callEngineHandlers(mUiModeChanged); } private: + MWLua::InputProcessor mInputProcessor; EngineHandlerList mStateChanged{ "onStateChanged" }; EngineHandlerList mConsoleCommandHandlers{ "onConsoleCommand" }; EngineHandlerList mUiModeChanged{ "_onUiModeChanged" }; diff --git a/apps/openmw/mwlua/playerscripts.hpp b/apps/openmw/mwlua/playerscripts.hpp index 2d3aa9bc78..bc3bee15ca 100644 --- a/apps/openmw/mwlua/playerscripts.hpp +++ b/apps/openmw/mwlua/playerscripts.hpp @@ -7,6 +7,7 @@ #include "../mwbase/luamanager.hpp" +#include "inputprocessor.hpp" #include "localscripts.hpp" namespace MWLua @@ -17,42 +18,14 @@ namespace MWLua public: PlayerScripts(LuaUtil::LuaState* lua, const LObject& obj) : LocalScripts(lua, obj) + , mInputProcessor(this) { - registerEngineHandlers({ &mConsoleCommandHandlers, &mKeyPressHandlers, &mKeyReleaseHandlers, - &mControllerButtonPressHandlers, &mControllerButtonReleaseHandlers, &mActionHandlers, &mOnFrameHandlers, - &mTouchpadPressed, &mTouchpadReleased, &mTouchpadMoved, &mQuestUpdate, &mUiModeChanged }); + registerEngineHandlers({ &mConsoleCommandHandlers, &mOnFrameHandlers, &mQuestUpdate, &mUiModeChanged }); } void processInputEvent(const MWBase::LuaManager::InputEvent& event) { - using InputEvent = MWBase::LuaManager::InputEvent; - switch (event.mType) - { - case InputEvent::KeyPressed: - callEngineHandlers(mKeyPressHandlers, std::get(event.mValue)); - break; - case InputEvent::KeyReleased: - callEngineHandlers(mKeyReleaseHandlers, std::get(event.mValue)); - break; - case InputEvent::ControllerPressed: - callEngineHandlers(mControllerButtonPressHandlers, std::get(event.mValue)); - break; - case InputEvent::ControllerReleased: - callEngineHandlers(mControllerButtonReleaseHandlers, std::get(event.mValue)); - break; - case InputEvent::Action: - callEngineHandlers(mActionHandlers, std::get(event.mValue)); - break; - case InputEvent::TouchPressed: - callEngineHandlers(mTouchpadPressed, std::get(event.mValue)); - break; - case InputEvent::TouchReleased: - callEngineHandlers(mTouchpadReleased, std::get(event.mValue)); - break; - case InputEvent::TouchMoved: - callEngineHandlers(mTouchpadMoved, std::get(event.mValue)); - break; - } + mInputProcessor.processInputEvent(event); } void onFrame(float dt) { callEngineHandlers(mOnFrameHandlers, dt); } @@ -75,16 +48,9 @@ namespace MWLua } private: + InputProcessor mInputProcessor; EngineHandlerList mConsoleCommandHandlers{ "onConsoleCommand" }; - EngineHandlerList mKeyPressHandlers{ "onKeyPress" }; - EngineHandlerList mKeyReleaseHandlers{ "onKeyRelease" }; - EngineHandlerList mControllerButtonPressHandlers{ "onControllerButtonPress" }; - EngineHandlerList mControllerButtonReleaseHandlers{ "onControllerButtonRelease" }; - EngineHandlerList mActionHandlers{ "onInputAction" }; EngineHandlerList mOnFrameHandlers{ "onFrame" }; - EngineHandlerList mTouchpadPressed{ "onTouchPress" }; - EngineHandlerList mTouchpadReleased{ "onTouchRelease" }; - EngineHandlerList mTouchpadMoved{ "onTouchMove" }; EngineHandlerList mQuestUpdate{ "onQuestUpdate" }; EngineHandlerList mUiModeChanged{ "_onUiModeChanged" }; }; diff --git a/components/lua/scriptscontainer.hpp b/components/lua/scriptscontainer.hpp index 631b1e58a8..b3fb0bd376 100644 --- a/components/lua/scriptscontainer.hpp +++ b/components/lua/scriptscontainer.hpp @@ -157,7 +157,8 @@ namespace LuaUtil void collectStats(std::vector& stats) const; static int64_t getInstanceCount() { return sInstanceCount; } - protected: + public: // TODO: public to be available to MWLua::InputProcessor. Consider other ways of reusing engine handlers + // between containers struct Handler { int mScriptId; @@ -198,6 +199,7 @@ namespace LuaUtil // a public function (see how ScriptsContainer::update is implemented) that calls `callEngineHandlers`. void registerEngineHandlers(std::initializer_list handlers); + protected: const std::string mNamePrefix; LuaUtil::LuaState& mLua; diff --git a/docs/source/reference/lua-scripting/engine_handlers.rst b/docs/source/reference/lua-scripting/engine_handlers.rst index 6ef9846d2e..e4ef9b20e4 100644 --- a/docs/source/reference/lua-scripting/engine_handlers.rst +++ b/docs/source/reference/lua-scripting/engine_handlers.rst @@ -80,23 +80,16 @@ Engine handler is a function defined by a script, that can be called by the engi | Similarly to onActivated, the item has already been removed | from the actor's inventory, and the count was set to zero. -**Only for local scripts attached to a player** +**Only menu scripts and local scripts attached to a player** .. list-table:: :widths: 20 80 - * - onFrame(dt) - - | Called every frame (even if the game is paused) right after - | processing user input. Use it only for latency-critical stuff - | and for UI that should work on pause. - | `dt` is simulation time delta (0 when on pause). - * - onKeyPress(key) +* - onKeyPress(key) - | `Key `_ is pressed. | Usage example: | ``if key.symbol == 'z' and key.withShift then ...`` - * - onQuestUpdate(questId, stage) - - | Called when a quest is updated. - * - onKeyRelease(key) + * - onKeyRelease(key) - | `Key `_ is released. | Usage example: | ``if key.symbol == 'z' and key.withShift then ...`` @@ -127,6 +120,24 @@ Engine handler is a function defined by a script, that can be called by the engi - | User entered `command` in in-game console. Called if either | `mode` is not default or `command` starts with prefix `lua`. +**Only for local scripts attached to a player** + +.. list-table:: + :widths: 20 80 + * - onFrame(dt) + - | Called every frame (even if the game is paused) right after + | processing user input. Use it only for latency-critical stuff + | and for UI that should work on pause. + | `dt` is simulation time delta (0 when on pause). + * - onKeyPress(key) + - | `Key `_ is pressed. + | Usage example: + | ``if key.symbol == 'z' and key.withShift then ...`` + * - onQuestUpdate(questId, stage) + - | Called when a quest is updated. + + + **Only for menu scripts** .. list-table:: @@ -134,7 +145,3 @@ Engine handler is a function defined by a script, that can be called by the engi * - onStateChanged() - | Called whenever the current game changes | (i. e. the result of `getState `_ changes) - * - | onConsoleCommand( - | mode, command, selectedObject) - - | User entered `command` in in-game console. Called if either - | `mode` is not default or `command` starts with prefix `lua`.