More work on the Input system
This commit is contained in:
parent
15b0e99460
commit
3fc7a85a52
16
assets/opensb/binds/opensb.binds
Normal file
16
assets/opensb/binds/opensb.binds
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"opensb": {
|
||||||
|
"name": "OpenStarbound",
|
||||||
|
"bannerName" : "Open^#ebd74a;Starbound",
|
||||||
|
"binds": {
|
||||||
|
"test": {
|
||||||
|
"default": [{
|
||||||
|
"type": "key",
|
||||||
|
"value": "C",
|
||||||
|
"mods": ["LShift"]
|
||||||
|
}],
|
||||||
|
"name": "Test Bind"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,39 @@
|
|||||||
|
|
||||||
namespace Star {
|
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 hash<InputVariant>::operator()(InputVariant const& v) const {
|
||||||
size_t indexHash = hashOf(v.typeIndex());
|
size_t indexHash = hashOf(v.typeIndex());
|
||||||
if (auto key = v.ptr<Key>())
|
if (auto key = v.ptr<Key>())
|
||||||
@ -16,6 +49,99 @@ size_t hash<InputVariant>::operator()(InputVariant const& v) const {
|
|||||||
return indexHash;
|
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::s_singleton;
|
||||||
|
|
||||||
Input* Input::singletonPtr() {
|
Input* Input::singletonPtr() {
|
||||||
@ -35,6 +161,13 @@ Input::Input() {
|
|||||||
|
|
||||||
s_singleton = this;
|
s_singleton = this;
|
||||||
|
|
||||||
|
reload();
|
||||||
|
|
||||||
|
m_rootReloadListener = make_shared<CallbackListener>([&]() {
|
||||||
|
reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
Root::singletonPtr()->registerReloadListener(m_rootReloadListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
Input::~Input() {
|
Input::~Input() {
|
||||||
@ -42,17 +175,33 @@ Input::~Input() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Input::reset() {
|
void Input::reset() {
|
||||||
|
m_inputStates.clear();
|
||||||
|
m_bindStates.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::reload() {
|
void Input::reload() {
|
||||||
reset();
|
reset();
|
||||||
|
m_bindCategories.clear();
|
||||||
|
m_inputsToBinds.clear();
|
||||||
|
|
||||||
auto assets = Root::singleton().assets();
|
auto assets = Root::singleton().assets();
|
||||||
|
|
||||||
for (auto& bindPath : assets->scanExtension("binds")) {
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -20,12 +20,6 @@ namespace Star {
|
|||||||
|
|
||||||
class Input {
|
class Input {
|
||||||
public:
|
public:
|
||||||
struct NoBind {
|
|
||||||
String error;
|
|
||||||
|
|
||||||
NoBind(String err);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct KeyBind {
|
struct KeyBind {
|
||||||
Key key = Key::Zero;
|
Key key = Key::Zero;
|
||||||
KeyMod mods = KeyMod::NoMod;
|
KeyMod mods = KeyMod::NoMod;
|
||||||
@ -51,27 +45,27 @@ namespace Star {
|
|||||||
ControllerButton button = ControllerButton::Invalid;
|
ControllerButton button = ControllerButton::Invalid;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Variant<NoBind, KeyBind, MouseBind, ControllerBind> Bind;
|
typedef MVariant<KeyBind, MouseBind, ControllerBind> Bind;
|
||||||
|
|
||||||
static Bind bindFromJson(Json const& json);
|
static Bind bindFromJson(Json const& json);
|
||||||
static Json bindToJson(Bind const& bind);
|
static Json bindToJson(Bind const& bind);
|
||||||
|
|
||||||
struct Category;
|
struct BindCategory;
|
||||||
|
|
||||||
struct BindEntry {
|
struct BindEntry {
|
||||||
// The internal ID of this entry.
|
// The internal ID of this entry.
|
||||||
String id;
|
String id;
|
||||||
// The category this entry belongs to.
|
|
||||||
String category;
|
|
||||||
// The user-facing name of this entry.
|
// The user-facing name of this entry.
|
||||||
String name;
|
String name;
|
||||||
|
// The category this entry belongs to.
|
||||||
|
BindCategory const* category;
|
||||||
|
|
||||||
// The default binds.
|
// The default binds.
|
||||||
List<Bind> defaultBinds;
|
List<Bind> defaultBinds;
|
||||||
// The user-configured binds.
|
// The user-configured binds.
|
||||||
List<Bind> customBinds;
|
List<Bind> customBinds;
|
||||||
|
|
||||||
BindEntry(Json const& config, Category const& category);
|
BindEntry(String entryId, Json const& config, BindCategory const& parentCategory);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BindRef {
|
struct BindRef {
|
||||||
@ -91,11 +85,11 @@ namespace Star {
|
|||||||
struct BindCategory {
|
struct BindCategory {
|
||||||
String id;
|
String id;
|
||||||
String name;
|
String name;
|
||||||
Json meta;
|
Json config;
|
||||||
|
|
||||||
StringMap<BindEntry> entries;
|
StringMap<BindEntry> entries;
|
||||||
|
|
||||||
BindCategory(Json const& data);
|
BindCategory(String categoryId, Json const& categoryConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InputState {
|
struct InputState {
|
||||||
|
Loading…
Reference in New Issue
Block a user