Input: binds can now make the clipboard available while held, config option to always allow

This commit is contained in:
Kae 2024-12-10 18:49:29 +11:00
parent dd52188e53
commit d95eac3164
7 changed files with 65 additions and 17 deletions

View File

@ -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<List<MainInterface::ScriptPaneInfo>>();

View File

@ -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<String> {
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<String> {
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;

View File

@ -6,7 +6,7 @@
namespace Star {
namespace LuaBindings {
LuaCallbacks makeClipboardCallbacks(ApplicationControllerPtr appController);
LuaCallbacks makeClipboardCallbacks(ApplicationControllerPtr appController, bool alwaysAllow);
}
}// namespace Star

View File

@ -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);
}
}

View File

@ -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<Bind> 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<BindEntry*> filterBindEntries(List<BindRef> 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<ControllerButton, ControllerInputState> m_controllerStates;
//Bind states
HashMap<BindEntry const*, InputState> m_bindStates;
StringMap<unsigned> m_activeTags;
KeyMod m_pressedMods;
bool m_textInputActive;

View File

@ -53,6 +53,7 @@ LuaCallbacks LuaBindings::makeInputCallbacks() {
});
callbacks.registerCallbackWithSignature<Vec2I>("mousePosition", bind(mem_fn(&Input::mousePosition), input));
callbacks.registerCallbackWithSignature<unsigned, String>("getTag", bind(mem_fn(&Input::getTag), input, _1));
return callbacks;
}

View File

@ -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);