Merge branch 'main' of https://git.poto.cafe/wanp/townengine
This commit is contained in:
commit
d34516c4ee
@ -20,9 +20,9 @@ static void title_tick(State *state) {
|
||||
((float)ctx.resolution.x / 2) - ((float)320 / 2), 64, 320, 128 }));
|
||||
|
||||
/* draw the tick count as an example of dynamic text */
|
||||
size_t text_str_len = snprintf(NULL, 0, "%lu", state->ctx->frame_number) + 1;
|
||||
size_t text_str_len = snprintf(NULL, 0, "%llu", state->ctx->frame_number) + 1;
|
||||
char *text_str = cmalloc(text_str_len);
|
||||
snprintf(text_str, text_str_len, "%lu", state->ctx->frame_number);
|
||||
snprintf(text_str, text_str_len, "%llu", state->ctx->frame_number);
|
||||
|
||||
const char *font = "/fonts/kenney-pixel.ttf";
|
||||
int text_h = 32;
|
||||
@ -39,7 +39,6 @@ static void title_tick(State *state) {
|
||||
);
|
||||
|
||||
draw_text(text_str, (Vec2){ 0, 0 }, text_h, (Color) { 255, 255, 255, 255 }, font);
|
||||
|
||||
free(text_str);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ TWN_API void draw_sprite(char const *path,
|
||||
TWN_API void draw_rectangle(Rect rect, Color color);
|
||||
|
||||
/* pushes a filled circle onto the circle render queue */
|
||||
/* note that its edges may look jagged with a radius larger than 2048 */
|
||||
TWN_API void draw_circle(Vec2 position, float radius, Color color);
|
||||
|
||||
/* TODO: have font optional, with something minimal coming embedded */
|
||||
|
@ -22,18 +22,14 @@ void draw_circle(Vec2 position, float radius, Color color) {
|
||||
arrput(ctx.render_queue_2d, primitive);
|
||||
}
|
||||
|
||||
/* TODO: caching and reuse scheme */
|
||||
/* vertices_out and indices_out MUST BE FREED */
|
||||
|
||||
void create_circle_geometry(Vec2 position,
|
||||
Color color,
|
||||
float radius,
|
||||
size_t num_vertices,
|
||||
SDL_Vertex **vertices_out,
|
||||
int **indices_out)
|
||||
SDL_Vertex vertices[],
|
||||
int indices[])
|
||||
{
|
||||
SDL_Vertex *vertices = cmalloc(sizeof *vertices * (num_vertices + 1));
|
||||
int *indices = cmalloc(sizeof *indices * (num_vertices * 3));
|
||||
|
||||
/* the angle (in radians) to rotate by on each iteration */
|
||||
float seg_rotation_angle = (360.0f / (float)num_vertices) * ((float)M_PI / 180);
|
||||
|
||||
@ -82,7 +78,4 @@ void create_circle_geometry(Vec2 position,
|
||||
index = num_vertices;
|
||||
indices[triangle_offset + 2] = (int)index;
|
||||
}
|
||||
|
||||
*vertices_out = vertices;
|
||||
*indices_out = indices;
|
||||
}
|
||||
|
@ -126,12 +126,14 @@ void render(void);
|
||||
/* clears all render queues */
|
||||
void render_queue_clear(void);
|
||||
|
||||
/* fills two existing arrays with the geometry data of a circle */
|
||||
/* the size of indices must be at least 3 times the number of vertices */
|
||||
void create_circle_geometry(Vec2 position,
|
||||
Color color,
|
||||
float radius,
|
||||
size_t num_vertices,
|
||||
SDL_Vertex **vertices_out,
|
||||
int **indices_out);
|
||||
SDL_Vertex vertices[],
|
||||
int indices[]);
|
||||
|
||||
struct QuadBatch {
|
||||
size_t size; /* how many primitives are in current batch */
|
||||
|
@ -87,6 +87,9 @@ typedef enum {
|
||||
static Pipeline pipeline_last_used = PIPELINE_NO;
|
||||
|
||||
|
||||
#define CIRCLE_VERTICES_MAX 2048
|
||||
|
||||
|
||||
void use_space_pipeline(void) {
|
||||
if (pipeline_last_used == PIPELINE_SPACE)
|
||||
return;
|
||||
@ -166,16 +169,16 @@ void use_2d_pipeline(void) {
|
||||
|
||||
|
||||
void render_circle(const CirclePrimitive *circle) {
|
||||
SDL_Vertex *vertices = NULL;
|
||||
int *indices = NULL;
|
||||
int num_vertices = (int)circle->radius;
|
||||
static SDL_Vertex vertices[CIRCLE_VERTICES_MAX];
|
||||
static int indices[CIRCLE_VERTICES_MAX * 3];
|
||||
int num_vertices = MIN((int)circle->radius, CIRCLE_VERTICES_MAX-1);
|
||||
|
||||
create_circle_geometry(circle->position,
|
||||
circle->color,
|
||||
circle->radius,
|
||||
num_vertices,
|
||||
&vertices,
|
||||
&indices);
|
||||
vertices,
|
||||
indices);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2,
|
||||
@ -196,9 +199,6 @@ void render_circle(const CirclePrimitive *circle) {
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
SDL_free(vertices);
|
||||
SDL_free(indices);
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,6 +31,19 @@ typedef struct StringArena {
|
||||
static StringArena string_arena;
|
||||
|
||||
|
||||
typedef struct FontFileBuffer {
|
||||
size_t len;
|
||||
unsigned char *buffer;
|
||||
} FontFileBuffer;
|
||||
|
||||
typedef struct FontFileCacheItem {
|
||||
char *key;
|
||||
FontFileBuffer value;
|
||||
} FontFileCacheItem;
|
||||
|
||||
static FontFileCacheItem *font_file_cache_hash;
|
||||
|
||||
|
||||
static void string_arena_init(StringArena *arena) {
|
||||
arena->head = cmalloc(sizeof *arena->head);
|
||||
arena->current_block = arena->head;
|
||||
@ -103,12 +116,22 @@ static FontData *text_load_font_data(const char *path, int height_px) {
|
||||
|
||||
{
|
||||
unsigned char *buf = NULL;
|
||||
int64_t buf_len = file_to_bytes(path, &buf);
|
||||
int64_t buf_len = 0;
|
||||
|
||||
/* if the file was already loaded just get it */
|
||||
FontFileCacheItem *font_file_ptr = shgetp_null(font_file_cache_hash, path);
|
||||
if (font_file_ptr != NULL) {
|
||||
buf = font_file_ptr->value.buffer;
|
||||
buf_len = font_file_ptr->value.len;
|
||||
} else {
|
||||
buf_len = file_to_bytes(path, &buf);
|
||||
FontFileBuffer buffer = { buf_len, buf };
|
||||
shput(font_file_cache_hash, path, buffer);
|
||||
}
|
||||
|
||||
stbtt_InitFont(&font_data->info, buf, stbtt_GetFontOffsetForIndex(buf, 0));
|
||||
|
||||
/* might as well get these now, for later */
|
||||
font_data->file_bytes = buf;
|
||||
font_data->file_bytes_len = buf_len;
|
||||
font_data->scale_factor = stbtt_ScaleForPixelHeight(&font_data->info, (float)height_px);
|
||||
stbtt_GetFontVMetrics(
|
||||
&font_data->info,
|
||||
@ -142,7 +165,6 @@ static FontData *text_load_font_data(const char *path, int height_px) {
|
||||
|
||||
|
||||
static void text_destroy_font_data(FontData *font_data) {
|
||||
SDL_free(font_data->file_bytes);
|
||||
delete_gpu_texture(font_data->texture);
|
||||
SDL_free(font_data);
|
||||
}
|
||||
@ -192,7 +214,7 @@ static void text_draw_with(FontData* font_data, char* text, Vec2 position, Color
|
||||
|
||||
|
||||
static void ensure_font_cache(const char *font_path, int height_px) {
|
||||
/* HACK: stupid, bad, don't do this */
|
||||
/* HACK: don't */
|
||||
bool is_cached = false;
|
||||
for (size_t i = 0; i < arrlenu(ctx.text_cache.data); ++i) {
|
||||
FontData *font_data = ctx.text_cache.data[i];
|
||||
@ -229,6 +251,8 @@ void render_text(const TextPrimitive *text) {
|
||||
void text_cache_init(TextCache *cache) {
|
||||
arrsetlen(cache->data, 0);
|
||||
string_arena_init(&string_arena);
|
||||
|
||||
sh_new_arena(font_file_cache_hash);
|
||||
}
|
||||
|
||||
|
||||
@ -237,8 +261,13 @@ void text_cache_deinit(TextCache *cache) {
|
||||
text_destroy_font_data(ctx.text_cache.data[i]);
|
||||
}
|
||||
|
||||
arrfree(cache->data);
|
||||
for (size_t i = 0; i < shlenu(font_file_cache_hash); ++i) {
|
||||
SDL_free(font_file_cache_hash[i].value.buffer);
|
||||
}
|
||||
shfree(font_file_cache_hash);
|
||||
|
||||
string_arena_deinit(&string_arena);
|
||||
arrfree(cache->data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,8 +22,6 @@ typedef struct FontData {
|
||||
stbtt_fontinfo info;
|
||||
|
||||
const char *file_path;
|
||||
unsigned char *file_bytes;
|
||||
size_t file_bytes_len;
|
||||
|
||||
GPUTexture texture;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user