From 46dd8625120376fd538e4a23dd3de3b65c23ca32 Mon Sep 17 00:00:00 2001 From: Patrick Cleavelin Date: Mon, 18 Mar 2024 17:04:48 -0500 Subject: [PATCH] yup layouting...stil need to clean up a few things --- src/main.c | 31 +++++----- src/ui.h | 165 +++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 132 insertions(+), 64 deletions(-) diff --git a/src/main.c b/src/main.c index e230d85..30a91e5 100644 --- a/src/main.c +++ b/src/main.c @@ -307,33 +307,36 @@ void ed_init() { }, }); - queue_text(_String("But what even is text! []!@#$%^&*()_=+"), (float[]){ 0, 0 }); - queue_text(_String("v0.1.0"), (float[]){ 32, 128 }); - queue_text(_String("an_editor - what even"), (float[]){ 32, 256 }); + // queue_text(_String("But what even is text! []!@#$%^&*()_=+"), (float[]){ 0, 0 }); + // queue_text(_String("v0.1.0"), (float[]){ 32, 128 }); + // 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"); - ht_set(&state.ui_cx.cached_elements, label, &(ui_element_cache_data) { - .label = label, - .size = { - .axis = UI_AXIS_HORIZONTAL, - .computed_size = { 200, 256 }, - } - }); + ui_element(&state.ui_cx, label); + ui_element(&state.ui_cx, _String("ui element 2")); + ui_element(&state.ui_cx, _String("ui element 3")); + 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) { if (state.ui_cx.cached_elements.key_slots[i].key.data != NULL) { string text = state.ui_cx.cached_elements.key_slots[i].key; ui_element_cache_data *value = ht_get(&state.ui_cx.cached_elements, text); 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) { sg_update_buffer(state.bind.vertex_buffers[1], &(sg_range) { .ptr = state.gpu_glyphs.data, diff --git a/src/ui.h b/src/ui.h index cd44bd9..37d1131 100644 --- a/src/ui.h +++ b/src/ui.h @@ -9,7 +9,7 @@ #define _FONT_WIDTH 16 #define _FONT_HEIGHT 32 -#define _elm(index) (&cx->frame_elements.data[index]) +#define _elm(index) (cx->frame_elements.data+index) #define _flags(index, flgs) ((_elm(index)->flags & (flgs)) == (flgs)) #define _first(index) (_elm(index)->first) @@ -110,11 +110,29 @@ void ui_compute_layout(ui_context *cx, size_t element_index); #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)); 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) { .cached_elements = cached_elements, .frame_elements = frame_elements, @@ -135,6 +153,8 @@ size_t ui_element(ui_context *cx, string label) { .next = -1, .prev = cx->frame_elements.data[cx->current_parent].last, .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 @@ -153,10 +173,10 @@ size_t ui_element(ui_context *cx, string label) { pushArray(ui_element_frame_data, &cx->frame_elements, frame_data); - if (frame_data.prev >= 0) { + if (frame_data.prev < SIZE_MAX) { _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)->last = frame_data.index; @@ -165,7 +185,9 @@ size_t ui_element(ui_context *cx, string label) { } static uint32_t _ui_ancestor_size(ui_context *cx, size_t element_index, ui_axis axis) { - if (element_index < 0 || _parent(element_index) < 0) return 0; + 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: @@ -214,7 +236,7 @@ static void _ui_compute_simple_layout(ui_context *cx, ui_element_frame_data *elm 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 @@ -226,35 +248,39 @@ static void _ui_compute_children_layout(ui_context *cx, ui_element_frame_data *e uint32_t elm_size[2] = { elm->size.computed_size[0], elm->size.computed_size[1] }; size_t child_index = elm->first; - do { - ui_compute_layout(cx, child_index); + 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)) >= 0); + 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; - do { - for (size_t axis = UI_AXIS_HORIZONTAL; axis < UI_AXIS_VERTICAL; ++axis) { - if (_elm(child_index)->size.semantic_size[axis].type == UI_SEMANTIC_SIZE_FILL) { - _elm(child_index)->size.computed_pos[axis] = (elm_size[axis] - child_size[axis]) / num_fills[axis]; + 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)) >= 0); + 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 <= 0) return; + if (element_index == SIZE_MAX) return; ui_axis axis = UI_AXIS_HORIZONTAL; __auto_type elm = _elm(element_index); - if (_parent(element_index) >= 0 && (_elm(element_index)->flags & UI_FLAG_FLOATING) > 0) { + if (_parent(element_index) < SIZE_MAX && !_flags(element_index, UI_FLAG_FLOATING)) { __auto_type parent = _parent_ref(element_index); axis = parent->size.axis; elm->size.computed_pos[0] = parent->size.computed_pos[0]; @@ -264,16 +290,19 @@ void ui_compute_layout(ui_context *cx, size_t element_index) { // elm->size.computed_pos[axis] += parent.scroll_offset; } - if (!_flags(element_index, UI_FLAG_FLOATING) && _prev(element_index) >= 0) { + if (!_flags(element_index, UI_FLAG_FLOATING) && _prev(element_index) < SIZE_MAX) { __auto_type prev = _prev_ref(element_index); - if (prev>= 0) { + if (prev >= 0) { elm->size.computed_pos[axis] = prev->size.computed_pos[axis] + prev->size.computed_size[axis]; } } bool post_compute[2] = { false, false }; - _ui_compute_simple_layout(cx, elm, UI_AXIS_HORIZONTAL, post_compute); + // 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 @@ -282,41 +311,77 @@ void ui_compute_layout(ui_context *cx, size_t element_index) { elm->size.computed_size[UI_AXIS_HORIZONTAL] = 0; size_t child_index = elm->first; - do { - __auto_type child = _elm(child_index); + 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; + 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)) >= 0); + 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); - 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)) >= 0); + 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