diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-04-09 17:20:23 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-04-09 17:20:23 -0400 |
| commit | 496637b40ec3b241a0b09ed909dd3d26f68520ab (patch) | |
| tree | 368f0a9f09e6af9df0556667b2aa168f1338bb7e | |
| parent | 3aa4bf34cf1f8a710764bfd35849c2474589bf2e (diff) | |
pke: first-pass ui box with text
| -rw-r--r-- | src/font.cpp | 25 | ||||
| -rw-r--r-- | src/font.hpp | 3 | ||||
| -rw-r--r-- | src/game.cpp | 11 | ||||
| -rw-r--r-- | src/static-ui.cpp | 42 | ||||
| -rw-r--r-- | src/static-ui.hpp | 27 |
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); |
