Files
vibe3_physics/source/logo_scaler.cpp
Sergio Valor a9d7b66e83 Refactorizar estilo del proyecto: .h → .hpp, #pragma once, includes desde raíz
Modernizar convenciones de código C++ aplicando las siguientes directivas:

## Cambios principales

**1. Renombrar headers (.h → .hpp)**
- 36 archivos renombrados a extensión .hpp (estándar C++)
- Mantenidos como .h: stb_image.h, stb_image_resize2.h (librerías C externas)

**2. Modernizar include guards (#ifndef → #pragma once)**
- resource_manager.hpp: #ifndef RESOURCE_MANAGER_H → #pragma once
- resource_pack.hpp: #ifndef RESOURCE_PACK_H → #pragma once
- spatial_grid.hpp: #ifndef SPATIAL_GRID_H → #pragma once

**3. Sistema de includes desde raíz del proyecto**
- CMakeLists.txt: añadido include_directories(${CMAKE_SOURCE_DIR}/source)
- Eliminadas rutas relativas (../) en todos los includes
- Includes ahora usan rutas absolutas desde source/

**Antes:**
```cpp
#include "../defines.h"
#include "../text/textrenderer.h"
```

**Ahora:**
```cpp
#include "defines.hpp"
#include "text/textrenderer.hpp"
```

## Archivos afectados

- 1 archivo CMakeLists.txt modificado
- 36 archivos renombrados (.h → .hpp)
- 32 archivos .cpp actualizados (includes)
- 36 archivos .hpp actualizados (includes + guards)
- 1 archivo tools/ actualizado

**Total: 70 archivos modificados**

## Verificación

 Proyecto compila sin errores
 Todas las rutas de includes correctas
 Include guards modernizados
 Librerías externas C mantienen extensión .h

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 13:49:58 +02:00

158 lines
5.9 KiB
C++

#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "logo_scaler.hpp"
#include <SDL3/SDL_error.h> // Para SDL_GetError
#include <SDL3/SDL_log.h> // Para SDL_Log
#include <SDL3/SDL_pixels.h> // Para SDL_PixelFormat
#include <SDL3/SDL_render.h> // Para SDL_CreateTexture
#include <SDL3/SDL_surface.h> // Para SDL_CreateSurfaceFrom
#include <SDL3/SDL_video.h> // Para SDL_GetDisplays
#include <cstdlib> // Para free()
#include <iostream> // Para std::cout
#include "external/stb_image.h" // Para stbi_load, stbi_image_free
#include "external/stb_image_resize2.h" // Para stbir_resize_uint8_srgb
#include "resource_manager.hpp" // Para cargar desde pack
// ============================================================================
// Detectar resolución nativa del monitor principal
// ============================================================================
bool LogoScaler::detectNativeResolution(int& native_width, int& native_height) {
int num_displays = 0;
SDL_DisplayID* displays = SDL_GetDisplays(&num_displays);
if (displays == nullptr || num_displays == 0) {
SDL_Log("Error al obtener displays: %s", SDL_GetError());
return false;
}
// Obtener resolución del display principal (displays[0])
const auto* dm = SDL_GetCurrentDisplayMode(displays[0]);
if (dm == nullptr) {
SDL_Log("Error al obtener modo del display: %s", SDL_GetError());
SDL_free(displays);
return false;
}
native_width = dm->w;
native_height = dm->h;
SDL_free(displays);
std::cout << "Resolución nativa detectada: " << native_width << "x" << native_height << std::endl;
return true;
}
// ============================================================================
// Cargar PNG y escalar al tamaño especificado
// ============================================================================
unsigned char* LogoScaler::loadAndScale(const std::string& path,
int target_width, int target_height,
int& out_width, int& out_height) {
// 1. Intentar cargar imagen desde ResourceManager (pack o disco)
int orig_width, orig_height, orig_channels;
unsigned char* orig_data = nullptr;
// 1a. Cargar desde ResourceManager
unsigned char* resourceData = nullptr;
size_t resourceSize = 0;
if (ResourceManager::loadResource(path, resourceData, resourceSize)) {
// Descodificar imagen desde memoria usando stb_image
orig_data = stbi_load_from_memory(resourceData, static_cast<int>(resourceSize),
&orig_width, &orig_height, &orig_channels, STBI_rgb_alpha);
delete[] resourceData; // Liberar buffer temporal
}
// 1b. Si falla todo, error
if (orig_data == nullptr) {
SDL_Log("Error al cargar imagen %s: %s", path.c_str(), stbi_failure_reason());
return nullptr;
}
std::cout << "Imagen cargada: " << path << " (" << orig_width << "x" << orig_height << ")" << std::endl;
// 2. Calcular tamaño final manteniendo aspect ratio
// El alto está fijado por target_height (APPLOGO_HEIGHT_PERCENT)
// Calcular ancho proporcional al aspect ratio original
float aspect_ratio = static_cast<float>(orig_width) / static_cast<float>(orig_height);
out_width = static_cast<int>(target_height * aspect_ratio);
out_height = target_height;
std::cout << " Escalando a: " << out_width << "x" << out_height << std::endl;
// 3. Alocar buffer para imagen escalada (RGBA = 4 bytes por píxel)
unsigned char* scaled_data = static_cast<unsigned char*>(malloc(out_width * out_height * 4));
if (scaled_data == nullptr) {
SDL_Log("Error al alocar memoria para imagen escalada");
stbi_image_free(orig_data);
return nullptr;
}
// 4. Escalar con stb_image_resize2 (algoritmo Mitchell, espacio sRGB)
// La función devuelve el puntero de salida, o nullptr si falla
unsigned char* result = stbir_resize_uint8_srgb(
orig_data, orig_width, orig_height, 0, // Input
scaled_data, out_width, out_height, 0, // Output
STBIR_RGBA // Formato píxel
);
// Liberar imagen original (ya no la necesitamos)
stbi_image_free(orig_data);
if (result == nullptr) {
SDL_Log("Error al escalar imagen");
free(scaled_data);
return nullptr;
}
std::cout << " Escalado completado correctamente" << std::endl;
return scaled_data;
}
// ============================================================================
// Crear textura SDL desde buffer RGBA
// ============================================================================
SDL_Texture* LogoScaler::createTextureFromBuffer(SDL_Renderer* renderer,
unsigned char* data,
int width, int height) {
if (renderer == nullptr || data == nullptr || width <= 0 || height <= 0) {
SDL_Log("Parámetros inválidos para createTextureFromBuffer");
return nullptr;
}
// 1. Crear surface SDL desde buffer RGBA
int pitch = width * 4; // 4 bytes por píxel (RGBA)
SDL_PixelFormat pixel_format = SDL_PIXELFORMAT_RGBA32;
SDL_Surface* surface = SDL_CreateSurfaceFrom(
width, height,
pixel_format,
data,
pitch
);
if (surface == nullptr) {
SDL_Log("Error al crear surface: %s", SDL_GetError());
return nullptr;
}
// 2. Crear textura desde surface
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
if (texture == nullptr) {
SDL_Log("Error al crear textura: %s", SDL_GetError());
SDL_DestroySurface(surface);
return nullptr;
}
// 3. Liberar surface (la textura ya tiene los datos)
SDL_DestroySurface(surface);
return texture;
}