#include "core/rendering/texture.hpp" #include #include // Para basic_ostream, operator<<, endl, cout #include // Para runtime_error #include // Para char_traits, operator<<, string, opera... #include // Para vector #include "utils/utils.hpp" // Para getFileName, Color, printWithDots #define STB_IMAGE_IMPLEMENTATION #include "external/stb_image.h" // para stbi_failure_reason, stbi_image_free // Constructor Texture::Texture(SDL_Renderer* renderer, const std::string& path) : renderer_(renderer), path_(path) { // Carga el fichero en la textura if (!path_.empty()) { // Obtiene la extensión const std::string EXTENSION = path_.substr(path_.find_last_of(".") + 1); // .png if (EXTENSION == "png") { loadFromFile(path_); } } } // Destructor Texture::~Texture() { unloadTexture(); palettes_.clear(); } // Carga una imagen desde un fichero bool Texture::loadFromFile(const std::string& file_path) { if (file_path.empty()) { return false; } int req_format = STBI_rgb_alpha; int width; int height; int orig_format; unsigned char* data = stbi_load(file_path.c_str(), &width, &height, &orig_format, req_format); if (data == nullptr) { std::cerr << "Error: Fichero no encontrado " << getFileName(file_path) << std::endl; throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path)); } printWithDots("Image : ", getFileName(file_path), "[ LOADED ]"); int pitch; SDL_PixelFormat pixel_format; // STBI_rgb_alpha (RGBA) pitch = 4 * width; pixel_format = SDL_PIXELFORMAT_RGBA32; // Limpia unloadTexture(); // La textura final SDL_Texture* new_texture = nullptr; // Carga la imagen desde una ruta específica auto* loaded_surface = SDL_CreateSurfaceFrom(width, height, pixel_format, static_cast(data), pitch); if (loaded_surface == nullptr) { std::cout << "Unable to load image " << file_path << std::endl; } else { // Crea la textura desde los pixels de la surface new_texture = SDL_CreateTextureFromSurface(renderer_, loaded_surface); if (new_texture == nullptr) { std::cout << "Unable to create texture from " << file_path << "! SDL Error: " << SDL_GetError() << std::endl; } else { // Obtiene las dimensiones de la imagen width_ = loaded_surface->w; height_ = loaded_surface->h; } // Elimina la textura cargada SDL_DestroySurface(loaded_surface); } // Return success stbi_image_free(data); texture_ = new_texture; return texture_ != nullptr; } // Crea una textura en blanco auto Texture::createBlank(int width, int height, SDL_PixelFormat format, SDL_TextureAccess access) -> bool { // Crea una textura sin inicializar texture_ = SDL_CreateTexture(renderer_, format, access, width, height); if (texture_ == nullptr) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create blank texture! SDL Error: %s", SDL_GetError()); } else { width_ = width; height_ = height; } return texture_ != nullptr; } // Libera la memoria de la textura void Texture::unloadTexture() { // Libera la textura if (texture_ != nullptr) { SDL_DestroyTexture(texture_); texture_ = nullptr; width_ = 0; height_ = 0; } } // Establece el color para la modulacion void Texture::setColor(Uint8 red, Uint8 green, Uint8 blue) { SDL_SetTextureColorMod(texture_, red, green, blue); } void Texture::setColor(Color color) { SDL_SetTextureColorMod(texture_, color.r, color.g, color.b); } // Establece el blending void Texture::setBlendMode(SDL_BlendMode blending) { SDL_SetTextureBlendMode(texture_, blending); } // Establece el alpha para la modulación void Texture::setAlpha(Uint8 alpha) { SDL_SetTextureAlphaMod(texture_, alpha); } // Renderiza la textura en un punto específico void Texture::render(float x, float y, SDL_FRect* clip, float zoom_w, float zoom_h, double angle, SDL_FPoint* center, SDL_FlipMode flip) { // Establece el destino de renderizado en la pantalla SDL_FRect render_quad = {x, y, width_, height_}; // Obtiene las dimesiones del clip de renderizado if (clip != nullptr) { render_quad.w = clip->w; render_quad.h = clip->h; } // Calcula el zoom y las coordenadas if (zoom_h != 1.0F || zoom_w != 1.0F) { render_quad.x = render_quad.x + (render_quad.w / 2); render_quad.y = render_quad.y + (render_quad.h / 2); render_quad.w = render_quad.w * zoom_w; render_quad.h = render_quad.h * zoom_h; render_quad.x = render_quad.x - (render_quad.w / 2); render_quad.y = render_quad.y - (render_quad.h / 2); } // Renderiza a pantalla SDL_RenderTextureRotated(renderer_, texture_, clip, &render_quad, angle, center, flip); } // Establece la textura como objetivo de renderizado void Texture::setAsRenderTarget(SDL_Renderer* renderer) { SDL_SetRenderTarget(renderer, texture_); } // Recarga la textura bool Texture::reLoad() { return loadFromFile(path_); } // Obtiene la textura SDL_Texture* Texture::getSDLTexture() { return texture_; } // Obtiene el renderizador SDL_Renderer* Texture::getRenderer() { return renderer_; }