Compare commits
2 Commits
b436268ffa
...
46dd862512
Author | SHA1 | Date |
---|---|---|
|
46dd862512 | |
|
74e3821233 |
4
justfile
4
justfile
|
@ -3,8 +3,8 @@ alias r := run
|
||||||
|
|
||||||
build: transpile_shaders_metal
|
build: transpile_shaders_metal
|
||||||
mkdir -p bin
|
mkdir -p bin
|
||||||
# cc -Ivendor/ -g -Wall -Wextra -framework Cocoa -framework QuartzCore -framework CoreImage -framework Metal -framework MetalKit -ObjC src/*.c -o bin/an_editor
|
cc -Ivendor/ -g -Wall -Wextra -framework Cocoa -framework QuartzCore -framework CoreImage -framework Metal -framework MetalKit -ObjC src/*.c -o bin/an_editor
|
||||||
cc -Ivendor/ -g -Wall -Wextra src/*.c -o bin/an_editor -lEGL -lGLESv2 -lGL -lm -lX11 -lXi -lXcursor
|
# cc -Ivendor/ -g -Wall -Wextra src/*.c -o bin/an_editor -lEGL -lGLESv2 -lGL -lm -lX11 -lXi -lXcursor
|
||||||
# cc bin/*.o -o bin/an_editor -lEGL -lGLESv2 -lGL -lm -lX11 -lXi -lXcursor
|
# cc bin/*.o -o bin/an_editor -lEGL -lGLESv2 -lGL -lm -lX11 -lXi -lXcursor
|
||||||
|
|
||||||
run: build
|
run: build
|
||||||
|
|
|
@ -15,23 +15,23 @@ struct VertexOutput {
|
||||||
@location(0) tex_coord: vec2<f32>,
|
@location(0) tex_coord: vec2<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct Params {
|
struct Params {
|
||||||
// screen_size: vec4<f32>,
|
screen_size: vec4<f32>,
|
||||||
// }
|
}
|
||||||
|
|
||||||
fn to_device_position(position: vec2<f32>, size: vec2<f32>) -> vec4<f32> {
|
fn to_device_position(position: vec2<f32>, size: vec2<f32>) -> vec4<f32> {
|
||||||
return vec4<f32>((((position / size) * 2.) - 1.), 1., 1.);
|
return vec4<f32>((((position / size) * 2.) - 1.), 1., 1.);
|
||||||
}
|
}
|
||||||
|
|
||||||
@group(0) @binding(0)
|
@group(0) @binding(0)
|
||||||
var<uniform> screen_size: vec4<f32>;
|
var<uniform> params: Params;
|
||||||
|
|
||||||
@vertex
|
@vertex
|
||||||
fn vs_main(input: VertexInput) -> VertexOutput {
|
fn vs_main(input: VertexInput) -> VertexOutput {
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
|
|
||||||
var vertex_pos = to_device_position(((input.position.xy + 1.) / 2.) * (input.size/2.0) + input.target_position + vec2<f32>(0., (input.y_offset/2.0)+32), screen_size.xy);
|
var vertex_pos = to_device_position(((input.position.xy + 1.) / 2.) * (input.size/2.0) + input.target_position + vec2<f32>(0., (input.y_offset/2.0)+32), params.screen_size.xy);
|
||||||
// vertex_pos.y = -vertex_pos.y;
|
vertex_pos.y = -vertex_pos.y;
|
||||||
var atlas_position = (((input.position.xy + 1.) / 2.) * input.size + input.atlas_position) / vec2<f32>(1024);
|
var atlas_position = (((input.position.xy + 1.) / 2.) * input.size + input.atlas_position) / vec2<f32>(1024);
|
||||||
|
|
||||||
out.position = vertex_pos;
|
out.position = vertex_pos;
|
||||||
|
|
41
src/main.c
41
src/main.c
|
@ -14,8 +14,13 @@
|
||||||
#define SOKOL_LOG_IMPL
|
#define SOKOL_LOG_IMPL
|
||||||
|
|
||||||
// TODO: condition compilation
|
// TODO: condition compilation
|
||||||
// #define SOKOL_METAL
|
#if defined (__APPLE__)
|
||||||
#define SOKOL_GLCORE33
|
#define SOKOL_METAL
|
||||||
|
#elif defined (__linux__) || defined (__unix__)
|
||||||
|
#define SOKOL_GLCORE33
|
||||||
|
#else
|
||||||
|
#error "Unsupported platform for shaders"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <sokol/sokol_log.h>
|
#include <sokol/sokol_log.h>
|
||||||
#include <sokol/sokol_gfx.h>
|
#include <sokol/sokol_gfx.h>
|
||||||
|
@ -140,6 +145,7 @@ void ed_init() {
|
||||||
// TODO: grab default font from the system
|
// TODO: grab default font from the system
|
||||||
FILE *ttf_file = fopen("./bin/JetBrainsMono-Medium.ttf", "rb");
|
FILE *ttf_file = fopen("./bin/JetBrainsMono-Medium.ttf", "rb");
|
||||||
if (!ttf_file) {
|
if (!ttf_file) {
|
||||||
|
fprintf(stderr, "failed to load font\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
assert(fread(ttf_buffer, 1, 1<<20, ttf_file));
|
assert(fread(ttf_buffer, 1, 1<<20, ttf_file));
|
||||||
|
@ -301,33 +307,36 @@ void ed_init() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
queue_text(_String("But what even is text! []!@#$%^&*()_=+"), (float[]){ 0, 0 });
|
// queue_text(_String("But what even is text! []!@#$%^&*()_=+"), (float[]){ 0, 0 });
|
||||||
queue_text(_String("v0.1.0"), (float[]){ 32, 128 });
|
// queue_text(_String("v0.1.0"), (float[]){ 32, 128 });
|
||||||
queue_text(_String("an_editor - what even"), (float[]){ 32, 256 });
|
// queue_text(_String("an_editor - what even"), (float[]){ 32, 256 });
|
||||||
|
|
||||||
state.ui_cx = init_ui_context();
|
state.ui_cx = ui_init_context();
|
||||||
|
|
||||||
|
}
|
||||||
|
void ed_frame() {
|
||||||
string label = _String("Number 1");
|
string label = _String("Number 1");
|
||||||
ht_set(&state.ui_cx.cached_elements, label, &(ui_element_cache_data) {
|
ui_element(&state.ui_cx, label);
|
||||||
.label = label,
|
ui_element(&state.ui_cx, _String("ui element 2"));
|
||||||
.size = {
|
ui_element(&state.ui_cx, _String("ui element 3"));
|
||||||
.axis = UI_AXIS_HORIZONTAL,
|
|
||||||
.computed_size = { 200, 256 },
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
ui_compute_layout(&state.ui_cx, 0);
|
||||||
|
state.ui_cx.frame_elements.data[0].size.computed_size[0] = sapp_width();
|
||||||
|
state.ui_cx.frame_elements.data[0].size.computed_size[1] = sapp_height();
|
||||||
|
ui_update_cache(&state.ui_cx, 0);
|
||||||
|
|
||||||
|
state.gpu_glyphs.size = 0;
|
||||||
for (size_t i = 0; i < state.ui_cx.cached_elements.capacity; ++i) {
|
for (size_t i = 0; i < state.ui_cx.cached_elements.capacity; ++i) {
|
||||||
if (state.ui_cx.cached_elements.key_slots[i].key.data != NULL) {
|
if (state.ui_cx.cached_elements.key_slots[i].key.data != NULL) {
|
||||||
string text = state.ui_cx.cached_elements.key_slots[i].key;
|
string text = state.ui_cx.cached_elements.key_slots[i].key;
|
||||||
|
|
||||||
ui_element_cache_data *value = ht_get(&state.ui_cx.cached_elements, text);
|
ui_element_cache_data *value = ht_get(&state.ui_cx.cached_elements, text);
|
||||||
if (value) {
|
if (value) {
|
||||||
queue_text(text, (float[]){ (float)value->size.computed_size[0], (float)value->size.computed_size[1] });
|
queue_text(text, (float[]){ (float)value->size.computed_pos[0], (float)value->size.computed_pos[1] });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
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,
|
||||||
|
|
245
src/ui.h
245
src/ui.h
|
@ -5,7 +5,12 @@
|
||||||
|
|
||||||
#define MAX_UI_ELEMENTS 2048
|
#define MAX_UI_ELEMENTS 2048
|
||||||
|
|
||||||
#define _elm(index) (&cx->frame_elements.data[index])
|
// TODO: replace this with functions
|
||||||
|
#define _FONT_WIDTH 16
|
||||||
|
#define _FONT_HEIGHT 32
|
||||||
|
|
||||||
|
#define _elm(index) (cx->frame_elements.data+index)
|
||||||
|
#define _flags(index, flgs) ((_elm(index)->flags & (flgs)) == (flgs))
|
||||||
|
|
||||||
#define _first(index) (_elm(index)->first)
|
#define _first(index) (_elm(index)->first)
|
||||||
#define _last(index) (_elm(index)->last)
|
#define _last(index) (_elm(index)->last)
|
||||||
|
@ -93,22 +98,45 @@ arrayTemplate(ui_element_frame_data);
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ed_ht cached_elements;
|
ed_ht cached_elements;
|
||||||
array(ui_element_frame_data) frame_elements;
|
array(ui_element_frame_data) frame_elements;
|
||||||
|
array(ui_element_frame_data) frame_floating_elements;
|
||||||
|
|
||||||
size_t frame_index;
|
size_t frame_index;
|
||||||
|
uint32_t canvas_size[2];
|
||||||
|
|
||||||
size_t current_parent;
|
size_t current_parent;
|
||||||
} ui_context;
|
} ui_context;
|
||||||
|
|
||||||
|
void ui_compute_layout(ui_context *cx, size_t element_index);
|
||||||
|
|
||||||
#ifdef ED_UI_IMPLEMENTATION
|
#ifdef ED_UI_IMPLEMENTATION
|
||||||
|
|
||||||
ui_context init_ui_context() {
|
ui_context ui_init_context() {
|
||||||
ed_ht cached_elements = ht_create(MAX_UI_ELEMENTS, sizeof(ui_element_cache_data));
|
ed_ht cached_elements = ht_create(MAX_UI_ELEMENTS, sizeof(ui_element_cache_data));
|
||||||
array(ui_element_frame_data) frame_elements = newArray(ui_element_frame_data, MAX_UI_ELEMENTS);
|
array(ui_element_frame_data) frame_elements = newArray(ui_element_frame_data, MAX_UI_ELEMENTS);
|
||||||
|
array(ui_element_frame_data) frame_floating_elements = newArray(ui_element_frame_data, MAX_UI_ELEMENTS);
|
||||||
|
|
||||||
|
ui_element_frame_data frame_data = (ui_element_frame_data) {
|
||||||
|
.index = 0,
|
||||||
|
// TODO: don't just set this to label, because then elements
|
||||||
|
// with the same label can't be created together
|
||||||
|
.key = _String("root"),
|
||||||
|
.label = _String("root"),
|
||||||
|
.first = -1,
|
||||||
|
.last = -1,
|
||||||
|
.next = -1,
|
||||||
|
.prev = -1,
|
||||||
|
.parent = -1,
|
||||||
|
.size = {
|
||||||
|
.axis = UI_AXIS_HORIZONTAL,
|
||||||
|
.computed_size = { 640, 480 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pushArray(ui_element_frame_data, &frame_elements, frame_data);
|
||||||
|
|
||||||
return (ui_context) {
|
return (ui_context) {
|
||||||
.cached_elements = cached_elements,
|
.cached_elements = cached_elements,
|
||||||
.frame_elements = frame_elements,
|
.frame_elements = frame_elements,
|
||||||
|
.frame_floating_elements = frame_floating_elements,
|
||||||
.frame_index = 0,
|
.frame_index = 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -120,11 +148,13 @@ size_t ui_element(ui_context *cx, string label) {
|
||||||
// with the same label can't be created together
|
// with the same label can't be created together
|
||||||
.key = label,
|
.key = label,
|
||||||
.label = label,
|
.label = label,
|
||||||
.first = 0,
|
.first = -1,
|
||||||
.last = 0,
|
.last = -1,
|
||||||
.next = 0,
|
.next = -1,
|
||||||
.prev = cx->frame_elements.data[cx->current_parent].last,
|
.prev = cx->frame_elements.data[cx->current_parent].last,
|
||||||
.parent = cx->current_parent,
|
.parent = cx->current_parent,
|
||||||
|
.size.semantic_size[0].type = UI_SEMANTIC_SIZE_FILL,
|
||||||
|
.size.semantic_size[1].type = UI_SEMANTIC_SIZE_FILL,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get cached element data
|
// Get cached element data
|
||||||
|
@ -143,20 +173,215 @@ size_t ui_element(ui_context *cx, string label) {
|
||||||
|
|
||||||
pushArray(ui_element_frame_data, &cx->frame_elements, frame_data);
|
pushArray(ui_element_frame_data, &cx->frame_elements, frame_data);
|
||||||
|
|
||||||
if (frame_data.prev) {
|
if (frame_data.prev < SIZE_MAX) {
|
||||||
_prev_ref(frame_data.index)->next = frame_data.index;
|
_prev_ref(frame_data.index)->next = frame_data.index;
|
||||||
}
|
}
|
||||||
if (_elm(cx->current_parent)->first == 0) {
|
if (_elm(cx->current_parent)->first == SIZE_MAX) {
|
||||||
_elm(cx->current_parent)->first = frame_data.index;
|
_elm(cx->current_parent)->first = frame_data.index;
|
||||||
}
|
}
|
||||||
_elm(cx->current_parent)->last = frame_data.index;
|
_elm(cx->current_parent)->last = frame_data.index;
|
||||||
|
|
||||||
|
return frame_data.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_compute_layout(ui_context *cx, uint32_t canvas_size[2], size_t element_index) {
|
static uint32_t _ui_ancestor_size(ui_context *cx, size_t element_index, ui_axis axis) {
|
||||||
|
if (element_index == SIZE_MAX || _parent(element_index) == SIZE_MAX) {
|
||||||
|
return cx->frame_elements.data[0].size.computed_size[axis];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (_parent_ref(element_index)->size.semantic_size[axis].type) {
|
||||||
|
case UI_SEMANTIC_SIZE_FIT_TEXT:
|
||||||
|
case UI_SEMANTIC_SIZE_FILL:
|
||||||
|
case UI_SEMANTIC_SIZE_EXACT:
|
||||||
|
case UI_SEMANTIC_SIZE_PERCENT_OF_PARENT:
|
||||||
|
return _parent_ref(element_index)->size.computed_size[axis];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SEMANTIC_SIZE_CHILDREN_SUM:
|
||||||
|
return _ui_ancestor_size(cx, _parent(element_index), axis);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _ui_compute_simple_layout(ui_context *cx, ui_element_frame_data *elm, ui_axis axis, bool *post_compute) {
|
||||||
|
switch (elm->size.semantic_size[axis].type) {
|
||||||
|
case UI_SEMANTIC_SIZE_FIT_TEXT:
|
||||||
|
if (axis == UI_AXIS_HORIZONTAL) {
|
||||||
|
elm->size.computed_size[axis] = elm->label.len * _FONT_WIDTH;
|
||||||
|
} else if (axis == UI_AXIS_VERTICAL) {
|
||||||
|
elm->size.computed_size[axis] = _FONT_WIDTH;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SEMANTIC_SIZE_CHILDREN_SUM:
|
||||||
|
post_compute[axis] = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SEMANTIC_SIZE_FILL:
|
||||||
|
// TODO: set to ancestor size for floating
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SEMANTIC_SIZE_EXACT:
|
||||||
|
elm->size.computed_size[axis] = elm->size.semantic_size[axis].integer;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SEMANTIC_SIZE_PERCENT_OF_PARENT:
|
||||||
|
{
|
||||||
|
float semantic_value = (float)elm->size.semantic_size[axis].integer;
|
||||||
|
elm->size.computed_size[axis] = (uint32_t)((float)(_ui_ancestor_size(cx, elm->index, axis)) * (semantic_value/100.0));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _ui_compute_children_layout(ui_context *cx, ui_element_frame_data *elm) {
|
||||||
|
uint32_t child_size[2] = { 0 };
|
||||||
|
|
||||||
|
// NOTE: the number of fills for the opposite axis of this box needs to be 1
|
||||||
|
// because it will never get incremented in the loop below and cause a divide by zero
|
||||||
|
// and the number of fills for the axis of the box needs to start at zero or else it will
|
||||||
|
// be n+1 causing incorrect sizes
|
||||||
|
uint32_t num_fills[2] = { 1 };
|
||||||
|
num_fills[elm->size.axis] = 0;
|
||||||
|
|
||||||
|
// TODO: maybe just use the actual data instead of copying?
|
||||||
|
uint32_t elm_size[2] = { elm->size.computed_size[0], elm->size.computed_size[1] };
|
||||||
|
|
||||||
|
size_t child_index = elm->first;
|
||||||
|
if (child_index < SIZE_MAX) {
|
||||||
|
do {
|
||||||
|
ui_compute_layout(cx, child_index);
|
||||||
|
|
||||||
|
if (_elm(child_index)->size.semantic_size[elm->size.axis].type == UI_SEMANTIC_SIZE_FILL) {
|
||||||
|
num_fills[elm->size.axis] += 1;
|
||||||
|
} else {
|
||||||
|
child_size[elm->size.axis] += _elm(child_index)->size.computed_size[elm->size.axis];
|
||||||
|
}
|
||||||
|
} while ((child_index = _next(child_index)) < SIZE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
child_index = elm->first;
|
||||||
|
if (child_index < SIZE_MAX) {
|
||||||
|
do {
|
||||||
|
for (size_t axis = 0; axis < 2; ++axis) {
|
||||||
|
if (_elm(child_index)->size.semantic_size[axis].type == UI_SEMANTIC_SIZE_FILL) {
|
||||||
|
_elm(child_index)->size.computed_size[axis] = (elm_size[axis] - child_size[axis]) / num_fills[axis];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_compute_layout(cx, child_index);
|
||||||
|
} while ((child_index = _next(child_index)) < SIZE_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_compute_layout(ui_context *cx, size_t element_index) {
|
||||||
|
if (element_index == SIZE_MAX) return;
|
||||||
|
|
||||||
ui_axis axis = UI_AXIS_HORIZONTAL;
|
ui_axis axis = UI_AXIS_HORIZONTAL;
|
||||||
|
__auto_type elm = _elm(element_index);
|
||||||
|
|
||||||
// FIXME: change me to use -1 for no reference to element
|
if (_parent(element_index) < SIZE_MAX && !_flags(element_index, UI_FLAG_FLOATING)) {
|
||||||
// TODO: actually compute layout
|
__auto_type parent = _parent_ref(element_index);
|
||||||
|
axis = parent->size.axis;
|
||||||
|
elm->size.computed_pos[0] = parent->size.computed_pos[0];
|
||||||
|
elm->size.computed_pos[1] = parent->size.computed_pos[1];
|
||||||
|
|
||||||
|
// TODO: implement scrolling
|
||||||
|
// elm->size.computed_pos[axis] += parent.scroll_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_flags(element_index, UI_FLAG_FLOATING) && _prev(element_index) < SIZE_MAX) {
|
||||||
|
__auto_type prev = _prev_ref(element_index);
|
||||||
|
|
||||||
|
if (prev >= 0) {
|
||||||
|
elm->size.computed_pos[axis] = prev->size.computed_pos[axis] + prev->size.computed_size[axis];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool post_compute[2] = { false, false };
|
||||||
|
// only compute layout for children of root
|
||||||
|
if (elm->index > 0) {
|
||||||
|
_ui_compute_simple_layout(cx, elm, axis, post_compute);
|
||||||
|
}
|
||||||
|
_ui_compute_children_layout(cx, elm);
|
||||||
|
|
||||||
|
// NOTE(pcleavelin): the only difference between these two blocks is the ordering of the switch block
|
||||||
|
// they can probably be merged
|
||||||
|
if (post_compute[UI_AXIS_HORIZONTAL]) {
|
||||||
|
elm->size.computed_size[UI_AXIS_HORIZONTAL] = 0;
|
||||||
|
|
||||||
|
size_t child_index = elm->first;
|
||||||
|
if (child_index < SIZE_MAX) {
|
||||||
|
do {
|
||||||
|
__auto_type child = _elm(child_index);
|
||||||
|
|
||||||
|
switch (elm->size.axis) {
|
||||||
|
case UI_AXIS_HORIZONTAL:
|
||||||
|
elm->size.computed_size[UI_AXIS_HORIZONTAL] += child->size.computed_size[UI_AXIS_HORIZONTAL];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_AXIS_VERTICAL:
|
||||||
|
if (child->size.computed_size[UI_AXIS_HORIZONTAL] > elm->size.computed_size[UI_AXIS_HORIZONTAL]) {
|
||||||
|
elm->size.computed_size[UI_AXIS_HORIZONTAL] = child->size.computed_size[UI_AXIS_HORIZONTAL];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ((child_index = _next(child_index)) < SIZE_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (post_compute[UI_AXIS_VERTICAL]) {
|
||||||
|
elm->size.computed_size[UI_AXIS_VERTICAL] = 0;
|
||||||
|
|
||||||
|
size_t child_index = elm->first;
|
||||||
|
if (child_index < SIZE_MAX) {
|
||||||
|
do {
|
||||||
|
__auto_type child = _elm(child_index);
|
||||||
|
|
||||||
|
switch (elm->size.axis) {
|
||||||
|
case UI_AXIS_HORIZONTAL:
|
||||||
|
if (child->size.computed_size[UI_AXIS_VERTICAL] > elm->size.computed_size[UI_AXIS_VERTICAL]) {
|
||||||
|
elm->size.computed_size[UI_AXIS_VERTICAL] = child->size.computed_size[UI_AXIS_VERTICAL];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UI_AXIS_VERTICAL:
|
||||||
|
elm->size.computed_size[UI_AXIS_VERTICAL] += child->size.computed_size[UI_AXIS_VERTICAL];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while ((child_index = _next(child_index)) < SIZE_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_update_cache(ui_context *cx, size_t element_index) {
|
||||||
|
if (element_index == SIZE_MAX) return;
|
||||||
|
|
||||||
|
size_t child_index = _elm(element_index)->first;
|
||||||
|
if (child_index < SIZE_MAX) {
|
||||||
|
do {
|
||||||
|
__auto_type child = _elm(child_index);
|
||||||
|
|
||||||
|
ht_set(&cx->cached_elements, child->key, &(ui_element_cache_data) {
|
||||||
|
.label = child->label,
|
||||||
|
.size = {
|
||||||
|
.axis = child->size.axis,
|
||||||
|
.semantic_size = { child->size.semantic_size[0], child->size.semantic_size[1] },
|
||||||
|
.computed_size = { child->size.computed_size[0], child->size.computed_size[1] },
|
||||||
|
.computed_pos = { child->size.computed_pos[0], child->size.computed_pos[1] },
|
||||||
|
}
|
||||||
|
// FIXME: don't mangle last_instantiated_index
|
||||||
|
});
|
||||||
|
|
||||||
|
ui_update_cache(cx, child_index);
|
||||||
|
} while ((child_index = _next(child_index)) < SIZE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
cx->frame_elements.size = 1;
|
||||||
|
cx->frame_elements.data[0].first = SIZE_MAX;
|
||||||
|
cx->frame_elements.data[0].prev = SIZE_MAX;
|
||||||
|
cx->frame_elements.data[0].next = SIZE_MAX;
|
||||||
|
cx->frame_elements.data[0].last = SIZE_MAX;
|
||||||
|
cx->frame_elements.data[0].parent = SIZE_MAX;
|
||||||
|
cx->current_parent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue