varies coses i detallets
This commit is contained in:
61
.gitignore
vendored
61
.gitignore
vendored
@@ -1,8 +1,57 @@
|
||||
aee
|
||||
aee.exe
|
||||
.DS_Store
|
||||
trick.ini
|
||||
.vscode/
|
||||
data.jrf
|
||||
# --- Build outputs ---
|
||||
build/
|
||||
dist/
|
||||
aee
|
||||
aee.exe
|
||||
*.o
|
||||
*.obj
|
||||
*.exe
|
||||
*.app
|
||||
|
||||
# --- Generated assets ---
|
||||
resource.pack
|
||||
data.jrf
|
||||
|
||||
# --- Runtime / debug junk ---
|
||||
trick.ini
|
||||
*.log
|
||||
*.dmp
|
||||
|
||||
# --- Editor / IDE ---
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.cache/
|
||||
compile_commands.json
|
||||
|
||||
# --- macOS ---
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
.fseventsd
|
||||
.DocumentRevisions-V100
|
||||
.TemporaryItems
|
||||
.VolumeIcon.icns
|
||||
Icon?
|
||||
|
||||
# --- Windows ---
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
Desktop.ini
|
||||
desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.lnk
|
||||
|
||||
# --- Linux ---
|
||||
*~
|
||||
.fuse_hidden*
|
||||
.directory
|
||||
.Trash-*
|
||||
.nfs*
|
||||
|
||||
14
CLAUDE.md
14
CLAUDE.md
@@ -113,9 +113,10 @@ Flat C-style APIs (no classes), prefixed by subsystem. Being progressively conve
|
||||
|
||||
### Input Layer (`source/core/input/`)
|
||||
|
||||
- **GlobalInputs** (`global_inputs.hpp/cpp`) — Maps configurable function keys to presentation actions. Uses debounce. Returns whether a key was consumed (to suppress from game layer)
|
||||
- **KeyConfig** (`key_config.hpp/cpp`) — **Font única de veritat per a les tecles d'UI/sistema**. Carrega `data/input/keys.yaml` al boot (12 entrades: F1-F10 GlobalInputs + F11 pausa + F12 menú de servei) i opcionalment aplica overrides des de `~/.config/jailgames/aee/keys.yaml`. Exposa `KeyConfig::scancode("id")`, `scancodePtr("id")` (per a Menu KeyBind), `setScancode(...)`, `isGuiKey(sc)` (filtre del Director per a no propagar tecles d'UI a `JI_AnyKey`). `saveOverrides()` només persistix les entrades que difereixen del default. Les tecles de moviment del jugador NO viuen ací — es queden a `Options::keys_game`
|
||||
- **GlobalInputs** (`global_inputs.hpp/cpp`) — Maps function keys (via `KeyConfig::scancode("dec_zoom")`, etc.) to presentation actions. Uses debounce. Returns whether a key was consumed (to suppress from game layer)
|
||||
- **Mouse** (`mouse.hpp/cpp`) — Auto-hides cursor after 3 seconds of inactivity
|
||||
- **Gamepad** (`gamepad.hpp/cpp`) — First-gamepad support with hot-plug. Poll-based each frame: D-pad/left stick (deadzone 12000) → virtual arrow keys for game movement; A/B buttons, Start, Back translate to synthetic SDL key events (F12/ESC/Enter/Backspace) when menu is open, so Director handles them exactly like keyboard. Loads extra mappings from `gamecontrollerdb.txt` (next to the executable) at init via `SDL_AddGamepadMappingsFromFile`, extending SDL's built-in controller database
|
||||
- **Gamepad** (`gamepad.hpp/cpp`) — First-gamepad support with hot-plug + overlay notification with controller name. Poll-based each frame: D-pad/left stick (deadzone 12000) → virtual arrow keys for game movement. Mapeig: SOUTH/EAST/WEST/NORTH (4 botons frontals) → Enter sintètic per avançar escenes; al menú EAST=accept, SOUTH=cancel/back. SELECT → menu_toggle (servei), START → pause_toggle (via `KeyConfig::scancode(...)`). Loads extra mappings from `gamecontrollerdb.txt` at init via `SDL_AddGamepadMappingsFromFile`
|
||||
- **KeyRemap** (`key_remap.hpp/cpp`) — Each frame, reads `Options::keys_game.*` and mirrors physical keyboard state to virtual standard scancodes (`SDL_SCANCODE_UP`/DOWN/LEFT/RIGHT). Allows full movement key remapping without touching hardcoded game code in `prota.cpp`/`mapa.cpp`
|
||||
|
||||
### Locale Layer (`source/core/locale/`)
|
||||
@@ -127,8 +128,8 @@ Flat C-style APIs (no classes), prefixed by subsystem. Being progressively conve
|
||||
Follows the pattern from `jaildoctors_dilemma`, persists to YAML:
|
||||
|
||||
- **defines.hpp** — Game constants: `Texts::WINDOW_TITLE`, `Texts::VERSION`, `GameScreen::WIDTH/HEIGHT`
|
||||
- **defaults.hpp** — Default values: `Defaults::KeysGUI`, `Defaults::KeysGame`, `Defaults::Video`, `Defaults::Audio`, `Defaults::Window`, `Defaults::Game`
|
||||
- **options.hpp/cpp** — `Options` namespace with inline globals and YAML load/save. Structs: `KeysGUI`, `KeysGame`, `Video`, `RenderInfo`, `Audio`, `Window`, `Game`, `PostFXPreset`, `CrtPiPreset`
|
||||
- **defaults.hpp** — Default values: `Defaults::KeysGame`, `Defaults::Video`, `Defaults::Audio`, `Defaults::Window`, `Defaults::Game`. (Les tecles d'UI viuen a `data/input/keys.yaml` via `KeyConfig`)
|
||||
- **options.hpp/cpp** — `Options` namespace with inline globals and YAML load/save. Structs: `KeysGame`, `Video`, `RenderInfo`, `Audio`, `Window`, `Game`, `PostFXPreset`, `CrtPiPreset`
|
||||
|
||||
### Utilities (`source/utils/`)
|
||||
|
||||
@@ -155,7 +156,7 @@ Follows the pattern from `jaildoctors_dilemma`, persists to YAML:
|
||||
| Backspace | Go up one menu level / close menu if at root |
|
||||
| ↑↓←→ / Enter | Menu navigation |
|
||||
|
||||
All key bindings are configurable via `Options::keys_gui` and stored in `config.yaml` (section `controls:` with SDL scancode names). Game movement keys (`Options::keys_game.up/down/left/right`) can be remapped via the CONTROLS submenu — the `KeyRemap` module mirrors custom physical keys to virtual standard scancodes so hardcoded game code keeps working.
|
||||
UI/system key bindings are loaded from [data/input/keys.yaml](data/input/keys.yaml) via `KeyConfig`. Overrides fets des del menú es persistixen a `~/.config/jailgames/aee/keys.yaml` (només les que difereixen del default). Game movement keys (`Options::keys_game.up/down/left/right`) viuen separadament a `config.yaml` (secció `controls:`) i es remapejen via la CONTROLS submenu — el `KeyRemap` module mirrors custom physical keys to virtual standard scancodes so hardcoded game code keeps working.
|
||||
|
||||
### Execution Model (Single-threaded, Scene-based)
|
||||
|
||||
@@ -224,7 +225,8 @@ JD8_Flip produces ABGR byte order: `0xFF000000 + R + (G<<8) + (B<<16)`. SDL text
|
||||
|
||||
| File | Content |
|
||||
|------|---------|
|
||||
| `~/.config/jailgames/aee/config.yaml` | Main config: video (incl. `vsync`, `integer_scale`), audio (incl. `enabled` master + `music_*` + `sound_*`), window, render_info (incl. `show_time`), game, shader selection, controls (movement keys + menu_toggle + pause_toggle) |
|
||||
| `~/.config/jailgames/aee/config.yaml` | Main config: video (incl. `vsync`, `integer_scale`), audio (incl. `enabled` master + `music_*` + `sound_*`), window, render_info (incl. `show_time`), game, shader selection, controls (només moviment del jugador) |
|
||||
| `~/.config/jailgames/aee/keys.yaml` | UI key overrides (només entrades que difereixen del default de [data/input/keys.yaml](data/input/keys.yaml)). Generat per `KeyConfig::saveOverrides()` |
|
||||
| `~/.config/jailgames/aee/postfx.yaml` | PostFX shader presets (6 defaults: CRT, NTSC, CURVED, SCANLINES, SUBTLE, CRT LIVE) |
|
||||
| `~/.config/jailgames/aee/crtpi.yaml` | CRT-Pi shader presets (4 defaults: DEFAULT, CURVED, SHARP, MINIMAL) |
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ set(APP_SOURCES
|
||||
# Core - Input (nova capa)
|
||||
source/core/input/gamepad.cpp
|
||||
source/core/input/global_inputs.cpp
|
||||
source/core/input/key_config.cpp
|
||||
source/core/input/key_remap.cpp
|
||||
source/core/input/mouse.cpp
|
||||
|
||||
@@ -241,6 +242,27 @@ if(NOT EMSCRIPTEN)
|
||||
)
|
||||
target_include_directories(pack_resources PRIVATE "${CMAKE_SOURCE_DIR}/source")
|
||||
target_compile_options(pack_resources PRIVATE -Wall)
|
||||
|
||||
# --- Regeneració automàtica de resource.pack ---
|
||||
# Cada `cmake --build build` torna a empaquetar `data/` si algun fitxer ha
|
||||
# canviat. Evita debugar amb un pack obsolet. CONFIGURE_DEPENDS força CMake
|
||||
# a re-globbar a la pròxima invocació (recull fitxers nous afegits a data/).
|
||||
file(GLOB_RECURSE DATA_FILES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/data/*")
|
||||
set(RESOURCE_PACK "${CMAKE_SOURCE_DIR}/resource.pack")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${RESOURCE_PACK}
|
||||
COMMAND $<TARGET_FILE:pack_resources>
|
||||
"${CMAKE_SOURCE_DIR}/data"
|
||||
"${RESOURCE_PACK}"
|
||||
DEPENDS pack_resources ${DATA_FILES}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "Empaquetant data/ → resource.pack"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(resource_pack ALL DEPENDS ${RESOURCE_PACK})
|
||||
add_dependencies(${PROJECT_NAME} resource_pack)
|
||||
endif()
|
||||
|
||||
# --- CLANG-FORMAT TARGETS ---
|
||||
|
||||
50
data/input/keys.yaml
Normal file
50
data/input/keys.yaml
Normal file
@@ -0,0 +1,50 @@
|
||||
# Aventures En Egipte — Configuració de tecles d'UI
|
||||
#
|
||||
# Font única de veritat per a les tecles de funció / sistema.
|
||||
# Les tecles de moviment del jugador viuen separades a config.yaml (secció `controls:`).
|
||||
#
|
||||
# Si l'usuari remapeja alguna tecla des del menú de servei, la diferència respecte
|
||||
# aquests valors per defecte es persistix a ~/.config/jailgames/aee/keys.yaml.
|
||||
#
|
||||
# Camps:
|
||||
# id - Identificador usat des del codi via KeyConfig::scancode("id")
|
||||
# code - Nom SDL del scancode (per SDL_GetScancodeFromName), p.ex. "F1", "Escape"
|
||||
# desc - Descripció curta (per a HELP / overlays futurs)
|
||||
|
||||
keys:
|
||||
- id: dec_zoom
|
||||
code: "F1"
|
||||
desc: "Redueix el zoom de la finestra"
|
||||
- id: inc_zoom
|
||||
code: "F2"
|
||||
desc: "Augmenta el zoom de la finestra"
|
||||
- id: fullscreen
|
||||
code: "F3"
|
||||
desc: "Pantalla completa"
|
||||
- id: toggle_shader
|
||||
code: "F4"
|
||||
desc: "Activa/desactiva shaders"
|
||||
- id: toggle_aspect_ratio
|
||||
code: "F5"
|
||||
desc: "Aspecte 4:3 / pixels quadrats"
|
||||
- id: toggle_supersampling
|
||||
code: "F6"
|
||||
desc: "Activa/desactiva supersampling"
|
||||
- id: next_shader
|
||||
code: "F7"
|
||||
desc: "Tipus de shader (PostFX / CRT-Pi)"
|
||||
- id: next_shader_preset
|
||||
code: "F8"
|
||||
desc: "Pròxim preset del shader"
|
||||
- id: toggle_stretch_filter
|
||||
code: "F9"
|
||||
desc: "Filtre 4:3 (nearest / linear)"
|
||||
- id: toggle_render_info
|
||||
code: "F10"
|
||||
desc: "Mostra info de renderitzat"
|
||||
- id: pause_toggle
|
||||
code: "F11"
|
||||
desc: "Pausa el joc"
|
||||
- id: menu_toggle
|
||||
code: "F12"
|
||||
desc: "Menú de servei"
|
||||
@@ -4,77 +4,78 @@
|
||||
|
||||
menu:
|
||||
titles:
|
||||
root: "OPCIONS"
|
||||
video: "VIDEO"
|
||||
audio: "AUDIO"
|
||||
controls: "CONTROLS"
|
||||
game: "JOC"
|
||||
root: "Opcions"
|
||||
video: "Vídeo"
|
||||
audio: "Àudio"
|
||||
controls: "Controls"
|
||||
game: "Joc"
|
||||
|
||||
items:
|
||||
video: "VIDEO"
|
||||
audio: "AUDIO"
|
||||
controls: "CONTROLS"
|
||||
game: "JOC"
|
||||
use_new_logo: "LOGO NOU"
|
||||
show_title_credits: "CREDITS DEL PORT"
|
||||
zoom: "ZOOM"
|
||||
screen: "PANTALLA"
|
||||
shader: "SHADER"
|
||||
aspect_4_3: "ASPECTE 4:3"
|
||||
supersampling: "SUPERSAMPLING"
|
||||
vsync: "VSYNC"
|
||||
integer_scale: "ESCALA ENTERA"
|
||||
shader_type: "TIPUS SHADER"
|
||||
preset: "PRESET"
|
||||
stretch_filter: "FILTRE 4:3"
|
||||
render_info: "RENDER INFO"
|
||||
uptime: "TEMPS DE JOC"
|
||||
master_enable: "AUDIO"
|
||||
master_volume: "MASTER"
|
||||
music: "MUSICA"
|
||||
music_volume: "VOL MUSICA"
|
||||
sounds: "SONS"
|
||||
sounds_volume: "VOL SONS"
|
||||
move_up: "MOU AMUNT"
|
||||
move_down: "MOU AVALL"
|
||||
move_left: "MOU ESQUERRA"
|
||||
move_right: "MOU DRETA"
|
||||
menu_key: "TECLA MENU"
|
||||
video: "Vídeo"
|
||||
audio: "Àudio"
|
||||
controls: "Controls"
|
||||
game: "Joc"
|
||||
use_new_logo: "Logo nou"
|
||||
show_title_credits: "Crèdits del port"
|
||||
zoom: "Zoom"
|
||||
screen: "Pantalla"
|
||||
shader: "Shader"
|
||||
aspect_4_3: "Aspecte 4:3"
|
||||
supersampling: "Supersampling"
|
||||
vsync: "Vsync"
|
||||
integer_scale: "Escala entera"
|
||||
shader_type: "Tipus shader"
|
||||
preset: "Preset"
|
||||
stretch_filter: "Filtre 4:3"
|
||||
render_info: "Render info"
|
||||
uptime: "Temps de joc"
|
||||
master_enable: "Àudio"
|
||||
master_volume: "Màster"
|
||||
music: "Música"
|
||||
music_volume: "Vol música"
|
||||
sounds: "Sons"
|
||||
sounds_volume: "Vol sons"
|
||||
move_up: "Mou amunt"
|
||||
move_down: "Mou avall"
|
||||
move_left: "Mou esquerra"
|
||||
move_right: "Mou dreta"
|
||||
menu_key: "Tecla menú"
|
||||
|
||||
values:
|
||||
"yes": "SI"
|
||||
"no": "NO"
|
||||
"on": "ON"
|
||||
"off": "OFF"
|
||||
fullscreen: "COMPLETA"
|
||||
windowed: "FINESTRA"
|
||||
linear: "LINEAR"
|
||||
nearest: "NEAREST"
|
||||
top: "TOP"
|
||||
bottom: "BOTTOM"
|
||||
press_key: "<PREM TECLA>"
|
||||
empty: "(BUIT)"
|
||||
"yes": "Sí"
|
||||
"no": "No"
|
||||
"on": "On"
|
||||
"off": "Off"
|
||||
fullscreen: "Completa"
|
||||
windowed: "Finestra"
|
||||
linear: "Linear"
|
||||
nearest: "Nearest"
|
||||
top: "Top"
|
||||
bottom: "Bottom"
|
||||
press_key: "<Prem tecla>"
|
||||
empty: "(Buit)"
|
||||
unknown: "---"
|
||||
|
||||
window:
|
||||
title: "© 2000 Aventures en Egipte — JailDesigner"
|
||||
|
||||
notifications:
|
||||
exit_double_esc: "TORNA A PULSAR ESC PER EIXIR"
|
||||
zoom_fmt: "ZOOM %dX"
|
||||
fullscreen: "PANTALLA COMPLETA"
|
||||
windowed: "FINESTRA"
|
||||
shader_on: "SHADER ON"
|
||||
shader_off: "SHADER OFF"
|
||||
exit_double_esc: "Torna a pulsar ESC per a eixir"
|
||||
zoom_fmt: "Zoom %dX"
|
||||
fullscreen: "Pantalla completa"
|
||||
windowed: "Finestra"
|
||||
shader_on: "Shader on"
|
||||
shader_off: "Shader off"
|
||||
aspect_43: "4:3 CRT"
|
||||
aspect_square: "PIXELS QUADRATS"
|
||||
ss_on: "SUPERSAMPLING ON"
|
||||
ss_off: "SUPERSAMPLING OFF"
|
||||
preset_fmt: "PRESET: %s"
|
||||
filter_linear: "FILTRE: LINEAR"
|
||||
filter_nearest: "FILTRE: NEAREST"
|
||||
pause: "PAUSA"
|
||||
resume: "REPRES"
|
||||
aspect_square: "Píxels quadrats"
|
||||
ss_on: "Supersampling on"
|
||||
ss_off: "Supersampling off"
|
||||
preset_fmt: "Preset: %s"
|
||||
filter_linear: "Filtre: linear"
|
||||
filter_nearest: "Filtre: nearest"
|
||||
pause: "Pausa"
|
||||
gamepad_connected: "connectat"
|
||||
gamepad_disconnected: "desconnectat"
|
||||
|
||||
credits:
|
||||
port_role: "Conversio a C++ i SDL3"
|
||||
|
||||
BIN
resource.pack
BIN
resource.pack
Binary file not shown.
@@ -1,10 +1,13 @@
|
||||
#include "core/input/gamepad.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include "core/input/key_config.hpp"
|
||||
#include "core/jail/jinput.hpp"
|
||||
#include "core/locale/locale.hpp"
|
||||
#include "core/rendering/menu.hpp"
|
||||
#include "game/options.hpp"
|
||||
#include "core/rendering/overlay.hpp"
|
||||
|
||||
namespace Gamepad {
|
||||
|
||||
@@ -19,11 +22,23 @@ namespace Gamepad {
|
||||
static bool prev_down_ = false;
|
||||
static bool prev_left_ = false;
|
||||
static bool prev_right_ = false;
|
||||
static bool prev_a_ = false;
|
||||
static bool prev_b_ = false;
|
||||
static bool prev_south_ = false;
|
||||
static bool prev_east_ = false;
|
||||
static bool prev_west_ = false;
|
||||
static bool prev_north_ = false;
|
||||
static bool prev_start_ = false;
|
||||
static bool prev_back_ = false;
|
||||
|
||||
static void notify(const char* name, const char* status_key) {
|
||||
std::string msg = (name && *name) ? name : "Gamepad";
|
||||
msg += ' ';
|
||||
msg += Locale::get(status_key);
|
||||
Overlay::showNotification(msg.c_str(), 2.5F);
|
||||
}
|
||||
|
||||
static void notifyConnected(const char* name) { notify(name, "notifications.gamepad_connected"); }
|
||||
static void notifyDisconnected(const char* name) { notify(name, "notifications.gamepad_disconnected"); }
|
||||
|
||||
static void openFirstGamepad() {
|
||||
int count = 0;
|
||||
SDL_JoystickID* ids = SDL_GetGamepads(&count);
|
||||
@@ -70,12 +85,16 @@ namespace Gamepad {
|
||||
pad_ = SDL_OpenGamepad(event.gdevice.which);
|
||||
if (pad_) {
|
||||
pad_id_ = event.gdevice.which;
|
||||
SDL_Log("Gamepad connectat: %s", SDL_GetGamepadName(pad_));
|
||||
const char* name = SDL_GetGamepadName(pad_);
|
||||
SDL_Log("Gamepad connectat: %s", name ? name : "");
|
||||
notifyConnected(name);
|
||||
}
|
||||
}
|
||||
} else if (event.type == SDL_EVENT_GAMEPAD_REMOVED) {
|
||||
if (pad_ && event.gdevice.which == pad_id_) {
|
||||
SDL_Log("Gamepad desconnectat");
|
||||
const char* name = SDL_GetGamepadName(pad_);
|
||||
std::string saved_name = name ? name : "";
|
||||
SDL_Log("Gamepad desconnectat: %s", saved_name.c_str());
|
||||
SDL_CloseGamepad(pad_);
|
||||
pad_ = nullptr;
|
||||
pad_id_ = 0;
|
||||
@@ -84,6 +103,7 @@ namespace Gamepad {
|
||||
JI_SetVirtualKey(SDL_SCANCODE_DOWN, JI_VSRC_GAMEPAD, false);
|
||||
JI_SetVirtualKey(SDL_SCANCODE_LEFT, JI_VSRC_GAMEPAD, false);
|
||||
JI_SetVirtualKey(SDL_SCANCODE_RIGHT, JI_VSRC_GAMEPAD, false);
|
||||
notifyDisconnected(saved_name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,16 +145,18 @@ namespace Gamepad {
|
||||
bool lt = dlt || slt;
|
||||
bool rt = drt || srt;
|
||||
|
||||
// Botons
|
||||
bool a = SDL_GetGamepadButton(pad_, SDL_GAMEPAD_BUTTON_SOUTH); // A/Cross
|
||||
bool b = SDL_GetGamepadButton(pad_, SDL_GAMEPAD_BUTTON_EAST); // B/Circle
|
||||
// Botons frontals (layout SDL: SOUTH=A/Cross, EAST=B/Circle, WEST=X/Square, NORTH=Y/Triangle)
|
||||
bool south = SDL_GetGamepadButton(pad_, SDL_GAMEPAD_BUTTON_SOUTH);
|
||||
bool east = SDL_GetGamepadButton(pad_, SDL_GAMEPAD_BUTTON_EAST);
|
||||
bool west = SDL_GetGamepadButton(pad_, SDL_GAMEPAD_BUTTON_WEST);
|
||||
bool north = SDL_GetGamepadButton(pad_, SDL_GAMEPAD_BUTTON_NORTH);
|
||||
bool start = SDL_GetGamepadButton(pad_, SDL_GAMEPAD_BUTTON_START);
|
||||
bool back = SDL_GetGamepadButton(pad_, SDL_GAMEPAD_BUTTON_BACK);
|
||||
|
||||
// Start → obre/tanca menú (flanc)
|
||||
if (start && !prev_start_) pushKey(Options::keys_gui.menu_toggle);
|
||||
// Back → ESC (flanc)
|
||||
if (back && !prev_back_) pushKey(SDL_SCANCODE_ESCAPE);
|
||||
// Select (Back) → obre/tanca menú de servei (flanc)
|
||||
if (back && !prev_back_) pushKey(KeyConfig::scancode("menu_toggle"));
|
||||
// Start → pausa (flanc)
|
||||
if (start && !prev_start_) pushKey(KeyConfig::scancode("pause_toggle"));
|
||||
|
||||
if (Menu::isOpen()) {
|
||||
// Navegació del menú per flanc
|
||||
@@ -142,8 +164,9 @@ namespace Gamepad {
|
||||
if (dn && !prev_down_) pushKey(SDL_SCANCODE_DOWN);
|
||||
if (lt && !prev_left_) pushKey(SDL_SCANCODE_LEFT);
|
||||
if (rt && !prev_right_) pushKey(SDL_SCANCODE_RIGHT);
|
||||
if (a && !prev_a_) pushKey(SDL_SCANCODE_RETURN);
|
||||
if (b && !prev_b_) pushKey(SDL_SCANCODE_BACKSPACE);
|
||||
// EAST accepta, SOUTH cancela / endarrere
|
||||
if (east && !prev_east_) pushKey(SDL_SCANCODE_RETURN);
|
||||
if (south && !prev_south_) pushKey(SDL_SCANCODE_BACKSPACE);
|
||||
|
||||
// Assegura que el joc no rep tecles de moviment mentre el menú està obert
|
||||
JI_SetVirtualKey(SDL_SCANCODE_UP, JI_VSRC_GAMEPAD, false);
|
||||
@@ -156,16 +179,21 @@ namespace Gamepad {
|
||||
JI_SetVirtualKey(SDL_SCANCODE_DOWN, JI_VSRC_GAMEPAD, dn);
|
||||
JI_SetVirtualKey(SDL_SCANCODE_LEFT, JI_VSRC_GAMEPAD, lt);
|
||||
JI_SetVirtualKey(SDL_SCANCODE_RIGHT, JI_VSRC_GAMEPAD, rt);
|
||||
// Botó A al joc: emet Enter per avançar seqüències (JI_AnyKey)
|
||||
if (a && !prev_a_) pushKey(SDL_SCANCODE_RETURN);
|
||||
// Qualsevol dels 4 botons frontals avança escenes (JI_AnyKey via Enter sintètic)
|
||||
if ((south && !prev_south_) || (east && !prev_east_) ||
|
||||
(west && !prev_west_) || (north && !prev_north_)) {
|
||||
pushKey(SDL_SCANCODE_RETURN);
|
||||
}
|
||||
}
|
||||
|
||||
prev_up_ = up;
|
||||
prev_down_ = dn;
|
||||
prev_left_ = lt;
|
||||
prev_right_ = rt;
|
||||
prev_a_ = a;
|
||||
prev_b_ = b;
|
||||
prev_south_ = south;
|
||||
prev_east_ = east;
|
||||
prev_west_ = west;
|
||||
prev_north_ = north;
|
||||
prev_start_ = start;
|
||||
prev_back_ = back;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include "core/input/key_config.hpp"
|
||||
#include "core/jail/jinput.hpp"
|
||||
#include "core/locale/locale.hpp"
|
||||
#include "core/rendering/overlay.hpp"
|
||||
@@ -26,7 +27,7 @@ namespace GlobalInputs {
|
||||
bool consumed = false;
|
||||
|
||||
// F1 — Reduir zoom
|
||||
bool dec_zoom = JI_KeyPressed(Options::keys_gui.dec_zoom);
|
||||
bool dec_zoom = JI_KeyPressed(KeyConfig::scancode("dec_zoom"));
|
||||
if (dec_zoom && !dec_zoom_prev) {
|
||||
Screen::get()->decZoom();
|
||||
char msg[32];
|
||||
@@ -37,7 +38,7 @@ namespace GlobalInputs {
|
||||
dec_zoom_prev = dec_zoom;
|
||||
|
||||
// F2 — Augmentar zoom
|
||||
bool inc_zoom = JI_KeyPressed(Options::keys_gui.inc_zoom);
|
||||
bool inc_zoom = JI_KeyPressed(KeyConfig::scancode("inc_zoom"));
|
||||
if (inc_zoom && !inc_zoom_prev) {
|
||||
Screen::get()->incZoom();
|
||||
char msg[32];
|
||||
@@ -48,7 +49,7 @@ namespace GlobalInputs {
|
||||
inc_zoom_prev = inc_zoom;
|
||||
|
||||
// F3 — Toggle pantalla completa
|
||||
bool fullscreen = JI_KeyPressed(Options::keys_gui.fullscreen);
|
||||
bool fullscreen = JI_KeyPressed(KeyConfig::scancode("fullscreen"));
|
||||
if (fullscreen && !fullscreen_prev) {
|
||||
Screen::get()->toggleFullscreen();
|
||||
Overlay::showNotification(Screen::get()->isFullscreen() ? Locale::get("notifications.fullscreen") : Locale::get("notifications.windowed"));
|
||||
@@ -57,7 +58,7 @@ namespace GlobalInputs {
|
||||
fullscreen_prev = fullscreen;
|
||||
|
||||
// F4 — Toggle shaders
|
||||
bool shader = JI_KeyPressed(Options::keys_gui.toggle_shader);
|
||||
bool shader = JI_KeyPressed(KeyConfig::scancode("toggle_shader"));
|
||||
if (shader && !shader_prev) {
|
||||
Screen::get()->toggleShaders();
|
||||
Overlay::showNotification(Options::video.shader_enabled ? Locale::get("notifications.shader_on") : Locale::get("notifications.shader_off"));
|
||||
@@ -66,7 +67,7 @@ namespace GlobalInputs {
|
||||
shader_prev = shader;
|
||||
|
||||
// F5 — Toggle aspect ratio 4:3
|
||||
bool aspect = JI_KeyPressed(Options::keys_gui.toggle_aspect_ratio);
|
||||
bool aspect = JI_KeyPressed(KeyConfig::scancode("toggle_aspect_ratio"));
|
||||
if (aspect && !aspect_prev) {
|
||||
Screen::get()->toggleAspectRatio();
|
||||
Overlay::showNotification(Options::video.aspect_ratio_4_3 ? Locale::get("notifications.aspect_43") : Locale::get("notifications.aspect_square"));
|
||||
@@ -75,7 +76,7 @@ namespace GlobalInputs {
|
||||
aspect_prev = aspect;
|
||||
|
||||
// F6 — Toggle supersampling
|
||||
bool ss = JI_KeyPressed(Options::keys_gui.toggle_supersampling);
|
||||
bool ss = JI_KeyPressed(KeyConfig::scancode("toggle_supersampling"));
|
||||
if (ss && !ss_prev) {
|
||||
Screen::get()->toggleSupersampling();
|
||||
Overlay::showNotification(Options::video.supersampling ? Locale::get("notifications.ss_on") : Locale::get("notifications.ss_off"));
|
||||
@@ -84,7 +85,7 @@ namespace GlobalInputs {
|
||||
ss_prev = ss;
|
||||
|
||||
// F7 — Canviar tipus de shader (PostFX ↔ CrtPi)
|
||||
bool next_shader = JI_KeyPressed(Options::keys_gui.next_shader);
|
||||
bool next_shader = JI_KeyPressed(KeyConfig::scancode("next_shader"));
|
||||
if (next_shader && !next_shader_prev) {
|
||||
Screen::get()->nextShaderType();
|
||||
char msg[64];
|
||||
@@ -95,7 +96,7 @@ namespace GlobalInputs {
|
||||
next_shader_prev = next_shader;
|
||||
|
||||
// F8 — Pròxim preset del shader actiu
|
||||
bool next_preset = JI_KeyPressed(Options::keys_gui.next_shader_preset);
|
||||
bool next_preset = JI_KeyPressed(KeyConfig::scancode("next_shader_preset"));
|
||||
if (next_preset && !next_preset_prev) {
|
||||
Screen::get()->nextPreset();
|
||||
char msg[64];
|
||||
@@ -106,7 +107,7 @@ namespace GlobalInputs {
|
||||
next_preset_prev = next_preset;
|
||||
|
||||
// F9 — Toggle filtre d'estirament 4:3 (NEAREST ↔ LINEAR)
|
||||
bool stretch_filter = JI_KeyPressed(Options::keys_gui.toggle_stretch_filter);
|
||||
bool stretch_filter = JI_KeyPressed(KeyConfig::scancode("toggle_stretch_filter"));
|
||||
if (stretch_filter && !stretch_filter_prev) {
|
||||
Screen::get()->toggleStretchFilter();
|
||||
Overlay::showNotification(Options::video.stretch_filter_linear ? Locale::get("notifications.filter_linear") : Locale::get("notifications.filter_nearest"));
|
||||
@@ -115,7 +116,7 @@ namespace GlobalInputs {
|
||||
stretch_filter_prev = stretch_filter;
|
||||
|
||||
// F10 — Toggle render info (FPS, driver, shader)
|
||||
bool render_info = JI_KeyPressed(Options::keys_gui.toggle_render_info);
|
||||
bool render_info = JI_KeyPressed(KeyConfig::scancode("toggle_render_info"));
|
||||
if (render_info && !render_info_prev) {
|
||||
Overlay::toggleRenderInfo();
|
||||
}
|
||||
|
||||
182
source/core/input/key_config.cpp
Normal file
182
source/core/input/key_config.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
#include "core/input/key_config.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include "core/resources/resource_helper.hpp"
|
||||
#include "external/fkyaml_node.hpp"
|
||||
|
||||
namespace KeyConfig {
|
||||
|
||||
namespace {
|
||||
std::vector<KeyEntry> entries_;
|
||||
std::unordered_map<std::string, size_t> index_;
|
||||
std::string overrides_path_;
|
||||
|
||||
auto findIndex(const std::string& id) -> size_t {
|
||||
auto it = index_.find(id);
|
||||
if (it == index_.end()) return SIZE_MAX;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void loadDefaults(const std::string& defaults_resource_path) {
|
||||
auto buf = ResourceHelper::loadFile(defaults_resource_path);
|
||||
if (buf.empty()) {
|
||||
std::cerr << "KeyConfig: no s'ha pogut llegir " << defaults_resource_path << '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
std::string content(buf.begin(), buf.end());
|
||||
try {
|
||||
auto yaml = fkyaml::node::deserialize(content);
|
||||
if (!yaml.contains("keys")) return;
|
||||
|
||||
for (const auto& node : yaml["keys"]) {
|
||||
KeyEntry entry;
|
||||
entry.id = node["id"].get_value<std::string>();
|
||||
entry.code = node["code"].get_value<std::string>();
|
||||
if (node.contains("desc")) {
|
||||
entry.desc = node["desc"].get_value<std::string>();
|
||||
}
|
||||
SDL_Scancode sc = SDL_GetScancodeFromName(entry.code.c_str());
|
||||
if (sc == SDL_SCANCODE_UNKNOWN) {
|
||||
std::cerr << "KeyConfig: scancode desconegut '" << entry.code
|
||||
<< "' per '" << entry.id << "'\n";
|
||||
}
|
||||
entry.scancode = sc;
|
||||
entry.default_scancode = sc;
|
||||
|
||||
index_[entry.id] = entries_.size();
|
||||
entries_.push_back(std::move(entry));
|
||||
}
|
||||
std::cout << "KeyConfig: " << entries_.size() << " tecles carregades de "
|
||||
<< defaults_resource_path << '\n';
|
||||
} catch (const fkyaml::exception& e) {
|
||||
std::cerr << "KeyConfig: error parsejant YAML: " << e.what() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
void applyOverrides(const std::string& disk_path) {
|
||||
std::ifstream file(disk_path);
|
||||
if (!file.good()) return;
|
||||
|
||||
std::string content((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
file.close();
|
||||
|
||||
try {
|
||||
auto yaml = fkyaml::node::deserialize(content);
|
||||
if (!yaml.contains("overrides")) return;
|
||||
|
||||
int applied = 0;
|
||||
for (const auto& kv : yaml["overrides"].as_map()) {
|
||||
auto id = kv.first.get_value<std::string>();
|
||||
auto code = kv.second.get_value<std::string>();
|
||||
auto idx = findIndex(id);
|
||||
if (idx == SIZE_MAX) {
|
||||
std::cerr << "KeyConfig: override per id desconegut '" << id << "'\n";
|
||||
continue;
|
||||
}
|
||||
SDL_Scancode sc = SDL_GetScancodeFromName(code.c_str());
|
||||
if (sc == SDL_SCANCODE_UNKNOWN) {
|
||||
std::cerr << "KeyConfig: override amb scancode invàlid '" << code
|
||||
<< "' per '" << id << "'\n";
|
||||
continue;
|
||||
}
|
||||
entries_[idx].scancode = sc;
|
||||
entries_[idx].code = code;
|
||||
applied++;
|
||||
}
|
||||
if (applied > 0) {
|
||||
std::cout << "KeyConfig: aplicats " << applied
|
||||
<< " overrides de " << disk_path << '\n';
|
||||
}
|
||||
} catch (const fkyaml::exception& e) {
|
||||
std::cerr << "KeyConfig: error parsejant overrides: " << e.what() << '\n';
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void init(const std::string& defaults_resource_path,
|
||||
const std::string& user_overrides_disk_path) {
|
||||
entries_.clear();
|
||||
index_.clear();
|
||||
overrides_path_ = user_overrides_disk_path;
|
||||
|
||||
loadDefaults(defaults_resource_path);
|
||||
if (!overrides_path_.empty()) {
|
||||
applyOverrides(overrides_path_);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
entries_.clear();
|
||||
index_.clear();
|
||||
overrides_path_.clear();
|
||||
}
|
||||
|
||||
auto scancode(const std::string& id) -> SDL_Scancode {
|
||||
auto idx = findIndex(id);
|
||||
if (idx == SIZE_MAX) return SDL_SCANCODE_UNKNOWN;
|
||||
return entries_[idx].scancode;
|
||||
}
|
||||
|
||||
auto scancodePtr(const std::string& id) -> SDL_Scancode* {
|
||||
auto idx = findIndex(id);
|
||||
if (idx == SIZE_MAX) return nullptr;
|
||||
return &entries_[idx].scancode;
|
||||
}
|
||||
|
||||
void setScancode(const std::string& id, SDL_Scancode sc) {
|
||||
auto idx = findIndex(id);
|
||||
if (idx == SIZE_MAX) return;
|
||||
entries_[idx].scancode = sc;
|
||||
const char* name = SDL_GetScancodeName(sc);
|
||||
entries_[idx].code = (name != nullptr) ? name : "";
|
||||
}
|
||||
|
||||
auto isGuiKey(SDL_Scancode sc) -> bool {
|
||||
if (sc == SDL_SCANCODE_UNKNOWN) return false;
|
||||
for (const auto& e : entries_) {
|
||||
if (e.scancode == sc) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto entries() -> const std::vector<KeyEntry>& {
|
||||
return entries_;
|
||||
}
|
||||
|
||||
auto saveOverrides() -> bool {
|
||||
if (overrides_path_.empty()) return false;
|
||||
|
||||
// Recull només les entrades remapeades.
|
||||
std::vector<const KeyEntry*> changed;
|
||||
for (const auto& e : entries_) {
|
||||
if (e.scancode != e.default_scancode) changed.push_back(&e);
|
||||
}
|
||||
|
||||
std::ofstream file(overrides_path_);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "KeyConfig: no es pot escriure " << overrides_path_ << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
file << "# AEE - Overrides de tecles d'UI\n";
|
||||
file << "# Auto-generat. Només llista les tecles modificades respecte\n";
|
||||
file << "# els valors per defecte de data/input/keys.yaml.\n";
|
||||
file << "\n";
|
||||
|
||||
if (changed.empty()) {
|
||||
file << "overrides: {}\n";
|
||||
} else {
|
||||
file << "overrides:\n";
|
||||
for (const auto* e : changed) {
|
||||
file << " " << e->id << ": \"" << e->code << "\"\n";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace KeyConfig
|
||||
52
source/core/input/key_config.hpp
Normal file
52
source/core/input/key_config.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
// KeyConfig: font única de veritat per a les tecles d'UI/sistema.
|
||||
//
|
||||
// Llegeix els valors per defecte des de `data/input/keys.yaml` (recurs read-only)
|
||||
// i opcionalment aplica overrides des d'un fitxer de l'usuari (per a remapejos
|
||||
// fets des del menú de servei). Els callers consulten per `id` (ex. "menu_toggle").
|
||||
//
|
||||
// Les tecles de moviment del jugador NO viuen ací — es queden a Options::keys_game.
|
||||
|
||||
struct KeyEntry {
|
||||
std::string id;
|
||||
std::string code; // nom SDL del scancode tal com apareix al YAML
|
||||
std::string desc;
|
||||
SDL_Scancode scancode{SDL_SCANCODE_UNKNOWN};
|
||||
SDL_Scancode default_scancode{SDL_SCANCODE_UNKNOWN};
|
||||
};
|
||||
|
||||
namespace KeyConfig {
|
||||
// Inicialitza KeyConfig llegint defaults des d'un recurs (via ResourceHelper)
|
||||
// i opcionalment sobreposant overrides des d'un fitxer de disc.
|
||||
void init(const std::string& defaults_resource_path,
|
||||
const std::string& user_overrides_disk_path);
|
||||
void destroy();
|
||||
|
||||
// Consulta el scancode actual associat a un id. Torna SDL_SCANCODE_UNKNOWN si no existix.
|
||||
[[nodiscard]] auto scancode(const std::string& id) -> SDL_Scancode;
|
||||
|
||||
// Punter estable al scancode d'un id — útil per a Menu::ItemKind::KeyBind.
|
||||
// Torna nullptr si l'id no existix.
|
||||
[[nodiscard]] auto scancodePtr(const std::string& id) -> SDL_Scancode*;
|
||||
|
||||
// Estableix el scancode d'un id. No persistix per si sol — cal cridar saveOverrides().
|
||||
void setScancode(const std::string& id, SDL_Scancode sc);
|
||||
|
||||
// True si el scancode coincidix amb alguna tecla d'UI registrada.
|
||||
// Usat pel Director per a evitar que tecles d'UI activen `key_pressed_` al joc.
|
||||
[[nodiscard]] auto isGuiKey(SDL_Scancode sc) -> bool;
|
||||
|
||||
// Llistat complet de les entrades (per a HELP / debug / iteració).
|
||||
[[nodiscard]] auto entries() -> const std::vector<KeyEntry>&;
|
||||
|
||||
// Persistix al fitxer d'overrides les entrades que difereixen del default.
|
||||
// Si no s'ha proporcionat user_overrides_disk_path al init, és no-op.
|
||||
auto saveOverrides() -> bool;
|
||||
} // namespace KeyConfig
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core/input/key_config.hpp"
|
||||
#include "core/locale/locale.hpp"
|
||||
#include "core/rendering/overlay.hpp"
|
||||
#include "core/rendering/screen.hpp"
|
||||
@@ -181,7 +182,7 @@ namespace Menu {
|
||||
p.items.push_back({Locale::get("menu.items.move_down"), ItemKind::KeyBind, nullptr, nullptr, nullptr, &Options::keys_game.down});
|
||||
p.items.push_back({Locale::get("menu.items.move_left"), ItemKind::KeyBind, nullptr, nullptr, nullptr, &Options::keys_game.left});
|
||||
p.items.push_back({Locale::get("menu.items.move_right"), ItemKind::KeyBind, nullptr, nullptr, nullptr, &Options::keys_game.right});
|
||||
p.items.push_back({Locale::get("menu.items.menu_key"), ItemKind::KeyBind, nullptr, nullptr, nullptr, &Options::keys_gui.menu_toggle});
|
||||
p.items.push_back({Locale::get("menu.items.menu_key"), ItemKind::KeyBind, nullptr, nullptr, nullptr, KeyConfig::scancodePtr("menu_toggle")});
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "core/input/gamepad.hpp"
|
||||
#include "core/input/global_inputs.hpp"
|
||||
#include "core/input/key_config.hpp"
|
||||
#include "core/input/key_remap.hpp"
|
||||
#include "core/input/mouse.hpp"
|
||||
#include "core/jail/jail_audio.hpp"
|
||||
@@ -281,17 +282,18 @@ void Director::handleEvent(const SDL_Event& event) {
|
||||
menu_keys_held_[event.key.scancode] = true;
|
||||
return;
|
||||
}
|
||||
// Pausa: F11 (o tecla configurada) pausa/reprén la simulació
|
||||
// Pausa: F11 (o tecla configurada) pausa/reprén la simulació.
|
||||
// No mostrem notificació — l'indicador persistent "Pausa" a la cantonada
|
||||
// superior dreta (pintat per Overlay) ja comunica l'estat.
|
||||
if (event.type == SDL_EVENT_KEY_DOWN && !event.key.repeat &&
|
||||
event.key.scancode == Options::keys_gui.pause_toggle) {
|
||||
event.key.scancode == KeyConfig::scancode("pause_toggle")) {
|
||||
togglePause();
|
||||
Overlay::showNotification(paused_ ? Locale::get("notifications.pause") : Locale::get("notifications.resume"));
|
||||
menu_keys_held_[event.key.scancode] = true;
|
||||
return;
|
||||
}
|
||||
// Menú: F12 (o tecla configurada) obre/tanca el menú flotant
|
||||
if (event.type == SDL_EVENT_KEY_DOWN && !event.key.repeat &&
|
||||
event.key.scancode == Options::keys_gui.menu_toggle) {
|
||||
event.key.scancode == KeyConfig::scancode("menu_toggle")) {
|
||||
Menu::toggle();
|
||||
JI_SetInputBlocked(Menu::isOpen());
|
||||
menu_keys_held_[event.key.scancode] = true;
|
||||
@@ -346,19 +348,12 @@ void Director::handleEvent(const SDL_Event& event) {
|
||||
// quan l'overlay faça timeout
|
||||
return;
|
||||
} else {
|
||||
// Comprova si és una tecla GUI (no passa al joc)
|
||||
// Comprova si és una tecla d'UI registrada (no passa al joc).
|
||||
// KeyConfig::isGuiKey cobreix totes les tecles GUI a la vegada,
|
||||
// incloent pause_toggle i menu_toggle (defensa en profunditat:
|
||||
// aquestes ja s'haurien hagut de menjar al swallow d'amunt).
|
||||
const auto sc = event.key.scancode;
|
||||
const bool is_gui_key = (sc == Options::keys_gui.dec_zoom ||
|
||||
sc == Options::keys_gui.inc_zoom ||
|
||||
sc == Options::keys_gui.fullscreen ||
|
||||
sc == Options::keys_gui.toggle_shader ||
|
||||
sc == Options::keys_gui.toggle_aspect_ratio ||
|
||||
sc == Options::keys_gui.toggle_supersampling ||
|
||||
sc == Options::keys_gui.next_shader ||
|
||||
sc == Options::keys_gui.next_shader_preset ||
|
||||
sc == Options::keys_gui.toggle_stretch_filter ||
|
||||
sc == Options::keys_gui.toggle_render_info);
|
||||
if (!is_gui_key) {
|
||||
if (!KeyConfig::isGuiKey(sc)) {
|
||||
key_pressed_ = true;
|
||||
JI_moveCheats(sc);
|
||||
}
|
||||
|
||||
@@ -2,21 +2,7 @@
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
// Tecles GUI (capa de presentació — finestra, zoom, shaders, etc.)
|
||||
namespace Defaults::KeysGUI {
|
||||
constexpr SDL_Scancode DEC_ZOOM = SDL_SCANCODE_F1;
|
||||
constexpr SDL_Scancode INC_ZOOM = SDL_SCANCODE_F2;
|
||||
constexpr SDL_Scancode FULLSCREEN = SDL_SCANCODE_F3;
|
||||
constexpr SDL_Scancode TOGGLE_SHADER = SDL_SCANCODE_F4;
|
||||
constexpr SDL_Scancode TOGGLE_ASPECT_RATIO = SDL_SCANCODE_F5;
|
||||
constexpr SDL_Scancode TOGGLE_SUPERSAMPLING = SDL_SCANCODE_F6;
|
||||
constexpr SDL_Scancode NEXT_SHADER = SDL_SCANCODE_F7;
|
||||
constexpr SDL_Scancode NEXT_SHADER_PRESET = SDL_SCANCODE_F8;
|
||||
constexpr SDL_Scancode TOGGLE_STRETCH_FILTER = SDL_SCANCODE_F9;
|
||||
constexpr SDL_Scancode TOGGLE_RENDER_INFO = SDL_SCANCODE_F10;
|
||||
constexpr SDL_Scancode PAUSE_TOGGLE = SDL_SCANCODE_F11;
|
||||
constexpr SDL_Scancode MENU_TOGGLE = SDL_SCANCODE_F12;
|
||||
} // namespace Defaults::KeysGUI
|
||||
// Tecles GUI: viuen a data/input/keys.yaml (font única — KeyConfig).
|
||||
|
||||
// Tecles de joc (moviment del personatge, accions)
|
||||
namespace Defaults::KeysGame {
|
||||
|
||||
@@ -58,7 +58,7 @@ void ModuleGame::onEnter() {
|
||||
// Arranca el fade-in tick-based. El `PaletteFade` avança un pas (de
|
||||
// 32) per cada tick; durant aquesta fase el gameplay no corre,
|
||||
// només Draw+fade. Substituïx la crida bloquejant `JD8_FadeToPal`.
|
||||
fade_.startFadeTo(JD8_LoadPalette(info::ctx.pepe_activat ? "frames2.gif" : "frames.gif"));
|
||||
fade_.startFadeTo(JD8_LoadPalette(info::ctx.pepe_activat ? "gfx/frames2.gif" : "gfx/frames.gif"));
|
||||
phase_ = Phase::FadingIn;
|
||||
}
|
||||
|
||||
|
||||
@@ -189,8 +189,6 @@ namespace Options {
|
||||
loadScancodeField(node, "down", keys_game.down);
|
||||
loadScancodeField(node, "left", keys_game.left);
|
||||
loadScancodeField(node, "right", keys_game.right);
|
||||
loadScancodeField(node, "menu_toggle", keys_gui.menu_toggle);
|
||||
loadScancodeField(node, "pause_toggle", keys_gui.pause_toggle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,15 +331,14 @@ namespace Options {
|
||||
file << " show_title_credits: " << (game.show_title_credits ? "true" : "false") << "\n";
|
||||
file << "\n";
|
||||
|
||||
// CONTROLS
|
||||
file << "# CONTROLS (noms SDL: \"Up\", \"Down\", \"W\", \"Space\", \"F12\", etc.)\n";
|
||||
// CONTROLS — només moviment del jugador. Les tecles d'UI viuen a
|
||||
// data/input/keys.yaml (defaults) + ~/.config/jailgames/aee/keys.yaml (overrides).
|
||||
file << "# CONTROLS (noms SDL: \"Up\", \"Down\", \"W\", \"Space\", etc.)\n";
|
||||
file << "controls:\n";
|
||||
file << " up: \"" << SDL_GetScancodeName(keys_game.up) << "\"\n";
|
||||
file << " down: \"" << SDL_GetScancodeName(keys_game.down) << "\"\n";
|
||||
file << " left: \"" << SDL_GetScancodeName(keys_game.left) << "\"\n";
|
||||
file << " right: \"" << SDL_GetScancodeName(keys_game.right) << "\"\n";
|
||||
file << " menu_toggle: \"" << SDL_GetScancodeName(keys_gui.menu_toggle) << "\"\n";
|
||||
file << " pause_toggle: \"" << SDL_GetScancodeName(keys_gui.pause_toggle) << "\"\n";
|
||||
|
||||
file.close();
|
||||
|
||||
|
||||
@@ -8,23 +8,8 @@
|
||||
|
||||
namespace Options {
|
||||
|
||||
// Tecles GUI (finestra, zoom, shaders)
|
||||
struct KeysGUI {
|
||||
SDL_Scancode dec_zoom{Defaults::KeysGUI::DEC_ZOOM};
|
||||
SDL_Scancode inc_zoom{Defaults::KeysGUI::INC_ZOOM};
|
||||
SDL_Scancode fullscreen{Defaults::KeysGUI::FULLSCREEN};
|
||||
SDL_Scancode toggle_shader{Defaults::KeysGUI::TOGGLE_SHADER};
|
||||
SDL_Scancode toggle_aspect_ratio{Defaults::KeysGUI::TOGGLE_ASPECT_RATIO};
|
||||
SDL_Scancode toggle_supersampling{Defaults::KeysGUI::TOGGLE_SUPERSAMPLING};
|
||||
SDL_Scancode next_shader{Defaults::KeysGUI::NEXT_SHADER};
|
||||
SDL_Scancode next_shader_preset{Defaults::KeysGUI::NEXT_SHADER_PRESET};
|
||||
SDL_Scancode toggle_stretch_filter{Defaults::KeysGUI::TOGGLE_STRETCH_FILTER};
|
||||
SDL_Scancode toggle_render_info{Defaults::KeysGUI::TOGGLE_RENDER_INFO};
|
||||
SDL_Scancode pause_toggle{Defaults::KeysGUI::PAUSE_TOGGLE};
|
||||
SDL_Scancode menu_toggle{Defaults::KeysGUI::MENU_TOGGLE};
|
||||
};
|
||||
|
||||
// Tecles de joc (moviment, accions)
|
||||
// Tecles de joc (moviment, accions). Les tecles d'UI viuen ara a KeyConfig
|
||||
// (carregades de data/input/keys.yaml).
|
||||
struct KeysGame {
|
||||
SDL_Scancode up{Defaults::KeysGame::UP};
|
||||
SDL_Scancode down{Defaults::KeysGame::DOWN};
|
||||
@@ -123,7 +108,6 @@ namespace Options {
|
||||
|
||||
// --- Variables globals ---
|
||||
inline std::string version{};
|
||||
inline KeysGUI keys_gui{};
|
||||
inline KeysGame keys_game{};
|
||||
inline Video video{};
|
||||
inline RenderInfo render_info{};
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
|
||||
#include "core/input/key_config.hpp"
|
||||
#include "core/jail/jail_audio.hpp"
|
||||
#include "core/jail/jdraw8.hpp"
|
||||
#include "core/jail/jfile.hpp"
|
||||
@@ -57,6 +58,10 @@ SDL_AppResult SDL_AppInit(void** /*appstate*/, int /*argc*/, char* /*argv*/[]) {
|
||||
Options::setConfigFile(std::string(file_getconfigfolder()) + "config.yaml");
|
||||
Options::loadFromFile();
|
||||
|
||||
// KeyConfig: defaults des de data/input/keys.yaml + overrides de l'usuari
|
||||
KeyConfig::init("input/keys.yaml",
|
||||
std::string(file_getconfigfolder()) + "keys.yaml");
|
||||
|
||||
#ifndef NDEBUG
|
||||
// debug.yaml: estat inicial de gameplay per a tests ràpids,
|
||||
// només en builds de debug.
|
||||
@@ -119,11 +124,13 @@ void SDL_AppQuit(void* /*appstate*/, SDL_AppResult /*result*/) {
|
||||
Director::get()->teardown();
|
||||
|
||||
Options::saveToFile();
|
||||
KeyConfig::saveOverrides();
|
||||
#ifndef NDEBUG
|
||||
Options::saveDebugToFile();
|
||||
#endif
|
||||
|
||||
Director::destroy();
|
||||
KeyConfig::destroy();
|
||||
Menu::destroy();
|
||||
Overlay::destroy();
|
||||
JA_Quit();
|
||||
|
||||
Reference in New Issue
Block a user