summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-04-09 17:20:23 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-04-09 17:20:23 -0400
commit496637b40ec3b241a0b09ed909dd3d26f68520ab (patch)
tree368f0a9f09e6af9df0556667b2aa168f1338bb7e
parent3aa4bf34cf1f8a710764bfd35849c2474589bf2e (diff)
pke: first-pass ui box with text
-rw-r--r--src/font.cpp25
-rw-r--r--src/font.hpp3
-rw-r--r--src/game.cpp11
-rw-r--r--src/static-ui.cpp42
-rw-r--r--src/static-ui.hpp27
5 files changed, 98 insertions, 10 deletions
diff --git a/src/font.cpp b/src/font.cpp
index 0335017..03ca3fd 100644
--- a/src/font.cpp
+++ b/src/font.cpp
@@ -218,8 +218,20 @@ void FontType_Inner_CalcTransforms(const FontType *ft, FontRender *fr, FontInsta
buf_item->bg_color = glm::vec4(0.0, 0.0, 0.0, 0.0);
buf_item->sprite_region_min = fgc->sprite_region_min;
buf_item->sprite_region_max = fgc->sprite_region_max;
- buf_item->bounding_region_min = glm::vec2(-1.1, -1.1);
- buf_item->bounding_region_max = glm::vec2(1.1, 1.1);
+
+ buf_item->bounding_region_min.x = fr->settings.surface_area_pos.x;
+ buf_item->bounding_region_min.y = fr->settings.surface_area_pos.y;
+ buf_item->bounding_region_max.x = fr->settings.surface_area_pos.x + fr->settings.surface_area_size.x;
+ buf_item->bounding_region_max.y = fr->settings.surface_area_pos.y + fr->settings.surface_area_size.y;
+ buf_item->bounding_region_min.x -= (Extent.width / 2.0);
+ buf_item->bounding_region_min.x /= (Extent.width / 2.0);
+ buf_item->bounding_region_max.x -= (Extent.width / 2.0);
+ buf_item->bounding_region_max.x /= (Extent.width / 2.0);
+ buf_item->bounding_region_min.y -= (Extent.height / 2.0);
+ buf_item->bounding_region_min.y /= (Extent.height / 2.0);
+ buf_item->bounding_region_max.y -= (Extent.height / 2.0);
+ buf_item->bounding_region_max.y /= (Extent.height / 2.0);
+
buf_item->width =
(fr->settings.char_scale / ft->msdf_settings.minimum_scale)
* ft->msdf_settings.px_range;
@@ -926,6 +938,15 @@ FontRenderHandle FontType_AddStringRender(FontTypeIndex idx_ft, const pk_str str
return fr->handle;
}
+void FontType_UpdateStringRender(FontRenderHandle frh, FontRenderSettings *settings) {
+ assert(settings != nullptr);
+ assert((FontTypeIndex_T)ftd.h_ft > (FontTypeIndex_T)frh.index_ft);
+ FontType *ft = &ftd.arr_ft[(FontTypeIndex_T)frh.index_ft];
+ assert((FontRenderIndex_T)ft->h_render > (FontRenderIndex_T)frh.index_fr);
+ ft->gr.should_update_instance_buffer = true;
+ ft->renders[(FontRenderIndex_T)frh.index_fr].settings = *settings;
+}
+
void FontType_RemoveStringRender(FontRenderHandle handle) {
FontRender *fr;
uint32_t buffer_start_index;
diff --git a/src/font.hpp b/src/font.hpp
index 562ecae..56977de 100644
--- a/src/font.hpp
+++ b/src/font.hpp
@@ -112,6 +112,7 @@ FontType* FontType_GetFonts(FontTypeIndex &count);
FontTypeIndex FontType_RegisterFont(pk_cstr title, AssetHandle fontTextureHandle, AssetHandle glyphsHandle, FontTypeMSDFSettings *msdf_settings, FontTypeSpacing *spacing);
void FontType_Unload(FontTypeIndex idx);
FontRenderHandle FontType_AddStringRender(FontTypeIndex idx_ft, pk_str str, FontRenderSettings *settings);
-void FontType_RemoveStringRender(FontRenderHandle fr);
+void FontType_UpdateStringRender(FontRenderHandle frh, FontRenderSettings *settings);
+void FontType_RemoveStringRender(FontRenderHandle frh);
#endif /* PKE_FONT_TYPE_HPP */
diff --git a/src/game.cpp b/src/game.cpp
index 03ea495..b5bb0a0 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -169,6 +169,8 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) {
pk_cstr test_text2 = cstring_to_pk_cstr("+0123456\n789\tThe quick brown fox jumped over the lazy dog.");
FontTypeIndex font_type_count;
FontRenderSettings fr_set;
+ FontRenderHandle fr_1;
+ FontRenderHandle fr_2;
fr_set.char_scale = 9 * 7.0;
fr_set.line_height_scale = 1.0;
fr_set.char_spacing_scale = 1.0;
@@ -178,12 +180,12 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) {
fr_set.surface_area_pos.y = 1080 / 3.0;
fr_set.surface_area_type_flags = FONT_RENDER_SURFACE_AREA_TYPE_FLAGS_NONE;
if ((FontType_GetFonts(font_type_count)); font_type_count != FontTypeIndex{0}) {
- FontType_AddStringRender(FontTypeIndex{0}, pk_cstr_to_pk_str(&test_text), &fr_set);
+ fr_1 = FontType_AddStringRender(FontTypeIndex{0}, pk_cstr_to_pk_str(&test_text), &fr_set);
}
if ((FontType_GetFonts(font_type_count)); font_type_count > FontTypeIndex{1}) {
fr_set.surface_area_pos.y *= 2;
fr_set.surface_area_size.y = 1080 - fr_set.surface_area_pos.y;
- FontType_AddStringRender(FontTypeIndex{1}, pk_cstr_to_pk_str(&test_text2), &fr_set);
+ fr_2 = FontType_AddStringRender(FontTypeIndex{1}, pk_cstr_to_pk_str(&test_text2), &fr_set);
}
// TODO remove me: temp stuff for testing
@@ -195,12 +197,15 @@ void Game_Main(PKEWindowProperties windowProps, const char *executablePath) {
ui_box->max_height = 0.8;
// TODO remove me: temp stuff for testing
- pke_ui_box *c_ui_box = pke_ui_box_new_child(ui_box);
+ pke_ui_box *c_ui_box = pke_ui_box_new_child(ui_box, PKE_UI_BOX_TYPE_TEXT);
c_ui_box->flags = PKE_UI_BOX_FLAG_POSITION_TYPE_STATIC;
c_ui_box->pos_top_left_x = 20;
c_ui_box->pos_top_left_y = 20;
c_ui_box->max_width = 3000;
c_ui_box->max_height = 3000;
+ pke_ui_box_type_data_text *box_text = reinterpret_cast<pke_ui_box_type_data_text*>(c_ui_box->type_data);
+ box_text->font_render_handle = fr_1;
+ box_text->font_render_settings = fr_set;
GameTimePoint lastTimePoint = pkeSettings.steadyClock.now();
double deltaTillNextRender = pkeSettings.deltaPerFrame;
diff --git a/src/static-ui.cpp b/src/static-ui.cpp
index f05a8dd..1c089b9 100644
--- a/src/static-ui.cpp
+++ b/src/static-ui.cpp
@@ -224,6 +224,17 @@ void pke_ui_calc_px(DynArray<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl
buffer_item->px_scale.x = (2.0 / (float)Extent.width);
buffer_item->px_scale.y = (2.0 / (float)Extent.height);
buffer_item->depth = (float)box->layer;
+
+ if (box->type_data == nullptr) return;
+
+ // type-specific changes
+ if (box->type == PKE_UI_BOX_TYPE_TEXT) {
+ pke_ui_box_type_data_text *data_text = reinterpret_cast<pke_ui_box_type_data_text*>(box->type_data);
+ data_text->font_render_settings.surface_area_pos = box->internal.px_corner;
+ data_text->font_render_settings.surface_area_size = box->internal.px_size;
+ FontType_UpdateStringRender(data_text->font_render_handle, &data_text->font_render_settings);
+ return;
+ }
}
void pke_ui_recalc_sizes_recursive(DynArray<pke_ui_box_instance_buffer_item> &arr, pke_ui_box *box, uint8_t depth = 0) {
@@ -429,7 +440,22 @@ void pke_ui_teardown() {
pke_ui_master.bindings.deviceMemoryVert = VK_NULL_HANDLE;
}
-pke_ui_box *pke_ui_box_new_root() {
+void pke_ui_internal_new_typed_box(pke_ui_box *box, const PKE_UI_BOX_TYPE type) {
+ assert(box->type == type);
+ switch (type) {
+ case PKE_UI_BOX_TYPE_STANDARD:
+ break;
+ case PKE_UI_BOX_TYPE_TEXT:
+ box->type_data = pk_new<pke_ui_box_type_data_text>(pke_ui_master.bkt);
+ break;
+ case PKE_UI_BOX_TYPE_INPUT_TEXT:
+ break;
+ default:
+ break;
+ }
+}
+
+pke_ui_box *pke_ui_box_new_root(const PKE_UI_BOX_TYPE type) {
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;
@@ -445,11 +471,21 @@ pke_ui_box *pke_ui_box_new_root() {
pke_ui_master.root_boxes[pke_ui_master.h_root_boxes] = box;
pke_ui_master.h_root_boxes += 1;
pke_ui_master.should_recalc_ui = true;
+ box->type = type;
+ pke_ui_internal_new_typed_box(box, type);
return box;
}
-pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent) {
+pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent, const PKE_UI_BOX_TYPE type) {
assert(parent != nullptr);
+
+ // validation
+ if (parent->type >= PKE_UI_BOX_TYPE_TEXT) {
+ // this might be too broad, alter if needed
+ fprintf(stdout, "[pke_ui_box_new_child] Validation error: PKE_UI_BOX_TYPE_TEXT cannot have children.");
+ return 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_MAX(parent->internal.r_children * 1.5, 2);
@@ -466,8 +502,10 @@ pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent) {
memset(box, 0, sizeof(pke_ui_box));
parent->internal.children[parent->internal.h_children] = box;
parent->internal.h_children += 1;
+ box->type = type;
box->internal.parent = parent;
pke_ui_master.should_recalc_ui = true;
+ pke_ui_internal_new_typed_box(box, type);
return box;
}
diff --git a/src/static-ui.hpp b/src/static-ui.hpp
index 6586a02..3d64ce8 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 "font.hpp"
+#include "pk.h"
#include "vendor-glm-include.hpp"
#include <cstdint>
@@ -16,6 +18,20 @@ struct MSDFGlyphSettings {
float range_em;
};
+enum PKE_UI_BOX_TYPE : uint8_t {
+ // layouts
+ PKE_UI_BOX_TYPE_STANDARD = 000,
+ // TODO columns, rows, tabs, etc
+
+ // special (content)
+ PKE_UI_BOX_TYPE_TEXT = 050,
+ // TODO image, render target, etc
+
+ // inputs
+ PKE_UI_BOX_TYPE_INPUT_TEXT = 100, // TODO
+ // TODO multi-line text, scalar, float, slider, button, etc
+};
+
enum PKE_UI_BOX_FLAGS : uint64_t {
PKE_UI_BOX_FLAG_NONE = 0,
// [00-04] position type
@@ -43,8 +59,10 @@ struct pke_ui_box {
float min_width, min_height;
float max_width, max_height;
float flex_weight;
+ PKE_UI_BOX_TYPE type;
uint8_t flex_direction;
uint8_t layer;
+ void *type_data;
struct pke_ui_box_internals {
// the exact px to translate (shader)
glm::vec2 px_corner;
@@ -60,6 +78,11 @@ struct pke_ui_box {
} internal;
};
+struct pke_ui_box_type_data_text {
+ FontRenderHandle font_render_handle;
+ FontRenderSettings font_render_settings;
+};
+
struct pke_ui_graphics_bindings {
VkDeviceMemory deviceMemoryVert = VK_NULL_HANDLE;
VkDeviceMemory deviceMemoryInst = VK_NULL_HANDLE;
@@ -77,8 +100,8 @@ void pke_ui_init_bindings();
void pke_ui_tick(double delta);
void pke_ui_teardown();
-pke_ui_box *pke_ui_box_new_root();
-pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent);
+pke_ui_box *pke_ui_box_new_root(const PKE_UI_BOX_TYPE type = PKE_UI_BOX_TYPE_STANDARD);
+pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent, const PKE_UI_BOX_TYPE type = PKE_UI_BOX_TYPE_STANDARD);
#ifdef PKE_TEST_EXPOSE
void pke_ui_calc_px(DynArray<pke_ui_box_instance_buffer_item> &buffer, pke_ui_flex_params *flex_params, pke_ui_box *box);