Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I7b6991f7342362033ad72ab4700fdb9f6a6a6964
118 lines
3 KiB
C
118 lines
3 KiB
C
#include "tileset.h"
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
int tileset_init(Tileset *ts, int tile_w, int tile_h) {
|
|
if (ts == NULL)
|
|
return 0;
|
|
if (tile_w <= 0 || tile_h <= 0)
|
|
return 0;
|
|
|
|
memset(ts, 0, sizeof(Tileset));
|
|
|
|
ts->tile_w = tile_w;
|
|
ts->tile_h = tile_h;
|
|
|
|
// Compute grid dimensions to fit MAX_TILE_ID tiles
|
|
ts->atlas_cols = 4; // 4 columns
|
|
ts->atlas_rows = (MAX_TILE_ID + ts->atlas_cols - 1) / ts->atlas_cols; // round up
|
|
|
|
int atlas_w = ts->atlas_cols * tile_w;
|
|
int atlas_h = ts->atlas_rows * tile_h;
|
|
|
|
// Validate atlas dimensions are reasonable
|
|
if (atlas_w <= 0 || atlas_h <= 0 || atlas_w > 4096 || atlas_h > 4096)
|
|
return 0;
|
|
|
|
ts->render_target = LoadRenderTexture(atlas_w, atlas_h);
|
|
if (!IsRenderTextureValid(ts->render_target))
|
|
return 0;
|
|
|
|
// Clear to transparent so unpainted regions don't show artifacts
|
|
BeginTextureMode(ts->render_target);
|
|
ClearBackground(BLANK);
|
|
EndTextureMode();
|
|
|
|
ts->finalized = 0;
|
|
ts->tile_count = 0;
|
|
return 1;
|
|
}
|
|
|
|
int tileset_register(Tileset *ts, int id) {
|
|
if (ts == NULL)
|
|
return 0;
|
|
if (id < 0 || id >= MAX_TILE_ID)
|
|
return 0;
|
|
if (ts->render_target.id == 0)
|
|
return 0;
|
|
if (ts->finalized)
|
|
return 0;
|
|
if (ts->regions[id].width != 0)
|
|
return 0; // already registered
|
|
|
|
int col = id % ts->atlas_cols;
|
|
int row = id / ts->atlas_cols;
|
|
|
|
ts->regions[id] =
|
|
(Rectangle){(float)(col * ts->tile_w), (float)(row * ts->tile_h), (float)ts->tile_w, (float)ts->tile_h};
|
|
ts->tile_count++;
|
|
return 1;
|
|
}
|
|
|
|
int tileset_finalize(Tileset *ts) {
|
|
if (ts == NULL)
|
|
return 0;
|
|
if (ts->render_target.id == 0)
|
|
return 0;
|
|
if (ts->finalized)
|
|
return 1; // already finalized
|
|
|
|
// Convert RenderTexture to regular Texture2D
|
|
// RenderTexture textures are flipped vertically in raylib, so we need to handle that
|
|
Texture2D old_texture = ts->render_target.texture;
|
|
|
|
// Create a new texture from the render texture data
|
|
Image img = LoadImageFromTexture(old_texture);
|
|
if (img.data == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
// Flip image vertically because RenderTexture is upside-down
|
|
ImageFlipVertical(&img);
|
|
|
|
Texture2D new_tex = LoadTextureFromImage(img);
|
|
UnloadImage(img);
|
|
|
|
if (new_tex.id == 0) {
|
|
return 0;
|
|
}
|
|
|
|
// Unload the old render texture and replace with the new regular texture
|
|
UnloadRenderTexture(ts->render_target);
|
|
ts->render_target.id = 0;
|
|
ts->atlas = new_tex;
|
|
ts->finalized = 1;
|
|
return 1;
|
|
}
|
|
|
|
Rectangle tileset_get_region(const Tileset *ts, int id) {
|
|
if (ts == NULL || id < 0 || id >= MAX_TILE_ID)
|
|
return (Rectangle){0, 0, 0, 0};
|
|
if (!ts->finalized)
|
|
return (Rectangle){0, 0, 0, 0};
|
|
return ts->regions[id];
|
|
}
|
|
|
|
void tileset_destroy(Tileset *ts) {
|
|
if (ts == NULL)
|
|
return;
|
|
if (ts->finalized) {
|
|
if (ts->atlas.id != 0)
|
|
UnloadTexture(ts->atlas);
|
|
} else {
|
|
if (ts->render_target.id != 0)
|
|
UnloadRenderTexture(ts->render_target);
|
|
}
|
|
memset(ts, 0, sizeof(Tileset));
|
|
}
|