Allow setting keybinding names from config

This commit is contained in:
Struma 2021-01-15 04:49:27 -05:00 committed by Roza
parent a833c96109
commit 4233d36b22
6 changed files with 138 additions and 19 deletions

View file

@ -1240,6 +1240,7 @@
3B10EC6C2568E5EA00372D13 /* Source */ = {
isa = PBXGroup;
children = (
3B3F7D1325B19C5A00EA5F1C /* MacOS */,
3B10ED342568E95D00372D13 /* src */,
3B1C236625A19B780075EF5D /* steamshim */,
3B10EDD52568E96A00372D13 /* binding */,
@ -1561,6 +1562,13 @@
name = Steam;
sourceTree = "<group>";
};
3B3F7D1325B19C5A00EA5F1C /* MacOS */ = {
isa = PBXGroup;
children = (
);
name = MacOS;
sourceTree = "<group>";
};
3B426F6A256B8AC0009EA00F /* ghc */ = {
isa = PBXGroup;
children = (

View file

@ -7,6 +7,7 @@
#include "config.h"
#include <SDL_filesystem.h>
#include <assert.h>
#include <stdint.h>
#include <vector>
@ -47,12 +48,42 @@ void fillStringVec(json::value &item, std::vector<std::string> &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);

View file

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

View file

@ -1125,6 +1125,37 @@ void Input::update()
p->repeating = None;
}
std::vector<std::string> Input::getBindings(ButtonCode code) {
std::vector<std::string> 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;

View file

@ -24,6 +24,7 @@
#include <unordered_map>
#include <string>
#include <vector>
extern std::unordered_map<int, int> vKeyToScancode;
extern std::unordered_map<std::string, int> strToScancode;
@ -53,6 +54,11 @@ public:
};
void update();
std::vector<std::string> getBindings(ButtonCode code);
std::string &getActionName(int button);
void setActionName(int button, const char *name);
bool isPressed(int button);
bool isTriggered(int button);

View file

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