diff --git a/macos/mkxp-z.xcodeproj/project.pbxproj b/macos/mkxp-z.xcodeproj/project.pbxproj index b2e585a6..1fc72f09 100644 --- a/macos/mkxp-z.xcodeproj/project.pbxproj +++ b/macos/mkxp-z.xcodeproj/project.pbxproj @@ -1240,6 +1240,7 @@ 3B10EC6C2568E5EA00372D13 /* Source */ = { isa = PBXGroup; children = ( + 3B3F7D1325B19C5A00EA5F1C /* MacOS */, 3B10ED342568E95D00372D13 /* src */, 3B1C236625A19B780075EF5D /* steamshim */, 3B10EDD52568E96A00372D13 /* binding */, @@ -1561,6 +1562,13 @@ name = Steam; sourceTree = ""; }; + 3B3F7D1325B19C5A00EA5F1C /* MacOS */ = { + isa = PBXGroup; + children = ( + ); + name = MacOS; + sourceTree = ""; + }; 3B426F6A256B8AC0009EA00F /* ghc */ = { isa = PBXGroup; children = ( diff --git a/src/config.cpp b/src/config.cpp index 49791f51..863fb6d9 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -7,6 +7,7 @@ #include "config.h" #include +#include #include #include @@ -47,12 +48,42 @@ void fillStringVec(json::value &item, std::vector &vector) { } } +bool copyObject(json::value &dest, json::value &src, const char *objectName = "") { + assert(dest.is_object()); + if (src.is_null()) + return false; + + if (!src.is_object()) + return false; + + auto &srcVec = src.as_object(); + auto &destVec = dest.as_object(); + + for (auto it : srcVec) { + // Specifically processs this object later. + if (it.second.is_object() && destVec[it.first].is_object()) + continue; + + if (it.second.is_array() && destVec[it.first].is_array() || + it.second.is_number() && destVec[it.first].is_number() || + it.second.is_string() && destVec[it.first].is_string() || + it.second.is_boolean() && destVec[it.first].is_boolean()) + { + destVec[it.first] = it.second; + } + else { + Debug() << "Invalid or unrecognized variable in configuration:" << objectName << it.first; + } + } + return true; +} + #define CONF_FILE "mkxp.json" Config::Config() {} void Config::read(int argc, char *argv[]) { - auto opts = json::object({ + auto optsJ = json::object({ {"rgssVersion", 0}, {"debugMode", false}, {"printFPS", false}, @@ -94,8 +125,20 @@ void Config::read(int argc, char *argv[]) { {"JITEnable", false}, {"JITVerboseLevel", 0}, {"JITMaxCache", 100}, - {"JITMinCalls", 10000} - }).as_object(); + {"JITMinCalls", 10000}, + {"bindingNames", json::object({ + {"a", "A"}, + {"b", "B"}, + {"c", "C"}, + {"x", "X"}, + {"y", "Y"}, + {"z", "Z"}, + {"l", "L"}, + {"r", "R"} + })} + }); + + auto &opts = optsJ.as_object(); #define GUARD(exp) \ try { exp } catch (...) {} @@ -122,20 +165,8 @@ try { exp } catch (...) {} if (!confData.is_object()) confData = json::object({}); - auto &cdObject = confData.as_object(); - - for (auto it : cdObject) { - if (it.second.is_array() && opts[it.first].is_array() || - it.second.is_number() && opts[it.first].is_number() || - it.second.is_string() && opts[it.first].is_string() || - it.second.is_boolean() && opts[it.first].is_boolean()) - { - opts[it.first] = it.second; - } - else { - Debug() << "Invalid or unrecognized variable in configuration:" << it.first; - } - } + copyObject(optsJ, confData); + copyObject(opts["bindingNames"], confData.as_object()["bindingNames"], "bindingNames ."); } #define SET_OPT_CUSTOMKEY(var, key, type) GUARD(var = opts[#key].as_##type();) @@ -185,6 +216,19 @@ try { exp } catch (...) {} fillStringVec(opts["RTP"], rtps); fillStringVec(opts["fontSub"], fontSubs); fillStringVec(opts["rubyLoadpath"], rubyLoadpaths); + + auto &bnames = opts["bindingNames"].as_object(); + +#define BINDING_NAME(btn) kbActionNames.btn = bnames[#btn].as_string() + BINDING_NAME(a); + BINDING_NAME(b); + BINDING_NAME(c); + BINDING_NAME(x); + BINDING_NAME(y); + BINDING_NAME(z); + BINDING_NAME(l); + BINDING_NAME(r); + rgssVersion = clamp(rgssVersion, 0, 3); SE.sourceCount = clamp(SE.sourceCount, 1, 64); diff --git a/src/config.h b/src/config.h index d83f5bfd..a0549350 100644 --- a/src/config.h +++ b/src/config.h @@ -105,6 +105,20 @@ struct Config { int maxCache; int minCalls; } jit; + + // Keybinding action name mappings + struct { + std::string a; + std::string b; + std::string c; + + std::string x; + std::string y; + std::string z; + + std::string l; + std::string r; + } kbActionNames; /* Internal */ std::string customDataPath; diff --git a/src/input/input.cpp b/src/input/input.cpp index cc1041dd..7f6dc596 100644 --- a/src/input/input.cpp +++ b/src/input/input.cpp @@ -1125,6 +1125,37 @@ void Input::update() p->repeating = None; } +std::vector Input::getBindings(ButtonCode code) { + std::vector ret; + for (const auto &b : p->kbBindings) { + if (b.target != code) continue; + ret.push_back(SDL_GetScancodeName(b.source)); + } + + for (const auto &b : p->jsBBindings) { + if (b.target != code) continue; + ret.push_back(std::string("JSBUTTON") + std::to_string(b.source)); + } + + for (const auto &b : p->jsABindings) { + if (b.target != code) continue; + ret.push_back(std::string("JSAXIS") + std::to_string(b.source)); + } + + for (const auto &b : p->jsHBindings) { + if (b.target != code) continue; + ret.push_back(std::string("JSHAT") + std::to_string(b.source)); + } + + return ret; +} + +std::string &Input::getActionName(int button) { + for (const auto &b : p->kbBindings) { + + } +} + bool Input::isPressed(int button) { return p->getStateCheck(button).pressed; diff --git a/src/input/input.h b/src/input/input.h index 7b0b8b12..69a29aec 100644 --- a/src/input/input.h +++ b/src/input/input.h @@ -24,6 +24,7 @@ #include #include +#include extern std::unordered_map vKeyToScancode; extern std::unordered_map strToScancode; @@ -53,6 +54,11 @@ public: }; void update(); + + std::vector getBindings(ButtonCode code); + + std::string &getActionName(int button); + void setActionName(int button, const char *name); bool isPressed(int button); bool isTriggered(int button); diff --git a/src/settingsmenu.cpp b/src/settingsmenu.cpp index f5bfd920..f4df9aa9 100644 --- a/src/settingsmenu.cpp +++ b/src/settingsmenu.cpp @@ -60,7 +60,7 @@ struct VButton { Input::ButtonCode code; const char *str; -} static const vButtons[] = +} static vButtons[] = { BTN_STRING(Up), BTN_STRING(Down), @@ -181,7 +181,9 @@ struct BindingWidget : Widget : Widget(p, rect), vb(vButtons[vbIndex]), hoveredCell(-1) - {} + { + + } void appendBindings(BDescVec &d) const; @@ -949,6 +951,20 @@ void Label::drawHandler(SDL_Surface *surf) SettingsMenu::SettingsMenu(RGSSThreadData &rtData) { + // Set names to be shown in the menu + { +#define SET_BUTTON_NAME(n, b) vButtons[n].str = rtData.config.kbActionNames.b.c_str(); + SET_BUTTON_NAME(2, l); + SET_BUTTON_NAME(5, r); + SET_BUTTON_NAME(6, a); + SET_BUTTON_NAME(7, b); + SET_BUTTON_NAME(8, c); + SET_BUTTON_NAME(9, x); + SET_BUTTON_NAME(10, y); + SET_BUTTON_NAME(11, z); +#undef SET_BUTTON_NAME + } + p = new SettingsMenuPrivate(rtData); p->state = Idle;