summaryrefslogtreecommitdiff
path: root/src/static-ui.cpp
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-03-12 17:26:48 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-03-12 17:26:48 -0400
commit85a2ba407b1ae285b4080e14f8a18ecf4ec7da2c (patch)
tree0abe7044b6af5820e9f3c143733047b254e78e15 /src/static-ui.cpp
parent68ef51ed3247dc4e7bd5970b9279a7d6a938ca52 (diff)
pke: more testing features + more ui flex work
Diffstat (limited to 'src/static-ui.cpp')
-rw-r--r--src/static-ui.cpp91
1 files changed, 66 insertions, 25 deletions
diff --git a/src/static-ui.cpp b/src/static-ui.cpp
index 01af0db..fff8ecc 100644
--- a/src/static-ui.cpp
+++ b/src/static-ui.cpp
@@ -83,14 +83,19 @@ Some restrictions:
- this means that tables or similar need to consist of rows of columns
*/
-void pke_ui_calc_px(pke_ui_box *box, DynArray<pke_ui_box_instance_buffer_item> &buffer) {
+struct pke_ui_flex_params {
+ float px_per_unit;
+ float unit_total;
+};
+
+void pke_ui_calc_px(DynArray<pke_ui_box_instance_buffer_item> &buffer, pke_ui_flex_params *flex_params, pke_ui_box *box) {
assert(box != nullptr);
- static const float built_in_offset = 2.0;
glm::vec2 px_size;
+ glm::vec2 px_min_size;
+ glm::vec2 px_max_size;
glm::vec2 parent_size_padded;
glm::vec2 parent_pos_and_offset;
- assert(PK_HAS_FLAG(box->flags, PKE_UI_BOX_FLAG_POSITION_TYPE_ALL));
assert(box->pos_top_left_x >= 0.0);
assert(box->pos_top_left_y >= 0.0);
assert(box->max_width >= 0.0);
@@ -114,7 +119,20 @@ void pke_ui_calc_px(pke_ui_box *box, DynArray<pke_ui_box_instance_buffer_item> &
px_size = glm::vec2(Extent.width, Extent.height);
}
+ px_min_size.x = box->min_width;
+ px_min_size.y = box->min_height;
+ px_max_size.x = box->max_width;
+ px_max_size.y = box->max_height;
+ box->internal.px_corner_x = 0
+ + parent_pos_and_offset.x
+ + box->pos_top_left_x;
+ box->internal.px_corner_y = 0
+ + parent_pos_and_offset.y
+ + box->pos_top_left_y;
+
if (PK_HAS_FLAG(box->flags, PKE_UI_BOX_FLAG_POSITION_TYPE_FLEX)) {
+ assert(flex_params != nullptr);
+ assert(box->internal.parent != nullptr);
// TODO - think through how to organize this.
// It's almost like the parent needs to set the widths/heights of the children
// In every other method, the child determines its size,
@@ -122,19 +140,14 @@ void pke_ui_calc_px(pke_ui_box *box, DynArray<pke_ui_box_instance_buffer_item> &
// Could pass a struct around with all the needed details:
// - width or height per weight unit, current used weight or current offset
// Parent should assert that all or none of the children are position type flex?
- px_size.x = PK_CLAMP(parent_size_padded.x, box->min_width, box->max_width);
- px_size.y = PK_CLAMP(parent_size_padded.y, box->min_height, box->max_height);
+ if (box->internal.parent->flex_direction == 0) {
+ px_size.x = flex_params->px_per_unit * box->flex_weight;
+ } else {
+ px_size.y = flex_params->px_per_unit * box->flex_weight;
+ }
} else if (PK_HAS_FLAG(box->flags, PKE_UI_BOX_FLAG_POSITION_TYPE_STATIC)) {
px_size.x -= box->pos_top_left_x;
px_size.y -= box->pos_top_left_y;
- box->internal.px_corner_x = 0
- + parent_pos_and_offset.x
- + box->pos_top_left_x;
- box->internal.px_corner_y = 0
- + parent_pos_and_offset.y
- + box->pos_top_left_y;
- px_size.x = PK_CLAMP(parent_size_padded.x, box->min_width, box->max_width);
- px_size.y = PK_CLAMP(parent_size_padded.y, box->min_height, box->max_height);
} else {
assert(box->pos_top_left_x < 1.0);
assert(box->pos_top_left_y < 1.0);
@@ -144,33 +157,43 @@ void pke_ui_calc_px(pke_ui_box *box, DynArray<pke_ui_box_instance_buffer_item> &
float px_top = px_size.y * box->pos_top_left_y;
box->internal.px_corner_x += px_left;
box->internal.px_corner_y += px_top;
- px_size -= px_left;
- px_size -= px_top;
- px_size.x = PK_CLAMP(parent_size_padded.x, box->min_width * parent_size_padded.x, box->max_width * parent_size_padded.x);
- px_size.y = PK_CLAMP(parent_size_padded.y, box->min_height * parent_size_padded.y, box->max_height * parent_size_padded.y);
+ px_size.x -= px_left;
+ px_size.y -= px_top;
+ px_min_size.x = box->min_width * parent_size_padded.x;
+ px_min_size.y = box->min_height * parent_size_padded.y;
+ px_max_size.x = box->max_width * parent_size_padded.x;
+ px_max_size.y = box->max_height * parent_size_padded.y;
}
+
+ px_size = glm::clamp(px_size, px_min_size, px_max_size);
+
// built-in padding
box->internal.px_offset_x = built_in_offset;
box->internal.px_offset_y = built_in_offset;
if (PK_HAS_FLAG(box->flags, PKE_UI_BOX_FLAG_CENTER_HORIZONTAL)) {
if (parent_size_padded.x > px_size.x) {
- box->internal.px_offset_x += (parent_size_padded.x - px_size.x) / 2.0;
+ box->internal.px_corner_x += (parent_size_padded.x - px_size.x) / 2.0;
}
}
if (PK_HAS_FLAG(box->flags, PKE_UI_BOX_FLAG_CENTER_VERTICAL)) {
if (parent_size_padded.y > px_size.y) {
- box->internal.px_offset_y += (parent_size_padded.y - px_size.y) / 2.0;
+ box->internal.px_corner_y += (parent_size_padded.y - px_size.y) / 2.0;
}
}
box->internal.px_width = px_size.x;
box->internal.px_height = px_size.y;
if (box->internal.parent != nullptr) {
+ box->internal.parent->internal.px_offset_x += px_size.x;
box->internal.parent->internal.px_offset_y += px_size.y;
}
+ if (PK_HAS_FLAG(box->flags, PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE)) {
+ return;
+ }
+
// update buffer
glm::vec3 scale = glm::vec3(box->internal.px_width / (float)Extent.width, box->internal.px_height / (float)Extent.height, 1.0);
glm::vec3 translate = glm::vec3(1);
@@ -200,17 +223,35 @@ void pke_ui_calc_px(pke_ui_box *box, DynArray<pke_ui_box_instance_buffer_item> &
void pke_ui_recalc_sizes_recursive(DynArray<pke_ui_box_instance_buffer_item> &arr, pke_ui_box *box, uint8_t depth = 0) {
uint64_t flags_masked;
+ uint8_t flex_count = 0;
+ pke_ui_flex_params flex_params{};
+
+ flags_masked = box->flags & (PKE_UI_BOX_FLAG_POSITION_TYPE_ALL);
+ if (flags_masked == 0b000 || flags_masked == 0b011 || flags_masked == 0b101 || flags_masked == 0b110 || flags_masked == 0b111) {
+ fprintf(stderr, "[%s] ui box invalid flags: position type", __FILE__);
+ return;
+ }
for (pke_ui_box_count_T i = 0; i < box->internal.h_children; ++i) {
- flags_masked = box->flags & (PKE_UI_BOX_FLAG_POSITION_TYPE_ALL);
- if (flags_masked == 0 || flags_masked == 3 || flags_masked == 5 || flags_masked == 6 || flags_masked == 7) {
- fprintf(stderr, "[%s] ui box invalid flags: position", __FILE__);
- return;
+ if (PK_HAS_FLAG(box->internal.children[i]->flags, PKE_UI_BOX_FLAG_POSITION_TYPE_FLEX)) {
+ flex_count += 1;
+ flex_params.unit_total += box->internal.children[i]->flex_weight;
}
}
+ if (flex_count != 0 && flex_count != box->internal.h_children) {
+ fprintf(stderr, "[%s] ui box invalid flags: if one child is type FLEX, then all children must be type FLEX", __FILE__);
+ return;
+ }
+ if (flex_count != 0) {
+ flex_params.px_per_unit =
+ box->flex_direction == 0
+ ? box->internal.px_width / flex_params.unit_total
+ : box->internal.px_height / flex_params.unit_total;
+ }
+
for (pke_ui_box_count_T i = 0; i < box->internal.h_children; ++i) {
- pke_ui_calc_px(box->internal.children[i], arr);
+ pke_ui_calc_px(arr, &flex_params, box->internal.children[i]);
pke_ui_recalc_sizes_recursive(arr, box->internal.children[i], depth + 1);
}
}
@@ -316,7 +357,7 @@ void pke_ui_tick(double delta) {
);
for (pke_ui_box_count_T i = 0; i < pke_ui_master.h_root_boxes; ++i) {
pke_ui_box *box = pke_ui_master.root_boxes[i];
- pke_ui_calc_px(box, arr);
+ pke_ui_calc_px(arr, nullptr, box);
pke_ui_recalc_sizes_recursive(arr, box, 0);
}
pke_ui_update_instance_buffer(arr);