#pragma once #include #include // Para array #include // Para default_delete, shared_ptr, __shared_pt... #include // Para iota #include // Para string #include // Para move #include "utils/utils.hpp" // Para PaletteColor // Alias using Palette = std::array; using SubPalette = std::array; // Carga una paleta desde un archivo .gif auto loadPalette(const std::string& file_path) -> Palette; // Carga una paleta desde un archivo .pal auto readPalFile(const std::string& file_path) -> Palette; struct SurfaceData { std::shared_ptr data; // Usa std::shared_ptr para gestión automática float width; // Ancho de la imagen float height; // Alto de la imagen // Constructor por defecto SurfaceData() : data(nullptr), width(0), height(0) {} // Constructor que inicializa dimensiones y asigna memoria SurfaceData(float w, float h) : data(std::shared_ptr(new Uint8[static_cast(w * h)](), std::default_delete())), width(w), height(h) {} // Constructor para inicializar directamente con datos SurfaceData(float w, float h, std::shared_ptr pixels) : data(std::move(pixels)), width(w), height(h) {} // Constructor de movimiento SurfaceData(SurfaceData&& other) noexcept = default; // Operador de movimiento auto operator=(SurfaceData&& other) noexcept -> SurfaceData& = default; // Evita copias accidentales SurfaceData(const SurfaceData&) = delete; auto operator=(const SurfaceData&) -> SurfaceData& = delete; }; class Surface { private: std::shared_ptr surface_data_; // Datos a dibujar Palette palette_; // Paleta para volcar la SurfaceData a una Textura SubPalette sub_palette_; // Paleta para reindexar colores int transparent_color_; // Indice de la paleta que se omite en la copia de datos public: // Constructor Surface(int w, int h); explicit Surface(const std::string& file_path); // Destructor ~Surface() = default; // Carga una SurfaceData desde un archivo static auto loadSurface(const std::string& file_path) -> SurfaceData; // Carga una paleta desde un archivo void loadPalette(const std::string& file_path); void loadPalette(Palette palette); // Copia una región de la SurfaceData de origen a la SurfaceData de destino void render(float dx, float dy, float sx, float sy, float w, float h); void render(int x, int y, SDL_FRect* src_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); void render(SDL_FRect* src_rect = nullptr, SDL_FRect* dst_rect = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); // Copia una región de la SurfaceData de origen a la SurfaceData de destino reemplazando un color por otro 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); // Establece un color en la paleta void setColor(int index, Uint32 color); // Rellena la SurfaceData con un color void clear(Uint8 color); // Vuelca la SurfaceData a una textura void copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture); void copyToTexture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_FRect* src_rect, SDL_FRect* dest_rect); // Realiza un efecto de fundido en las paletas auto fadePalette() -> bool; auto fadeSubPalette(Uint32 delay = 0) -> bool; // Pone un pixel en la SurfaceData void putPixel(int x, int y, Uint8 color); // Obtiene el color de un pixel de la surface_data auto getPixel(int x, int y) -> Uint8; // Dibuja un rectangulo relleno void fillRect(const SDL_FRect* rect, Uint8 color); // Dibuja el borde de un rectangulo void drawRectBorder(const SDL_FRect* rect, Uint8 color); // Dibuja una linea void drawLine(float x1, float y1, float x2, float y2, Uint8 color); // Metodos para gestionar surface_data_ [[nodiscard]] auto getSurfaceData() const -> std::shared_ptr { return surface_data_; } void setSurfaceData(std::shared_ptr new_data) { surface_data_ = std::move(new_data); } // Obtien ancho y alto [[nodiscard]] auto getWidth() const -> float { return surface_data_->width; } [[nodiscard]] auto getHeight() const -> float { return surface_data_->height; } // Color transparente [[nodiscard]] auto getTransparentColor() const -> Uint8 { return transparent_color_; } void setTransparentColor(Uint8 color = 255) { transparent_color_ = color; } // Paleta void setPalette(const std::array& palette) { palette_ = palette; } // Inicializa la sub paleta static void initializeSubPalette(SubPalette& palette) { std::iota(palette.begin(), palette.end(), 0); } private: // Helper para calcular coordenadas con flip static void calculateFlippedCoords(int ix, int iy, float sx, float sy, float w, float h, SDL_FlipMode flip, int& src_x, int& src_y); // Helper para copiar un pixel si no es transparente void copyPixelIfNotTransparent(Uint8* dest_data, int dest_x, int dest_y, int dest_width, int src_x, int src_y) const; };