diff options
| -rw-r--r-- | src/static-ui.cpp | 71 | ||||
| -rw-r--r-- | src/static-ui.hpp | 19 | ||||
| -rw-r--r-- | tests/pke-test-static-ui.cpp | 48 |
3 files changed, 75 insertions, 63 deletions
diff --git a/src/static-ui.cpp b/src/static-ui.cpp index fff8ecc..7df5a34 100644 --- a/src/static-ui.cpp +++ b/src/static-ui.cpp @@ -106,12 +106,17 @@ void pke_ui_calc_px(DynArray<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl assert(box->min_height <= box->max_height); if (box->internal.parent != nullptr) { - parent_pos_and_offset.x = box->internal.parent->internal.px_corner_x + box->internal.parent->internal.px_offset_x; - parent_pos_and_offset.y = box->internal.parent->internal.px_corner_y + box->internal.parent->internal.px_offset_y; - parent_size_padded.x = box->internal.parent->internal.px_width; - parent_size_padded.y = box->internal.parent->internal.px_height; + parent_pos_and_offset.x = box->internal.parent->internal.px_corner.x + + box->internal.parent->internal.px_padding_l; + parent_pos_and_offset.y = box->internal.parent->internal.px_corner.y + + box->internal.parent->internal.px_padding_t; + parent_size_padded.x = box->internal.parent->internal.px_size.x; + parent_size_padded.y = box->internal.parent->internal.px_size.y; // built-in padding - parent_size_padded -= glm::vec2(built_in_offset * 2); + parent_size_padded.x -= box->internal.parent->internal.px_padding_l + + box->internal.parent->internal.px_padding_r; + parent_size_padded.y -= box->internal.parent->internal.px_padding_t + + box->internal.parent->internal.px_padding_b; px_size = parent_size_padded; } else { parent_pos_and_offset = glm::vec2(0); @@ -123,23 +128,16 @@ void pke_ui_calc_px(DynArray<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl 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 + box->internal.px_corner.x = 0 + parent_pos_and_offset.x + box->pos_top_left_x; - box->internal.px_corner_y = 0 + 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, - // in flex, the parent sums the weights and distributes the available size. - // 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? if (box->internal.parent->flex_direction == 0) { px_size.x = flex_params->px_per_unit * box->flex_weight; } else { @@ -151,12 +149,12 @@ void pke_ui_calc_px(DynArray<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl } else { assert(box->pos_top_left_x < 1.0); assert(box->pos_top_left_y < 1.0); - box->internal.px_corner_x = parent_pos_and_offset.x; - box->internal.px_corner_y = parent_pos_and_offset.y; + box->internal.px_corner.x = parent_pos_and_offset.x; + box->internal.px_corner.y = parent_pos_and_offset.y; float px_left = px_size.x * box->pos_top_left_x; 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; + box->internal.px_corner.x += px_left; + box->internal.px_corner.y += px_top; px_size.x -= px_left; px_size.y -= px_top; px_min_size.x = box->min_width * parent_size_padded.x; @@ -168,26 +166,33 @@ void pke_ui_calc_px(DynArray<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl 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; + box->internal.px_padding_l = built_in_offset; + box->internal.px_padding_b = built_in_offset; + box->internal.px_padding_r = built_in_offset; + box->internal.px_padding_t = 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_corner_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_corner_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; + box->internal.px_size.x = px_size.x; + box->internal.px_size.y = 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; + // TODO change this based on the parent's 'direction' + // 2025-03-13 JCB + // optional: auto-wrapping boxes possible if we keep track of two sizes: + // - remaining in active row/column + // - unused space + // box->internal.parent->internal.px_padding_l += px_size.x; + box->internal.parent->internal.px_padding_t += px_size.y; } if (PK_HAS_FLAG(box->flags, PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE)) { @@ -195,20 +200,20 @@ void pke_ui_calc_px(DynArray<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl } // 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 scale = glm::vec3(box->internal.px_size.x / (float)Extent.width, box->internal.px_size.y / (float)Extent.height, 1.0); glm::vec3 translate = glm::vec3(1); // ((val) - (width/2)) / (width/2) // place left line of box at edge of screen - translate.x = (box->internal.px_width / 2.0); + translate.x = (box->internal.px_size.x / 2.0); // box position - translate.x += box->internal.px_corner_x; + translate.x += box->internal.px_corner.x; translate.x -= ((float)Extent.width / 2.0); translate.x /= ((float)Extent.width / 2.0); // ((val) - (height/2)) / (height/2) // place top line of box at edge of screen - translate.y = (box->internal.px_height / 2.0); + translate.y = (box->internal.px_size.y / 2.0); // box position - translate.y += box->internal.px_corner_y; + translate.y += box->internal.px_corner.y; translate.y -= ((float)Extent.height / 2.0); translate.y /= ((float)Extent.height / 2.0); translate.z = 0; @@ -246,8 +251,8 @@ void pke_ui_recalc_sizes_recursive(DynArray<pke_ui_box_instance_buffer_item> &ar 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; + ? box->internal.px_size.x / flex_params.unit_total + : box->internal.px_size.y / flex_params.unit_total; } for (pke_ui_box_count_T i = 0; i < box->internal.h_children; ++i) { diff --git a/src/static-ui.hpp b/src/static-ui.hpp index a9b751b..6586a02 100644 --- a/src/static-ui.hpp +++ b/src/static-ui.hpp @@ -2,6 +2,8 @@ #define PKE_STATIC_UI_HPP #include "components-vk.hpp" +#include "vendor-glm-include.hpp" + #include <cstdint> #define built_in_offset 2.0 @@ -16,18 +18,19 @@ struct MSDFGlyphSettings { enum PKE_UI_BOX_FLAGS : uint64_t { PKE_UI_BOX_FLAG_NONE = 0, - // position type [0-4] + // [00-04] position type // exact screen coordinates PKE_UI_BOX_FLAG_POSITION_TYPE_FLEX = (1 << 0), PKE_UI_BOX_FLAG_POSITION_TYPE_STATIC = (1 << 1), PKE_UI_BOX_FLAG_POSITION_TYPE_DYNAMIC = (1 << 2), PKE_UI_BOX_FLAG_POSITION_TYPE_ALL = (1 << 0) | (1 << 1) | (1 << 2), - // center [5-6] + // [05-06] center PKE_UI_BOX_FLAG_CENTER_HORIZONTAL = (1 << 5), PKE_UI_BOX_FLAG_CENTER_VERTICAL = (1 << 6), PKE_UI_BOX_FLAG_CENTER_BOTH = (1 << 5) | (1 << 6), - // visibility [7-9] + // [07-09] visibility PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE = (1 << 7), + // [10-??] }; typedef uint16_t pke_ui_box_count_T; @@ -43,9 +46,13 @@ struct pke_ui_box { uint8_t flex_direction; uint8_t layer; struct pke_ui_box_internals { - float px_corner_x, px_corner_y; - float px_width, px_height; - float px_offset_x, px_offset_y; + // the exact px to translate (shader) + glm::vec2 px_corner; + // the exact px for scaling (shader) + glm::vec2 px_size; + // internal padding + running offset for adding children + // glm::vec4 px_padding; + float px_padding_l, px_padding_b, px_padding_r, px_padding_t; pke_ui_box *parent; pke_ui_box **children; pke_ui_box_count_T h_children; diff --git a/tests/pke-test-static-ui.cpp b/tests/pke-test-static-ui.cpp index 43ce76d..9ca4cdd 100644 --- a/tests/pke-test-static-ui.cpp +++ b/tests/pke-test-static-ui.cpp @@ -58,15 +58,15 @@ int pke_test_static_ui_000() { PKE_TEST_ASSERT(c_ui_box->internal.h_children == 0, err_index); PKE_TEST_ASSERT(c_ui_box->internal.r_children == 0, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_corner_x == 10, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_corner_y == 10, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_corner_x == calculated_offset, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_corner_y == calculated_offset, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_corner.x == 10, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_corner.y == 10, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_corner.x == calculated_offset, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_corner.y == calculated_offset, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_width == 500, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_height == 500, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_width == 100, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_height == 100, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_size.x == 500, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_size.y == 500, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_size.x == 100, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_size.y == 100, err_index); return 0; } @@ -109,18 +109,18 @@ int pke_test_static_ui_100() { PKE_TEST_ASSERT(c_ui_box->internal.h_children == 0, err_index); PKE_TEST_ASSERT(c_ui_box->internal.r_children == 0, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_corner_x == Extent.width * 0.1, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_corner_y == Extent.height * 0.1, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_corner_x == calculated_offset_x, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_corner_y == calculated_offset_y, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_corner.x == Extent.width * 0.1, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_corner.y == Extent.height * 0.1, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_corner.x == calculated_offset_x, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_corner.y == calculated_offset_y, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_width == (Extent.width * 0.1) * 8, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_height == (Extent.height * 0.1) * 8, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_size.x == (Extent.width * 0.1) * 8, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_size.y == (Extent.height * 0.1) * 8, err_index); // TODO rounding? // using a debugger, the actual and calculated values are ~0.01 off // this is either a real issue or a rounding issue, either here or within pke - PKE_TEST_ASSERT(c_ui_box->internal.px_width == (ui_box->internal.px_width - (built_in_offset * 2)) * 0.8, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_height == (ui_box->internal.px_height - (built_in_offset * 2)) * 0.8, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_size.x == (ui_box->internal.px_size.x - (built_in_offset * 2)) * 0.8, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_size.y == (ui_box->internal.px_size.y - (built_in_offset * 2)) * 0.8, err_index); return 0; } @@ -162,15 +162,15 @@ int pke_test_static_ui_200() { PKE_TEST_ASSERT(c_ui_box->internal.h_children == 0, err_index); PKE_TEST_ASSERT(c_ui_box->internal.r_children == 0, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_corner_x == Extent.width * 0.1, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_corner_y == Extent.height * 0.1, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_corner_x == calculated_offset_x, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_corner_y == calculated_offset_y, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_corner.x == Extent.width * 0.1, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_corner.y == Extent.height * 0.1, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_corner.x == calculated_offset_x, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_corner.y == calculated_offset_y, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_width == (Extent.width * 0.1) * 8, err_index); - PKE_TEST_ASSERT(ui_box->internal.px_height == (Extent.height * 0.1) * 8, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_width == 300, err_index); - PKE_TEST_ASSERT(c_ui_box->internal.px_height == 300, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_size.x == (Extent.width * 0.1) * 8, err_index); + PKE_TEST_ASSERT(ui_box->internal.px_size.y == (Extent.height * 0.1) * 8, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_size.x == 300, err_index); + PKE_TEST_ASSERT(c_ui_box->internal.px_size.y == 300, err_index); return 0; } |
