diff --git a/CMakeLists.txt b/CMakeLists.txt index 68d380e..a8a72cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -136,6 +136,11 @@ set(APP_SOURCES # Main source/main.cpp + + # External - implementacions aïllades de llibreries de tercers + # (fora del filtre de tidy/cppcheck via source/external/) + source/external/stb_image_write_impl.cpp + source/external/stb_vorbis_impl.cpp ) # Fuentes del sistema de renderizado (SDL3 GPU para todas las plataformas) @@ -240,6 +245,15 @@ else() add_executable(${PROJECT_NAME} ${APP_SOURCES} ${RENDERING_SOURCES}) endif() +# Silencia warnings de codi de tercers (mateixa filosofia que el +# .clang-tidy de source/external/). Només afecta aquests TUs concrets; +# la resta del codi continua compilant amb -Wall -Wextra -Wpedantic. +set_source_files_properties( + source/external/stb_image_write_impl.cpp + source/external/stb_vorbis_impl.cpp + PROPERTIES COMPILE_OPTIONS "-Wno-missing-field-initializers;-Wno-deprecated-declarations" +) + # Shaders deben compilarse antes que el ejecutable (Linux/Windows con glslc) if(NOT APPLE AND NOT EMSCRIPTEN AND GLSLC_EXE) add_dependencies(${PROJECT_NAME} shaders) diff --git a/source/core/audio/audio.cpp b/source/core/audio/audio.cpp index 633a767..80d5c2f 100644 --- a/source/core/audio/audio.cpp +++ b/source/core/audio/audio.cpp @@ -5,20 +5,9 @@ #include // Para clamp #include // Para std::cout -// Implementación de stb_vorbis (debe estar ANTES de incluir jail_audio.hpp). -// clang-format off -#undef STB_VORBIS_HEADER_ONLY -#include "external/stb_vorbis.c" -// stb_vorbis.c filtra les macros L, C i R (i PLAYBACK_*) al TU. Les netegem -// perquè xocarien amb noms de paràmetres de plantilla en altres headers. -#undef L -#undef C -#undef R -#undef PLAYBACK_MONO -#undef PLAYBACK_LEFT -#undef PLAYBACK_RIGHT -// clang-format on - +// La implementació de stb_vorbis viu en source/external/stb_vorbis_impl.cpp. +// Ací només en veiem les declaracions via jail_audio.hpp (que inclou amb +// STB_VORBIS_HEADER_ONLY). #include "core/audio/audio_adapter.hpp" // Para AudioResource::getMusic/getSound #include "core/audio/jail_audio.hpp" // Para JA_* #include "game/options.hpp" // Para Options::audio diff --git a/source/core/audio/jail_audio.hpp b/source/core/audio/jail_audio.hpp index 63308e0..a6289ac 100644 --- a/source/core/audio/jail_audio.hpp +++ b/source/core/audio/jail_audio.hpp @@ -265,13 +265,13 @@ inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) { auto* music = new JA_Music_t(); music->ogg_data.assign(buffer, buffer + length); - int error = 0; + int vorbis_error = 0; music->vorbis = stb_vorbis_open_memory(music->ogg_data.data(), static_cast(length), - &error, + &vorbis_error, nullptr); if (!music->vorbis) { - std::cout << "JA_LoadMusic: stb_vorbis_open_memory failed (error " << error << ")" << '\n'; + std::cout << "JA_LoadMusic: stb_vorbis_open_memory failed (error " << vorbis_error << ")" << '\n'; delete music; return nullptr; } diff --git a/source/core/input/input.cpp b/source/core/input/input.cpp index 375e6ca..1eab6a1 100644 --- a/source/core/input/input.cpp +++ b/source/core/input/input.cpp @@ -173,15 +173,11 @@ auto Input::checkAction(Action action, bool repeat, bool check_keyboard, const s auto Input::checkAnyInput(bool check_keyboard, const std::shared_ptr& gamepad) -> bool { // Obtenemos el número total de acciones posibles para iterar sobre ellas. + auto pressed = [](const auto& pair) { return pair.second.just_pressed; }; + // --- Comprobación del Teclado --- - if (check_keyboard) { - for (const auto& pair : keyboard_.bindings) { - // Simplemente leemos el estado pre-calculado por Input::update(). - // Ya no se llama a SDL_GetKeyboardState ni se modifica el estado '.active'. - if (pair.second.just_pressed) { - return true; // Se encontró una acción recién pulsada. - } - } + if (check_keyboard && std::ranges::any_of(keyboard_.bindings, pressed)) { + return true; } // Si gamepad es nullptr pero hay mandos conectados, usar el primero @@ -191,15 +187,8 @@ auto Input::checkAnyInput(bool check_keyboard, const std::shared_ptr& g } // --- Comprobación del Mando --- - // Comprobamos si hay mandos y si el índice solicitado es válido. - if (active_gamepad != nullptr) { - // Iteramos sobre todas las acciones, no sobre el número de mandos. - for (const auto& pair : active_gamepad->bindings) { - // Leemos el estado pre-calculado para el mando y la acción específicos. - if (pair.second.just_pressed) { - return true; // Se encontró una acción recién pulsada en el mando. - } - } + if (active_gamepad != nullptr && std::ranges::any_of(active_gamepad->bindings, pressed)) { + return true; } // Si llegamos hasta aquí, no se detectó ninguna nueva pulsación. @@ -208,22 +197,13 @@ auto Input::checkAnyInput(bool check_keyboard, const std::shared_ptr& g // Comprueba si hay algún botón pulsado auto Input::checkAnyButton(bool repeat) -> bool { - // Solo comprueba los botones definidos previamente - for (auto bi : BUTTON_INPUTS) { - // Comprueba el teclado - if (checkAction(bi, repeat, CHECK_KEYBOARD)) { - return true; - } - - // Comprueba los mandos - for (const auto& gamepad : gamepads_) { - if (checkAction(bi, repeat, DO_NOT_CHECK_KEYBOARD, gamepad)) { - return true; - } - } - } - - return false; + auto button_pressed = [&](auto bi) { + if (checkAction(bi, repeat, CHECK_KEYBOARD)) { return true; } + return std::ranges::any_of(gamepads_, [&](const auto& gp) { + return checkAction(bi, repeat, DO_NOT_CHECK_KEYBOARD, gp); + }); + }; + return std::ranges::any_of(BUTTON_INPUTS, button_pressed); } // Comprueba si hay algun mando conectado @@ -237,9 +217,8 @@ auto Input::getControllerName(const std::shared_ptr& gamepad) -> std::s // Obtiene la lista de nombres de mandos auto Input::getControllerNames() const -> std::vector { std::vector names; - for (const auto& gamepad : gamepads_) { - names.push_back(gamepad->name); - } + names.reserve(gamepads_.size()); + std::ranges::transform(gamepads_, std::back_inserter(names), [](const auto& gp) { return gp->name; }); return names; } @@ -248,21 +227,13 @@ auto Input::getNumGamepads() const -> int { return gamepads_.size(); } // Obtiene el gamepad a partir de un event.id auto Input::getGamepad(SDL_JoystickID id) const -> std::shared_ptr { - for (const auto& gamepad : gamepads_) { - if (gamepad->instance_id == id) { - return gamepad; - } - } - return nullptr; + auto it = std::ranges::find_if(gamepads_, [id](const auto& gp) { return gp->instance_id == id; }); + return (it != gamepads_.end()) ? *it : nullptr; } auto Input::getGamepadByName(const std::string& name) const -> std::shared_ptr { - for (const auto& gamepad : gamepads_) { - if (gamepad && gamepad->name == name) { - return gamepad; - } - } - return nullptr; + auto it = std::ranges::find_if(gamepads_, [&](const auto& gp) { return gp && gp->name == name; }); + return (it != gamepads_.end()) ? *it : nullptr; } // Obtiene el SDL_GamepadButton asignado a un action @@ -495,19 +466,14 @@ auto Input::findAvailableGamepadByName(const std::string& gamepad_name) -> std:: } // Buscar por nombre - for (const auto& gamepad : gamepads_) { - if (gamepad && gamepad->name == gamepad_name) { - return gamepad; - } + auto by_name = std::ranges::find_if(gamepads_, [&](const auto& gp) { + return gp && gp->name == gamepad_name; + }); + if (by_name != gamepads_.end()) { + return *by_name; } // Si no se encuentra por nombre, devolver el primer gamepad válido - for (const auto& gamepad : gamepads_) { - if (gamepad) { - return gamepad; - } - } - - // Si llegamos aquí, no hay gamepads válidos - return nullptr; + auto any_valid = std::ranges::find_if(gamepads_, [](const auto& gp) { return static_cast(gp); }); + return (any_valid != gamepads_.end()) ? *any_valid : nullptr; } \ No newline at end of file diff --git a/source/core/rendering/palette_manager.cpp b/source/core/rendering/palette_manager.cpp index 64cd553..f839424 100644 --- a/source/core/rendering/palette_manager.cpp +++ b/source/core/rendering/palette_manager.cpp @@ -178,9 +178,7 @@ namespace { } // Si quedan colores sin asignar, añadirlos al final - for (const auto& c : available) { - result.push_back(c); - } + std::ranges::copy(available, std::back_inserter(result)); Palette out{}; out.fill(0); @@ -208,11 +206,11 @@ PaletteManager::PaletteManager( // Leer la paleta de referencia directamente desde el archivo // (Resource::Cache aún no está disponible en este punto del ciclo de vida) const std::string REF_NAME = std::string(Defaults::Video::PALETTE_NAME) + ".pal"; - for (const auto& p : palettes_) { - if (getFileName(p) == REF_NAME) { - reference_palette_ = readPalFile(p); - break; - } + auto ref_it = std::ranges::find_if(palettes_, [&](const auto& p) { + return getFileName(p) == REF_NAME; + }); + if (ref_it != palettes_.end()) { + reference_palette_ = readPalFile(*ref_it); } // Leer y aplicar paleta inicial diff --git a/source/core/rendering/screenshot.cpp b/source/core/rendering/screenshot.cpp index eeba243..80fdee4 100644 --- a/source/core/rendering/screenshot.cpp +++ b/source/core/rendering/screenshot.cpp @@ -8,9 +8,8 @@ #include // Para string #include // Para vector -#define STB_IMAGE_WRITE_IMPLEMENTATION #include "core/rendering/surface.hpp" // Para Surface -#include "external/stb_image_write.h" // Para stbi_write_png +#include "external/stb_image_write.h" // Para stbi_write_png (impl en source/external/stb_image_write_impl.cpp) namespace Screenshot { @@ -21,7 +20,7 @@ namespace Screenshot { auto now = std::chrono::system_clock::now(); std::time_t time = std::chrono::system_clock::to_time_t(now); - std::tm* tm = std::localtime(&time); + const std::tm* tm = std::localtime(&time); char timestamp[20]; std::strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", tm); @@ -45,15 +44,15 @@ namespace Screenshot { } // namespace auto save(const Surface& surface) -> std::string { - int width = static_cast(surface.getWidth()); - int height = static_cast(surface.getHeight()); - std::vector buffer(static_cast(width * height)); + const int WIDTH = surface.getWidth(); + const int HEIGHT = surface.getHeight(); + std::vector buffer(static_cast(WIDTH * HEIGHT)); surface.toARGBBuffer(buffer.data()); std::string filename; std::string filepath = generateFilePath(filename); - return writePng(buffer.data(), width, height, filepath) ? filename : ""; + return writePng(buffer.data(), WIDTH, HEIGHT, filepath) ? filename : ""; } auto save(const Uint32* buffer, int width, int height) -> std::string { diff --git a/source/core/rendering/sprite/animated_sprite.cpp b/source/core/rendering/sprite/animated_sprite.cpp index 4075b61..5565c3f 100644 --- a/source/core/rendering/sprite/animated_sprite.cpp +++ b/source/core/rendering/sprite/animated_sprite.cpp @@ -4,6 +4,7 @@ #include // Para size_t #include // Para basic_ostream, basic_istream, operator<<, basic... #include // Para cout, cerr +#include // Para std::accumulate #include // Para basic_stringstream #include // Para runtime_error #include @@ -155,11 +156,10 @@ void AnimatedSprite::animate(float delta_time) { anim.accumulated_time += delta_time; // Calcular duración total de la animación - float total = 0.0F; - for (auto s : anim.speeds) { total += s; } + const float TOTAL = std::accumulate(anim.speeds.begin(), anim.speeds.end(), 0.0F); // Si hemos superado la duración total, manejar loop o congelar - if (anim.accumulated_time >= total) { + if (anim.accumulated_time >= TOTAL) { if (anim.loop_from < 0) { // Sin loop: congelar en el último frame anim.current_frame = static_cast(anim.frames.size()) - 1; @@ -168,10 +168,9 @@ void AnimatedSprite::animate(float delta_time) { return; } // Con loop: envolver el tiempo en el rango del loop - float loop_start = 0.0F; - for (int i = 0; i < anim.loop_from; ++i) { loop_start += anim.speeds[i]; } - float loop_len = total - loop_start; - anim.accumulated_time = loop_start + std::fmod(anim.accumulated_time - loop_start, loop_len); + const float LOOP_START = std::accumulate(anim.speeds.begin(), anim.speeds.begin() + anim.loop_from, 0.0F); + const float LOOP_LEN = TOTAL - LOOP_START; + anim.accumulated_time = LOOP_START + std::fmod(anim.accumulated_time - LOOP_START, LOOP_LEN); } // Buscar el frame correspondiente al tiempo acumulado diff --git a/source/core/rendering/surface.cpp b/source/core/rendering/surface.cpp index 14e1f2e..de96e2b 100644 --- a/source/core/rendering/surface.cpp +++ b/source/core/rendering/surface.cpp @@ -427,7 +427,7 @@ static auto computeFadeDensity(int screen_y, int fade_h, int canvas_height) -> f } // Render amb dissolució als cantons superior/inferior (hash 2D, sense parpelleig) -void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, SDL_FRect* src_rect) const { +void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, const SDL_FRect* src_rect) const { // Aplicar render offset (usado per transicions entre pantalles) x += Screen::get()->getRenderOffsetX(); y += Screen::get()->getRenderOffsetY(); @@ -468,7 +468,7 @@ void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height } // Idem però reemplaçant un color índex -void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, SDL_FRect* src_rect) const { +void Surface::renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, const SDL_FRect* src_rect) const { // Aplicar render offset (usado per transicions entre pantalles) x += Screen::get()->getRenderOffsetX(); y += Screen::get()->getRenderOffsetY(); diff --git a/source/core/rendering/surface.hpp b/source/core/rendering/surface.hpp index 572847d..7cb3032 100644 --- a/source/core/rendering/surface.hpp +++ b/source/core/rendering/surface.hpp @@ -87,10 +87,10 @@ class Surface { void renderWithColorReplace(int x, int y, Uint8 source_color = 0, Uint8 target_color = 0, SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE) const; // Render amb dissolució als cantons superior/inferior (hash 2D, sense parpelleig) - void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, SDL_FRect* src_rect = nullptr) const; + void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, const SDL_FRect* src_rect = nullptr) const; // Idem però reemplaçant un color índex (per a sprites sobre fons del mateix color) - void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, SDL_FRect* src_rect = nullptr) const; + void renderWithVerticalFade(int x, int y, int fade_h, int canvas_height, Uint8 source_color, Uint8 target_color, const SDL_FRect* src_rect = nullptr) const; // Establece un color en la paleta void setColor(int index, Uint32 color); diff --git a/source/core/resources/resource_cache.cpp b/source/core/resources/resource_cache.cpp index 2311800..ceb3b15 100644 --- a/source/core/resources/resource_cache.cpp +++ b/source/core/resources/resource_cache.cpp @@ -577,27 +577,13 @@ namespace Resource { animations_.clear(); rooms_.clear(); - for (const auto& l : List::get()->getListByType(List::Type::SOUND)) { - sounds_.emplace_back(SoundResource{.name = getFileName(l), .sound = nullptr}); - } - for (const auto& l : List::get()->getListByType(List::Type::MUSIC)) { - musics_.emplace_back(MusicResource{.name = getFileName(l), .music = nullptr}); - } - for (const auto& l : List::get()->getListByType(List::Type::BITMAP)) { - surfaces_.emplace_back(SurfaceResource{.name = getFileName(l), .surface = nullptr}); - } - for (const auto& l : List::get()->getListByType(List::Type::PALETTE)) { - palettes_.emplace_back(ResourcePalette{.name = getFileName(l)}); - } - for (const auto& l : List::get()->getListByType(List::Type::FONT)) { - text_files_.emplace_back(TextFileResource{.name = getFileName(l), .text_file = nullptr}); - } - for (const auto& l : List::get()->getListByType(List::Type::ANIMATION)) { - animations_.emplace_back(AnimationResource{.name = getFileName(l), .yaml_data = {}}); - } - for (const auto& l : List::get()->getListByType(List::Type::ROOM)) { - rooms_.emplace_back(RoomResource{.name = getFileName(l), .room = nullptr}); - } + std::ranges::transform(List::get()->getListByType(List::Type::SOUND), std::back_inserter(sounds_), [](const auto& l) { return SoundResource{.name = getFileName(l), .sound = nullptr}; }); + std::ranges::transform(List::get()->getListByType(List::Type::MUSIC), std::back_inserter(musics_), [](const auto& l) { return MusicResource{.name = getFileName(l), .music = nullptr}; }); + std::ranges::transform(List::get()->getListByType(List::Type::BITMAP), std::back_inserter(surfaces_), [](const auto& l) { return SurfaceResource{.name = getFileName(l), .surface = nullptr}; }); + std::ranges::transform(List::get()->getListByType(List::Type::PALETTE), std::back_inserter(palettes_), [](const auto& l) { return ResourcePalette{.name = getFileName(l)}; }); + std::ranges::transform(List::get()->getListByType(List::Type::FONT), std::back_inserter(text_files_), [](const auto& l) { return TextFileResource{.name = getFileName(l), .text_file = nullptr}; }); + std::ranges::transform(List::get()->getListByType(List::Type::ANIMATION), std::back_inserter(animations_), [](const auto& l) { return AnimationResource{.name = getFileName(l), .yaml_data = {}}; }); + std::ranges::transform(List::get()->getListByType(List::Type::ROOM), std::back_inserter(rooms_), [](const auto& l) { return RoomResource{.name = getFileName(l), .room = nullptr}; }); } void Cache::loadSoundByName(const std::string& name) { diff --git a/source/core/resources/resource_pack.cpp b/source/core/resources/resource_pack.cpp index aa510e6..8fb42b9 100644 --- a/source/core/resources/resource_pack.cpp +++ b/source/core/resources/resource_pack.cpp @@ -9,16 +9,13 @@ #include #include #include +#include namespace Resource { // Calculate CRC32 checksum for data verification auto Pack::calculateChecksum(const std::vector& data) -> uint32_t { - uint32_t checksum = 0x12345678; - for (unsigned char byte : data) { - checksum = ((checksum << 5) + checksum) + byte; - } - return checksum; + return std::accumulate(data.begin(), data.end(), static_cast(0x12345678), [](uint32_t acc, unsigned char byte) { return ((acc << 5) + acc) + byte; }); } // XOR encryption (symmetric - same function for encrypt/decrypt) diff --git a/source/external/stb_image_write_impl.cpp b/source/external/stb_image_write_impl.cpp new file mode 100644 index 0000000..9036100 --- /dev/null +++ b/source/external/stb_image_write_impl.cpp @@ -0,0 +1,13 @@ +// Unitat de compilació aïllada per a la implementació de stb_image_write. +// Viu dins de source/external/ perquè el `.clang-tidy` d'aquesta carpeta +// desactiva tots els checks (com fa per stb_vorbis.c) i el pre-commit hook +// ja filtra aquesta ruta de clang-format / clang-tidy. Així els fals +// positius de clang-analyzer-* dins de codi de tercers no afecten el +// nostre codi, que continua tenint tots els checks actius. +// +// La resta del codi inclou només el header (sense la macro d'implementació), +// que queda només amb declaracions — clang-analyzer no pot trobar cap bug +// dins d'una declaració, així que l'inclusió és innòcua. + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "external/stb_image_write.h" diff --git a/source/external/stb_vorbis_impl.cpp b/source/external/stb_vorbis_impl.cpp new file mode 100644 index 0000000..f42c239 --- /dev/null +++ b/source/external/stb_vorbis_impl.cpp @@ -0,0 +1,13 @@ +// Unitat de compilació aïllada per a la implementació de stb_vorbis. +// Viu dins de source/external/ perquè el `.clang-tidy` d'aquesta carpeta +// desactiva tots els checks (com fa per stb_image_write_impl.cpp) i el +// pre-commit hook ja filtra aquesta ruta de clang-format / clang-tidy. +// Així els fals positius de clang-analyzer-* dins de codi C de tercers +// no afecten el nostre codi, que continua tenint tots els checks actius. +// +// jail_audio.hpp defineix STB_VORBIS_HEADER_ONLY abans d'incloure el .c, +// així només en veu les declaracions; les definicions les aporta aquest +// TU i l'enllaçador les resol. + +// NOLINTNEXTLINE(bugprone-suspicious-include) +#include "external/stb_vorbis.c" diff --git a/source/game/editor/map_editor.cpp b/source/game/editor/map_editor.cpp index a88a58f..ebcab76 100644 --- a/source/game/editor/map_editor.cpp +++ b/source/game/editor/map_editor.cpp @@ -2075,11 +2075,10 @@ auto MapEditor::deleteRoom() -> std::string { // NOLINT(readability-function-co if (target == "0") { // Buscar la primera room que no sea esta - for (const auto& r : Resource::Cache::get()->getRooms()) { - if (r.name != deleted_name) { - target = r.name; - break; - } + const auto& ROOMS = Resource::Cache::get()->getRooms(); + auto it = std::ranges::find_if(ROOMS, [&](const auto& r) { return r.name != deleted_name; }); + if (it != ROOMS.end()) { + target = it->name; } } if (target == "0") { return "Cannot delete: no other room to navigate to"; } diff --git a/source/game/gameplay/room_format.cpp b/source/game/gameplay/room_format.cpp index 40d3649..b0da8f4 100644 --- a/source/game/gameplay/room_format.cpp +++ b/source/game/gameplay/room_format.cpp @@ -1,7 +1,9 @@ #include "game/gameplay/room_format.hpp" +#include // Para std::ranges::copy, transform #include // Para exception #include // Para cout, cerr +#include // Para std::back_inserter #include "core/resources/resource_helper.hpp" // Para Resource::Helper #include "external/fkyaml_node.hpp" // Para fkyaml::node @@ -38,9 +40,7 @@ namespace { std::vector row; row.reserve(Map::WIDTH); - for (const auto& tile_node : row_node) { - row.push_back(tile_node.get_value()); - } + std::ranges::transform(row_node, std::back_inserter(row), [](const auto& tile_node) { return tile_node.template get_value(); }); tilemap_2d.push_back(row); } @@ -81,9 +81,7 @@ auto RoomFormat::flattenTilemap(const std::vector>& tilemap_2d) tilemap_flat.reserve(static_cast(Map::WIDTH) * static_cast(Map::HEIGHT)); for (const auto& row : tilemap_2d) { - for (int tile : row) { - tilemap_flat.push_back(tile); - } + std::ranges::copy(row, std::back_inserter(tilemap_flat)); } return tilemap_flat; diff --git a/source/game/gameplay/zone_manager.cpp b/source/game/gameplay/zone_manager.cpp index 4a4c215..b73744c 100644 --- a/source/game/gameplay/zone_manager.cpp +++ b/source/game/gameplay/zone_manager.cpp @@ -1,7 +1,9 @@ #include "game/gameplay/zone_manager.hpp" +#include // Para std::ranges::find_if, transform #include // Para exception #include // Para cerr, cout +#include // Para std::back_inserter #include // Para string #include "core/resources/resource_helper.hpp" // Para Resource::Helper::loadFile @@ -78,12 +80,8 @@ void ZoneManager::loadFromFile(const std::string& file_path) { } auto ZoneManager::getZone(const std::string& name) const -> const Zone::Data* { - for (const auto& zone : zones_) { - if (zone.name == name) { - return &zone; - } - } - return nullptr; + auto it = std::ranges::find_if(zones_, [&](const auto& z) { return z.name == name; }); + return (it != zones_.end()) ? &(*it) : nullptr; } auto ZoneManager::getDefaultZone() const -> const Zone::Data* { @@ -94,8 +92,6 @@ auto ZoneManager::getDefaultZone() const -> const Zone::Data* { auto ZoneManager::getZoneNames() const -> std::vector { std::vector names; names.reserve(zones_.size()); - for (const auto& zone : zones_) { - names.push_back(zone.name); - } + std::ranges::transform(zones_, std::back_inserter(names), [](const auto& z) { return z.name; }); return names; } diff --git a/source/game/scenes/logo.cpp b/source/game/scenes/logo.cpp index f22362f..d1230c7 100644 --- a/source/game/scenes/logo.cpp +++ b/source/game/scenes/logo.cpp @@ -2,8 +2,9 @@ #include -#include // Para std::clamp +#include // Para std::clamp, std::ranges::copy #include // Para std::array +#include // Para std::back_inserter #include // Para generador aleatorio #include "core/audio/audio.hpp" // Para Audio @@ -245,9 +246,7 @@ void Logo::initColors() { 10, 12, 15}; - for (const auto& color : COLORS) { - color_.push_back(color); - } + std::ranges::copy(COLORS, std::back_inserter(color_)); } // Crea los sprites de cada linea diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index f90b1e6..f47d8ba 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -2,8 +2,10 @@ #include -#include // Para ranges::transform +#include // Para ranges::transform, copy_if #include // Para toupper +#include // Para std::back_inserter +#include // Para std::accumulate #include // Para std::istringstream #include // Para string #include // Para vector @@ -209,11 +211,10 @@ void Console::update(float delta_time) { // NOLINT(readability-function-cogniti // Efecto typewriter: revelar letras una a una (solo cuando ACTIVE) if (status_ == Status::ACTIVE) { - int total_chars = 0; - for (const auto& line : msg_lines_) { total_chars += static_cast(line.size()); } - if (typewriter_chars_ < total_chars) { + const int TOTAL_CHARS = std::accumulate(msg_lines_.begin(), msg_lines_.end(), 0, [](int acc, const auto& line) { return acc + static_cast(line.size()); }); + if (typewriter_chars_ < TOTAL_CHARS) { typewriter_timer_ += delta_time; - while (typewriter_timer_ >= TYPEWRITER_CHAR_DELAY && typewriter_chars_ < total_chars) { + while (typewriter_timer_ >= TYPEWRITER_CHAR_DELAY && typewriter_chars_ < TOTAL_CHARS) { typewriter_timer_ -= TYPEWRITER_CHAR_DELAY; ++typewriter_chars_; } @@ -394,11 +395,8 @@ void Console::handleEvent(const SDL_Event& event) { // NOLINT(readability-funct const size_t SPACE_POS = upper.rfind(' '); if (SPACE_POS == std::string::npos) { // Modo comando: ciclar keywords visibles que empiecen por el prefijo - for (const auto& kw : registry_.getVisibleKeywords()) { - if (upper.empty() || kw.starts_with(upper)) { - tab_matches_.emplace_back(kw); - } - } + const auto VISIBLE = registry_.getVisibleKeywords(); + std::ranges::copy_if(VISIBLE, std::back_inserter(tab_matches_), [&](const auto& kw) { return upper.empty() || kw.starts_with(upper); }); } else { const std::string BASE_CMD = upper.substr(0, SPACE_POS); const std::string SUB_PREFIX = upper.substr(SPACE_POS + 1); @@ -417,7 +415,7 @@ void Console::handleEvent(const SDL_Event& event) { // NOLINT(readability-funct if (tab_matches_.empty()) { break; } tab_index_ = (tab_index_ + 1) % static_cast(tab_matches_.size()); std::string result = tab_matches_[static_cast(tab_index_)]; - for (char& c : result) { c = static_cast(std::tolower(static_cast(c))); } + std::ranges::transform(result, result.begin(), [](unsigned char c) { return static_cast(std::tolower(c)); }); input_line_ = result; break; } @@ -463,9 +461,7 @@ void Console::processCommand() { // Typewriter: instantáneo si el comando lo requiere, letra a letra si no if (instant) { - int total = 0; - for (const auto& l : msg_lines_) { total += static_cast(l.size()); } - typewriter_chars_ = total; + typewriter_chars_ = std::accumulate(msg_lines_.begin(), msg_lines_.end(), 0, [](int acc, const auto& l) { return acc + static_cast(l.size()); }); } else { typewriter_chars_ = 0; } diff --git a/source/game/ui/console_commands.cpp b/source/game/ui/console_commands.cpp index 1ee1d8f..a5c550f 100644 --- a/source/game/ui/console_commands.cpp +++ b/source/game/ui/console_commands.cpp @@ -1054,9 +1054,8 @@ void CommandRegistry::registerHandlers() { // NOLINT(readability-function-cogni dynamic_providers_["PALETTE"] = []() -> std::vector { std::vector result = {"NEXT", "PREV", "SORT", "DEFAULT"}; if (Screen::get() != nullptr) { - for (const auto& name : Screen::get()->getPaletteNames()) { - result.push_back(toUpper(name)); - } + const auto NAMES = Screen::get()->getPaletteNames(); + std::ranges::transform(NAMES, std::back_inserter(result), [](const auto& name) { return toUpper(name); }); } return result; }; @@ -1065,10 +1064,11 @@ void CommandRegistry::registerHandlers() { // NOLINT(readability-function-cogni dynamic_providers_["SHADER PRESET"] = []() -> std::vector { std::vector result = {"NEXT", "PREV"}; const bool IS_CRTPI = Options::video.shader.current_shader == Rendering::ShaderType::CRTPI; + auto upper_name = [](const auto& p) { return toUpper(p.name); }; if (IS_CRTPI) { - for (const auto& p : Options::crtpi_presets) { result.push_back(toUpper(p.name)); } + std::ranges::transform(Options::crtpi_presets, std::back_inserter(result), upper_name); } else { - for (const auto& p : Options::postfx_presets) { result.push_back(toUpper(p.name)); } + std::ranges::transform(Options::postfx_presets, std::back_inserter(result), upper_name); } return result; }; @@ -1162,7 +1162,7 @@ void CommandRegistry::load(const std::string& yaml_path) { // NOLINT(readabilit if (cat_node.contains("scope")) { const auto& scope_node = cat_node["scope"]; if (scope_node.is_sequence()) { - for (const auto& s : scope_node) { cat_scopes.push_back(s.get_value()); } + std::ranges::transform(scope_node, std::back_inserter(cat_scopes), [](const auto& s) { return s.template get_value(); }); } else { cat_scopes.push_back(scope_node.get_value()); } @@ -1187,7 +1187,7 @@ void CommandRegistry::load(const std::string& yaml_path) { // NOLINT(readabilit if (cmd_node.contains("scope")) { const auto& scope_node = cmd_node["scope"]; if (scope_node.is_sequence()) { - for (const auto& s : scope_node) { def.scopes.push_back(s.get_value()); } + std::ranges::transform(scope_node, std::back_inserter(def.scopes), [](const auto& s) { return s.template get_value(); }); } else { def.scopes.push_back(scope_node.get_value()); } @@ -1203,9 +1203,8 @@ void CommandRegistry::load(const std::string& yaml_path) { // NOLINT(readabilit for (auto it = completions_node.begin(); it != completions_node.end(); ++it) { auto path = it.key().get_value(); std::vector opts; - for (const auto& opt : *it) { - opts.push_back(opt.get_value()); - } + const auto& options_node = *it; + std::ranges::transform(options_node, std::back_inserter(opts), [](const auto& opt) { return opt.template get_value(); }); def.completions[path] = std::move(opts); } } @@ -1224,9 +1223,8 @@ void CommandRegistry::load(const std::string& yaml_path) { // NOLINT(readabilit for (auto it = extras_completions.begin(); it != extras_completions.end(); ++it) { auto path = it.key().get_value(); std::vector opts; - for (const auto& opt : *it) { - opts.push_back(opt.get_value()); - } + const auto& options_node = *it; + std::ranges::transform(options_node, std::back_inserter(opts), [](const auto& opt) { return opt.template get_value(); }); def.completions[path] = std::move(opts); } } @@ -1285,9 +1283,8 @@ void CommandRegistry::load(const std::string& yaml_path) { // NOLINT(readabilit dynamic_providers_["HELP KEYS"] = []() -> std::vector { std::vector names; if (KeyConfig::get() != nullptr) { - for (const auto& scope : KeyConfig::get()->getScopes()) { - names.push_back(scope.name); - } + const auto& scopes = KeyConfig::get()->getScopes(); + std::ranges::transform(scopes, std::back_inserter(names), [](const auto& sc) { return sc.name; }); } return names; }; @@ -1321,10 +1318,8 @@ auto CommandRegistry::generateKeysHelp(const std::string& scope_filter) -> std:: } auto CommandRegistry::findCommand(const std::string& keyword) const -> const CommandDef* { - for (const auto& cmd : commands_) { - if (cmd.keyword == keyword) { return &cmd; } - } - return nullptr; + auto it = std::ranges::find_if(commands_, [&](const auto& cmd) { return cmd.keyword == keyword; }); + return (it != commands_.end()) ? &(*it) : nullptr; } auto CommandRegistry::execute(const std::string& keyword, const std::vector& args) const -> std::string { diff --git a/source/game/ui/notifier.cpp b/source/game/ui/notifier.cpp index b63cdea..bca4a41 100644 --- a/source/game/ui/notifier.cpp +++ b/source/game/ui/notifier.cpp @@ -24,7 +24,7 @@ Notifier* Notifier::notifier = nullptr; // Parte un texto en varias líneas cuando no cabe en max_width píxeles. // Divide por espacios; si una palabra sola excede el ancho, queda en su propia línea. -static auto wrapToWidth(const std::string& text, int max_width, Text* text_obj, int kerning = 1) -> std::vector { +static auto wrapToWidth(const std::string& text, int max_width, const Text* text_obj, int kerning = 1) -> std::vector { if (max_width <= 0 || text_obj->length(text, kerning) <= max_width) { return {text}; } @@ -45,11 +45,11 @@ static auto wrapToWidth(const std::string& text, int max_width, Text* text_obj, word.clear(); }; - for (const char c : text) { - if (c == ' ') { + for (const char CH : text) { + if (CH == ' ') { flush_word(); } else { - word += c; + word += CH; } } flush_word(); @@ -336,8 +336,8 @@ auto Notifier::getVisibleHeight() const -> int { int bottom = 0; for (const auto& n : notifications_) { if (n.state == Status::FINISHED) { continue; } - int n_bottom = static_cast(n.rect.y + n.rect.h) - y_offset_; - if (n_bottom > bottom) { bottom = n_bottom; } + const int N_BOTTOM = static_cast(n.rect.y + n.rect.h) - y_offset_; + bottom = std::max(N_BOTTOM, bottom); } return bottom; } @@ -346,8 +346,6 @@ auto Notifier::getVisibleHeight() const -> int { auto Notifier::getCodes() -> std::vector { std::vector codes; codes.reserve(notifications_.size()); - for (const auto& notification : notifications_) { - codes.emplace_back(notification.code); - } + std::ranges::transform(notifications_, std::back_inserter(codes), [](const auto& n) { return n.code; }); return codes; } \ No newline at end of file