Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/StarInput.cpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-07-02 08:16:14 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-07-02 08:16:14 +1000
commit3fc7a85a525ad98e44268fed3f3852ba4e6e7336 (patch)
treeb451b4d72e8d2dcaf5cd629c2b4b639fde11f987 /source/game/StarInput.cpp
parent15b0e9946049946133c9c932ef23d06a665f63fb (diff)
More work on the Input system
Diffstat (limited to 'source/game/StarInput.cpp')
-rw-r--r--source/game/StarInput.cpp155
1 files changed, 152 insertions, 3 deletions
diff --git a/source/game/StarInput.cpp b/source/game/StarInput.cpp
index 0a9b56d..89b2ed3 100644
--- a/source/game/StarInput.cpp
+++ b/source/game/StarInput.cpp
@@ -4,6 +4,39 @@
namespace Star {
+Json keyModsToJson(KeyMod mod) {
+ JsonArray array;
+
+ if ((bool)(mod & KeyMod::LShift)) array.emplace_back("LShift");
+ if ((bool)(mod & KeyMod::RShift)) array.emplace_back("RShift");
+ if ((bool)(mod & KeyMod::LCtrl )) array.emplace_back("LCtrl" );
+ if ((bool)(mod & KeyMod::RCtrl )) array.emplace_back("RCtrl" );
+ if ((bool)(mod & KeyMod::LAlt )) array.emplace_back("LAlt" );
+ if ((bool)(mod & KeyMod::RAlt )) array.emplace_back("RAlt" );
+ if ((bool)(mod & KeyMod::LGui )) array.emplace_back("LGui" );
+ if ((bool)(mod & KeyMod::RGui )) array.emplace_back("RGui" );
+ if ((bool)(mod & KeyMod::Num )) array.emplace_back("Num" );
+ if ((bool)(mod & KeyMod::Caps )) array.emplace_back("Caps" );
+ if ((bool)(mod & KeyMod::AltGr )) array.emplace_back("AltGr" );
+ if ((bool)(mod & KeyMod::Scroll)) array.emplace_back("Scroll");
+
+ return move(array);
+}
+
+// Optional pointer argument to output calculated priority
+KeyMod keyModsFromJson(Json const& json, uint8_t* priority = nullptr) {
+ KeyMod mod = KeyMod::NoMod;
+ if (!json.isType(Json::Type::Array))
+ return mod;
+
+ for (Json const& jMod : json.toArray()) {
+ if (priority && mod != (mod |= KeyModNames.getLeft(jMod.toString())))
+ ++*priority;
+ }
+
+ return mod;
+}
+
size_t hash<InputVariant>::operator()(InputVariant const& v) const {
size_t indexHash = hashOf(v.typeIndex());
if (auto key = v.ptr<Key>())
@@ -16,6 +49,99 @@ size_t hash<InputVariant>::operator()(InputVariant const& v) const {
return indexHash;
}
+Input::Bind Input::bindFromJson(Json const& json) {
+ Bind bind;
+
+ String type = json.getString("type");
+ Json value = json.get("value");
+
+ if (type == "key") {
+ KeyBind keyBind;
+ keyBind.key = KeyNames.getLeft(value.toString());
+ keyBind.mods = keyModsFromJson(json.getArray("mods", {}), &keyBind.priority);
+ bind = move(keyBind);
+ }
+ else if (type == "mouse") {
+ MouseBind mouseBind;
+ mouseBind.button = MouseButtonNames.getLeft(value.toString());
+ mouseBind.mods = keyModsFromJson(json.getArray("mods", {}), &mouseBind.priority);
+ bind = move(mouseBind);
+ }
+ else if (type == "controller") {
+ ControllerBind controllerBind;
+ controllerBind.button = ControllerButtonNames.getLeft(value.toString());
+ controllerBind.controller = json.getUInt("controller", 0);
+ bind = move(controllerBind);
+ }
+
+ return bind;
+}
+
+Json Input::bindToJson(Bind const& bind) {
+ if (auto keyBind = bind.ptr<KeyBind>()) {
+ return JsonObject{
+ {"type", "key"},
+ {"value", KeyNames.getRight(keyBind->key)},
+ {"mods", keyModsToJson(keyBind->mods)}
+ };
+ }
+ else if (auto mouseBind = bind.ptr<MouseBind>()) {
+ return JsonObject{
+ {"type", "mouse"},
+ {"value", MouseButtonNames.getRight(mouseBind->button)},
+ {"mods", keyModsToJson(mouseBind->mods)}
+ };
+ }
+ else if (auto controllerBind = bind.ptr<ControllerBind>()) {
+ return JsonObject{
+ {"type", "controller"},
+ {"value", ControllerButtonNames.getRight(controllerBind->button)}
+ };
+ }
+
+ return Json();
+}
+
+Input::BindEntry::BindEntry(String entryId, Json const& config, BindCategory const& parentCategory) {
+ category = &parentCategory;
+ id = move(entryId);
+ name = config.getString("name", id);
+
+ for (Json const& jBind : config.getArray("default", {})) {
+ try
+ { defaultBinds.emplace_back(bindFromJson(jBind)); }
+ catch (JsonException const& e)
+ { Logger::error("Binds: Error loading default bind in {}.{}: {}", parentCategory.id, id, e.what()); }
+ }
+}
+
+Input::BindCategory::BindCategory(String categoryId, Json const& categoryConfig) {
+ id = move(categoryId);
+ name = config.getString("name", id);
+ config = categoryConfig;
+
+ ConfigurationPtr userConfig = Root::singletonPtr()->configuration();
+ auto userBindings = userConfig->get("modBindings");
+
+ for (auto& pair : config.getObject("binds", {})) {
+ String const& bindId = pair.first;
+ Json const& bindConfig = pair.second;
+ if (!bindConfig.isType(Json::Type::Object))
+ continue;
+
+ BindEntry& entry = entries.insert(bindId, BindEntry(bindId, bindConfig, *this)).first->second;
+
+ if (userBindings.isType(Json::Type::Object)) {
+ for (auto& jBind : userBindings.queryArray(strf("{}.{}", id, bindId), {})) {
+ try
+ { entry.customBinds.emplace_back(bindFromJson(jBind)); }
+ catch (JsonException const& e)
+ { Logger::error("Binds: Error loading user bind in {}.{}: {}", id, bindId, e.what()); }
+ }
+ }
+ }
+}
+
Input* Input::s_singleton;
Input* Input::singletonPtr() {
@@ -35,6 +161,13 @@ Input::Input() {
s_singleton = this;
+ reload();
+
+ m_rootReloadListener = make_shared<CallbackListener>([&]() {
+ reload();
+ });
+
+ Root::singletonPtr()->registerReloadListener(m_rootReloadListener);
}
Input::~Input() {
@@ -42,17 +175,33 @@ Input::~Input() {
}
void Input::reset() {
-
+ m_inputStates.clear();
+ m_bindStates.clear();
}
void Input::reload() {
reset();
-
+ m_bindCategories.clear();
+ m_inputsToBinds.clear();
+
auto assets = Root::singleton().assets();
for (auto& bindPath : assets->scanExtension("binds")) {
- Json config = assets->json(bindPath);
+ for (auto& pair : assets->json(bindPath).toObject()) {
+ String const& categoryId = pair.first;
+ Json const& categoryConfig = pair.second;
+ if (!categoryConfig.isType(Json::Type::Object))
+ continue;
+
+ m_bindCategories.insert(categoryId, BindCategory(categoryId, categoryConfig));
+ }
}
+
+ size_t count = 0;
+ for (auto& pair : m_bindCategories)
+ count += pair.second.entries.size();
+
+ Logger::info("Binds: Loaded {} bind{}", count, count == 1 ? "" : "s");
}
} \ No newline at end of file