integrada classe Input
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "core/defaults.hpp"
|
||||
#include "external/fkyaml_node.hpp"
|
||||
@@ -10,6 +11,111 @@
|
||||
|
||||
namespace Options {
|
||||
|
||||
// ========== FUNCIONS AUXILIARS PER CONVERSIÓ DE CONTROLES ==========
|
||||
|
||||
// Mapa de SDL_Scancode a string
|
||||
static const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING = {
|
||||
{SDL_SCANCODE_A, "A"}, {SDL_SCANCODE_B, "B"}, {SDL_SCANCODE_C, "C"}, {SDL_SCANCODE_D, "D"},
|
||||
{SDL_SCANCODE_E, "E"}, {SDL_SCANCODE_F, "F"}, {SDL_SCANCODE_G, "G"}, {SDL_SCANCODE_H, "H"},
|
||||
{SDL_SCANCODE_I, "I"}, {SDL_SCANCODE_J, "J"}, {SDL_SCANCODE_K, "K"}, {SDL_SCANCODE_L, "L"},
|
||||
{SDL_SCANCODE_M, "M"}, {SDL_SCANCODE_N, "N"}, {SDL_SCANCODE_O, "O"}, {SDL_SCANCODE_P, "P"},
|
||||
{SDL_SCANCODE_Q, "Q"}, {SDL_SCANCODE_R, "R"}, {SDL_SCANCODE_S, "S"}, {SDL_SCANCODE_T, "T"},
|
||||
{SDL_SCANCODE_U, "U"}, {SDL_SCANCODE_V, "V"}, {SDL_SCANCODE_W, "W"}, {SDL_SCANCODE_X, "X"},
|
||||
{SDL_SCANCODE_Y, "Y"}, {SDL_SCANCODE_Z, "Z"},
|
||||
{SDL_SCANCODE_1, "1"}, {SDL_SCANCODE_2, "2"}, {SDL_SCANCODE_3, "3"}, {SDL_SCANCODE_4, "4"},
|
||||
{SDL_SCANCODE_5, "5"}, {SDL_SCANCODE_6, "6"}, {SDL_SCANCODE_7, "7"}, {SDL_SCANCODE_8, "8"},
|
||||
{SDL_SCANCODE_9, "9"}, {SDL_SCANCODE_0, "0"},
|
||||
{SDL_SCANCODE_RETURN, "RETURN"}, {SDL_SCANCODE_ESCAPE, "ESCAPE"},
|
||||
{SDL_SCANCODE_BACKSPACE, "BACKSPACE"}, {SDL_SCANCODE_TAB, "TAB"},
|
||||
{SDL_SCANCODE_SPACE, "SPACE"},
|
||||
{SDL_SCANCODE_UP, "UP"}, {SDL_SCANCODE_DOWN, "DOWN"},
|
||||
{SDL_SCANCODE_LEFT, "LEFT"}, {SDL_SCANCODE_RIGHT, "RIGHT"},
|
||||
{SDL_SCANCODE_LSHIFT, "LSHIFT"}, {SDL_SCANCODE_RSHIFT, "RSHIFT"},
|
||||
{SDL_SCANCODE_LCTRL, "LCTRL"}, {SDL_SCANCODE_RCTRL, "RCTRL"},
|
||||
{SDL_SCANCODE_LALT, "LALT"}, {SDL_SCANCODE_RALT, "RALT"}
|
||||
};
|
||||
|
||||
// Mapa invers: string a SDL_Scancode
|
||||
static const std::unordered_map<std::string, SDL_Scancode> STRING_TO_SCANCODE = {
|
||||
{"A", SDL_SCANCODE_A}, {"B", SDL_SCANCODE_B}, {"C", SDL_SCANCODE_C}, {"D", SDL_SCANCODE_D},
|
||||
{"E", SDL_SCANCODE_E}, {"F", SDL_SCANCODE_F}, {"G", SDL_SCANCODE_G}, {"H", SDL_SCANCODE_H},
|
||||
{"I", SDL_SCANCODE_I}, {"J", SDL_SCANCODE_J}, {"K", SDL_SCANCODE_K}, {"L", SDL_SCANCODE_L},
|
||||
{"M", SDL_SCANCODE_M}, {"N", SDL_SCANCODE_N}, {"O", SDL_SCANCODE_O}, {"P", SDL_SCANCODE_P},
|
||||
{"Q", SDL_SCANCODE_Q}, {"R", SDL_SCANCODE_R}, {"S", SDL_SCANCODE_S}, {"T", SDL_SCANCODE_T},
|
||||
{"U", SDL_SCANCODE_U}, {"V", SDL_SCANCODE_V}, {"W", SDL_SCANCODE_W}, {"X", SDL_SCANCODE_X},
|
||||
{"Y", SDL_SCANCODE_Y}, {"Z", SDL_SCANCODE_Z},
|
||||
{"1", SDL_SCANCODE_1}, {"2", SDL_SCANCODE_2}, {"3", SDL_SCANCODE_3}, {"4", SDL_SCANCODE_4},
|
||||
{"5", SDL_SCANCODE_5}, {"6", SDL_SCANCODE_6}, {"7", SDL_SCANCODE_7}, {"8", SDL_SCANCODE_8},
|
||||
{"9", SDL_SCANCODE_9}, {"0", SDL_SCANCODE_0},
|
||||
{"RETURN", SDL_SCANCODE_RETURN}, {"ESCAPE", SDL_SCANCODE_ESCAPE},
|
||||
{"BACKSPACE", SDL_SCANCODE_BACKSPACE}, {"TAB", SDL_SCANCODE_TAB},
|
||||
{"SPACE", SDL_SCANCODE_SPACE},
|
||||
{"UP", SDL_SCANCODE_UP}, {"DOWN", SDL_SCANCODE_DOWN},
|
||||
{"LEFT", SDL_SCANCODE_LEFT}, {"RIGHT", SDL_SCANCODE_RIGHT},
|
||||
{"LSHIFT", SDL_SCANCODE_LSHIFT}, {"RSHIFT", SDL_SCANCODE_RSHIFT},
|
||||
{"LCTRL", SDL_SCANCODE_LCTRL}, {"RCTRL", SDL_SCANCODE_RCTRL},
|
||||
{"LALT", SDL_SCANCODE_LALT}, {"RALT", SDL_SCANCODE_RALT}
|
||||
};
|
||||
|
||||
// Mapa de botó de gamepad (int) a string
|
||||
static const std::unordered_map<int, std::string> BUTTON_TO_STRING = {
|
||||
{SDL_GAMEPAD_BUTTON_SOUTH, "SOUTH"}, // A (Xbox), Cross (PS)
|
||||
{SDL_GAMEPAD_BUTTON_EAST, "EAST"}, // B (Xbox), Circle (PS)
|
||||
{SDL_GAMEPAD_BUTTON_WEST, "WEST"}, // X (Xbox), Square (PS)
|
||||
{SDL_GAMEPAD_BUTTON_NORTH, "NORTH"}, // Y (Xbox), Triangle (PS)
|
||||
{SDL_GAMEPAD_BUTTON_BACK, "BACK"},
|
||||
{SDL_GAMEPAD_BUTTON_START, "START"},
|
||||
{SDL_GAMEPAD_BUTTON_LEFT_SHOULDER, "LEFT_SHOULDER"},
|
||||
{SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, "RIGHT_SHOULDER"},
|
||||
{SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"},
|
||||
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"},
|
||||
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"},
|
||||
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"},
|
||||
{100, "L2_AS_BUTTON"}, // Trigger L2 com a botó digital
|
||||
{101, "R2_AS_BUTTON"} // Trigger R2 com a botó digital
|
||||
};
|
||||
|
||||
// Mapa invers: string a botó de gamepad
|
||||
static const std::unordered_map<std::string, int> STRING_TO_BUTTON = {
|
||||
{"SOUTH", SDL_GAMEPAD_BUTTON_SOUTH},
|
||||
{"EAST", SDL_GAMEPAD_BUTTON_EAST},
|
||||
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
||||
{"NORTH", SDL_GAMEPAD_BUTTON_NORTH},
|
||||
{"BACK", SDL_GAMEPAD_BUTTON_BACK},
|
||||
{"START", SDL_GAMEPAD_BUTTON_START},
|
||||
{"LEFT_SHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER},
|
||||
{"RIGHT_SHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER},
|
||||
{"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
|
||||
{"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
|
||||
{"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
||||
{"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT},
|
||||
{"L2_AS_BUTTON", 100},
|
||||
{"R2_AS_BUTTON", 101}
|
||||
};
|
||||
|
||||
static auto scancodeToString(SDL_Scancode code) -> std::string {
|
||||
auto it = SCANCODE_TO_STRING.find(code);
|
||||
return (it != SCANCODE_TO_STRING.end()) ? it->second : "UNKNOWN";
|
||||
}
|
||||
|
||||
static auto stringToScancode(const std::string& str) -> SDL_Scancode {
|
||||
auto it = STRING_TO_SCANCODE.find(str);
|
||||
return (it != STRING_TO_SCANCODE.end()) ? it->second : SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
static auto buttonToString(int button) -> std::string {
|
||||
auto it = BUTTON_TO_STRING.find(button);
|
||||
return (it != BUTTON_TO_STRING.end()) ? it->second : "UNKNOWN";
|
||||
}
|
||||
|
||||
static auto stringToButton(const std::string& str) -> int {
|
||||
auto it = STRING_TO_BUTTON.find(str);
|
||||
return (it != STRING_TO_BUTTON.end()) ? it->second : SDL_GAMEPAD_BUTTON_INVALID;
|
||||
}
|
||||
|
||||
// ========== FI FUNCIONS AUXILIARS ==========
|
||||
|
||||
|
||||
// Inicialitzar opcions amb valors per defecte de Defaults::
|
||||
void init() {
|
||||
#ifdef _DEBUG
|
||||
@@ -278,6 +384,80 @@ static void loadAudioConfigFromYaml(const fkyaml::node& yaml) {
|
||||
}
|
||||
}
|
||||
|
||||
// Carregar controls del jugador 1 des de YAML
|
||||
static void loadPlayer1ControlsFromYaml(const fkyaml::node& yaml) {
|
||||
if (!yaml.contains("player1")) return;
|
||||
|
||||
const auto& p1 = yaml["player1"];
|
||||
|
||||
// Carregar controls de teclat
|
||||
if (p1.contains("keyboard")) {
|
||||
const auto& kb = p1["keyboard"];
|
||||
if (kb.contains("key_left"))
|
||||
player1.keyboard.key_left = stringToScancode(kb["key_left"].get_value<std::string>());
|
||||
if (kb.contains("key_right"))
|
||||
player1.keyboard.key_right = stringToScancode(kb["key_right"].get_value<std::string>());
|
||||
if (kb.contains("key_thrust"))
|
||||
player1.keyboard.key_thrust = stringToScancode(kb["key_thrust"].get_value<std::string>());
|
||||
if (kb.contains("key_shoot"))
|
||||
player1.keyboard.key_shoot = stringToScancode(kb["key_shoot"].get_value<std::string>());
|
||||
}
|
||||
|
||||
// Carregar controls de gamepad
|
||||
if (p1.contains("gamepad")) {
|
||||
const auto& gp = p1["gamepad"];
|
||||
if (gp.contains("button_left"))
|
||||
player1.gamepad.button_left = stringToButton(gp["button_left"].get_value<std::string>());
|
||||
if (gp.contains("button_right"))
|
||||
player1.gamepad.button_right = stringToButton(gp["button_right"].get_value<std::string>());
|
||||
if (gp.contains("button_thrust"))
|
||||
player1.gamepad.button_thrust = stringToButton(gp["button_thrust"].get_value<std::string>());
|
||||
if (gp.contains("button_shoot"))
|
||||
player1.gamepad.button_shoot = stringToButton(gp["button_shoot"].get_value<std::string>());
|
||||
}
|
||||
|
||||
// Carregar nom del gamepad
|
||||
if (p1.contains("gamepad_name"))
|
||||
player1.gamepad_name = p1["gamepad_name"].get_value<std::string>();
|
||||
}
|
||||
|
||||
// Carregar controls del jugador 2 des de YAML
|
||||
static void loadPlayer2ControlsFromYaml(const fkyaml::node& yaml) {
|
||||
if (!yaml.contains("player2")) return;
|
||||
|
||||
const auto& p2 = yaml["player2"];
|
||||
|
||||
// Carregar controls de teclat
|
||||
if (p2.contains("keyboard")) {
|
||||
const auto& kb = p2["keyboard"];
|
||||
if (kb.contains("key_left"))
|
||||
player2.keyboard.key_left = stringToScancode(kb["key_left"].get_value<std::string>());
|
||||
if (kb.contains("key_right"))
|
||||
player2.keyboard.key_right = stringToScancode(kb["key_right"].get_value<std::string>());
|
||||
if (kb.contains("key_thrust"))
|
||||
player2.keyboard.key_thrust = stringToScancode(kb["key_thrust"].get_value<std::string>());
|
||||
if (kb.contains("key_shoot"))
|
||||
player2.keyboard.key_shoot = stringToScancode(kb["key_shoot"].get_value<std::string>());
|
||||
}
|
||||
|
||||
// Carregar controls de gamepad
|
||||
if (p2.contains("gamepad")) {
|
||||
const auto& gp = p2["gamepad"];
|
||||
if (gp.contains("button_left"))
|
||||
player2.gamepad.button_left = stringToButton(gp["button_left"].get_value<std::string>());
|
||||
if (gp.contains("button_right"))
|
||||
player2.gamepad.button_right = stringToButton(gp["button_right"].get_value<std::string>());
|
||||
if (gp.contains("button_thrust"))
|
||||
player2.gamepad.button_thrust = stringToButton(gp["button_thrust"].get_value<std::string>());
|
||||
if (gp.contains("button_shoot"))
|
||||
player2.gamepad.button_shoot = stringToButton(gp["button_shoot"].get_value<std::string>());
|
||||
}
|
||||
|
||||
// Carregar nom del gamepad
|
||||
if (p2.contains("gamepad_name"))
|
||||
player2.gamepad_name = p2["gamepad_name"].get_value<std::string>();
|
||||
}
|
||||
|
||||
// Carregar configuració des del fitxer YAML
|
||||
auto loadFromFile() -> bool {
|
||||
const std::string CONFIG_VERSION = std::string(Project::VERSION);
|
||||
@@ -325,6 +505,8 @@ auto loadFromFile() -> bool {
|
||||
loadGameplayConfigFromYaml(yaml);
|
||||
loadRenderingConfigFromYaml(yaml);
|
||||
loadAudioConfigFromYaml(yaml);
|
||||
loadPlayer1ControlsFromYaml(yaml);
|
||||
loadPlayer2ControlsFromYaml(yaml);
|
||||
|
||||
if (console) {
|
||||
std::cout << "Config carregada correctament des de: " << config_file_path
|
||||
@@ -345,6 +527,40 @@ auto loadFromFile() -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Guardar controls del jugador 1 a YAML
|
||||
static void savePlayer1ControlsToYaml(std::ofstream& file) {
|
||||
file << "# CONTROLS JUGADOR 1\n";
|
||||
file << "player1:\n";
|
||||
file << " keyboard:\n";
|
||||
file << " key_left: " << scancodeToString(player1.keyboard.key_left) << "\n";
|
||||
file << " key_right: " << scancodeToString(player1.keyboard.key_right) << "\n";
|
||||
file << " key_thrust: " << scancodeToString(player1.keyboard.key_thrust) << "\n";
|
||||
file << " key_shoot: " << scancodeToString(player1.keyboard.key_shoot) << "\n";
|
||||
file << " gamepad:\n";
|
||||
file << " button_left: " << buttonToString(player1.gamepad.button_left) << "\n";
|
||||
file << " button_right: " << buttonToString(player1.gamepad.button_right) << "\n";
|
||||
file << " button_thrust: " << buttonToString(player1.gamepad.button_thrust) << "\n";
|
||||
file << " button_shoot: " << buttonToString(player1.gamepad.button_shoot) << "\n";
|
||||
file << " gamepad_name: \"" << player1.gamepad_name << "\" # Buit = primer disponible\n\n";
|
||||
}
|
||||
|
||||
// Guardar controls del jugador 2 a YAML
|
||||
static void savePlayer2ControlsToYaml(std::ofstream& file) {
|
||||
file << "# CONTROLS JUGADOR 2\n";
|
||||
file << "player2:\n";
|
||||
file << " keyboard:\n";
|
||||
file << " key_left: " << scancodeToString(player2.keyboard.key_left) << "\n";
|
||||
file << " key_right: " << scancodeToString(player2.keyboard.key_right) << "\n";
|
||||
file << " key_thrust: " << scancodeToString(player2.keyboard.key_thrust) << "\n";
|
||||
file << " key_shoot: " << scancodeToString(player2.keyboard.key_shoot) << "\n";
|
||||
file << " gamepad:\n";
|
||||
file << " button_left: " << buttonToString(player2.gamepad.button_left) << "\n";
|
||||
file << " button_right: " << buttonToString(player2.gamepad.button_right) << "\n";
|
||||
file << " button_thrust: " << buttonToString(player2.gamepad.button_thrust) << "\n";
|
||||
file << " button_shoot: " << buttonToString(player2.gamepad.button_shoot) << "\n";
|
||||
file << " gamepad_name: \"" << player2.gamepad_name << "\" # Buit = segon disponible\n\n";
|
||||
}
|
||||
|
||||
// Guardar configuració al fitxer YAML
|
||||
auto saveToFile() -> bool {
|
||||
std::ofstream file(config_file_path);
|
||||
@@ -399,7 +615,11 @@ auto saveToFile() -> bool {
|
||||
file << " volume: " << audio.music.volume << " # 0.0 to 1.0\n";
|
||||
file << " sound:\n";
|
||||
file << " enabled: " << (audio.sound.enabled ? "true" : "false") << "\n";
|
||||
file << " volume: " << audio.sound.volume << " # 0.0 to 1.0\n";
|
||||
file << " volume: " << audio.sound.volume << " # 0.0 to 1.0\n\n";
|
||||
|
||||
// Guardar controls de jugadors
|
||||
savePlayer1ControlsToYaml(file);
|
||||
savePlayer2ControlsToYaml(file);
|
||||
|
||||
file.close();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user