summaryrefslogtreecommitdiff
path: root/src/static-ui.cpp
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-02-28 22:33:58 -0500
committerJonathan Bradley <jcb@pikum.xyz>2025-02-28 22:33:58 -0500
commit37347bf7811a5fa42c98e2a19adfee15252ee479 (patch)
tree70fe178ad777f52404f51b90c06b8d14ef101276 /src/static-ui.cpp
parent85bbecbdebf4f096418aea1cd4f9616f9d97e451 (diff)
pke: checkpoint: vk renames + first-pass ui
Renamed pipeline and descriptor names to be more self-descriptive. UI work is not done, and will not record. Needs vulkan items created (buffers).
Diffstat (limited to 'src/static-ui.cpp')
-rw-r--r--src/static-ui.cpp200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/static-ui.cpp b/src/static-ui.cpp
new file mode 100644
index 0000000..0c5d124
--- /dev/null
+++ b/src/static-ui.cpp
@@ -0,0 +1,200 @@
+
+#include "static-ui.hpp"
+
+#include "pk.h"
+#include "vendor-glm-include.hpp"
+#include "window.hpp"
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+
+struct pke_ui_box_instance_buffer_item {
+ glm::mat4 pos_scale;
+ glm::vec2 px_scale;
+ float depth;
+ float padding[1];
+};
+
+struct pke_ui_master {
+ pk_membucket *bkt;
+ pke_ui_box **root_boxes;
+ pke_ui_box_count_T h_root_boxes;
+ pke_ui_box_count_T r_root_boxes;
+ pke_ui_graphics_bindings bindings;
+ bool should_recalc_ui = false;
+ glm::vec2 px_scale;
+} pke_ui_master;
+
+void pke_ui_init() {
+ pke_ui_master.bkt = pk_bucket_create("pke ui", PK_DEFAULT_BUCKET_SIZE, false);
+ pke_ui_master.root_boxes = pk_new<pke_ui_box*>(1, pke_ui_master.bkt);
+ pke_ui_master.h_root_boxes = 0;
+ pke_ui_master.r_root_boxes = 1;
+ pke_ui_master.bindings = {};
+}
+
+void pke_ui_init_bindings() {
+ // TODO vulkan
+}
+
+/* UI layout notes
+Some restrictions:
+- children cannot change the size of a parent, parents must be sized manually
+ - e.g.: exact font width
+ - consider writing a method to calculate text
+*/
+
+void pke_ui_calc_px(pke_ui_box *box) {
+ assert(box != nullptr);
+ glm::vec2 size;
+ glm::vec2 parent_pos_and_offset;
+
+ assert(box->pos_top_left_x >= 0.0);
+ assert(box->pos_top_left_y >= 0.0);
+ assert(box->max_width >= 0.0);
+ assert(box->max_height >= 0.0);
+
+ 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;
+ size.x = box->internal.parent->internal.px_width - box->internal.parent->internal.px_offset_x;
+ size.y = box->internal.parent->internal.px_height - box->internal.parent->internal.px_offset_y;
+ // built-in padding
+ size -= glm::vec2(2);
+ } else {
+ parent_pos_and_offset = glm::vec2(0);
+ size = glm::vec2(Extent.width, Extent.height);
+ }
+
+ if (PK_HAS_FLAG(box->flags, PKE_UI_BOX_FLAG_POSITION_TYPE_STATIC)) {
+ size.x -= box->pos_top_left_x;
+ 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;
+ } 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;
+ float px_left = size.x * box->pos_top_left_x;
+ float px_top = size.y * box->pos_top_left_y;
+ box->internal.px_corner_x += px_left;
+ box->internal.px_corner_y += px_top;
+ size -= px_left;
+ size -= px_top;
+ }
+ size.x = PK_MIN(size.x, box->max_width);
+ size.y = PK_MIN(size.y, box->max_height);
+ if (box->internal.parent != nullptr) {
+ box->internal.parent->internal.px_offset_y += size.y;
+ }
+ // built-in padding
+ box->internal.px_offset_x = 1;
+ box->internal.px_offset_y = 1;
+ box->internal.px_width = size.x;
+ box->internal.px_height = size.y;
+}
+
+void pke_ui_recalc_sizes_recursive(pke_ui_box *box, uint8_t depth = 0) {
+ uint64_t flags_masked;
+
+ for (pke_ui_box_count_T i = 0; i < box->internal.h_children; ++i) {
+ flags_masked = box->flags & (PKE_UI_BOX_FLAG_POSITION_TYPE_BOTH);
+ if (flags_masked == 0 || flags_masked == PKE_UI_BOX_FLAG_POSITION_TYPE_BOTH) {
+ fprintf(stderr, "[%s] ui box invalid flags: position", __FILE__);
+ return;
+ }
+ }
+
+ for (pke_ui_box_count_T i = 0; i < box->internal.h_children; ++i) {
+ pke_ui_calc_px(box->internal.children[i]);
+ pke_ui_recalc_sizes_recursive(box->internal.children[i], depth + 1);
+ }
+}
+
+void pke_ui_tick(double delta) {
+ (void)delta;
+ if (pke_ui_master.should_recalc_ui == true) {
+ pke_ui_master.should_recalc_ui = false;
+ pke_ui_master.px_scale = glm::vec2(
+ 2.0 / (float)Extent.width,
+ 2.0 / (float)Extent.height
+ );
+ 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);
+ pke_ui_recalc_sizes_recursive(box, 0);
+ }
+ }
+}
+
+void pke_ui_teardown_box_recursive(pke_ui_box *box) {
+ for (pke_ui_box_count_T i = 0; i < box->internal.h_children; ++i) {
+ pke_ui_teardown_box_recursive(box->internal.children[i]);
+ }
+ if (box->internal.children != nullptr) {
+ pk_delete<pke_ui_box *>(box->internal.children, box->internal.r_children);
+ }
+}
+
+void pke_ui_teardown() {
+ for (pke_ui_box_count_T i = 0; i < pke_ui_master.h_root_boxes; ++i) {
+ pke_ui_teardown_box_recursive(pke_ui_master.root_boxes[i]);
+ }
+ pk_delete<pke_ui_box *>(pke_ui_master.root_boxes, pke_ui_master.r_root_boxes);
+ pk_bucket_destroy(pke_ui_master.bkt);
+ pke_ui_master.bkt = nullptr;
+ pke_ui_master.root_boxes = nullptr;
+ pke_ui_master.h_root_boxes = 0;
+ pke_ui_master.r_root_boxes = 0;
+ // TODO vulkan
+}
+
+pke_ui_box *pke_ui_box_new_root() {
+ if (pke_ui_master.h_root_boxes == pke_ui_master.r_root_boxes) {
+ pke_ui_box_count_T prev_r_root_boxes = pke_ui_master.r_root_boxes;
+ pke_ui_master.r_root_boxes *= 1.5;
+ pke_ui_box **boxes = pk_new<pke_ui_box*>(pke_ui_master.r_root_boxes);
+ for (pke_ui_box_count_T i = 0; i < pke_ui_master.h_root_boxes; ++i) {
+ boxes[i] = pke_ui_master.root_boxes[i];
+ }
+ pk_delete<pke_ui_box*>(pke_ui_master.root_boxes, prev_r_root_boxes);
+ pke_ui_master.root_boxes = boxes;
+ }
+ pke_ui_box *box = pk_new<pke_ui_box>(pke_ui_master.bkt);
+ memset(box, 0, sizeof(pke_ui_box));
+ pke_ui_master.root_boxes[pke_ui_master.h_root_boxes] = box;
+ pke_ui_master.h_root_boxes += 1;
+ return box;
+}
+
+pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent) {
+ assert(parent != nullptr);
+ if (parent->internal.h_children == parent->internal.r_children) {
+ pke_ui_box_count_T prev_r_children = parent->internal.r_children;
+ parent->internal.r_children *= PK_MIN(1.5, 2);
+ pke_ui_box **boxes = pk_new<pke_ui_box*>(parent->internal.r_children);
+ for (pke_ui_box_count_T i = 0; i < parent->internal.h_children; ++i) {
+ boxes[i] = parent->internal.children[i];
+ }
+ if (parent->internal.children != nullptr) {
+ pk_delete<pke_ui_box*>(parent->internal.children, prev_r_children);
+ }
+ parent->internal.children = boxes;
+ }
+ pke_ui_box *box = pk_new<pke_ui_box>(pke_ui_master.bkt);
+ memset(box, 0, sizeof(pke_ui_box));
+ parent->internal.children[parent->internal.h_children] = box;
+ parent->internal.h_children += 1;
+ box->internal.parent = parent;
+ return box;
+}
+
+pke_ui_graphics_bindings *pke_ui_get_graphics_bindings() {
+ return &pke_ui_master.bindings;
+}