#include "texture.h" #include // Para SDL_GetError #include // Para SDL_CreateRGBSurfaceWithFormatFrom #include // Para basic_ostream, operator<<, endl, cout #include // Para runtime_error #include // Para char_traits, operator<<, string, opera... #include // Para vector #include "utils.h" // Para getFileName, Color, printWithDots #define STB_IMAGE_IMPLEMENTATION #include "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, height, orig_format; unsigned char* data = stbi_load(file_path.c_str(), &width, &height, &orig_format, req_format); if (!data) { std::cerr << "Error: Fichero no encontrado " << getFileName(file_path) << std::endl; throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path)); } else { printWithDots("Image : ", getFileName(file_path), "[ LOADED ]"); } int depth, pitch; Uint32 pixel_format; // STBI_rgb_alpha (RGBA) depth = 32; pitch = 4 * width; pixel_format = SDL_PIXELFORMAT_RGBA32; // Limpia unloadTexture(); // La textura final SDL_Texture* newTexture = nullptr; // Carga la imagen desde una ruta específica auto loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom(static_cast(data), width, height, depth, pitch, pixel_format); if (loadedSurface == nullptr) { std::cout << "Unable to load image " << file_path << std::endl; } else { // Crea la textura desde los pixels de la surface newTexture = SDL_CreateTextureFromSurface(renderer_, loadedSurface); if (newTexture == nullptr) { std::cout << "Unable to create texture from " << file_path << "! SDL Error: " << SDL_GetError() << std::endl; } else { // Obtiene las dimensiones de la imagen width_ = loadedSurface->w; height_ = loadedSurface->h; } // Elimina la textura cargada SDL_FreeSurface(loadedSurface); } // Return success stbi_image_free(data); texture_ = newTexture; return texture_ != nullptr; } // Crea una textura en blanco bool Texture::createBlank(int width, int height, SDL_PixelFormatEnum format, SDL_TextureAccess access) { // Crea una textura sin inicializar texture_ = SDL_CreateTexture(renderer_, format, access, width, height); if (!texture_) { std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl; } else { width_ = width; height_ = height; } return texture_ != nullptr; } // Libera la memoria de la textura void Texture::unloadTexture() { // Libera la textura if (texture_) { 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(int x, int y, SDL_Rect* clip, float zoomW, float zoomH, double angle, SDL_Point* center, SDL_RendererFlip flip) { // Establece el destino de renderizado en la pantalla SDL_Rect renderQuad = {x, y, width_, height_}; // Obtiene las dimesiones del clip de renderizado if (clip != nullptr) { renderQuad.w = clip->w; renderQuad.h = clip->h; } // Calcula el zoom y las coordenadas if (zoomH != 1.0f || zoomW != 1.0f) { renderQuad.x = renderQuad.x + (renderQuad.w / 2); renderQuad.y = renderQuad.y + (renderQuad.h / 2); renderQuad.w = renderQuad.w * zoomW; renderQuad.h = renderQuad.h * zoomH; renderQuad.x = renderQuad.x - (renderQuad.w / 2); renderQuad.y = renderQuad.y - (renderQuad.h / 2); } // Renderiza a pantalla SDL_RenderCopyEx(renderer_, texture_, clip, &renderQuad, angle, center, flip); } // Establece la textura como objetivo de renderizado void Texture::setAsRenderTarget(SDL_Renderer* renderer) { SDL_SetRenderTarget(renderer, texture_); } // Obtiene el ancho de la imagen int Texture::getWidth() { return width_; } // Obtiene el alto de la imagen int Texture::getHeight() { return height_; } // 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_; }