afegits metodes per a poder ciclar presets i altres opcions
esc en el joc + menu ja no tanca la app
This commit is contained in:
@@ -64,63 +64,46 @@ namespace Menu {
|
|||||||
items_.clear();
|
items_.clear();
|
||||||
|
|
||||||
// ZOOM
|
// ZOOM
|
||||||
items_.push_back({"ZOOM", ItemKind::IntRange,
|
items_.push_back({"ZOOM", ItemKind::IntRange, [] {
|
||||||
[] {
|
|
||||||
char buf[16];
|
char buf[16];
|
||||||
std::snprintf(buf, sizeof(buf), "%dX", Screen::get()->getZoom());
|
std::snprintf(buf, sizeof(buf), "%dX", Screen::get()->getZoom());
|
||||||
return std::string(buf);
|
return std::string(buf); }, [](int dir) {
|
||||||
},
|
|
||||||
[](int dir) {
|
|
||||||
if (dir < 0) Screen::get()->decZoom();
|
if (dir < 0) Screen::get()->decZoom();
|
||||||
else if (dir > 0) Screen::get()->incZoom();
|
else if (dir > 0) Screen::get()->incZoom(); }});
|
||||||
}});
|
|
||||||
|
|
||||||
// PANTALLA (fullscreen)
|
// PANTALLA (fullscreen)
|
||||||
items_.push_back({"PANTALLA", ItemKind::Toggle,
|
items_.push_back({"PANTALLA", ItemKind::Toggle, [] { return std::string(Screen::get()->isFullscreen() ? "COMPLETA" : "FINESTRA"); }, [](int) { Screen::get()->toggleFullscreen(); }});
|
||||||
[] { return std::string(Screen::get()->isFullscreen() ? "COMPLETA" : "FINESTRA"); },
|
|
||||||
[](int) { Screen::get()->toggleFullscreen(); }});
|
|
||||||
|
|
||||||
// SHADER
|
// SHADER
|
||||||
items_.push_back({"SHADER", ItemKind::Toggle,
|
items_.push_back({"SHADER", ItemKind::Toggle, [] { return onOff(Options::video.shader_enabled); }, [](int) { Screen::get()->toggleShaders(); }});
|
||||||
[] { return onOff(Options::video.shader_enabled); },
|
|
||||||
[](int) { Screen::get()->toggleShaders(); }});
|
|
||||||
|
|
||||||
// ASPECTE 4:3
|
// ASPECTE 4:3
|
||||||
items_.push_back({"ASPECTE 4:3", ItemKind::Toggle,
|
items_.push_back({"ASPECTE 4:3", ItemKind::Toggle, [] { return yesNo(Options::video.aspect_ratio_4_3); }, [](int) { Screen::get()->toggleAspectRatio(); }});
|
||||||
[] { return yesNo(Options::video.aspect_ratio_4_3); },
|
|
||||||
[](int) { Screen::get()->toggleAspectRatio(); }});
|
|
||||||
|
|
||||||
// SUPERSAMPLING
|
// SUPERSAMPLING
|
||||||
items_.push_back({"SUPERSAMPLING", ItemKind::Toggle,
|
items_.push_back({"SUPERSAMPLING", ItemKind::Toggle, [] { return onOff(Options::video.supersampling); }, [](int) { Screen::get()->toggleSupersampling(); }});
|
||||||
[] { return onOff(Options::video.supersampling); },
|
|
||||||
[](int) { Screen::get()->toggleSupersampling(); }});
|
|
||||||
|
|
||||||
// TIPUS SHADER
|
// TIPUS SHADER
|
||||||
items_.push_back({"TIPUS SHADER", ItemKind::Cycle,
|
items_.push_back({"TIPUS SHADER", ItemKind::Cycle, [] { return std::string(Screen::get()->getActiveShaderName()); }, [](int dir) {
|
||||||
[] { return std::string(Screen::get()->getActiveShaderName()); },
|
if (dir < 0) Screen::get()->prevShaderType();
|
||||||
[](int) { Screen::get()->nextShaderType(); }});
|
else Screen::get()->nextShaderType(); }});
|
||||||
|
|
||||||
// PRESET
|
// PRESET
|
||||||
items_.push_back({"PRESET", ItemKind::Cycle,
|
items_.push_back({"PRESET", ItemKind::Cycle, [] { return std::string(Screen::get()->getCurrentPresetName()); }, [](int dir) {
|
||||||
[] { return std::string(Screen::get()->getCurrentPresetName()); },
|
if (dir < 0) Screen::get()->prevPreset();
|
||||||
[](int) { Screen::get()->nextPreset(); }});
|
else Screen::get()->nextPreset(); }});
|
||||||
|
|
||||||
// FILTRE 4:3
|
// FILTRE 4:3
|
||||||
items_.push_back({"FILTRE 4:3", ItemKind::Toggle,
|
items_.push_back({"FILTRE 4:3", ItemKind::Toggle, [] { return std::string(Options::video.stretch_filter_linear ? "LINEAR" : "NEAREST"); }, [](int) { Screen::get()->toggleStretchFilter(); }});
|
||||||
[] { return std::string(Options::video.stretch_filter_linear ? "LINEAR" : "NEAREST"); },
|
|
||||||
[](int) { Screen::get()->toggleStretchFilter(); }});
|
|
||||||
|
|
||||||
// RENDER INFO
|
// RENDER INFO
|
||||||
items_.push_back({"RENDER INFO", ItemKind::Cycle,
|
items_.push_back({"RENDER INFO", ItemKind::Cycle, [] {
|
||||||
[] {
|
|
||||||
switch (Options::render_info.position) {
|
switch (Options::render_info.position) {
|
||||||
case Options::RenderInfoPosition::OFF: return std::string("OFF");
|
case Options::RenderInfoPosition::OFF: return std::string("OFF");
|
||||||
case Options::RenderInfoPosition::TOP: return std::string("TOP");
|
case Options::RenderInfoPosition::TOP: return std::string("TOP");
|
||||||
case Options::RenderInfoPosition::BOTTOM: return std::string("BOTTOM");
|
case Options::RenderInfoPosition::BOTTOM: return std::string("BOTTOM");
|
||||||
}
|
}
|
||||||
return std::string("OFF");
|
return std::string("OFF"); }, [](int dir) { Overlay::cycleRenderInfo(dir); }});
|
||||||
},
|
|
||||||
[](int) { Overlay::toggleRenderInfo(); }});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Dibuix ---
|
// --- Dibuix ---
|
||||||
|
|||||||
@@ -170,19 +170,13 @@ namespace Overlay {
|
|||||||
notifications_.push_back(notif);
|
notifications_.push_back(notif);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleRenderInfo() {
|
void toggleRenderInfo() { cycleRenderInfo(+1); }
|
||||||
// Cicla: OFF → TOP → BOTTOM → OFF
|
|
||||||
switch (Options::render_info.position) {
|
void cycleRenderInfo(int dir) {
|
||||||
case Options::RenderInfoPosition::OFF:
|
// Seqüència: OFF → TOP → BOTTOM → OFF
|
||||||
Options::render_info.position = Options::RenderInfoPosition::TOP;
|
int pos = static_cast<int>(Options::render_info.position);
|
||||||
break;
|
pos = (pos + (dir >= 0 ? 1 : -1) + 3) % 3;
|
||||||
case Options::RenderInfoPosition::TOP:
|
Options::render_info.position = static_cast<Options::RenderInfoPosition>(pos);
|
||||||
Options::render_info.position = Options::RenderInfoPosition::BOTTOM;
|
|
||||||
break;
|
|
||||||
case Options::RenderInfoPosition::BOTTOM:
|
|
||||||
Options::render_info.position = Options::RenderInfoPosition::OFF;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRenderInfoText(const char* text) {
|
void setRenderInfoText(const char* text) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace Overlay {
|
|||||||
|
|
||||||
// Activa/desactiva la info de renderitzat (FPS, driver, shader, preset)
|
// Activa/desactiva la info de renderitzat (FPS, driver, shader, preset)
|
||||||
void toggleRenderInfo();
|
void toggleRenderInfo();
|
||||||
|
void cycleRenderInfo(int dir); // dir=+1 avant, -1 endarrere
|
||||||
void setRenderInfoText(const char* text);
|
void setRenderInfoText(const char* text);
|
||||||
|
|
||||||
// Gestió d'eixida amb doble ESC
|
// Gestió d'eixida amb doble ESC
|
||||||
|
|||||||
@@ -240,6 +240,29 @@ void Screen::nextPreset() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Screen::prevShaderType() {
|
||||||
|
// Només dues opcions — prev == next
|
||||||
|
nextShaderType();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::prevPreset() {
|
||||||
|
if (!shader_backend_ || !shader_backend_->isHardwareAccelerated()) return;
|
||||||
|
|
||||||
|
if (shader_backend_->getActiveShader() == Rendering::ShaderType::POSTFX) {
|
||||||
|
if (Options::postfx_presets.empty()) return;
|
||||||
|
int n = static_cast<int>(Options::postfx_presets.size());
|
||||||
|
Options::current_postfx_preset = (Options::current_postfx_preset - 1 + n) % n;
|
||||||
|
Options::video.current_postfx_preset = Options::postfx_presets[Options::current_postfx_preset].name;
|
||||||
|
applyCurrentPostFXPreset();
|
||||||
|
} else {
|
||||||
|
if (Options::crtpi_presets.empty()) return;
|
||||||
|
int n = static_cast<int>(Options::crtpi_presets.size());
|
||||||
|
Options::current_crtpi_preset = (Options::current_crtpi_preset - 1 + n) % n;
|
||||||
|
Options::video.current_crtpi_preset = Options::crtpi_presets[Options::current_crtpi_preset].name;
|
||||||
|
applyCurrentCrtPiPreset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto Screen::getCurrentPresetName() const -> const char* {
|
auto Screen::getCurrentPresetName() const -> const char* {
|
||||||
if (!shader_backend_ || !shader_backend_->isHardwareAccelerated()) return "---";
|
if (!shader_backend_ || !shader_backend_->isHardwareAccelerated()) return "---";
|
||||||
if (shader_backend_->getActiveShader() == Rendering::ShaderType::POSTFX) {
|
if (shader_backend_->getActiveShader() == Rendering::ShaderType::POSTFX) {
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ class Screen {
|
|||||||
void toggleIntegerScale();
|
void toggleIntegerScale();
|
||||||
void toggleStretchFilter();
|
void toggleStretchFilter();
|
||||||
void nextShaderType(); // Cicla PostFX ↔ CrtPi (F7)
|
void nextShaderType(); // Cicla PostFX ↔ CrtPi (F7)
|
||||||
|
void prevShaderType(); // Cicla al revés
|
||||||
void nextPreset(); // Cicla presets del shader actiu (F8)
|
void nextPreset(); // Cicla presets del shader actiu (F8)
|
||||||
|
void prevPreset(); // Cicla presets al revés
|
||||||
[[nodiscard]] auto getCurrentPresetName() const -> const char*;
|
[[nodiscard]] auto getCurrentPresetName() const -> const char*;
|
||||||
void setActiveShader(Rendering::ShaderType type);
|
void setActiveShader(Rendering::ShaderType type);
|
||||||
void applyCurrentPostFXPreset();
|
void applyCurrentPostFXPreset();
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ void Director::handleEvents() {
|
|||||||
if (event.key.scancode == SDL_SCANCODE_ESCAPE) {
|
if (event.key.scancode == SDL_SCANCODE_ESCAPE) {
|
||||||
Menu::close();
|
Menu::close();
|
||||||
JI_SetInputBlocked(false);
|
JI_SetInputBlocked(false);
|
||||||
|
// Empassa l'ESC fins al release perquè el joc no la veja per polling
|
||||||
|
esc_swallow_until_release_ = true;
|
||||||
} else {
|
} else {
|
||||||
Menu::handleKey(event.key.scancode);
|
Menu::handleKey(event.key.scancode);
|
||||||
}
|
}
|
||||||
@@ -128,6 +130,11 @@ void Director::handleEvents() {
|
|||||||
if (Menu::isOpen() && event.type == SDL_EVENT_KEY_UP) {
|
if (Menu::isOpen() && event.type == SDL_EVENT_KEY_UP) {
|
||||||
continue; // no deixem passar KEY_UP al joc tampoc
|
continue; // no deixem passar KEY_UP al joc tampoc
|
||||||
}
|
}
|
||||||
|
// Allibera el bloqueig d'ESC quan l'usuari la deixa anar
|
||||||
|
if (event.type == SDL_EVENT_KEY_UP && event.key.scancode == SDL_SCANCODE_ESCAPE && esc_swallow_until_release_) {
|
||||||
|
esc_swallow_until_release_ = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// ESC: interceptem KEY_DOWN per bloquejar-la ABANS que el joc la veja per polling
|
// ESC: interceptem KEY_DOWN per bloquejar-la ABANS que el joc la veja per polling
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN && event.key.scancode == SDL_SCANCODE_ESCAPE && !event.key.repeat) {
|
if (event.type == SDL_EVENT_KEY_DOWN && event.key.scancode == SDL_SCANCODE_ESCAPE && !event.key.repeat) {
|
||||||
esc_blocked_ = true; // Bloqueja ESC per polling immediatament
|
esc_blocked_ = true; // Bloqueja ESC per polling immediatament
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class Director {
|
|||||||
auto consumeKeyPressed() -> bool;
|
auto consumeKeyPressed() -> bool;
|
||||||
|
|
||||||
// Indica si ESC està bloquejada (el joc no l'ha de veure)
|
// Indica si ESC està bloquejada (el joc no l'ha de veure)
|
||||||
auto isEscBlocked() const -> bool { return esc_blocked_; }
|
auto isEscBlocked() const -> bool { return esc_blocked_ || esc_swallow_until_release_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Director() = default;
|
Director() = default;
|
||||||
@@ -56,4 +56,7 @@ class Director {
|
|||||||
std::atomic<bool> game_thread_done_{false};
|
std::atomic<bool> game_thread_done_{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};
|
||||||
|
// Quan el menú tanca amb ESC, empassem-nos l'ESC fins que l'usuari la deixe anar,
|
||||||
|
// per no fer eixir el joc al proper poll de JI_KeyPressed.
|
||||||
|
std::atomic<bool> esc_swallow_until_release_{false};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user