fcf13591be
Singleton inspirat en aee_arcade DefineButtons: pinta una caixa central modal, captura events SDL i avança per una sequencia fixa d'accions per jugador. Teclat: LEFT/RIGHT/FIRE/ACCELERATE. Mando: FIRE/ACCELERATE/ START/MENU. ESC cancel-la, duplicats dins la sessio es rebutgen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
108 lines
3.7 KiB
C++
108 lines
3.7 KiB
C++
// define_inputs.hpp - Overlay modal de redefinici de controls (singleton)
|
|
// © 2026 JailDesigner
|
|
//
|
|
// Sub-mòdul inspirat en aee_arcade/source/core/input/define_buttons. Quan el
|
|
// menú de servei dispara una acció "Redefinir tecles/botons P1/P2", aquest
|
|
// singleton pren el control: pinta una caixa central, captura events SDL i
|
|
// avança per una seqüència fixa d'accions, persistint les noves assignacions
|
|
// a config.yaml en acabar.
|
|
//
|
|
// Cicle de vida:
|
|
// 1. begin(mode, player) → construeix la seqüència (4 passos) i activa
|
|
// l'overlay. Per a GAMEPAD, retorna false si el jugador no té pad.
|
|
// 2. handleEvent() captura el següent event vàlid; ESC cancel·la sense
|
|
// desar; duplicats dins de la sessió es rebutgen silenciosament.
|
|
// 3. Quan la seqüència es completa, persistim a engine_config + saveToFile,
|
|
// reapliquem els bindings i mostrem un missatge "OK" durant 1.5 s
|
|
// abans d'auto-tancar-se.
|
|
//
|
|
// El routing d'events es fa des de GlobalEvents::handle: mentre isActive()
|
|
// retorna true, tots els events SDL es desvien aquí i no arriben al joc ni
|
|
// al menú de servei.
|
|
|
|
#pragma once
|
|
|
|
#include <SDL3/SDL.h>
|
|
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "core/graphics/vector_text.hpp"
|
|
#include "core/input/input_types.hpp"
|
|
#include "core/rendering/render_context.hpp"
|
|
|
|
namespace System {
|
|
|
|
class DefineInputs {
|
|
public:
|
|
enum class Mode : std::uint8_t { KEYBOARD,
|
|
GAMEPAD };
|
|
enum class Player : std::uint8_t { P1,
|
|
P2 };
|
|
|
|
static void init(Rendering::Renderer* renderer);
|
|
static void destroy();
|
|
[[nodiscard]] static auto get() -> DefineInputs*;
|
|
|
|
// Comença la sessió. Retorna false per a GAMEPAD si el jugador no té
|
|
// cap pad assignat (el caller hauria de notificar a l'usuari abans).
|
|
auto begin(Mode mode, Player player) -> bool;
|
|
void cancel();
|
|
|
|
[[nodiscard]] auto isActive() const -> bool;
|
|
|
|
void update(float delta_time);
|
|
void draw() const;
|
|
|
|
// Retorna true si l'event s'ha consumit (és a dir, mentre l'overlay
|
|
// és actiu sempre consumeix tot per evitar passages al joc o menú).
|
|
auto handleEvent(const SDL_Event& event) -> bool;
|
|
|
|
private:
|
|
explicit DefineInputs(Rendering::Renderer* renderer);
|
|
|
|
enum class Phase : std::uint8_t {
|
|
INACTIVE,
|
|
CAPTURING,
|
|
COMPLETE, // mostra missatge OK breu abans d'auto-cancel
|
|
};
|
|
|
|
struct Step {
|
|
std::string action_label_key; // p.ex. "define.action.left"
|
|
InputAction action; // mapeig a la struct PlayerBindings
|
|
int captured{-1}; // scancode o button code; -1 = sense capturar
|
|
};
|
|
|
|
void buildSequence();
|
|
[[nodiscard]] auto isInUse(int code) const -> bool;
|
|
void captureAndAdvance(int code);
|
|
void persistAndComplete();
|
|
|
|
// Handlers especialitzats segons mode_.
|
|
auto handleKeyboardEvent(const SDL_Event& event) -> bool;
|
|
auto handleGamepadEvent(const SDL_Event& event) -> bool;
|
|
|
|
// Edge-detect per als triggers L2/R2 com a botons virtuals.
|
|
void processTrigger(int virtual_button, bool& was_pressed, bool now);
|
|
|
|
Rendering::Renderer* renderer_;
|
|
Graphics::VectorText text_;
|
|
|
|
Phase phase_{Phase::INACTIVE};
|
|
Mode mode_{Mode::KEYBOARD};
|
|
Player player_{Player::P1};
|
|
std::vector<Step> sequence_;
|
|
std::size_t index_{0};
|
|
float complete_timer_s_{0.0F};
|
|
|
|
// Estat d'edge-detect dels triggers durant la sessió GAMEPAD.
|
|
bool l2_was_pressed_{false};
|
|
bool r2_was_pressed_{false};
|
|
|
|
static std::unique_ptr<DefineInputs> instance;
|
|
};
|
|
|
|
} // namespace System
|