feat(input): assignació mando↔jugador persistida a config.yaml
This commit is contained in:
1 parent
4e9d5df872
commit
a725b76684
5 files changed
+226
-13
No files matched your search
@@ -25,11 +25,14 @@ namespace {
|
||||
// repòs i no contribueix a la velocitat.
|
||||
constexpr Sint16 STICK_DEADZONE = 12000;
|
||||
|
||||
// Acumula la contribució del primer gamepad (cruceta + stick esquerre)
|
||||
// sobre els acumuladors de velocitat. Extracció d'`update()` per a
|
||||
// mantenir la complexitat cognitiva sota llindar (threshold 25).
|
||||
void accumulateGamepadMovement(float& vx, float& vy) {
|
||||
SDL_Gamepad* pad = GamepadManager::get().getPrimary();
|
||||
// Acumula la contribució del mando assignat al jugador (cruceta +
|
||||
// stick esquerre) sobre els acumuladors de velocitat. Extracció
|
||||
// d'`update()` per a mantenir la complexitat cognitiva sota llindar
|
||||
// (threshold 25). L'assignació mando↔jugador viu al `GamepadManager`
|
||||
// i la persisteix Options; si aquest jugador no en té cap assignat,
|
||||
// la funció és un no-op (sols es mou amb el teclat).
|
||||
void accumulateGamepadMovement(int player_id, float& vx, float& vy) {
|
||||
SDL_Gamepad* pad = GamepadManager::get().getForPlayer(player_id);
|
||||
if (pad == nullptr) { return; }
|
||||
if (InputState::getGamepadButton(pad, SDL_GAMEPAD_BUTTON_DPAD_LEFT)) { vx -= SPEED_PX_PER_S; }
|
||||
if (InputState::getGamepadButton(pad, SDL_GAMEPAD_BUTTON_DPAD_RIGHT)) { vx += SPEED_PX_PER_S; }
|
||||
@@ -256,7 +259,7 @@ void Player::update(float delta_time) {
|
||||
// Direccions oposades (teclat left + d-pad right) es cancel·len de
|
||||
// forma natural; premuda simultània en la mateixa direcció no duplica
|
||||
// la velocitat perquè cada branca només resta/suma una vegada.
|
||||
accumulateGamepadMovement(vx, vy);
|
||||
accumulateGamepadMovement(id_, vx, vy);
|
||||
|
||||
setVelX(vx);
|
||||
setVelY(vy);
|
||||
|
||||
+46
-1
@@ -9,6 +9,7 @@
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "core/input/gamepad_manager.hpp"
|
||||
#include "external/fkyaml_node.hpp"
|
||||
#include "utils/defines.hpp"
|
||||
|
||||
@@ -26,6 +27,7 @@ namespace {
|
||||
Options::Window g_window{};
|
||||
Options::Video g_video{};
|
||||
Options::Audio g_audio{};
|
||||
Options::Controls g_controls{};
|
||||
std::vector<Options::PostFXPreset> g_postfx_presets{};
|
||||
std::vector<Options::CrtPiPreset> g_crtpi_presets{};
|
||||
|
||||
@@ -160,6 +162,29 @@ namespace {
|
||||
readField(node, "volume", g_audio.sound.volume);
|
||||
}
|
||||
|
||||
void parseGamepadAssignment(const fkyaml::node& parent, const char* key, Options::GamepadAssignment& dst) {
|
||||
if (!parent.contains(key)) { return; }
|
||||
const auto& node = parent[key];
|
||||
readField(node, "name", dst.name);
|
||||
readField(node, "path", dst.path);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Aplica les assignacions persistides al GamepadManager. Cridat
|
||||
// després de `loadFromFile` perquè l'ordre és: GamepadManager::init
|
||||
// (obre tots els mandos físics) → Options::loadFromFile (llig YAML)
|
||||
// → aquesta funció (casa mandos↔jugadors).
|
||||
void applyControlsToGamepadManager() {
|
||||
GamepadManager::get().assignToPlayer(0, g_controls.gamepad_p1.name, g_controls.gamepad_p1.path);
|
||||
GamepadManager::get().assignToPlayer(1, g_controls.gamepad_p2.name, g_controls.gamepad_p2.path);
|
||||
}
|
||||
|
||||
void parseAudio(const fkyaml::node& yaml) {
|
||||
if (!yaml.contains("audio")) { return; }
|
||||
const auto& node = yaml["audio"];
|
||||
@@ -442,6 +467,7 @@ namespace Options {
|
||||
auto window() -> const Window& { return g_window; }
|
||||
auto video() -> const Video& { return g_video; }
|
||||
auto audio() -> const Audio& { return g_audio; }
|
||||
auto controls() -> const Controls& { return g_controls; }
|
||||
auto locale() -> const std::string& { return g_locale; }
|
||||
auto configVersion() -> const std::string& { return g_config_version; }
|
||||
auto postfxPresets() -> const std::vector<PostFXPreset>& { return g_postfx_presets; }
|
||||
@@ -513,6 +539,15 @@ namespace Options {
|
||||
saveToFile();
|
||||
}
|
||||
|
||||
void setGamepadAssignment(int player_id, const std::string& name, const std::string& path) {
|
||||
if (player_id < 0 || player_id > 1) { return; }
|
||||
auto& slot = (player_id == 0) ? g_controls.gamepad_p1 : g_controls.gamepad_p2;
|
||||
slot.name = name;
|
||||
slot.path = path;
|
||||
GamepadManager::get().assignToPlayer(player_id, name, path);
|
||||
saveToFile();
|
||||
}
|
||||
|
||||
void setConfigFile(const std::string& path) {
|
||||
g_config_file_path = path;
|
||||
}
|
||||
@@ -548,6 +583,8 @@ namespace Options {
|
||||
parseWindow(yaml);
|
||||
parseVideo(yaml);
|
||||
parseAudio(yaml);
|
||||
parseControls(yaml);
|
||||
applyControlsToGamepadManager();
|
||||
return true;
|
||||
} catch (const std::exception& e) {
|
||||
std::cout << "Options: error parsejant config.yaml: " << e.what() << '\n';
|
||||
@@ -594,7 +631,15 @@ namespace Options {
|
||||
out << " volume: " << g_audio.music.volume << "\n";
|
||||
out << " sound:\n";
|
||||
out << " enabled: " << (g_audio.sound.enabled ? "true" : "false") << "\n";
|
||||
out << " volume: " << g_audio.sound.volume << "\n";
|
||||
out << " volume: " << g_audio.sound.volume << "\n\n";
|
||||
|
||||
out << "controls:\n";
|
||||
out << " gamepad_p1:\n";
|
||||
out << " name: \"" << g_controls.gamepad_p1.name << "\"\n";
|
||||
out << " path: \"" << g_controls.gamepad_p1.path << "\"\n";
|
||||
out << " gamepad_p2:\n";
|
||||
out << " name: \"" << g_controls.gamepad_p2.name << "\"\n";
|
||||
out << " path: \"" << g_controls.gamepad_p2.path << "\"\n";
|
||||
|
||||
return writeFile(g_config_file_path, out.str());
|
||||
}
|
||||
|
||||
@@ -104,10 +104,26 @@ namespace Options {
|
||||
Sound sound{};
|
||||
};
|
||||
|
||||
// Assignació d'un mando a un jugador: nom visible (el que retorna
|
||||
// `GamepadManager::Info::name`) + ruta física (de `SDL_GetGamepadPath`).
|
||||
// Tots dos buits = sense mando. La ruta serveix per re-vincular
|
||||
// automàticament el mateix mando al mateix port; el nom és el
|
||||
// fallback quan l'usuari el canvia de port USB.
|
||||
struct GamepadAssignment {
|
||||
std::string name;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
struct Controls {
|
||||
GamepadAssignment gamepad_p1{};
|
||||
GamepadAssignment gamepad_p2{};
|
||||
};
|
||||
|
||||
// --- Getters de l'estat (read-only) ---
|
||||
[[nodiscard]] auto window() -> const Window&;
|
||||
[[nodiscard]] auto video() -> const Video&;
|
||||
[[nodiscard]] auto audio() -> const Audio&;
|
||||
[[nodiscard]] auto controls() -> const Controls&;
|
||||
[[nodiscard]] auto locale() -> const std::string&;
|
||||
[[nodiscard]] auto configVersion() -> const std::string&;
|
||||
[[nodiscard]] auto postfxPresets() -> const std::vector<PostFXPreset>&;
|
||||
@@ -132,6 +148,10 @@ namespace Options {
|
||||
void setAudioMusicVolume(float value);
|
||||
void setAudioSoundEnabled(bool value);
|
||||
void setAudioSoundVolume(float value);
|
||||
// Fixa l'assignació mando→jugador. Persisteix a `config.yaml` i
|
||||
// propaga a `GamepadManager::assignToPlayer`. `name` i `path` buits
|
||||
// = desassignació. `player_id`: 0 = P1, 1 = P2.
|
||||
void setGamepadAssignment(int player_id, const std::string& name, const std::string& path);
|
||||
|
||||
// --- API pública: càrrega/desament de fitxers ---
|
||||
void setConfigFile(const std::string& path);
|
||||
|
||||
Reference in new issue
Block a user