feat(controls): redefinició de tecles i botons del mando des del menú de servei

This commit is contained in:
JailDesigner committed 2026-04-29 19:54:47 +02:00
1 parent 4739354875
commit 37fdcb4751
15 files changed
+1169 -80

No files matched your search

+68
View File
@@ -169,11 +169,51 @@ namespace {
readField(node, "path", dst.path);
}
// Llegeix una tecla del YAML pel nom (com `SDL_GetScancodeName`). Si la
// clau no hi és o és invàlida, deixa `dst` intacte per preservar el
// default. Replica la política d'AEE (`KeyConfig::applyOverrides`).
void readScancodeField(const fkyaml::node& node, const char* key, SDL_Scancode& dst) {
if (!node.contains(key)) { return; }
const auto NAME = node[key].get_value<std::string>();
const SDL_Scancode SC = SDL_GetScancodeFromName(NAME.c_str());
if (SC != SDL_SCANCODE_UNKNOWN) { dst = SC; }
}
void parseKeyboard(const fkyaml::node& parent, const char* key, Options::Keyboard& dst) {
if (!parent.contains(key)) { return; }
const auto& node = parent[key];
readScancodeField(node, "up", dst.up);
readScancodeField(node, "down", dst.down);
readScancodeField(node, "left", dst.left);
readScancodeField(node, "right", dst.right);
readScancodeField(node, "jump", dst.jump);
readScancodeField(node, "attack", dst.attack);
}
void parseControls(const fkyaml::node& yaml) {
if (!yaml.contains("controls")) { return; }
const auto& node = yaml["controls"];
parseGamepadAssignment(node, "gamepad_p1", g_controls.gamepad_p1);
parseGamepadAssignment(node, "gamepad_p2", g_controls.gamepad_p2);
parseKeyboard(node, "keyboard_p1", g_controls.keyboard_p1);
parseKeyboard(node, "keyboard_p2", g_controls.keyboard_p2);
}
// Escriu una tecla com a string del nom SDL ("Up", "W", ...). Si
// l'scancode és UNKNOWN o sense nom registrat, escriu "" — no en farem
// override en càrrega gràcies a `readScancodeField`.
void writeKeyboard(std::ostringstream& out, const char* key, const Options::Keyboard& kb) {
const auto NAME_OR_EMPTY = [](SDL_Scancode sc) -> std::string {
const char* n = SDL_GetScancodeName(sc);
return (n != nullptr) ? std::string{n} : std::string{};
};
out << " " << key << ":\n";
out << " up: \"" << NAME_OR_EMPTY(kb.up) << "\"\n";
out << " down: \"" << NAME_OR_EMPTY(kb.down) << "\"\n";
out << " left: \"" << NAME_OR_EMPTY(kb.left) << "\"\n";
out << " right: \"" << NAME_OR_EMPTY(kb.right) << "\"\n";
out << " jump: \"" << NAME_OR_EMPTY(kb.jump) << "\"\n";
out << " attack: \"" << NAME_OR_EMPTY(kb.attack) << "\"\n";
}
// Aplica les assignacions persistides al GamepadManager. Ordre garantit
@@ -561,6 +601,32 @@ namespace Options {
saveToFile();
}
void setKeyboardBinding(int player_id, KeyboardAction action, SDL_Scancode scancode) {
if (player_id < 0 || player_id > 1) { return; }
auto& kb = (player_id == 0) ? g_controls.keyboard_p1 : g_controls.keyboard_p2;
switch (action) {
case KeyboardAction::UP:
kb.up = scancode;
break;
case KeyboardAction::DOWN:
kb.down = scancode;
break;
case KeyboardAction::LEFT:
kb.left = scancode;
break;
case KeyboardAction::RIGHT:
kb.right = scancode;
break;
case KeyboardAction::JUMP:
kb.jump = scancode;
break;
case KeyboardAction::ATTACK:
kb.attack = scancode;
break;
}
saveToFile();
}
void setConfigFile(const std::string& path) {
g_config_file_path = path;
}
@@ -666,6 +732,8 @@ namespace Options {
out << " gamepad_p2:\n";
out << " name: \"" << g_controls.gamepad_p2.name << "\"\n";
out << " path: \"" << g_controls.gamepad_p2.path << "\"\n";
writeKeyboard(out, "keyboard_p1", g_controls.keyboard_p1);
writeKeyboard(out, "keyboard_p2", g_controls.keyboard_p2);
return writeFile(g_config_file_path, out.str());
}