Lua package 'openmw.input'

pull/3097/head
Petr Mikheev 4 years ago
parent ee1ec53cd9
commit 0e6fbbc126

@ -57,7 +57,8 @@ add_openmw_dir (mwscript
add_openmw_dir (mwlua
luamanagerimp actions object worldview userdataserializer eventqueue query
luabindings localscripts objectbindings cellbindings asyncbindings camerabindings uibindings settingsbindings
luabindings localscripts objectbindings cellbindings asyncbindings settingsbindings
camerabindings uibindings inputbindings
)
add_openmw_dir (mwsound

@ -5,6 +5,7 @@
#include <set>
#include <vector>
#include <SDL_gamecontroller.h>
#include <stdint.h>
namespace Loading
@ -51,9 +52,17 @@ namespace MWBase
virtual void toggleControlSwitch (const std::string& sw, bool value) = 0;
virtual bool getControlSwitch (const std::string& sw) = 0;
virtual std::string getActionDescription (int action) = 0;
virtual std::string getActionKeyBindingName (int action) = 0;
virtual std::string getActionControllerBindingName (int action) = 0;
virtual std::string getActionDescription (int action) const = 0;
virtual std::string getActionKeyBindingName (int action) const = 0;
virtual std::string getActionControllerBindingName (int action) const = 0;
virtual bool actionIsActive(int action) const = 0;
virtual float getActionValue(int action) const = 0; // returns value in range [0, 1]
virtual float getControllerAxisValue(SDL_GameControllerAxis axis) const = 0; // returns value in range [-1, 1]
virtual uint32_t getMouseButtonsState() const = 0;
virtual int getMouseMoveX() const = 0;
virtual int getMouseMoveY() const = 0;
///Actions available for binding to keyboard buttons
virtual std::vector<int> getActionKeySorting() = 0;
///Actions available for binding to controller buttons
@ -74,6 +83,7 @@ namespace MWBase
virtual void readRecord(ESM::ESMReader& reader, uint32_t type) = 0;
virtual void resetIdleTime() = 0;
virtual bool isIdle() const = 0;
virtual void executeAction(int action) = 0;

@ -1,6 +1,7 @@
#ifndef GAME_MWBASE_LUAMANAGER_H
#define GAME_MWBASE_LUAMANAGER_H
#include <variant>
#include <SDL_events.h>
namespace MWWorld
@ -29,8 +30,6 @@ namespace MWBase
virtual ~LuaManager() = default;
virtual void newGameStarted() = 0;
virtual void keyPressed(const SDL_KeyboardEvent &arg) = 0;
virtual void registerObject(const MWWorld::Ptr& ptr) = 0;
virtual void deregisterObject(const MWWorld::Ptr& ptr) = 0;
virtual void objectAddedToScene(const MWWorld::Ptr& ptr) = 0;
@ -40,6 +39,13 @@ namespace MWBase
// virtual void objectOnHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object,
// const MWWorld::Ptr &attacker, const osg::Vec3f &hitPosition, bool successful) = 0;
struct InputEvent
{
enum {KeyPressed, KeyReleased, ControllerPressed, ControllerReleased, Action} mType;
std::variant<SDL_Keysym, int> mValue;
};
virtual void inputEvent(const InputEvent& event) = 0;
struct ActorControls
{
bool mDisableAI = false;

@ -9,6 +9,7 @@
#include "../mwbase/inputmanager.hpp"
#include "../mwbase/statemanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/luamanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
@ -195,6 +196,7 @@ namespace MWInput
void ActionManager::executeAction(int action)
{
MWBase::Environment::get().getLuaManager()->inputEvent({MWBase::LuaManager::InputEvent::Action, action});
auto* inputManager = MWBase::Environment::get().getInputManager();
auto* windowManager = MWBase::Environment::get().getWindowManager();
// trigger action activated

@ -48,6 +48,7 @@ namespace MWInput
void showQuickKeysMenu();
void resetIdleTime();
float getIdleTime() const { return mTimeIdle; }
bool isAlwaysRunActive() const { return mAlwaysRunActive; };
bool isSneaking() const { return mSneaking; };

@ -653,6 +653,16 @@ namespace MWInput
return mInputBinder->getKeyBinding(mInputBinder->getControl(actionId), ICS::Control::INCREASE);
}
float BindingsManager::getControllerAxisValue(SDL_GameControllerAxis axis) const
{
const auto& controllers = mInputBinder->getJoystickInstanceMap();
if (controllers.empty())
return 0;
SDL_GameController* cntrl = controllers.begin()->second;
constexpr int AXIS_MAX_ABSOLUTE_VALUE = 32768;
return SDL_GameControllerGetAxis(cntrl, axis) / static_cast<float>(AXIS_MAX_ABSOLUTE_VALUE);
}
void BindingsManager::actionValueChanged(int action, float currentValue, float previousValue)
{
MWBase::Environment::get().getInputManager()->resetIdleTime();

@ -42,7 +42,8 @@ namespace MWInput
bool isLeftOrRightButton(int action, bool joystick) const;
bool actionIsActive(int id) const;
float getActionValue(int id) const;
float getActionValue(int id) const; // returns value in range [0, 1]
float getControllerAxisValue(SDL_GameControllerAxis axis) const; // returns value in range [-1, 1]
void mousePressed(const SDL_MouseButtonEvent &evt, int deviceID);
void mouseReleased(const SDL_MouseButtonEvent &arg, int deviceID);

@ -8,6 +8,7 @@
#include "../mwbase/environment.hpp"
#include "../mwbase/inputmanager.hpp"
#include "../mwbase/luamanager.hpp"
#include "../mwbase/statemanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
@ -198,6 +199,9 @@ namespace MWInput
if (!mJoystickEnabled || mBindingsManager->isDetectingBindingState())
return;
MWBase::Environment::get().getLuaManager()->inputEvent(
{MWBase::LuaManager::InputEvent::ControllerPressed, arg.button});
mJoystickLastUsed = true;
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
@ -240,6 +244,12 @@ namespace MWInput
return;
}
if (mJoystickEnabled)
{
MWBase::Environment::get().getLuaManager()->inputEvent(
{MWBase::LuaManager::InputEvent::ControllerReleased, arg.button});
}
if (!mJoystickEnabled || MWBase::Environment::get().getInputManager()->controlsDisabled())
return;

@ -150,21 +150,56 @@ namespace MWInput
mActionManager->resetIdleTime();
}
std::string InputManager::getActionDescription(int action)
bool InputManager::isIdle() const
{
return mActionManager->getIdleTime() > 0.5;
}
std::string InputManager::getActionDescription(int action) const
{
return mBindingsManager->getActionDescription(action);
}
std::string InputManager::getActionKeyBindingName(int action)
std::string InputManager::getActionKeyBindingName(int action) const
{
return mBindingsManager->getActionKeyBindingName(action);
}
std::string InputManager::getActionControllerBindingName(int action)
std::string InputManager::getActionControllerBindingName(int action) const
{
return mBindingsManager->getActionControllerBindingName(action);
}
bool InputManager::actionIsActive(int action) const
{
return mBindingsManager->actionIsActive(action);
}
float InputManager::getActionValue(int action) const
{
return mBindingsManager->getActionValue(action);
}
float InputManager::getControllerAxisValue(SDL_GameControllerAxis axis) const
{
return mBindingsManager->getControllerAxisValue(axis);
}
uint32_t InputManager::getMouseButtonsState() const
{
return mMouseManager->getButtonsState();
}
int InputManager::getMouseMoveX() const
{
return mMouseManager->getMouseMoveX();
}
int InputManager::getMouseMoveY() const
{
return mMouseManager->getMouseMoveY();
}
std::vector<int> InputManager::getActionKeySorting()
{
return mBindingsManager->getActionKeySorting();

@ -73,9 +73,17 @@ namespace MWInput
void toggleControlSwitch (const std::string& sw, bool value) override;
bool getControlSwitch (const std::string& sw) override;
std::string getActionDescription (int action) override;
std::string getActionKeyBindingName (int action) override;
std::string getActionControllerBindingName (int action) override;
std::string getActionDescription (int action) const override;
std::string getActionKeyBindingName (int action) const override;
std::string getActionControllerBindingName (int action) const override;
bool actionIsActive(int action) const override;
float getActionValue(int action) const override;
float getControllerAxisValue(SDL_GameControllerAxis axis) const override;
uint32_t getMouseButtonsState() const override;
int getMouseMoveX() const override;
int getMouseMoveY() const override;
int getNumActions() override { return A_Last; }
std::vector<int> getActionKeySorting() override;
std::vector<int> getActionControllerSorting() override;
@ -91,6 +99,7 @@ namespace MWInput
void readRecord(ESM::ESMReader& reader, uint32_t type) override;
void resetIdleTime() override;
bool isIdle() const override;
void executeAction(int action) override;

@ -60,7 +60,10 @@ namespace MWInput
mBindingsManager->keyPressed(arg);
if (!consumed)
MWBase::Environment::get().getLuaManager()->keyPressed(arg);
{
MWBase::Environment::get().getLuaManager()->inputEvent(
{MWBase::LuaManager::InputEvent::KeyPressed, arg.keysym});
}
input->setJoystickLastUsed(false);
}
@ -73,5 +76,6 @@ namespace MWInput
if (!mBindingsManager->isDetectingBindingState())
mBindingsManager->setPlayerControlsEnabled(!MyGUI::InputManager::getInstance().injectKeyRelease(kc));
mBindingsManager->keyReleased(arg);
MWBase::Environment::get().getLuaManager()->inputEvent({MWBase::LuaManager::InputEvent::KeyReleased, arg.keysym});
}
}

@ -34,6 +34,9 @@ namespace MWInput
, mMouseWheel(0)
, mMouseLookEnabled(false)
, mGuiCursorEnabled(true)
, mButtonsState(0)
, mMouseMoveX(0)
, mMouseMoveY(0)
{
int w,h;
SDL_GetWindowSize(window, &w, &h);
@ -196,6 +199,8 @@ namespace MWInput
void MouseManager::update(float dt)
{
mButtonsState = SDL_GetRelativeMouseState(&mMouseMoveX, &mMouseMoveY);
if (!mMouseLookEnabled)
return;

@ -38,6 +38,10 @@ namespace MWInput
void setMouseLookEnabled(bool enabled) { mMouseLookEnabled = enabled; }
void setGuiCursorEnabled(bool enabled) { mGuiCursorEnabled = enabled; }
uint32_t getButtonsState() const { return mButtonsState; }
int getMouseMoveX() const { return mMouseMoveX; }
int getMouseMoveY() const { return mMouseMoveY; }
private:
bool mInvertX;
bool mInvertY;
@ -53,6 +57,10 @@ namespace MWInput
int mMouseWheel;
bool mMouseLookEnabled;
bool mGuiCursorEnabled;
uint32_t mButtonsState;
int mMouseMoveX;
int mMouseMoveY;
};
}
#endif

@ -0,0 +1,150 @@
#include "luabindings.hpp"
#include <SDL_events.h>
#include <SDL_gamecontroller.h>
#include "../mwbase/inputmanager.hpp"
#include "../mwinput/actions.hpp"
namespace sol
{
template <>
struct is_automagical<SDL_Keysym> : std::false_type {};
}
namespace MWLua
{
sol::table initInputPackage(const Context& context)
{
sol::usertype<SDL_Keysym> keyEvent = context.mLua->sol().new_usertype<SDL_Keysym>("KeyEvent");
keyEvent["symbol"] = sol::readonly_property([](const SDL_Keysym& e) { return std::string(1, static_cast<char>(e.sym)); });
keyEvent["code"] = sol::readonly_property([](const SDL_Keysym& e) -> int { return e.sym; });
keyEvent["modifiers"] = sol::readonly_property([](const SDL_Keysym& e) -> int { return e.mod; });
keyEvent["withShift"] = sol::readonly_property([](const SDL_Keysym& e) -> bool { return e.mod & KMOD_SHIFT; });
keyEvent["withCtrl"] = sol::readonly_property([](const SDL_Keysym& e) -> bool { return e.mod & KMOD_CTRL; });
keyEvent["withAlt"] = sol::readonly_property([](const SDL_Keysym& e) -> bool { return e.mod & KMOD_ALT; });
keyEvent["withSuper"] = sol::readonly_property([](const SDL_Keysym& e) -> bool { return e.mod & KMOD_GUI; });
MWBase::InputManager* input = MWBase::Environment::get().getInputManager();
sol::table api(context.mLua->sol(), sol::create);
api["isIdle"] = [input]() { return input->isIdle(); };
api["isActionPressed"] = [input](int action) { return input->actionIsActive(action); };
api["isMouseButtonPressed"] = [input](int button) -> bool
{
return input->getMouseButtonsState() & (1 << (button - 1));
};
api["getMouseMoveX"] = [input]() { return input->getMouseMoveX(); };
api["getMouseMoveY"] = [input]() { return input->getMouseMoveY(); };
api["getAxisValue"] = [input](int axis)
{
if (axis < SDL_CONTROLLER_AXIS_MAX)
return input->getControllerAxisValue(static_cast<SDL_GameControllerAxis>(axis));
else
return input->getActionValue(axis - SDL_CONTROLLER_AXIS_MAX) * 2 - 1;
};
api["getControlSwitch"] = [input](const std::string& key) { return input->getControlSwitch(key); };
api["setControlSwitch"] = [input](const std::string& key, bool v) { input->toggleControlSwitch(key, v); };
api["ACTION"] = context.mLua->makeReadOnly(context.mLua->sol().create_table_with(
"GameMenu", MWInput::A_GameMenu,
"Screenshot", MWInput::A_Screenshot,
"Inventory", MWInput::A_Inventory,
"Console", MWInput::A_Console,
"MoveLeft", MWInput::A_MoveLeft,
"MoveRight", MWInput::A_MoveRight,
"MoveForward", MWInput::A_MoveForward,
"MoveBackward", MWInput::A_MoveBackward,
"Activate", MWInput::A_Activate,
"Use", MWInput::A_Use,
"Jump", MWInput::A_Jump,
"AutoMove", MWInput::A_AutoMove,
"Rest", MWInput::A_Rest,
"Journal", MWInput::A_Journal,
"Weapon", MWInput::A_Weapon,
"Spell", MWInput::A_Spell,
"Run", MWInput::A_Run,
"CycleSpellLeft", MWInput::A_CycleSpellLeft,
"CycleSpellRight", MWInput::A_CycleSpellRight,
"CycleWeaponLeft", MWInput::A_CycleWeaponLeft,
"CycleWeaponRight", MWInput::A_CycleWeaponRight,
"ToggleSneak", MWInput::A_ToggleSneak,
"AlwaysRun", MWInput::A_AlwaysRun,
"Sneak", MWInput::A_Sneak,
"QuickSave", MWInput::A_QuickSave,
"QuickLoad", MWInput::A_QuickLoad,
"QuickMenu", MWInput::A_QuickMenu,
"ToggleWeapon", MWInput::A_ToggleWeapon,
"ToggleSpell", MWInput::A_ToggleSpell,
"TogglePOV", MWInput::A_TogglePOV,
"QuickKey1", MWInput::A_QuickKey1,
"QuickKey2", MWInput::A_QuickKey2,
"QuickKey3", MWInput::A_QuickKey3,
"QuickKey4", MWInput::A_QuickKey4,
"QuickKey5", MWInput::A_QuickKey5,
"QuickKey6", MWInput::A_QuickKey6,
"QuickKey7", MWInput::A_QuickKey7,
"QuickKey8", MWInput::A_QuickKey8,
"QuickKey9", MWInput::A_QuickKey9,
"QuickKey10", MWInput::A_QuickKey10,
"QuickKeysMenu", MWInput::A_QuickKeysMenu,
"ToggleHUD", MWInput::A_ToggleHUD,
"ToggleDebug", MWInput::A_ToggleDebug,
"ZoomIn", MWInput::A_ZoomIn,
"ZoomOut", MWInput::A_ZoomOut
));
api["CONTROL_SWITCH"] = context.mLua->makeReadOnly(context.mLua->sol().create_table_with(
"Controls", "playercontrols",
"Fighting", "playerfighting",
"Jumping", "playerjumping",
"Looking", "playerlooking",
"Magic", "playermagic",
"ViewMode", "playerviewswitch",
"VanityMode", "vanitymode"
));
api["CONTROLLER_BUTTON"] = context.mLua->makeReadOnly(context.mLua->sol().create_table_with(
"A", SDL_CONTROLLER_BUTTON_A,
"B", SDL_CONTROLLER_BUTTON_B,
"X", SDL_CONTROLLER_BUTTON_X,
"Y", SDL_CONTROLLER_BUTTON_Y,
"Back", SDL_CONTROLLER_BUTTON_BACK,
"Guide", SDL_CONTROLLER_BUTTON_GUIDE,
"Start", SDL_CONTROLLER_BUTTON_START,
"LeftStick", SDL_CONTROLLER_BUTTON_LEFTSTICK,
"RightStick", SDL_CONTROLLER_BUTTON_RIGHTSTICK,
"LeftShoulder", SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
"RightShoulder", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
"DPadUp", SDL_CONTROLLER_BUTTON_DPAD_UP,
"DPadDown", SDL_CONTROLLER_BUTTON_DPAD_DOWN,
"DPadLeft", SDL_CONTROLLER_BUTTON_DPAD_LEFT,
"DPadRight", SDL_CONTROLLER_BUTTON_DPAD_RIGHT
));
api["CONTROLLER_AXIS"] = context.mLua->makeReadOnly(context.mLua->sol().create_table_with(
"LeftX", SDL_CONTROLLER_AXIS_LEFTX,
"LeftY", SDL_CONTROLLER_AXIS_LEFTY,
"RightX", SDL_CONTROLLER_AXIS_RIGHTX,
"RightY", SDL_CONTROLLER_AXIS_RIGHTY,
"TriggerLeft", SDL_CONTROLLER_AXIS_TRIGGERLEFT,
"TriggerRight", SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
"LookUpDown", SDL_CONTROLLER_AXIS_MAX + MWInput::A_LookUpDown,
"LookLeftRight", SDL_CONTROLLER_AXIS_MAX + MWInput::A_LookLeftRight,
"MoveForwardBackward", SDL_CONTROLLER_AXIS_MAX + MWInput::A_MoveForwardBackward,
"MoveLeftRight", SDL_CONTROLLER_AXIS_MAX + MWInput::A_MoveLeftRight
));
return context.mLua->makeReadOnly(api);
}
}

@ -1,7 +1,5 @@
#include "luabindings.hpp"
#include <SDL_events.h>
#include <components/lua/luastate.hpp>
#include <components/queries/luabindings.hpp>
@ -12,12 +10,6 @@
#include "eventqueue.hpp"
#include "worldview.hpp"
namespace sol
{
template <>
struct is_automagical<SDL_Keysym> : std::false_type {};
}
namespace MWLua
{
@ -33,7 +25,7 @@ namespace MWLua
{
auto* lua = context.mLua;
sol::table api(lua->sol(), sol::create);
api["API_REVISION"] = 3;
api["API_REVISION"] = 4;
api["quit"] = [lua]()
{
std::string traceback = lua->sol()["debug"]["traceback"]().get<std::string>();
@ -179,17 +171,5 @@ namespace MWLua
return context.mLua->makeReadOnly(res);
}
void initInputBindings(const Context& context)
{
sol::usertype<SDL_Keysym> keyEvent = context.mLua->sol().new_usertype<SDL_Keysym>("KeyEvent");
keyEvent["symbol"] = sol::readonly_property([](const SDL_Keysym& e) { return std::string(1, static_cast<char>(e.sym)); });
keyEvent["code"] = sol::readonly_property([](const SDL_Keysym& e) -> int { return e.sym; });
keyEvent["modifiers"] = sol::readonly_property([](const SDL_Keysym& e) -> int { return e.mod; });
keyEvent["withShift"] = sol::readonly_property([](const SDL_Keysym& e) -> bool { return e.mod & KMOD_SHIFT; });
keyEvent["withCtrl"] = sol::readonly_property([](const SDL_Keysym& e) -> bool { return e.mod & KMOD_CTRL; });
keyEvent["withAlt"] = sol::readonly_property([](const SDL_Keysym& e) -> bool { return e.mod & KMOD_ALT; });
keyEvent["withSuper"] = sol::readonly_property([](const SDL_Keysym& e) -> bool { return e.mod & KMOD_GUI; });
}
}

@ -26,8 +26,6 @@ namespace MWLua
sol::table initFieldGroup(const Context&, const QueryFieldGroup&);
void initInputBindings(const Context&);
// Implemented in objectbindings.cpp
void initObjectBindingsForLocalScripts(const Context&);
void initObjectBindingsForGlobalScripts(const Context&);
@ -59,6 +57,9 @@ namespace MWLua
// Implemented in uibindings.cpp
sol::table initUserInterfacePackage(const Context&);
// Implemented in inputbindings.cpp
sol::table initInputPackage(const Context&);
// Implemented in settingsbindings.cpp
sol::table initGlobalSettingsPackage(const Context&);
sol::table initLocalSettingsPackage(const Context&);

@ -53,7 +53,6 @@ namespace MWLua
initObjectBindingsForLocalScripts(localContext);
initCellBindingsForLocalScripts(localContext);
LocalScripts::initializeSelfPackage(localContext);
initInputBindings(localContext);
mLua.addCommonPackage("openmw.async", getAsyncPackageInitializer(context));
mLua.addCommonPackage("openmw.util", LuaUtil::initUtilPackage(mLua.sol()));
@ -63,11 +62,12 @@ namespace MWLua
mGlobalScripts.addPackage("openmw.settings", initGlobalSettingsPackage(context));
mCameraPackage = initCameraPackage(localContext);
mUserInterfacePackage = initUserInterfacePackage(localContext);
mInputPackage = initInputPackage(localContext);
mNearbyPackage = initNearbyPackage(localContext);
mLocalSettingsPackage = initLocalSettingsPackage(localContext);
mPlayerSettingsPackage = initPlayerSettingsPackage(localContext);
mKeyPressEvents.clear();
mInputEvents.clear();
for (const std::string& path : mGlobalScriptList)
if (mGlobalScripts.addNewScript(path))
Log(Debug::Info) << "Global script started: " << path;
@ -93,7 +93,7 @@ namespace MWLua
if (paused)
{
mKeyPressEvents.clear();
mInputEvents.clear();
return;
}
@ -130,10 +130,10 @@ namespace MWLua
PlayerScripts* playerScripts = dynamic_cast<PlayerScripts*>(mPlayer.getRefData().getLuaScripts());
if (playerScripts)
{
for (const SDL_Keysym& key : mKeyPressEvents)
playerScripts->keyPress(key);
for (const auto& event : mInputEvents)
playerScripts->processInputEvent(event);
}
mKeyPressEvents.clear();
mInputEvents.clear();
for (const LocalEngineEvent& e : mLocalEngineEvents)
{
@ -187,7 +187,7 @@ namespace MWLua
mActiveLocalScripts.clear();
mLocalEvents.clear();
mGlobalEvents.clear();
mKeyPressEvents.clear();
mInputEvents.clear();
mActorAddedEvents.clear();
mLocalEngineEvents.clear();
mPlayerChanged = false;
@ -253,11 +253,6 @@ namespace MWLua
mWorldView.getObjectRegistry()->deregisterPtr(ptr);
}
void LuaManager::keyPressed(const SDL_KeyboardEvent& arg)
{
mKeyPressEvents.push_back(arg.keysym);
}
void LuaManager::appliedToObject(const MWWorld::Ptr& toPtr, std::string_view recordId, const MWWorld::Ptr& fromPtr)
{
mLocalEngineEvents.push_back({getId(toPtr), LocalScripts::OnConsume{std::string(recordId)}});
@ -294,6 +289,7 @@ namespace MWLua
scripts = std::make_shared<PlayerScripts>(&mLua, LObject(getId(ptr), mWorldView.getObjectRegistry()));
scripts->addPackage("openmw.ui", mUserInterfacePackage);
scripts->addPackage("openmw.camera", mCameraPackage);
scripts->addPackage("openmw.input", mInputPackage);
scripts->addPackage("openmw.settings", mPlayerSettingsPackage);
}
else

@ -41,7 +41,7 @@ namespace MWLua
void objectRemovedFromScene(const MWWorld::Ptr& ptr) override;
void registerObject(const MWWorld::Ptr& ptr) override;
void deregisterObject(const MWWorld::Ptr& ptr) override;
void keyPressed(const SDL_KeyboardEvent &arg) override;
void inputEvent(const InputEvent& event) override { mInputEvents.push_back(event); }
void appliedToObject(const MWWorld::Ptr& toPtr, std::string_view recordId, const MWWorld::Ptr& fromPtr) override;
MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override;
@ -75,6 +75,7 @@ namespace MWLua
sol::table mNearbyPackage;
sol::table mUserInterfacePackage;
sol::table mCameraPackage;
sol::table mInputPackage;
sol::table mLocalSettingsPackage;
sol::table mPlayerSettingsPackage;
@ -96,7 +97,7 @@ namespace MWLua
std::unique_ptr<LuaUtil::UserdataSerializer> mGlobalLoader;
std::unique_ptr<LuaUtil::UserdataSerializer> mLocalLoader;
std::vector<SDL_Keysym> mKeyPressEvents;
std::vector<MWBase::LuaManager::InputEvent> mInputEvents;
std::vector<ObjectId> mActorAddedEvents;
struct LocalEngineEvent

@ -3,6 +3,8 @@
#include <SDL_events.h>
#include "../mwbase/luamanager.hpp"
#include "localscripts.hpp"
namespace MWLua
@ -13,13 +15,40 @@ namespace MWLua
public:
PlayerScripts(LuaUtil::LuaState* lua, const LObject& obj) : LocalScripts(lua, obj)
{
registerEngineHandlers({&mKeyPressHandlers});
registerEngineHandlers({&mKeyPressHandlers, &mKeyReleaseHandlers,
&mControllerButtonPressHandlers, &mControllerButtonReleaseHandlers,
&mActionHandlers});
}
void keyPress(const SDL_Keysym& key) { callEngineHandlers(mKeyPressHandlers, key); }
void processInputEvent(const MWBase::LuaManager::InputEvent& event)
{
using InputEvent = MWBase::LuaManager::InputEvent;
switch (event.mType)
{
case InputEvent::KeyPressed:
callEngineHandlers(mKeyPressHandlers, std::get<SDL_Keysym>(event.mValue));
break;
case InputEvent::KeyReleased:
callEngineHandlers(mKeyReleaseHandlers, std::get<SDL_Keysym>(event.mValue));
break;
case InputEvent::ControllerPressed:
callEngineHandlers(mControllerButtonPressHandlers, std::get<int>(event.mValue));
break;
case InputEvent::ControllerReleased:
callEngineHandlers(mControllerButtonReleaseHandlers, std::get<int>(event.mValue));
break;
case InputEvent::Action:
callEngineHandlers(mActionHandlers, std::get<int>(event.mValue));
break;
}
}
private:
EngineHandlerList mKeyPressHandlers{"onKeyPress"};
EngineHandlerList mKeyReleaseHandlers{"onKeyRelease"};
EngineHandlerList mControllerButtonPressHandlers{"onControllerButtonPress"};
EngineHandlerList mControllerButtonReleaseHandlers{"onControllerButtonRelease"};
EngineHandlerList mActionHandlers{"onInputAction"};
};
}

@ -14,6 +14,7 @@ Lua API reference
openmw_world
openmw_self
openmw_nearby
openmw_input
openmw_ui
openmw_aux_util
@ -53,6 +54,8 @@ Player scripts are local scripts that are attached to a player.
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|:ref:`openmw.nearby <Package openmw.nearby>` | by local scripts | | Read-only access to the nearest area of the game world. |
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|:ref:`openmw.input <Package openmw.input>` | by player scripts | | User input |
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|:ref:`openmw.ui <Package openmw.ui>` | by player scripts | | Controls user interface |
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|openmw.camera | by player scripts | | Controls camera (not implemented) |

@ -36,8 +36,21 @@ Engine handler is a function defined by a script, that can be called by the engi
+----------------------------------+----------------------------------------------------------------------+
| **Only for local scripts attached to a player** |
+----------------------------------+----------------------------------------------------------------------+
| onKeyPress(key) | | `Key <openmw_core.html##(KeyboardEvent)>`_ pressed. Usage example: |
| | | ``if key.symbol == 'z' and key.withShift then ...`` |
| onKeyPress(key) | | `Key <openmw_input.html##(KeyboardEvent)>`_ is pressed. |
| | | Usage example: ``if key.symbol == 'z' and key.withShift then ...`` |
+----------------------------------+----------------------------------------------------------------------+
| onKeyRelease(key) | | `Key <openmw_input.html##(KeyboardEvent)>`_ is released. |
| | | Usage example: ``if key.symbol == 'z' and key.withShift then ...`` |
+----------------------------------+----------------------------------------------------------------------+
| onControllerButtonPress(id) | | A `button <openmw_input.html##(CONTROLLER_BUTTON)>`_ on a game |
| | controller is pressed. Usage example: |
| | | ``if id == input.CONTROLLER_BUTTON.LeftStick then ...`` |
+----------------------------------+----------------------------------------------------------------------+
| onControllerButtonRelease(id) | | A `button <openmw_input.html##(CONTROLLER_BUTTON)>`_ on a game |
| | controller is released. Usage example: |
| | | ``if id == input.CONTROLLER_BUTTON.LeftStick then ...`` |
+----------------------------------+----------------------------------------------------------------------+
| onInputAction(id) | | `Game control <openmw_input.html##(ACTION)>`_ is pressed. |
| | | Usage example: ``if id == input.ACTION.ToggleWeapon then ...`` |
+----------------------------------+----------------------------------------------------------------------+

@ -0,0 +1,6 @@
Package openmw.input
====================
.. raw:: html
:file: generated_html/openmw_input.html

@ -314,6 +314,8 @@ Player scripts are local scripts that are attached to a player.
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|:ref:`openmw.nearby <Package openmw.nearby>` | by local scripts | | Read-only access to the nearest area of the game world. |
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|:ref:`openmw.input <Package openmw.input>` | by player scripts | | User input |
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|:ref:`openmw.ui <Package openmw.ui>` | by player scripts | | Controls user interface |
+---------------------------------------------------------+--------------------+---------------------------------------------------------------+
|openmw.camera | by player scripts | | Controls camera (not implemented) |

@ -318,15 +318,5 @@
-- @return #ObjectList
-------------------------------------------------------------------------------
-- Argument of `onKeyPress` engine handler
-- @type KeyboardEvent
-- @field [parent=#KeyboardEvent] #string symbol The pressed symbol (1-symbol string).
-- @field [parent=#KeyboardEvent] #string code Key code.
-- @field [parent=#KeyboardEvent] #boolean withShift Is `Shift` key pressed.
-- @field [parent=#KeyboardEvent] #boolean withCtrl Is `Control` key pressed.
-- @field [parent=#KeyboardEvent] #boolean withAlt Is `Alt` key pressed.
-- @field [parent=#KeyboardEvent] #boolean withSuper Is `Super`/`Win` key pressed.
return nil

@ -0,0 +1,170 @@
-------------------------------------------------------------------------------
-- `openmw.input` can be used only in scripts attached to a player.
-- @module input
-- @usage local input = require('openmw.input')
-------------------------------------------------------------------------------
-- Is player idle.
-- @function [parent=#input] isIdle
-- @return #boolean
-------------------------------------------------------------------------------
-- Is a specific control currently pressed.
-- Input bindings can be changed ingame using Options/Controls menu.
-- @function [parent=#input] isActionPressed
-- @param #number actionId One of @{openmw.input#ACTION}
-- @return #boolean
-------------------------------------------------------------------------------
-- Is a mouse button currently pressed.
-- @function [parent=#input] isMouseButtonPressed
-- @param #number buttonId Button index (1 - left, 2 - middle, 3 - right, 4 - X1, 5 - X2)
-- @return #boolean
-------------------------------------------------------------------------------
-- Horizontal mouse movement during the last frame.
-- @function [parent=#input] getMouseMoveX
-- @return #number
-------------------------------------------------------------------------------
-- Vertical mouse movement during the last frame.
-- @function [parent=#input] getMouseMoveY
-- @return #number
-------------------------------------------------------------------------------
-- Get value of an axis of a game controller.
-- @function [parent=#input] getAxisValue
-- @param #number axisId Index of a controller axis, one of @{openmw.input#CONTROLLER_AXIS}.
-- @return #number Value in range [-1, 1].
-------------------------------------------------------------------------------
-- Get state of a control switch. I.e. is player able to move/fight/jump/etc.
-- @function [parent=#input] getControlSwitch
-- @param #string key Control type (see @{openmw.input#CONTROL_SWITCH})
-- @return #boolean
-------------------------------------------------------------------------------
-- Set state of a control switch. I.e. forbid or allow player to move/fight/jump/etc.
-- @function [parent=#input] setControlSwitch
-- @param #string key Control type (see @{openmw.input#CONTROL_SWITCH})
-- @param #boolean value
-------------------------------------------------------------------------------
-- @type CONTROL_SWITCH
-- @field [parent=#CONTROL_SWITCH] #string Controls Ability to move
-- @field [parent=#CONTROL_SWITCH] #string Fighting Ability to attack
-- @field [parent=#CONTROL_SWITCH] #string Jumping Ability to jump
-- @field [parent=#CONTROL_SWITCH] #string Looking Ability to change view direction
-- @field [parent=#CONTROL_SWITCH] #string Magic Ability to use magic
-- @field [parent=#CONTROL_SWITCH] #string ViewMode Ability to toggle 1st/3rd person view
-- @field [parent=#CONTROL_SWITCH] #string VanityMode Vanity view if player doesn't touch controls for a long time
-------------------------------------------------------------------------------
-- Values that can be used with getControlSwitch/setControlSwitch.
-- @field [parent=#input] #CONTROL_SWITCH CONTROL_SWITCH
-------------------------------------------------------------------------------
-- @type ACTION
-- @field [parent=#ACTION] #number GameMenu
-- @field [parent=#ACTION] #number Screenshot
-- @field [parent=#ACTION] #number Inventory
-- @field [parent=#ACTION] #number Console
-- @field [parent=#ACTION] #number MoveLeft
-- @field [parent=#ACTION] #number MoveRight
-- @field [parent=#ACTION] #number MoveForward
-- @field [parent=#ACTION] #number MoveBackward
-- @field [parent=#ACTION] #number Activate
-- @field [parent=#ACTION] #number Use
-- @field [parent=#ACTION] #number Jump
-- @field [parent=#ACTION] #number AutoMove
-- @field [parent=#ACTION] #number Journal
-- @field [parent=#ACTION] #number Weapon
-- @field [parent=#ACTION] #number Spell
-- @field [parent=#ACTION] #number Run
-- @field [parent=#ACTION] #number CycleSpellLeft
-- @field [parent=#ACTION] #number CycleSpellRight
-- @field [parent=#ACTION] #number CycleWeaponLeft
-- @field [parent=#ACTION] #number CycleWeaponRight
-- @field [parent=#ACTION] #number ToggleSneak
-- @field [parent=#ACTION] #number AlwaysRun
-- @field [parent=#ACTION] #number Sneak
-- @field [parent=#ACTION] #number QuickSave
-- @field [parent=#ACTION] #number QuickLoad
-- @field [parent=#ACTION] #number QuickMenu
-- @field [parent=#ACTION] #number ToggleWeapon
-- @field [parent=#ACTION] #number ToggleSpell
-- @field [parent=#ACTION] #number TogglePOV
-- @field [parent=#ACTION] #number QuickKey1
-- @field [parent=#ACTION] #number QuickKey2
-- @field [parent=#ACTION] #number QuickKey3
-- @field [parent=#ACTION] #number QuickKey4
-- @field [parent=#ACTION] #number QuickKey5
-- @field [parent=#ACTION] #number QuickKey6
-- @field [parent=#ACTION] #number QuickKey7
-- @field [parent=#ACTION] #number QuickKey8
-- @field [parent=#ACTION] #number QuickKey9
-- @field [parent=#ACTION] #number QuickKey10
-- @field [parent=#ACTION] #number QuickKeysMenu
-- @field [parent=#ACTION] #number ToggleHUD
-- @field [parent=#ACTION] #number ToggleDebug
-- @field [parent=#ACTION] #number ZoomIn
-- @field [parent=#ACTION] #number ZoomOut
-------------------------------------------------------------------------------
-- Values that can be used with isActionPressed.
-- @field [parent=#input] #ACTION ACTION
-------------------------------------------------------------------------------
-- @type CONTROLLER_BUTTON
-- @field [parent=#CONTROLLER_BUTTON] #number A
-- @field [parent=#CONTROLLER_BUTTON] #number B
-- @field [parent=#CONTROLLER_BUTTON] #number X
-- @field [parent=#CONTROLLER_BUTTON] #number Y
-- @field [parent=#CONTROLLER_BUTTON] #number Back
-- @field [parent=#CONTROLLER_BUTTON] #number Guide
-- @field [parent=#CONTROLLER_BUTTON] #number Start
-- @field [parent=#CONTROLLER_BUTTON] #number LeftStick
-- @field [parent=#CONTROLLER_BUTTON] #number RightStick
-- @field [parent=#CONTROLLER_BUTTON] #number LeftShoulder
-- @field [parent=#CONTROLLER_BUTTON] #number RightShoulder
-- @field [parent=#CONTROLLER_BUTTON] #number DPadUp
-- @field [parent=#CONTROLLER_BUTTON] #number DPadDown
-- @field [parent=#CONTROLLER_BUTTON] #number DPadLeft
-- @field [parent=#CONTROLLER_BUTTON] #number DPadRight
-------------------------------------------------------------------------------
-- Values that can be passed to onControllerButtonPress/onControllerButtonRelease engine handlers.
-- @field [parent=#input] #CONTROLLER_BUTTON CONTROLLER_BUTTON
-------------------------------------------------------------------------------
-- Ids of game controller axises. Used as an argument in getAxisValue.
-- @type CONTROLLER_AXIS
-- @field [parent=#CONTROLLER_AXIS] #number LeftX Left stick horizontal axis (from -1 to 1)
-- @field [parent=#CONTROLLER_AXIS] #number LeftY Left stick vertical axis (from -1 to 1)
-- @field [parent=#CONTROLLER_AXIS] #number RightX Right stick horizontal axis (from -1 to 1)
-- @field [parent=#CONTROLLER_AXIS] #number RightY Right stick vertical axis (from -1 to 1)
-- @field [parent=#CONTROLLER_AXIS] #number TriggerLeft Left trigger (from 0 to 1)
-- @field [parent=#CONTROLLER_AXIS] #number TriggerRight Right trigger (from 0 to 1)
-- @field [parent=#CONTROLLER_AXIS] #number LookUpDown View direction vertical axis (RightY by default, can be mapped to another axis in Options/Controls menu)
-- @field [parent=#CONTROLLER_AXIS] #number LookLeftRight View direction horizontal axis (RightX by default, can be mapped to another axis in Options/Controls menu)
-- @field [parent=#CONTROLLER_AXIS] #number MoveForwardBackward Movement forward/backward (LeftY by default, can be mapped to another axis in Options/Controls menu)
-- @field [parent=#CONTROLLER_AXIS] #number MoveLeftRight Side movement (LeftX by default, can be mapped to another axis in Options/Controls menu)
-------------------------------------------------------------------------------
-- Values that can be used with getAxisValue.
-- @field [parent=#input] #CONTROLLER_AXIS CONTROLLER_AXIS
-------------------------------------------------------------------------------
-- The argument of `onKeyPress`/`onKeyRelease` engine handlers.
-- @type KeyboardEvent
-- @field [parent=#KeyboardEvent] #string symbol The pressed symbol (1-symbol string).
-- @field [parent=#KeyboardEvent] #string code Key code.
-- @field [parent=#KeyboardEvent] #boolean withShift Is `Shift` key pressed.
-- @field [parent=#KeyboardEvent] #boolean withCtrl Is `Control` key pressed.
-- @field [parent=#KeyboardEvent] #boolean withAlt Is `Alt` key pressed.
-- @field [parent=#KeyboardEvent] #boolean withSuper Is `Super`/`Win` key pressed.
return nil
Loading…
Cancel
Save