Files
dilemmaker/source/draw.cpp
2025-10-24 14:22:11 +02:00

178 lines
4.6 KiB
C++

#include "draw.h"
#include <vector>
#include "gif.h"
#include <algorithm>
namespace draw
{
SDL_Window *win = nullptr;
SDL_Renderer *ren = nullptr;
SDL_Texture *tex = nullptr;
SDL_Texture *source = nullptr;
SDL_Texture *dest = nullptr;
std::vector<texture_t> textures;
uint32_t palette[16];
void init()
{
SDL_Init(SDL_INIT_VIDEO);
win = SDL_CreateWindow("DILEMMAKER v0.1", 1280, 960, 0);
ren = SDL_CreateRenderer(win, NULL);
tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 256, 192);
SDL_SetTextureScaleMode(tex, SDL_SCALEMODE_NEAREST);
}
void fillRect(int x, int y, int w, int h, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
SDL_SetRenderDrawColor(ren, r, g, b, a);
SDL_FRect rect {float(x), float(y), float(w), float(h)};
SDL_RenderFillRect(ren, &rect);
}
void setSource(SDL_Texture *texture)
{
source = texture;
}
void setDest(SDL_Texture *texture)
{
dest = texture;
SDL_SetRenderTarget(ren, dest);
}
void regenerateTexture(texture_t &texture)
{
if (texture.target) return;
uint32_t *argb;
int pitch;
SDL_LockTexture(texture.texture, NULL, (void**)&argb, &pitch);
for (int i=0; i<texture.w*texture.h; ++i) argb[i] = palette[texture.pixels[i]];
SDL_UnlockTexture(texture.texture);
}
int loadPalette(const char *filename)
{
FILE *fp = fopen(filename, "r");
if (!fp) return -1;
char header[32];
int version, count;
// Read and validate header
if (!fgets(header, sizeof(header), fp) || strncmp(header, "JASC-PAL", 8) != 0) {
fclose(fp);
return -2;
}
if (fscanf(fp, "%d\n%d\n", &version, &count) != 2 || count != 16) {
fclose(fp);
return -3;
}
for (int i = 0; i < 16; ++i) {
int r, g, b;
if (fscanf(fp, "%d %d %d\n", &b, &g, &r) != 3) {
fclose(fp);
return -4;
}
palette[i] = (0xFF << 24) | (r << 16) | (g << 8) | b;
}
fclose(fp);
regenerateTextures();
return 0; // Success
}
void regenerateTextures()
{
for (auto &tex : textures)
{
regenerateTexture(tex);
}
}
texture_t getTexture(const char *filename)
{
std::string name = filename;
for (auto tex : textures) if (tex.name == name) return tex;
FILE *f = fopen(filename, "rb");
fseek(f, 0, SEEK_END);
int file_size = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t *buffer = (uint8_t*)malloc(file_size);
fread(buffer, file_size, 1, f);
fclose(f);
uint16_t w, h;
uint8_t *pixels = gif::Load(buffer, &w, &h);
free(buffer);
SDL_Texture * tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h);
SDL_SetTextureScaleMode(tex, SDL_SCALEMODE_NEAREST);
texture_t t;
t.name = filename;
t.texture = tex;
t.pixels = pixels;
t.w = w;
t.h = h;
regenerateTexture(t);
textures.push_back(t);
return t;
}
texture_t createTexture(const char* name, int w, int h, SDL_TextureAccess access)
{
SDL_Texture * tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, access, w, h);
SDL_SetTextureScaleMode(tex, SDL_SCALEMODE_NEAREST);
texture_t t;
t.name = name;
t.texture = tex;
if (access == SDL_TEXTUREACCESS_TARGET) {
t.target = true;
} else {
t.pixels = (uint8_t*)malloc(w*h);
for (int i=0; i<w*h; ++i) t.pixels[i] = 0x00000000;
}
t.w = w;
t.h = h;
regenerateTexture(t);
textures.push_back(t);
return t;
}
void deleteTexture(const char *name)
{
for (auto it = textures.begin(); it != textures.end(); ++it) {
if ((*it).name == name)
{
SDL_DestroyTexture((*it).texture);
free((*it).pixels);
textures.erase(it);
return;
}
}
}
void draw(int dx, int dy, int dw, int dh, int sx, int sy, int sw, int sh)
{
SDL_FRect src {float(sx), float(sy), float(sw), float(sh)};
SDL_FRect dst {float(dx), float(dy), float(dw), float(dh)};
SDL_RenderTexture(ren, source, &src, &dst);
}
void present()
{
SDL_RenderPresent(ren);
}
}