menu de sistema amb versió i opció per a tancar i reiniciar
This commit is contained in:
@@ -10,6 +10,29 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|||||||
# Exportar comandos de compilación para herramientas de análisis
|
# Exportar comandos de compilación para herramientas de análisis
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
# --- GENERACIÓ AUTOMÀTICA DE VERSIÓ ---
|
||||||
|
# Si GIT_HASH ve de fora (p. ex. el Makefile via -DGIT_HASH=xxx), l'usem tal
|
||||||
|
# qual. Això evita problemes amb Docker/emscripten on git avorta per
|
||||||
|
# "dubious ownership" al volum muntat. En builds locals sense -DGIT_HASH
|
||||||
|
# resolem ací executant git directament.
|
||||||
|
if(NOT DEFINED GIT_HASH OR GIT_HASH STREQUAL "")
|
||||||
|
find_package(Git QUIET)
|
||||||
|
if(GIT_FOUND)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GIT_EXECUTABLE} rev-parse --short=7 HEAD
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE GIT_HASH
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(NOT DEFINED GIT_HASH OR GIT_HASH STREQUAL "")
|
||||||
|
set(GIT_HASH "unknown")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/source/version.h.in ${CMAKE_BINARY_DIR}/version.h @ONLY)
|
||||||
|
|
||||||
# --- LISTA EXPLÍCITA DE FUENTES ---
|
# --- LISTA EXPLÍCITA DE FUENTES ---
|
||||||
set(APP_SOURCES
|
set(APP_SOURCES
|
||||||
# Core - Motor original "Jail" (no tocar gameplay)
|
# Core - Motor original "Jail" (no tocar gameplay)
|
||||||
@@ -181,6 +204,7 @@ endif()
|
|||||||
# --- DIRECTORIOS DE INCLUSIÓN ---
|
# --- DIRECTORIOS DE INCLUSIÓN ---
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||||
"${CMAKE_SOURCE_DIR}/source"
|
"${CMAKE_SOURCE_DIR}/source"
|
||||||
|
"${CMAKE_BINARY_DIR}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Enlazar SDL3
|
# Enlazar SDL3
|
||||||
|
|||||||
30
Makefile
30
Makefile
@@ -23,6 +23,20 @@ else
|
|||||||
VERSION := v$(shell grep 'constexpr const char\* VERSION' source/game/defines.hpp | sed -E 's/.*VERSION = "([^"]+)".*/\1/')
|
VERSION := v$(shell grep 'constexpr const char\* VERSION' source/game/defines.hpp | sed -E 's/.*VERSION = "([^"]+)".*/\1/')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# GIT HASH (computat al host, passat a CMake via -DGIT_HASH)
|
||||||
|
# Evita que CMake haja de cridar git des de Docker/emscripten on falla per
|
||||||
|
# "dubious ownership" del volum muntat.
|
||||||
|
# ==============================================================================
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
GIT_HASH := $(shell git rev-parse --short=7 HEAD 2>NUL)
|
||||||
|
else
|
||||||
|
GIT_HASH := $(shell git rev-parse --short=7 HEAD 2>/dev/null)
|
||||||
|
endif
|
||||||
|
ifeq ($(GIT_HASH),)
|
||||||
|
GIT_HASH := unknown
|
||||||
|
endif
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
# SHELL (Windows usa cmd.exe para que las recetas con powershell funcionen igual
|
# SHELL (Windows usa cmd.exe para que las recetas con powershell funcionen igual
|
||||||
# desde cualquier terminal: PowerShell, cmd o git-bash)
|
# desde cualquier terminal: PowerShell, cmd o git-bash)
|
||||||
@@ -69,16 +83,16 @@ endif
|
|||||||
# COMPILACIÓN CON CMAKE
|
# COMPILACIÓN CON CMAKE
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
all:
|
all:
|
||||||
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DGIT_HASH=$(GIT_HASH)
|
||||||
@cmake --build build
|
@cmake --build build
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
|
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DGIT_HASH=$(GIT_HASH)
|
||||||
@cmake --build build
|
@cmake --build build
|
||||||
|
|
||||||
# Empaqueta data/ a resource.pack (format AEE1). Build previ de l'eina + execució.
|
# Empaqueta data/ a resource.pack (format AEE1). Build previ de l'eina + execució.
|
||||||
pack:
|
pack:
|
||||||
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DGIT_HASH=$(GIT_HASH)
|
||||||
@cmake --build build --target pack_resources
|
@cmake --build build --target pack_resources
|
||||||
@./build/pack_resources data resource.pack
|
@./build/pack_resources data resource.pack
|
||||||
|
|
||||||
@@ -104,7 +118,7 @@ _windows_release: pack
|
|||||||
@echo Creando release para Windows - Version: $(VERSION)
|
@echo Creando release para Windows - Version: $(VERSION)
|
||||||
|
|
||||||
# Compila con cmake
|
# Compila con cmake
|
||||||
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DGIT_HASH=$(GIT_HASH)
|
||||||
@cmake --build build
|
@cmake --build build
|
||||||
|
|
||||||
# Crea carpeta de distribución y carpeta temporal 'RELEASE_FOLDER'
|
# Crea carpeta de distribución y carpeta temporal 'RELEASE_FOLDER'
|
||||||
@@ -139,7 +153,7 @@ _macos_release: pack
|
|||||||
@which create-dmg > /dev/null || (echo "Instalando create-dmg..." && brew install create-dmg)
|
@which create-dmg > /dev/null || (echo "Instalando create-dmg..." && brew install create-dmg)
|
||||||
|
|
||||||
# Compila la versión para procesadores Intel con cmake
|
# Compila la versión para procesadores Intel con cmake
|
||||||
@cmake -S . -B build/intel -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DMACOS_BUNDLE=ON
|
@cmake -S . -B build/intel -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DMACOS_BUNDLE=ON -DGIT_HASH=$(GIT_HASH)
|
||||||
@cmake --build build/intel
|
@cmake --build build/intel
|
||||||
|
|
||||||
# Elimina datos de compilaciones anteriores
|
# Elimina datos de compilaciones anteriores
|
||||||
@@ -193,7 +207,7 @@ _macos_release: pack
|
|||||||
@echo "Release Intel creado: $(MACOS_INTEL_RELEASE)"
|
@echo "Release Intel creado: $(MACOS_INTEL_RELEASE)"
|
||||||
|
|
||||||
# Compila la versión para procesadores Apple Silicon con cmake
|
# Compila la versión para procesadores Apple Silicon con cmake
|
||||||
@cmake -S . -B build/arm -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DMACOS_BUNDLE=ON
|
@cmake -S . -B build/arm -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DMACOS_BUNDLE=ON -DGIT_HASH=$(GIT_HASH)
|
||||||
@cmake --build build/arm
|
@cmake --build build/arm
|
||||||
cp "$(TARGET_FILE)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)"
|
cp "$(TARGET_FILE)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)"
|
||||||
|
|
||||||
@@ -237,7 +251,7 @@ wasm:
|
|||||||
-v $(DIR_ROOT):/src \
|
-v $(DIR_ROOT):/src \
|
||||||
-w /src \
|
-w /src \
|
||||||
emscripten/emsdk:latest \
|
emscripten/emsdk:latest \
|
||||||
bash -c "emcmake cmake -S . -B build/wasm -DCMAKE_BUILD_TYPE=Release && cmake --build build/wasm"
|
bash -c "emcmake cmake -S . -B build/wasm -DCMAKE_BUILD_TYPE=Release -DGIT_HASH=$(GIT_HASH) && cmake --build build/wasm"
|
||||||
@$(MKDIR) "$(DIST_DIR)/wasm"
|
@$(MKDIR) "$(DIST_DIR)/wasm"
|
||||||
@cp build/wasm/$(TARGET_NAME).html $(DIST_DIR)/wasm/
|
@cp build/wasm/$(TARGET_NAME).html $(DIST_DIR)/wasm/
|
||||||
@cp build/wasm/$(TARGET_NAME).js $(DIST_DIR)/wasm/
|
@cp build/wasm/$(TARGET_NAME).js $(DIST_DIR)/wasm/
|
||||||
@@ -256,7 +270,7 @@ _linux_release: pack
|
|||||||
@echo "Creando release para Linux - Version: $(VERSION)"
|
@echo "Creando release para Linux - Version: $(VERSION)"
|
||||||
|
|
||||||
# Compila con cmake
|
# Compila con cmake
|
||||||
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DGIT_HASH=$(GIT_HASH)
|
||||||
@cmake --build build
|
@cmake --build build
|
||||||
|
|
||||||
# Elimina carpeta temporal previa y la recrea (crea dist/ si no existe)
|
# Elimina carpeta temporal previa y la recrea (crea dist/ si no existe)
|
||||||
|
|||||||
@@ -9,12 +9,16 @@ menu:
|
|||||||
audio: "Àudio"
|
audio: "Àudio"
|
||||||
controls: "Controls"
|
controls: "Controls"
|
||||||
game: "Joc"
|
game: "Joc"
|
||||||
|
system: "Sistema"
|
||||||
|
|
||||||
items:
|
items:
|
||||||
video: "Vídeo"
|
video: "Vídeo"
|
||||||
audio: "Àudio"
|
audio: "Àudio"
|
||||||
controls: "Controls"
|
controls: "Controls"
|
||||||
game: "Joc"
|
game: "Joc"
|
||||||
|
system: "Sistema"
|
||||||
|
restart: "Reinicia"
|
||||||
|
exit_game: "Eixir del joc"
|
||||||
use_new_logo: "Logo nou"
|
use_new_logo: "Logo nou"
|
||||||
show_title_credits: "Crèdits del port"
|
show_title_credits: "Crèdits del port"
|
||||||
zoom: "Zoom"
|
zoom: "Zoom"
|
||||||
|
|||||||
@@ -12,8 +12,11 @@
|
|||||||
#include "core/rendering/overlay.hpp"
|
#include "core/rendering/overlay.hpp"
|
||||||
#include "core/rendering/screen.hpp"
|
#include "core/rendering/screen.hpp"
|
||||||
#include "core/rendering/text.hpp"
|
#include "core/rendering/text.hpp"
|
||||||
|
#include "core/system/director.hpp"
|
||||||
|
#include "game/defines.hpp"
|
||||||
#include "game/options.hpp"
|
#include "game/options.hpp"
|
||||||
#include "utils/easing.hpp"
|
#include "utils/easing.hpp"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
namespace Menu {
|
namespace Menu {
|
||||||
|
|
||||||
@@ -37,6 +40,7 @@ namespace Menu {
|
|||||||
static constexpr int ITEM_SPACING = 11;
|
static constexpr int ITEM_SPACING = 11;
|
||||||
static constexpr int BOTTOM_PAD = 6;
|
static constexpr int BOTTOM_PAD = 6;
|
||||||
static constexpr int HEADER_H = TITLE_PAD_Y + 8 /*charH*/ + 2 + 4; // títol + línia + gap
|
static constexpr int HEADER_H = TITLE_PAD_Y + 8 /*charH*/ + 2 + 4; // títol + línia + gap
|
||||||
|
static constexpr int SUBTITLE_H = 8 + 3; // línia de subtítol + gap
|
||||||
|
|
||||||
// --- Animació ---
|
// --- Animació ---
|
||||||
static constexpr float OPEN_SPEED = 8.0F; // 1.0 / 0.125s
|
static constexpr float OPEN_SPEED = 8.0F; // 1.0 / 0.125s
|
||||||
@@ -47,14 +51,15 @@ namespace Menu {
|
|||||||
Cycle,
|
Cycle,
|
||||||
IntRange,
|
IntRange,
|
||||||
Submenu,
|
Submenu,
|
||||||
KeyBind };
|
KeyBind,
|
||||||
|
Action };
|
||||||
|
|
||||||
struct Item {
|
struct Item {
|
||||||
const char* label;
|
const char* label;
|
||||||
ItemKind kind;
|
ItemKind kind;
|
||||||
std::function<std::string()> getValue; // opcional
|
std::function<std::string()> getValue; // opcional
|
||||||
std::function<void(int dir)> change; // per Toggle/Cycle/IntRange
|
std::function<void(int dir)> change; // per Toggle/Cycle/IntRange
|
||||||
std::function<void()> enter; // per Submenu
|
std::function<void()> enter; // per Submenu i Action
|
||||||
SDL_Scancode* scancode{nullptr}; // per KeyBind
|
SDL_Scancode* scancode{nullptr}; // per KeyBind
|
||||||
std::function<bool()> visible; // nullptr ⇒ sempre visible
|
std::function<bool()> visible; // nullptr ⇒ sempre visible
|
||||||
};
|
};
|
||||||
@@ -63,6 +68,7 @@ namespace Menu {
|
|||||||
const char* title;
|
const char* title;
|
||||||
std::vector<Item> items;
|
std::vector<Item> items;
|
||||||
int cursor{0};
|
int cursor{0};
|
||||||
|
std::string subtitle; // opcional — si no buit, es dibuixa sota el títol
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool isVisible(const Item& it) { return !it.visible || it.visible(); }
|
static bool isVisible(const Item& it) { return !it.visible || it.visible(); }
|
||||||
@@ -121,6 +127,7 @@ namespace Menu {
|
|||||||
static Page buildAudio();
|
static Page buildAudio();
|
||||||
static Page buildControls();
|
static Page buildControls();
|
||||||
static Page buildGame();
|
static Page buildGame();
|
||||||
|
static Page buildSystem();
|
||||||
|
|
||||||
static Page buildRoot() {
|
static Page buildRoot() {
|
||||||
Page p{Locale::get("menu.titles.root"), {}, 0};
|
Page p{Locale::get("menu.titles.root"), {}, 0};
|
||||||
@@ -128,6 +135,7 @@ namespace Menu {
|
|||||||
p.items.push_back({Locale::get("menu.items.audio"), ItemKind::Submenu, nullptr, nullptr, [] { pushPage(buildAudio()); }, nullptr});
|
p.items.push_back({Locale::get("menu.items.audio"), ItemKind::Submenu, nullptr, nullptr, [] { pushPage(buildAudio()); }, nullptr});
|
||||||
p.items.push_back({Locale::get("menu.items.controls"), ItemKind::Submenu, nullptr, nullptr, [] { pushPage(buildControls()); }, nullptr});
|
p.items.push_back({Locale::get("menu.items.controls"), ItemKind::Submenu, nullptr, nullptr, [] { pushPage(buildControls()); }, nullptr});
|
||||||
p.items.push_back({Locale::get("menu.items.game"), ItemKind::Submenu, nullptr, nullptr, [] { pushPage(buildGame()); }, nullptr});
|
p.items.push_back({Locale::get("menu.items.game"), ItemKind::Submenu, nullptr, nullptr, [] { pushPage(buildGame()); }, nullptr});
|
||||||
|
p.items.push_back({Locale::get("menu.items.system"), ItemKind::Submenu, nullptr, nullptr, [] { pushPage(buildSystem()); }, nullptr});
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,6 +273,25 @@ namespace Menu {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Page buildSystem() {
|
||||||
|
Page p{Locale::get("menu.titles.system"), {}, 0};
|
||||||
|
p.subtitle = std::string("v") + Texts::VERSION + " (" + Version::GIT_HASH + ")";
|
||||||
|
|
||||||
|
p.items.push_back({Locale::get("menu.items.restart"), ItemKind::Action, nullptr, nullptr, [] {
|
||||||
|
if (Director::get()) Director::get()->requestRestart();
|
||||||
|
},
|
||||||
|
nullptr, nullptr});
|
||||||
|
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
p.items.push_back({Locale::get("menu.items.exit_game"), ItemKind::Action, nullptr, nullptr, [] {
|
||||||
|
if (Director::get()) Director::get()->requestQuit();
|
||||||
|
},
|
||||||
|
nullptr, nullptr});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
// --- Dibuix ---
|
// --- Dibuix ---
|
||||||
|
|
||||||
// Alpha blending per pixel sobre el buffer ARGB (ABGR en memòria)
|
// Alpha blending per pixel sobre el buffer ARGB (ABGR en memòria)
|
||||||
@@ -308,14 +335,17 @@ namespace Menu {
|
|||||||
fillRect(buf, x + w - 1, y, 1, h, color);
|
fillRect(buf, x + w - 1, y, 1, h, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mida final de la caixa segons el nombre d'items *visibles*
|
// Mida final de la caixa segons el nombre d'items *visibles*.
|
||||||
|
// body = (N-1) * ITEM_SPACING + charH — així BOTTOM_PAD és el buit real
|
||||||
|
// sota el text del darrer ítem, no un buit extra per sobre d'un "slot" buit.
|
||||||
static int boxHeight(const Page& page) {
|
static int boxHeight(const Page& page) {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (const auto& it : page.items) {
|
for (const auto& it : page.items) {
|
||||||
if (isVisible(it)) ++n;
|
if (isVisible(it)) ++n;
|
||||||
}
|
}
|
||||||
int body = (n == 0) ? ITEM_SPACING : n * ITEM_SPACING;
|
int body = (n == 0) ? 8 : (n - 1) * ITEM_SPACING + 8;
|
||||||
return HEADER_H + body + BOTTOM_PAD;
|
int header = HEADER_H + (page.subtitle.empty() ? 0 : SUBTITLE_H);
|
||||||
|
return header + body + BOTTOM_PAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- API pública ---
|
// --- API pública ---
|
||||||
@@ -410,7 +440,8 @@ namespace Menu {
|
|||||||
break;
|
break;
|
||||||
case SDL_SCANCODE_RETURN:
|
case SDL_SCANCODE_RETURN:
|
||||||
case SDL_SCANCODE_KP_ENTER:
|
case SDL_SCANCODE_KP_ENTER:
|
||||||
if (page.items[page.cursor].kind == ItemKind::Submenu) {
|
if (page.items[page.cursor].kind == ItemKind::Submenu ||
|
||||||
|
page.items[page.cursor].kind == ItemKind::Action) {
|
||||||
if (page.items[page.cursor].enter) page.items[page.cursor].enter();
|
if (page.items[page.cursor].enter) page.items[page.cursor].enter();
|
||||||
} else if (page.items[page.cursor].kind == ItemKind::KeyBind) {
|
} else if (page.items[page.cursor].kind == ItemKind::KeyBind) {
|
||||||
capturing_ = page.items[page.cursor].scancode;
|
capturing_ = page.items[page.cursor].scancode;
|
||||||
@@ -459,8 +490,14 @@ namespace Menu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Items o placeholder buit
|
// Subtítol opcional (sota la línia del títol, abans dels items)
|
||||||
int items_y = title_line_y + 4;
|
int items_y = title_line_y + 4;
|
||||||
|
if (!page.subtitle.empty()) {
|
||||||
|
int sub_w = font_->width(page.subtitle.c_str());
|
||||||
|
int sub_x = box_x + (BOX_W - sub_w) / 2 + x_offset;
|
||||||
|
font_->drawClipped(pixel_data, sub_x, items_y, page.subtitle.c_str(), LABEL_COLOR, clip_x_min, clip_x_max, clip_y_min, clip_y_max);
|
||||||
|
items_y += SUBTITLE_H;
|
||||||
|
}
|
||||||
// Compta visibles — si cap, dibuixa placeholder (caixa totalment col·lapsada però oberta)
|
// Compta visibles — si cap, dibuixa placeholder (caixa totalment col·lapsada però oberta)
|
||||||
int visible_count = 0;
|
int visible_count = 0;
|
||||||
for (const auto& it : page.items) if (isVisible(it)) ++visible_count;
|
for (const auto& it : page.items) if (isVisible(it)) ++visible_count;
|
||||||
@@ -478,12 +515,23 @@ namespace Menu {
|
|||||||
int y = items_y + y_slot * ITEM_SPACING;
|
int y = items_y + y_slot * ITEM_SPACING;
|
||||||
++y_slot;
|
++y_slot;
|
||||||
bool selected = (static_cast<int>(i) == page.cursor);
|
bool selected = (static_cast<int>(i) == page.cursor);
|
||||||
|
Uint32 label_color = selected ? CURSOR_COLOR : LABEL_COLOR;
|
||||||
|
|
||||||
|
// Action: sense valor a la dreta — centrem el label amb el cursor just a l'esquerra.
|
||||||
|
if (item.kind == ItemKind::Action) {
|
||||||
|
int lw = font_->width(item.label);
|
||||||
|
int lx = box_x + (BOX_W - lw) / 2 + x_offset;
|
||||||
|
if (selected) {
|
||||||
|
font_->drawClipped(pixel_data, lx - font_->width("> "), y, ">", CURSOR_COLOR, clip_x_min, clip_x_max, clip_y_min, clip_y_max);
|
||||||
|
}
|
||||||
|
font_->drawClipped(pixel_data, lx, y, item.label, label_color, clip_x_min, clip_x_max, clip_y_min, clip_y_max);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
font_->drawClipped(pixel_data, box_x + 4 + x_offset, y, ">", CURSOR_COLOR, clip_x_min, clip_x_max, clip_y_min, clip_y_max);
|
font_->drawClipped(pixel_data, box_x + 4 + x_offset, y, ">", CURSOR_COLOR, clip_x_min, clip_x_max, clip_y_min, clip_y_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint32 label_color = selected ? CURSOR_COLOR : LABEL_COLOR;
|
|
||||||
font_->drawClipped(pixel_data, box_x + ITEM_PAD_X + x_offset, y, item.label, label_color, clip_x_min, clip_x_max, clip_y_min, clip_y_max);
|
font_->drawClipped(pixel_data, box_x + ITEM_PAD_X + x_offset, y, item.label, label_color, clip_x_min, clip_x_max, clip_y_min, clip_y_max);
|
||||||
|
|
||||||
if (item.kind == ItemKind::Submenu) {
|
if (item.kind == ItemKind::Submenu) {
|
||||||
|
|||||||
@@ -138,6 +138,25 @@ bool Director::iterate() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reinici "suau": processat al començament del frame per no manipular
|
||||||
|
// l'escena des d'una lambda del menú mentre encara s'està executant.
|
||||||
|
if (restart_requested_) {
|
||||||
|
restart_requested_ = false;
|
||||||
|
JA_StopMusic();
|
||||||
|
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i) JA_StopChannel(i);
|
||||||
|
// Reinicialitza info::ctx des d'Options (vides, diners, diamants...)
|
||||||
|
// en lloc de ctx.reset() pla que deixaria vida=0 → jugador mort.
|
||||||
|
initGameContext();
|
||||||
|
// Força l'intro independentment de `piramide_inicial` (que pot estar
|
||||||
|
// configurat a una piràmide intermèdia per a proves ràpides).
|
||||||
|
info::ctx.num_piramide = 255;
|
||||||
|
current_scene_.reset();
|
||||||
|
game_state_ = 1; // 1 = dispatch via SceneRegistry per num_piramide
|
||||||
|
has_frame_ = false;
|
||||||
|
Menu::close();
|
||||||
|
JI_SetInputBlocked(false); // el menú ho havia bloquejat — cal desfer-ho
|
||||||
|
}
|
||||||
|
|
||||||
if (!context_initialized_) {
|
if (!context_initialized_) {
|
||||||
initGameContext();
|
initGameContext();
|
||||||
context_initialized_ = true;
|
context_initialized_ = true;
|
||||||
@@ -369,6 +388,10 @@ void Director::requestQuit() {
|
|||||||
JG_QuitSignal();
|
JG_QuitSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Director::requestRestart() {
|
||||||
|
restart_requested_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
auto Director::consumeKeyPressed() -> bool {
|
auto Director::consumeKeyPressed() -> bool {
|
||||||
return key_pressed_.exchange(false);
|
return key_pressed_.exchange(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ class Director {
|
|||||||
void requestQuit();
|
void requestQuit();
|
||||||
auto isQuitRequested() const -> bool { return quit_requested_; }
|
auto isQuitRequested() const -> bool { return quit_requested_; }
|
||||||
|
|
||||||
|
// Demana un reinici "suau": para música i sons, reseteja info::ctx i
|
||||||
|
// torna a l'intro (state 255). Es processa al començament del pròxim
|
||||||
|
// iterate() per evitar manipular l'escena des d'una lambda del menú.
|
||||||
|
void requestRestart();
|
||||||
|
|
||||||
// Consumeix el flag de "tecla polsada" (com l'antic JI_AnyKey)
|
// Consumeix el flag de "tecla polsada" (com l'antic JI_AnyKey)
|
||||||
auto consumeKeyPressed() -> bool;
|
auto consumeKeyPressed() -> bool;
|
||||||
|
|
||||||
@@ -77,6 +82,7 @@ class Director {
|
|||||||
bool context_initialized_{false};
|
bool context_initialized_{false};
|
||||||
|
|
||||||
std::atomic<bool> quit_requested_{false};
|
std::atomic<bool> quit_requested_{false};
|
||||||
|
std::atomic<bool> restart_requested_{false};
|
||||||
std::atomic<bool> key_pressed_{false};
|
std::atomic<bool> key_pressed_{false};
|
||||||
std::atomic<bool> esc_blocked_{false};
|
std::atomic<bool> esc_blocked_{false};
|
||||||
std::atomic<bool> paused_{false};
|
std::atomic<bool> paused_{false};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// Textos
|
// Textos
|
||||||
namespace Texts {
|
namespace Texts {
|
||||||
constexpr const char* WINDOW_TITLE = "© 2000 Aventures en Egipte — JailDesigner";
|
constexpr const char* WINDOW_TITLE = "© 2000 Aventures en Egipte — JailDesigner";
|
||||||
constexpr const char* VERSION = "1.11";
|
constexpr const char* VERSION = "1.2";
|
||||||
} // namespace Texts
|
} // namespace Texts
|
||||||
|
|
||||||
// Resolución del juego
|
// Resolución del juego
|
||||||
|
|||||||
6
source/version.h.in
Normal file
6
source/version.h.in
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Version {
|
||||||
|
constexpr const char* GIT_HASH = "@GIT_HASH@";
|
||||||
|
constexpr const char* APP_NAME = "Aventures en Egipte";
|
||||||
|
} // namespace Version
|
||||||
Reference in New Issue
Block a user