Files
jaildoctors_dilemma/source/options.cpp
Sergio Valor 7c102e42cc corregits mes includes
llevats els errors en texture
2025-10-15 09:14:30 +02:00

227 lines
8.8 KiB
C++

#include "options.h"
#include <SDL3/SDL.h>
#include <algorithm> // Para find_if
#include <cctype> // Para isspace
#include <fstream> // Para basic_ostream, operator<<, basic_ofstream
#include <functional> // Para function
#include <iostream> // Para cout, cerr
#include <sstream> // Para basic_istringstream
#include <string> // Para char_traits, string, operator<<, hash
#include <unordered_map> // Para unordered_map, operator==, _Node_const_i...
#include <utility> // Para pair
// Variables
Options options;
bool setOptions(const std::string& var, const std::string& value);
// Crea e inicializa las opciones del programa
void initOptions() {
options = Options();
#ifdef DEBUG
options.section = SectionState(Section::ENDING2, Subsection::LOGO_TO_INTRO);
options.console = true;
#else
options.section = SectionState(Section::LOGO, Subsection::LOGO_TO_INTRO);
options.console = false;
#endif
}
// Carga las opciones desde un fichero
bool loadOptionsFromFile(const std::string& file_path) {
// Indicador de éxito en la carga
bool success = true;
// Versión actual del fichero
const std::string configVersion = options.version;
options.version = "";
// Variables para manejar el fichero
std::ifstream file(file_path);
// Si el fichero se puede abrir
if (file.good()) {
// Procesa el fichero línea a línea
if (options.console) {
std::cout << "Reading file config.txt\n";
}
std::string line;
while (std::getline(file, line)) {
// Elimina espacios en blanco iniciales y finales
line = std::string(std::find_if(line.begin(), line.end(), [](int ch) { return !std::isspace(ch); }),
line.end());
line.erase(std::find_if(line.rbegin(), line.rend(), [](int ch) { return !std::isspace(ch); })
.base(),
line.end());
// Ignora líneas vacías o comentarios
if (line.empty() || line[0] == '#') {
continue;
}
// Usa un stringstream para dividir la línea en dos partes
std::istringstream iss(line);
std::string key, value;
if (iss >> key >> value) {
if (!setOptions(key, value)) {
if (options.console) {
std::cout << "Warning: file config.txt\n";
std::cout << "unknown parameter " << key << std::endl;
}
success = false;
}
}
}
// Cierra el fichero
if (options.console) {
std::cout << "Closing file config.txt\n\n";
}
file.close();
} else {
// Crea el fichero con los valores por defecto
saveOptionsToFile(file_path);
}
// Si la versión de fichero no coincide, crea un fichero nuevo con los valores por defecto
if (configVersion != options.version) {
initOptions();
saveOptionsToFile(file_path);
if (options.console) {
std::cout << "Wrong config file: initializing options.\n\n";
}
}
return success;
}
// Guarda las opciones en un fichero
bool saveOptionsToFile(const std::string& file_path) {
// Crea y abre el fichero de texto
std::ofstream file(file_path);
bool success = file.is_open(); // Verifica si el archivo se abrió correctamente
if (!success) // Si no se pudo abrir el archivo, muestra un mensaje de error y devuelve false
{
if (options.console) {
std::cerr << "Error: Unable to open file " << file_path << " for writing." << std::endl;
}
return false;
}
if (options.console) {
std::cout << file_path << " open for writing" << std::endl;
}
// Escribe en el fichero
file << "# Versión de la configuración\n";
file << "version " << options.version << "\n";
file << "\n## CONTROL\n";
file << "# Esquema de control: 0 = Cursores, 1 = OPQ, 2 = WAD\n";
file << "keys " << static_cast<int>(options.keys) << "\n";
file << "\n## WINDOW\n";
file << "# Zoom de la ventana: 1 = Normal, 2 = Doble, 3 = Triple, ...\n";
file << "window.zoom " << options.window.zoom << "\n";
file << "\n## VIDEO\n";
file << "# Modo de video: 0 = Ventana, 1 = Pantalla completa, 2 = Pantalla completa (escritorio)\n";
file << "video.mode " << options.video.mode << "\n\n";
file << "# Filtro de pantalla: 0 = Nearest, 1 = Linear\n";
file << "video.filter " << static_cast<int>(options.video.filter) << "\n\n";
file << "# Shaders: 1 = Activado, 0 = Desactivado\n";
file << "video.shaders " << boolToString(options.video.shaders) << "\n\n";
file << "# Sincronización vertical: 1 = Activado, 0 = Desactivado\n";
file << "video.vertical_sync " << boolToString(options.video.vertical_sync) << "\n\n";
file << "# Escalado entero: 1 = Activado, 0 = Desactivado\n";
file << "video.integer_scale " << boolToString(options.video.integer_scale) << "\n\n";
file << "# Mantener aspecto: 1 = Activado, 0 = Desactivado\n";
file << "video.keep_aspect " << boolToString(options.video.keep_aspect) << "\n\n";
file << "# Borde: 1 = Activado, 0 = Desactivado\n";
file << "video.border.enabled " << boolToString(options.video.border.enabled) << "\n\n";
file << "# Ancho del borde\n";
file << "video.border.width " << options.video.border.width << "\n\n";
file << "# Alto del borde\n";
file << "video.border.height " << options.video.border.height << "\n\n";
file << "# Paleta\n";
file << "video.palette " << options.video.palette << "\n";
// Cierra el fichero
file.close();
return success;
}
bool setOptions(const std::string& var, const std::string& value) {
static const std::unordered_map<std::string, std::function<void(const std::string&)>> optionHandlers = {
{"version", [](const std::string& v) { options.version = v; }},
{"keys", [](const std::string& v) {
int val = safeStoi(v, static_cast<int>(DEFAULT_CONTROL_SCHEME));
if (val == static_cast<int>(ControlScheme::CURSOR) || val == static_cast<int>(ControlScheme::OPQA) || val == static_cast<int>(ControlScheme::WASD)) {
options.keys = static_cast<ControlScheme>(val);
} else {
options.keys = DEFAULT_CONTROL_SCHEME;
}
}},
{"window.zoom", [](const std::string& v) {
int val = safeStoi(v, DEFAULT_WINDOW_ZOOM);
if (val > 0) {
options.window.zoom = val;
} else {
options.window.zoom = DEFAULT_WINDOW_ZOOM;
}
}},
{"video.mode", [](const std::string& v) {
int val = safeStoi(v, 0);
if (val == 0 || val == SDL_WINDOW_FULLSCREEN_DESKTOP) {
options.video.mode = val;
} else {
options.video.mode = 0;
}
}},
{"video.filter", [](const std::string& v) {
int val = safeStoi(v, static_cast<int>(DEFAULT_VIDEO_FILTER));
if (val == static_cast<int>(ScreenFilter::NEAREST) || val == static_cast<int>(ScreenFilter::LINEAR)) {
options.video.filter = static_cast<ScreenFilter>(val);
} else {
options.video.filter = DEFAULT_VIDEO_FILTER;
}
}},
{"video.shaders", [](const std::string& v) { options.video.shaders = stringToBool(v); }},
{"video.vertical_sync", [](const std::string& v) { options.video.vertical_sync = stringToBool(v); }},
{"video.integer_scale", [](const std::string& v) { options.video.integer_scale = stringToBool(v); }},
{"video.keep_aspect", [](const std::string& v) { options.video.keep_aspect = stringToBool(v); }},
{"video.border.enabled", [](const std::string& v) { options.video.border.enabled = stringToBool(v); }},
{"video.border.width", [](const std::string& v) {
int val = safeStoi(v, DEFAULT_BORDER_WIDTH);
if (val > 0) {
options.video.border.width = val;
} else {
options.video.border.width = DEFAULT_BORDER_WIDTH;
}
}},
{"video.border.height", [](const std::string& v) {
int val = safeStoi(v, DEFAULT_BORDER_HEIGHT);
if (val > 0) {
options.video.border.height = val;
} else {
options.video.border.height = DEFAULT_BORDER_HEIGHT;
}
}},
{"video.palette", [](const std::string& v) {
options.video.palette = v;
}}};
auto it = optionHandlers.find(var);
if (it != optionHandlers.end()) {
it->second(value);
return true;
}
return false;
}