Compare commits
No commits in common. "b436268ffa908898e7ba77dc86df8541d94b11dc" and "11a53fa08783be282d3f654e019df5f9b53f35d9" have entirely different histories.
b436268ffa
...
11a53fa087
|
@ -1,33 +0,0 @@
|
||||||
#ifndef ED_ARRAY_INCLUDED
|
|
||||||
#define ED_ARRAY_INCLUDED
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#define array(T) struct T ## Array
|
|
||||||
#define arrayTemplate(T) array(T) {\
|
|
||||||
size_t size, capacity;\
|
|
||||||
T *data;\
|
|
||||||
};\
|
|
||||||
array(T) T ## ArrayConstruct(size_t size) {\
|
|
||||||
array(T) this;\
|
|
||||||
this.size = 0;\
|
|
||||||
this.capacity = size;\
|
|
||||||
this.data = malloc(size * sizeof(T));\
|
|
||||||
if (!this.data) {\
|
|
||||||
assert("failed to allocate memory for array");\
|
|
||||||
}\
|
|
||||||
return this;\
|
|
||||||
};\
|
|
||||||
void T ## PushArray(array(T) *arr, T value) {\
|
|
||||||
if (arr->size+1 <= arr->capacity) {\
|
|
||||||
arr->data[arr->size] = value;\
|
|
||||||
arr->size += 1;\
|
|
||||||
} else {\
|
|
||||||
fprintf(stderr, "failed to push to u8 array, size+num > capacity\n");\
|
|
||||||
}\
|
|
||||||
};
|
|
||||||
|
|
||||||
#define newArray(T, size) T ## ArrayConstruct(size)
|
|
||||||
#define pushArray(T, arr, value) T ## PushArray(arr, (value))
|
|
||||||
|
|
||||||
#endif
|
|
61
src/main.c
61
src/main.c
|
@ -32,7 +32,6 @@
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "ht.h"
|
#include "ht.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "ed_array.h"
|
|
||||||
|
|
||||||
|
|
||||||
// static Arena default_arena = {0};
|
// static Arena default_arena = {0};
|
||||||
|
@ -50,7 +49,6 @@ typedef struct {
|
||||||
float size[2];
|
float size[2];
|
||||||
float border_size[2];
|
float border_size[2];
|
||||||
} GpuUiRect;
|
} GpuUiRect;
|
||||||
arrayTemplate(GpuUiRect);
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float atlas_position[2];
|
float atlas_position[2];
|
||||||
|
@ -58,12 +56,38 @@ typedef struct {
|
||||||
float position[2];
|
float position[2];
|
||||||
float y_offset;
|
float y_offset;
|
||||||
} GpuGlyph;
|
} GpuGlyph;
|
||||||
arrayTemplate(GpuGlyph);
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float screen_size[4];
|
float screen_size[4];
|
||||||
} GpuUniformParams;
|
} GpuUniformParams;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
uint8_t *data;
|
||||||
|
} U8Array;
|
||||||
|
|
||||||
|
U8Array new_u8array(size_t capacity) {
|
||||||
|
return (U8Array) {
|
||||||
|
.size = 0,
|
||||||
|
.capacity = capacity,
|
||||||
|
.data = context_alloc(capacity),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_u8array(U8Array *array, uint8_t *items, size_t num) {
|
||||||
|
if (array->size + num <= array->capacity) {
|
||||||
|
memcpy(array->data + array->size, items, num);
|
||||||
|
array->size += num;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "failed to push to u8 array, size+num > capacity\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_u8array(U8Array *array) {
|
||||||
|
array->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
sg_pass_action pass_action;
|
sg_pass_action pass_action;
|
||||||
sg_pipeline pip;
|
sg_pipeline pip;
|
||||||
|
@ -74,9 +98,9 @@ static struct {
|
||||||
|
|
||||||
sg_shader_desc scratch_shader_desc;
|
sg_shader_desc scratch_shader_desc;
|
||||||
|
|
||||||
array(GpuUiRect) gpu_ui_rects;
|
U8Array gpu_ui_rects;
|
||||||
array(GpuGlyph) gpu_glyphs;
|
U8Array gpu_glyphs;
|
||||||
array(GpuGlyph) glyph_cache;
|
U8Array glyph_cache;
|
||||||
|
|
||||||
bool should_exit;
|
bool should_exit;
|
||||||
|
|
||||||
|
@ -87,14 +111,13 @@ void queue_text(string text, float position[2]) {
|
||||||
float x = 0;
|
float x = 0;
|
||||||
for (size_t i=0; i < text.len; ++i) {
|
for (size_t i=0; i < text.len; ++i) {
|
||||||
if (text.data[i] >= 32) {
|
if (text.data[i] >= 32) {
|
||||||
//GpuGlyph glyph = *((GpuGlyph *)(state.glyph_cache.data+((text.data[i] - 32) * sizeof(GpuGlyph))));
|
GpuGlyph glyph = *((GpuGlyph *)(state.glyph_cache.data+((text.data[i] - 32) * sizeof(GpuGlyph))));
|
||||||
GpuGlyph glyph = state.glyph_cache.data[text.data[i] - 32];
|
|
||||||
|
|
||||||
glyph.position[0] = x+position[0];
|
glyph.position[0] = x+position[0];
|
||||||
glyph.position[1] = position[1];
|
glyph.position[1] = position[1];
|
||||||
x += glyph.size[0]/2;
|
x += glyph.size[0]/2;
|
||||||
|
|
||||||
pushArray(GpuGlyph, &state.gpu_glyphs, glyph);
|
push_u8array(&state.gpu_glyphs, (uint8_t *)(&glyph), sizeof(GpuGlyph));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,9 +230,9 @@ void ed_init() {
|
||||||
const int rasterized_font_height = 64;
|
const int rasterized_font_height = 64;
|
||||||
uint8_t *font_bitmap = context_alloc(font_bitmap_size*font_bitmap_size * sizeof(uint8_t));
|
uint8_t *font_bitmap = context_alloc(font_bitmap_size*font_bitmap_size * sizeof(uint8_t));
|
||||||
|
|
||||||
state.gpu_ui_rects = newArray(GpuUiRect, 2000);
|
state.gpu_ui_rects = new_u8array(sizeof(GpuUiRect) * 2000);
|
||||||
state.gpu_glyphs = newArray(GpuGlyph, 1024);
|
state.gpu_glyphs = new_u8array(sizeof(GpuGlyph) * 1024);
|
||||||
state.glyph_cache = newArray(GpuGlyph, 97);
|
state.glyph_cache = new_u8array(sizeof(GpuGlyph) * 97);
|
||||||
|
|
||||||
int ascent, descent, line_gap;
|
int ascent, descent, line_gap;
|
||||||
float scale = stbtt_ScaleForPixelHeight(&font, rasterized_font_height);
|
float scale = stbtt_ScaleForPixelHeight(&font, rasterized_font_height);
|
||||||
|
@ -221,12 +244,12 @@ void ed_init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// manually add glyph for SPACE
|
// manually add glyph for SPACE
|
||||||
pushArray(GpuGlyph, &state.glyph_cache, ((GpuGlyph){
|
push_u8array(&state.glyph_cache, (uint8_t *)(&(GpuGlyph){
|
||||||
.atlas_position = { 0 },
|
.atlas_position = { 0 },
|
||||||
.size = { rasterized_font_height/4, rasterized_font_height },
|
.size = { rasterized_font_height/4, rasterized_font_height },
|
||||||
.position = { 0 },
|
.position = { 0 },
|
||||||
.y_offset = -rasterized_font_height,
|
.y_offset = -rasterized_font_height,
|
||||||
}));
|
}), 1 * sizeof(GpuGlyph));
|
||||||
|
|
||||||
int x = rasterized_font_height/4;
|
int x = rasterized_font_height/4;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
@ -251,18 +274,18 @@ void ed_init() {
|
||||||
xxx += 1;
|
xxx += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pushArray(GpuGlyph, &state.glyph_cache, ((GpuGlyph){
|
push_u8array(&state.glyph_cache, (uint8_t *)(&(GpuGlyph){
|
||||||
.atlas_position = { (float)(x), (float)(y) },
|
.atlas_position = { (float)(x), (float)(y) },
|
||||||
.size = { (float)width, (float)height },
|
.size = { (float)width, (float)height },
|
||||||
.position = { (float)x, (float)y },
|
.position = { (float)x, (float)y },
|
||||||
.y_offset = (float)(yoff),
|
.y_offset = (float)(yoff),
|
||||||
}));
|
}), 1 * sizeof(GpuGlyph));
|
||||||
|
|
||||||
x += width;
|
x += width;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.bind.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc) {
|
state.bind.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc) {
|
||||||
.size = state.gpu_glyphs.capacity * sizeof(GpuGlyph),
|
.size = state.gpu_glyphs.capacity,
|
||||||
.usage = SG_USAGE_STREAM,
|
.usage = SG_USAGE_STREAM,
|
||||||
.label = "glyph buffer"
|
.label = "glyph buffer"
|
||||||
});
|
});
|
||||||
|
@ -331,7 +354,7 @@ void ed_frame() {
|
||||||
if (state.gpu_glyphs.size > 0) {
|
if (state.gpu_glyphs.size > 0) {
|
||||||
sg_update_buffer(state.bind.vertex_buffers[1], &(sg_range) {
|
sg_update_buffer(state.bind.vertex_buffers[1], &(sg_range) {
|
||||||
.ptr = state.gpu_glyphs.data,
|
.ptr = state.gpu_glyphs.data,
|
||||||
.size = state.gpu_glyphs.size * sizeof(GpuGlyph)
|
.size = state.gpu_glyphs.size
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +372,7 @@ void ed_frame() {
|
||||||
sg_apply_pipeline(state.pip);
|
sg_apply_pipeline(state.pip);
|
||||||
sg_apply_bindings(&state.bind);
|
sg_apply_bindings(&state.bind);
|
||||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &(sg_range) { .ptr = &gpu_uniform_params, .size = sizeof(GpuUniformParams) });
|
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &(sg_range) { .ptr = &gpu_uniform_params, .size = sizeof(GpuUniformParams) });
|
||||||
sg_draw(0, 6, state.gpu_glyphs.size);
|
sg_draw(0, 6, state.gpu_glyphs.size/sizeof(GpuGlyph));
|
||||||
}
|
}
|
||||||
sg_end_pass();
|
sg_end_pass();
|
||||||
sg_commit();
|
sg_commit();
|
||||||
|
|
74
src/ui.h
74
src/ui.h
|
@ -3,28 +3,11 @@
|
||||||
#ifndef ED_UI_INCLUDED
|
#ifndef ED_UI_INCLUDED
|
||||||
#define ED_UI_INCLUDED
|
#define ED_UI_INCLUDED
|
||||||
|
|
||||||
#define MAX_UI_ELEMENTS 2048
|
|
||||||
|
|
||||||
#define _elm(index) (&cx->frame_elements.data[index])
|
|
||||||
|
|
||||||
#define _first(index) (_elm(index)->first)
|
|
||||||
#define _last(index) (_elm(index)->last)
|
|
||||||
#define _next(index) (_elm(index)->next)
|
|
||||||
#define _prev(index) (_elm(index)->prev)
|
|
||||||
#define _parent(index) (_elm(index)->parent)
|
|
||||||
|
|
||||||
#define _first_ref(index) (_elm(_first(index)))
|
|
||||||
#define _last_ref(index) (_elm(_last(index)))
|
|
||||||
#define _next_ref(index) (_elm(_next(index)))
|
|
||||||
#define _prev_ref(index) (_elm(_prev(index)))
|
|
||||||
#define _parent_ref(index) (_elm(_parent(index)))
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "ht.h"
|
#include "ht.h"
|
||||||
#include "ed_array.h"
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UI_AXIS_HORIZONTAL,
|
UI_AXIS_HORIZONTAL,
|
||||||
|
@ -88,76 +71,21 @@ typedef struct {
|
||||||
size_t prev;
|
size_t prev;
|
||||||
size_t parent;
|
size_t parent;
|
||||||
} ui_element_frame_data;
|
} ui_element_frame_data;
|
||||||
arrayTemplate(ui_element_frame_data);
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ed_ht cached_elements;
|
ed_ht cached_elements;
|
||||||
array(ui_element_frame_data) frame_elements;
|
|
||||||
|
|
||||||
size_t frame_index;
|
|
||||||
|
|
||||||
size_t current_parent;
|
|
||||||
} ui_context;
|
} ui_context;
|
||||||
|
|
||||||
|
|
||||||
#ifdef ED_UI_IMPLEMENTATION
|
#ifdef ED_UI_IMPLEMENTATION
|
||||||
|
|
||||||
ui_context init_ui_context() {
|
ui_context init_ui_context() {
|
||||||
ed_ht cached_elements = ht_create(MAX_UI_ELEMENTS, sizeof(ui_element_cache_data));
|
ed_ht cached_elements = ht_create(32, sizeof(ui_element_cache_data));
|
||||||
array(ui_element_frame_data) frame_elements = newArray(ui_element_frame_data, MAX_UI_ELEMENTS);
|
|
||||||
|
|
||||||
return (ui_context) {
|
return (ui_context) {
|
||||||
.cached_elements = cached_elements,
|
.cached_elements = cached_elements,
|
||||||
.frame_elements = frame_elements,
|
|
||||||
.frame_index = 0,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ui_element(ui_context *cx, string label) {
|
|
||||||
ui_element_frame_data frame_data = (ui_element_frame_data) {
|
|
||||||
.index = cx->frame_elements.size,
|
|
||||||
// TODO: don't just set this to label, because then elements
|
|
||||||
// with the same label can't be created together
|
|
||||||
.key = label,
|
|
||||||
.label = label,
|
|
||||||
.first = 0,
|
|
||||||
.last = 0,
|
|
||||||
.next = 0,
|
|
||||||
.prev = cx->frame_elements.data[cx->current_parent].last,
|
|
||||||
.parent = cx->current_parent,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get cached element data
|
|
||||||
ui_element_cache_data *cache_data = ht_get(&cx->cached_elements, label);
|
|
||||||
if (cache_data) {
|
|
||||||
cache_data->last_instantiated_index = cx->frame_index;
|
|
||||||
|
|
||||||
frame_data.size = cache_data->size;
|
|
||||||
} else {
|
|
||||||
assert("couldn't insert into ui element cache" && ht_set(&cx->cached_elements, label, &(ui_element_cache_data) {
|
|
||||||
.label = label,
|
|
||||||
.size = { 0 },
|
|
||||||
.last_instantiated_index = cx->frame_index,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
pushArray(ui_element_frame_data, &cx->frame_elements, frame_data);
|
|
||||||
|
|
||||||
if (frame_data.prev) {
|
|
||||||
_prev_ref(frame_data.index)->next = frame_data.index;
|
|
||||||
}
|
|
||||||
if (_elm(cx->current_parent)->first == 0) {
|
|
||||||
_elm(cx->current_parent)->first = frame_data.index;
|
|
||||||
}
|
|
||||||
_elm(cx->current_parent)->last = frame_data.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui_compute_layout(ui_context *cx, uint32_t canvas_size[2], size_t element_index) {
|
|
||||||
ui_axis axis = UI_AXIS_HORIZONTAL;
|
|
||||||
|
|
||||||
// FIXME: change me to use -1 for no reference to element
|
|
||||||
// TODO: actually compute layout
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue