diff --git a/src/logic/scripting/lua/libs/libinput.cpp b/src/logic/scripting/lua/libs/libinput.cpp index 4aac2976..47233a49 100644 --- a/src/logic/scripting/lua/libs/libinput.cpp +++ b/src/logic/scripting/lua/libs/libinput.cpp @@ -30,7 +30,21 @@ static int l_mousecode(lua::State* L) { } static int l_add_callback(lua::State* L) { - auto bindname = lua::require_string(L, 1); + std::string bindname = lua::require_string(L, 1); + size_t pos = bindname.find(':'); + if (pos != std::string::npos) { + std::string prefix = bindname.substr(0, pos); + if (prefix == "key") { + if (hud == nullptr) { + throw std::runtime_error("on_hud_open is not called yet"); + } + auto key = input_util::keycode_from(bindname.substr(pos + 1)); + auto callback = lua::create_runnable(L); + hud->keepAlive(Events::keyCallbacks[key].add(callback)); + return 0; + } + } + const auto& bind = Events::bindings.find(bindname); if (bind == Events::bindings.end()) { throw std::runtime_error("unknown binding " + util::quote(bindname)); diff --git a/src/util/RunnablesList.hpp b/src/util/RunnablesList.hpp index e655b42c..c9771de3 100644 --- a/src/util/RunnablesList.hpp +++ b/src/util/RunnablesList.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -11,17 +12,33 @@ namespace util { class RunnablesList { int nextid = 1; std::unordered_map runnables; + std::mutex mutex; public: + RunnablesList() = default; + + RunnablesList(RunnablesList&& o) { + runnables = std::move(o.runnables); + nextid = o.nextid; + } + + void operator=(RunnablesList&& o) { + runnables = std::move(o.runnables); + nextid = o.nextid; + } + observer_handler add(runnable callback) { + std::lock_guard lock(mutex); int id = nextid++; runnables[id] = std::move(callback); return observer_handler(new int(id), [this](int* id) { //-V508 + std::lock_guard lock(mutex); runnables.erase(*id); delete id; }); } void notify() { + std::lock_guard lock(mutex); for (auto& entry : runnables) { entry.second(); } diff --git a/src/window/Events.cpp b/src/window/Events.cpp index f63431cf..1465b77b 100644 --- a/src/window/Events.cpp +++ b/src/window/Events.cpp @@ -23,6 +23,7 @@ bool Events::_cursor_locked = false; std::vector Events::codepoints; std::vector Events::pressedKeys; std::unordered_map Events::bindings; +std::unordered_map Events::keyCallbacks; bool Events::pressed(keycode keycode) { return pressed(static_cast(keycode)); @@ -156,6 +157,12 @@ bool Events::jactive(const std::string& name) { void Events::setKey(int key, bool b) { Events::keys[key] = b; Events::frames[key] = currentFrame; + if (b) { + const auto& callbacks = keyCallbacks.find(static_cast(key)); + if (callbacks != keyCallbacks.end()) { + callbacks->second.notify(); + } + } } void Events::setButton(int button, bool b) { @@ -173,6 +180,10 @@ void Events::setPosition(float xpos, float ypos) { Events::cursor.y = ypos; } +observer_handler Events::addKeyCallback(keycode key, runnable callback) { + return keyCallbacks[key].add(std::move(callback)); +} + #include "coders/json.hpp" #include "coders/toml.hpp" @@ -228,7 +239,6 @@ void Events::loadBindings( } else if (bindType == BindType::REBIND) { Events::rebind(key, type, code); } - } } } diff --git a/src/window/Events.hpp b/src/window/Events.hpp index 8155bb2b..e231462a 100644 --- a/src/window/Events.hpp +++ b/src/window/Events.hpp @@ -27,6 +27,7 @@ public: static std::vector codepoints; static std::vector pressedKeys; static std::unordered_map bindings; + static std::unordered_map keyCallbacks; static void pollEvents(); @@ -50,6 +51,8 @@ public: static bool active(const std::string& name); static bool jactive(const std::string& name); + static observer_handler addKeyCallback(keycode key, runnable callback); + static void setKey(int key, bool b); static void setButton(int button, bool b);