From d95eac316405fb100963d47dcd95ccced3462383 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Tue, 10 Dec 2024 18:49:29 +1100 Subject: [PATCH] Input: binds can now make the clipboard available while held, config option to always allow --- source/client/StarClientApplication.cpp | 5 +-- source/frontend/StarClipboardLuaBindings.cpp | 28 +++++++++++---- source/frontend/StarClipboardLuaBindings.hpp | 2 +- source/game/StarInput.cpp | 35 ++++++++++++++++--- source/game/StarInput.hpp | 7 ++++ .../game/scripting/StarInputLuaBindings.cpp | 1 + source/game/scripting/StarRootLuaBindings.cpp | 4 +-- 7 files changed, 65 insertions(+), 17 deletions(-) diff --git a/source/client/StarClientApplication.cpp b/source/client/StarClientApplication.cpp index b4e0955..71bec5d 100644 --- a/source/client/StarClientApplication.cpp +++ b/source/client/StarClientApplication.cpp @@ -543,8 +543,9 @@ void ClientApplication::changeState(MainAppState newState) { m_universeClient->setLuaCallbacks("input", LuaBindings::makeInputCallbacks()); m_universeClient->setLuaCallbacks("voice", LuaBindings::makeVoiceCallbacks()); m_universeClient->setLuaCallbacks("camera", LuaBindings::makeCameraCallbacks(&m_worldPainter->camera())); - if (!m_root->configuration()->get("safeScripts").toBool()) - m_universeClient->setLuaCallbacks("clipboard", LuaBindings::makeClipboardCallbacks(appController())); + + Json alwaysAllow = m_root->configuration()->getPath("safe.alwaysAllowClipboard"); + m_universeClient->setLuaCallbacks("clipboard", LuaBindings::makeClipboardCallbacks(appController(), alwaysAllow && alwaysAllow.toBool())); auto heldScriptPanes = make_shared>(); diff --git a/source/frontend/StarClipboardLuaBindings.cpp b/source/frontend/StarClipboardLuaBindings.cpp index c8a8dfe..037a7dd 100644 --- a/source/frontend/StarClipboardLuaBindings.cpp +++ b/source/frontend/StarClipboardLuaBindings.cpp @@ -1,21 +1,35 @@ #include "StarClipboardLuaBindings.hpp" #include "StarLuaConverters.hpp" +#include "StarInput.hpp" namespace Star { -LuaCallbacks LuaBindings::makeClipboardCallbacks(ApplicationControllerPtr appController) { +LuaCallbacks LuaBindings::makeClipboardCallbacks(ApplicationControllerPtr appController, bool alwaysAllow) { LuaCallbacks callbacks; - callbacks.registerCallback("hasText", [appController]() -> bool { - return appController->hasClipboard(); + auto available = [alwaysAllow]() { return alwaysAllow || Input::singleton().getTag("clipboard") > 0; }; + + callbacks.registerCallback("available", [=]() -> bool { + return available(); }); - callbacks.registerCallback("getText", [appController]() -> Maybe { - return appController->getClipboard(); + callbacks.registerCallback("hasText", [=]() -> bool { + return available() && appController->hasClipboard(); }); - callbacks.registerCallback("setText", [appController](String const& text) { - appController->setClipboard(text); + callbacks.registerCallback("getText", [=]() -> Maybe { + if (!available()) + return {}; + else + return appController->getClipboard(); + }); + + callbacks.registerCallback("setText", [=](String const& text) -> bool { + if (available()) { + appController->setClipboard(text); + return true; + } + return false; }); return callbacks; diff --git a/source/frontend/StarClipboardLuaBindings.hpp b/source/frontend/StarClipboardLuaBindings.hpp index 7515c0b..f38f8d8 100644 --- a/source/frontend/StarClipboardLuaBindings.hpp +++ b/source/frontend/StarClipboardLuaBindings.hpp @@ -6,7 +6,7 @@ namespace Star { namespace LuaBindings { -LuaCallbacks makeClipboardCallbacks(ApplicationControllerPtr appController); +LuaCallbacks makeClipboardCallbacks(ApplicationControllerPtr appController, bool alwaysAllow); } }// namespace Star diff --git a/source/game/StarInput.cpp b/source/game/StarInput.cpp index 7869b52..20e6f18 100644 --- a/source/game/StarInput.cpp +++ b/source/game/StarInput.cpp @@ -223,7 +223,7 @@ Input::BindEntry::BindEntry(String entryId, Json const& config, BindCategory con category = &parentCategory; id = entryId; name = config.getString("name", id); - + tags = jsonToStringList(config.get("tags", JsonArray())); for (Json const& jBind : config.getArray("default", {})) { try { defaultBinds.emplace_back(bindFromJson(jBind)); } @@ -342,6 +342,15 @@ Input::InputState* Input::bindStatePtr(String const& categoryId, String const& b return nullptr; } +Input::InputState& Input::addBindState(BindEntry const* bindEntry) { + auto insertion = m_bindStates.insert(bindEntry, InputState()); + if (insertion.second) { + for (auto& tag : bindEntry->tags) + ++m_activeTags[tag]; + } + return insertion.first->second; +} + Input* Input::s_singleton; Input* Input::singletonPtr() { @@ -393,7 +402,19 @@ void Input::reset() { eraseWhere(m_keyStates, eraseCond); eraseWhere(m_mouseStates, eraseCond); eraseWhere(m_controllerStates, eraseCond); - eraseWhere(m_bindStates, eraseCond); + eraseWhere(m_bindStates, [&](auto& p) { + if (p.second.held) + p.second.reset(); + else { + for (auto& tag : p.first->tags) { + auto find = m_activeTags.find(tag); + if (find != m_activeTags.end() && !--find->second) + m_activeTags.erase(find); + } + return true; + } + return false; + }); } void Input::update() { @@ -415,7 +436,7 @@ bool Input::handleInput(InputEvent const& input, bool gameProcessed) { if (auto binds = m_bindMappings.ptr(keyDown->key)) { for (auto bind : filterBindEntries(*binds, keyDown->mods)) - m_bindStates[bind].press(); + addBindState(bind).press(); } } } @@ -447,7 +468,7 @@ bool Input::handleInput(InputEvent const& input, bool gameProcessed) { if (auto binds = m_bindMappings.ptr(mouseDown->mouseButton)) { for (auto bind : filterBindEntries(*binds, m_pressedMods)) - m_bindStates[bind].press(); + addBindState(bind).press(); } } } @@ -475,7 +496,7 @@ bool Input::handleInput(InputEvent const& input, bool gameProcessed) { if (auto binds = m_bindMappings.ptr(controllerDown->controllerButton)) { for (auto bind : filterBindEntries(*binds, m_pressedMods)) - m_bindStates[bind].press(); + addBindState(bind).press(); } } } @@ -650,4 +671,8 @@ void Input::setBinds(String const& categoryId, String const& bindId, Json const& entry.updated(); } +unsigned Input::getTag(String const& tag) { + return m_activeTags.maybe(tag).value(0); +} + } \ No newline at end of file diff --git a/source/game/StarInput.hpp b/source/game/StarInput.hpp index 113eea9..90a1e05 100644 --- a/source/game/StarInput.hpp +++ b/source/game/StarInput.hpp @@ -61,6 +61,8 @@ public: String name; // The category this entry belongs to. BindCategory const* category; + // Associated string tags that become active when this bind is pressed. + StringList tags; // The default binds. List defaultBinds; @@ -176,6 +178,8 @@ public: void setBinds(String const& categoryId, String const& bindId, Json const& binds); Json getDefaultBinds(String const& categoryId, String const& bindId); Json getBinds(String const& categoryId, String const& bindId); + unsigned getTag(String const& tag); + private: List filterBindEntries(List const& binds, KeyMod mods) const; @@ -184,6 +188,8 @@ private: InputState* bindStatePtr(String const& categoryId, String const& bindId); + InputState& addBindState(BindEntry const* bindEntry); + static Input* s_singleton; // Regenerated on reload. @@ -203,6 +209,7 @@ private: HashMap m_controllerStates; //Bind states HashMap m_bindStates; + StringMap m_activeTags; KeyMod m_pressedMods; bool m_textInputActive; diff --git a/source/game/scripting/StarInputLuaBindings.cpp b/source/game/scripting/StarInputLuaBindings.cpp index 9a99c4a..565e3b9 100644 --- a/source/game/scripting/StarInputLuaBindings.cpp +++ b/source/game/scripting/StarInputLuaBindings.cpp @@ -53,6 +53,7 @@ LuaCallbacks LuaBindings::makeInputCallbacks() { }); callbacks.registerCallbackWithSignature("mousePosition", bind(mem_fn(&Input::mousePosition), input)); + callbacks.registerCallbackWithSignature("getTag", bind(mem_fn(&Input::getTag), input, _1)); return callbacks; } diff --git a/source/game/scripting/StarRootLuaBindings.cpp b/source/game/scripting/StarRootLuaBindings.cpp index e1d7e3e..d87b423 100644 --- a/source/game/scripting/StarRootLuaBindings.cpp +++ b/source/game/scripting/StarRootLuaBindings.cpp @@ -230,7 +230,7 @@ LuaCallbacks LuaBindings::makeRootCallbacks() { }); callbacks.registerCallback("setConfiguration", [root](String const& key, Json const& value) { - if (key == "safeScripts") + if (key == "safeScripts" || key == "safe") throw StarException(strf("Cannot set {}", key)); else root->configuration()->set(key, value); @@ -245,7 +245,7 @@ LuaCallbacks LuaBindings::makeRootCallbacks() { }); callbacks.registerCallback("setConfigurationPath", [root](String const& path, Json const& value) { - if (path.empty() || path.beginsWith("safeScripts")) + if (path.empty() || path.beginsWith("safeScripts") || path.splitAny("[].").get(0) == "safe") throw ConfigurationException(strf("cannot set {}", path)); else root->configuration()->setPath(path, value);