Files
jaildoctors_dilemma/source/surface.h

148 lines
4.8 KiB
C++

#pragma once
#include <SDL2/SDL_render.h> // Para SDL_Renderer
#include <SDL2/SDL_stdinc.h> // Para Uint8, Uint32
#include <array>
#include <numeric>
#include <memory>
#include <string>
// Alias
using Palette = std::array<Uint32, 256>;
using SubPalette = std::array<Uint8, 256>;
// Carga una paleta desde un archivo .gif
Palette loadPalette(const std::string &file_path);
// Carga una paleta desde un archivo .pal
Palette readPalFile(const std::string &file_path);
struct SurfaceData
{
Uint8 *data; // Listado de indices de la paleta que conforman la imagen almacenada
Uint16 width; // Ancho de la imagen
Uint16 height; // Alto de la imagen
// Constructor por defecto
SurfaceData() : data(nullptr), width(0), height(0) {}
// Constructor que inicializa dimensiones y asigna memoria
SurfaceData(Uint16 w, Uint16 h)
: data(new Uint8[w * h]()), width(w), height(h) {}
// Constructor para inicializar directamente con datos
SurfaceData(Uint16 w, Uint16 h, Uint8 *pixels)
: data(pixels), width(w), height(h) {}
// Destructor para liberar memoria
~SurfaceData() { delete[] data; }
// Evita copias accidentales (opcional para mayor seguridad)
SurfaceData(const SurfaceData &) = delete;
SurfaceData &operator=(const SurfaceData &) = delete;
// Permite movimiento para evitar copias costosas
SurfaceData(SurfaceData &&other) noexcept
: data(other.data), width(other.width), height(other.height)
{
other.data = nullptr;
other.width = 0;
other.height = 0;
}
SurfaceData &operator=(SurfaceData &&other) noexcept
{
if (this != &other)
{
delete[] data;
data = other.data;
width = other.width;
height = other.height;
other.data = nullptr;
other.width = 0;
other.height = 0;
}
return *this;
}
};
class Surface
{
private:
std::shared_ptr<SurfaceData> 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);
Surface(const std::string &file_path);
// Destructor
~Surface() = default;
// Carga una SurfaceData desde un archivo
SurfaceData loadSurface(const std::string &file_path);
// 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(int dx, int dy, int sx, int sy, int w, int h);
void render(int x, int y, SDL_Rect *clip = nullptr, SDL_RendererFlip flip = SDL_FLIP_NONE);
void render(SDL_Rect *srcRect = nullptr, SDL_Rect *dstRect = nullptr, SDL_RendererFlip 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_Rect *srcRect = nullptr, SDL_RendererFlip 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);
// Realiza un efecto de fundido en las paletas
bool fadePalette();
bool fadeSubPalette();
// Pone un pixel en la SurfaceData
void putPixel(int x, int y, Uint8 color);
// Obtiene el color de un pixel de la surface_data
Uint8 getPixel(int x, int y);
// Dibuja un rectangulo relleno
void fillRect(SDL_Rect *rect, Uint8 color);
// Dibuja el borde de un rectangulo
void drawRectBorder(SDL_Rect *rect, Uint8 color);
// Dibuja una linea
void drawLine(int x1, int y1, int x2, int y2, Uint8 color);
// Metodos para gestionar surface_data_
std::shared_ptr<SurfaceData> getSurfaceData() const { return surface_data_; }
void setSurfaceData(std::shared_ptr<SurfaceData> new_data) { surface_data_ = new_data; }
// Obtien ancho y alto
int getWidth() const { return surface_data_->width; }
int getHeight() const { return surface_data_->height; }
// Color transparente
Uint8 getTransparentColor() const { return transparent_color_; }
void setTransparentColor(Uint8 color) { transparent_color_ = color; }
// Paleta
void setPalette(const std::array<Uint32, 256> &palette) { palette_ = palette; }
// Inicializa la sub paleta
void initializeSubPalette(SubPalette &palette) { std::iota(palette.begin(), palette.end(), 0); }
};