204 lines
6.1 KiB
C++
204 lines
6.1 KiB
C++
#include "draw.h"
|
|
#include <SDL3/SDL.h>
|
|
#include "gif.h"
|
|
#include "file.h"
|
|
|
|
namespace draw
|
|
{
|
|
SDL_Window *sdl_window {nullptr}; // La finestra de SDL
|
|
SDL_Renderer *sdl_renderer {nullptr}; // El renderer de SDL
|
|
SDL_Texture *sdl_texture {nullptr}; // La textura a la que ho renderitze tot
|
|
SDL_Texture *sdl_source {nullptr};
|
|
|
|
void init(const char *titol, const uint16_t width, const uint16_t height)
|
|
{
|
|
sdl_window = SDL_CreateWindow(titol, width, height, SDL_WINDOW_RESIZABLE);
|
|
if (!sdl_window) {
|
|
SDL_LogCritical(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize window!\n");
|
|
exit(1);
|
|
}
|
|
|
|
sdl_renderer = SDL_CreateRenderer(sdl_window, NULL);
|
|
if (!sdl_renderer) {
|
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize renderer!\n");
|
|
exit(1);
|
|
}
|
|
|
|
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, width, height);
|
|
//SDL_SetRenderDrawBlendMode(sdl_renderer, SDL_BLENDMODE_BLEND);
|
|
}
|
|
|
|
void resizeSystemTexture(const uint16_t width, const uint16_t height)
|
|
{
|
|
SDL_DestroyTexture(sdl_texture);
|
|
sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, width, height);
|
|
}
|
|
|
|
void quit()
|
|
{
|
|
SDL_DestroyRenderer(sdl_renderer);
|
|
SDL_DestroyWindow(sdl_window);
|
|
|
|
sdl_window = nullptr;
|
|
sdl_renderer = nullptr;
|
|
}
|
|
|
|
SDL_Texture *createSurface(const uint16_t w, const uint16_t h)
|
|
{
|
|
return SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w, h);
|
|
}
|
|
|
|
SDL_Texture *loadSurface(const char *filename, const int transparent)
|
|
{
|
|
int size;
|
|
uint8_t *buffer = (uint8_t *)file::getFileBuffer(filename, size);
|
|
if (buffer == nullptr) return nullptr;
|
|
|
|
uint16_t w, h;
|
|
uint8_t *pixels = LoadGif(buffer, &w, &h);
|
|
|
|
int paletteSize;
|
|
uint32_t *pal = LoadPalette(buffer, &paletteSize);
|
|
|
|
SDL_Texture *surf = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h);
|
|
SDL_SetTextureBlendMode(surf, SDL_BLENDMODE_BLEND);
|
|
|
|
Uint32 *sdl_pixels;
|
|
int sdl_pitch;
|
|
|
|
SDL_LockTexture(surf, NULL, (void **)&sdl_pixels, &sdl_pitch);
|
|
int i=0;
|
|
for (int y=0; y<h; ++y) {
|
|
for (int x=0; x<w; ++x) {
|
|
sdl_pixels[x+y*(sdl_pitch/4)] = transparent==pixels[i] ? 0x00000000 : pal[pixels[i]] | 0xff000000;
|
|
i++;
|
|
}
|
|
}
|
|
//for (uint32_t i = 0; i < w*h; ++i) sdl_pixels[i] = transparent==pixels[i] ? 0x00000000 : pal[pixels[i]] | 0xff000000;
|
|
SDL_UnlockTexture(surf);
|
|
|
|
free(pal);
|
|
free(pixels);
|
|
free(buffer);
|
|
|
|
return surf;
|
|
}
|
|
|
|
void freeSurface(SDL_Texture *surf)
|
|
{
|
|
SDL_DestroyTexture(surf);
|
|
}
|
|
|
|
void setDestination(SDL_Texture *surf)
|
|
{
|
|
SDL_SetRenderTarget(sdl_renderer, surf ? surf : sdl_texture);
|
|
}
|
|
|
|
void setSource(SDL_Texture *surf)
|
|
{
|
|
sdl_source = surf;
|
|
}
|
|
|
|
|
|
void setClip(const int x, const int y, const int w, const int h)
|
|
{
|
|
SDL_Rect rect {x, y, w, h};
|
|
SDL_SetRenderClipRect(sdl_renderer, &rect);
|
|
}
|
|
|
|
void resetClip()
|
|
{
|
|
SDL_SetRenderClipRect(sdl_renderer, nullptr);
|
|
}
|
|
|
|
SDL_Point getWindowSize()
|
|
{
|
|
SDL_Point p;
|
|
SDL_GetWindowSize(sdl_window, &p.x, &p.y);
|
|
return p;
|
|
}
|
|
|
|
void setColor(const uint32_t col)
|
|
{
|
|
SDL_SetRenderDrawColor(sdl_renderer, (col>>16)&0xff, (col>>8)&0xff, (col)&0xff, (col>>24)&0xff);
|
|
}
|
|
|
|
void cls(const uint32_t color)
|
|
{
|
|
setColor(color);
|
|
SDL_RenderClear(sdl_renderer);
|
|
}
|
|
|
|
void line(const int x1, const int y1, const int x2, const int y2)
|
|
{
|
|
SDL_RenderLine(sdl_renderer, x1, y1, x2, y2);
|
|
}
|
|
|
|
void fillrect(const int x, const int y, const int w, const int h)
|
|
{
|
|
SDL_FRect rect {float(x), float(y), float(w),float(h)};
|
|
SDL_RenderFillRect(sdl_renderer, &rect);
|
|
}
|
|
|
|
void rect(const int x, const int y, const int w, const int h)
|
|
{
|
|
SDL_FRect rect {float(x), float(y), float(w),float(h)};
|
|
SDL_RenderRect(sdl_renderer, &rect);
|
|
}
|
|
|
|
void draw(const SDL_Rect source, const SDL_Rect dest, const SDL_FlipMode flip)
|
|
{
|
|
if (!sdl_source) return;
|
|
SDL_FRect src {float(source.x), float(source.y), float(source.w),float(source.h)};
|
|
SDL_FRect dst {float(dest.x), float(dest.y), float(dest.w),float(dest.h)};
|
|
SDL_RenderTextureRotated(sdl_renderer, sdl_source, &src, &dst, 0.0, nullptr, flip);
|
|
}
|
|
|
|
/*
|
|
void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const int zoom)
|
|
{
|
|
// Si no hi ha superficie d'oritge especificada, no fem res, o petarà el mame
|
|
if (source == nullptr) return;
|
|
|
|
for (int y=0; y<h; ++y) {
|
|
for (int x=0; x<w; ++x) {
|
|
const uint8_t pixel = pget(source, sx+x, sy+y);
|
|
for (int zx=0; zx<zoom; ++zx)
|
|
for (int zy=0; zy<zoom; ++zy) {
|
|
pset(destination, dx+zx+x*zoom, dy+zy+y*zoom, pixel);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Pinta tota la superficie "source" en la superficie "destination", posició (x,y).
|
|
void draw(const int x, const int y)
|
|
{
|
|
draw(x, y, source->w, source->h, 0, 0);
|
|
}
|
|
|
|
// Pinta tota la superficie "source" en la superficie "destination", posició (0,0)
|
|
void draw()
|
|
{
|
|
draw(0,0,source->w, source->h, 0, 0);
|
|
}
|
|
|
|
// Carrega la superficie especificada en "source" i la pinta tota en la superficie "destination", posició (0,0).
|
|
void draw(SDL_Texture* surf)
|
|
{
|
|
setSource(surf);
|
|
draw();
|
|
}
|
|
*/
|
|
|
|
// Refresca la pantalla
|
|
void render()
|
|
{
|
|
SDL_SetRenderTarget(sdl_renderer, nullptr);
|
|
SDL_RenderTexture(sdl_renderer, sdl_texture, nullptr, nullptr);
|
|
SDL_RenderPresent(sdl_renderer);
|
|
SDL_SetRenderTarget(sdl_renderer, sdl_texture);
|
|
}
|
|
|
|
}
|