summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-12-03 14:47:53 -0500
committerJonathan Bradley <jcb@pikum.xyz>2025-12-03 14:47:53 -0500
commit119e1e91af301a00c1e58aa787bb8b3c0132a1f0 (patch)
tree1df248616c495ce6913d9e30b151e017664bcff3
parent06fe41bf9a2f7442893a8f03281c2ad0abb7882f (diff)
pke: font stop rendering immediately on remove
-rw-r--r--src/font.cpp21
-rw-r--r--src/static-ui.cpp20
2 files changed, 28 insertions, 13 deletions
diff --git a/src/font.cpp b/src/font.cpp
index 004e9f8..de7814a 100644
--- a/src/font.cpp
+++ b/src/font.cpp
@@ -508,6 +508,11 @@ void FontType_Tick(double delta) {
ft->gr.should_update_instance_buffer = true;
return;
}
+ // skip text if not valid.
+ // reminder: happens intentionally in FontType_RemoveStringRender.
+ if (fr->text.val == nullptr) {
+ return;
+ }
index += fr->n_glyphs;
};
pk_bkt_arr_iterate(&ft->renders, iter_fn.invoke, &iter_fn);
@@ -538,6 +543,11 @@ void FontType_Tick(double delta) {
if (fr->isMarkedForRemoval == true) {
return;
}
+ // skip text if not valid.
+ // reminder: happens intentionally in FontType_RemoveStringRender.
+ if (fr->text.val == nullptr) {
+ return;
+ }
FontType_Inner_CalcTransforms(ft, fr, &fibis[index], &index);
};
pk_bkt_arr_iterate(&ft->renders, iter_fn.invoke, &iter_fn);
@@ -1156,9 +1166,16 @@ void FontType_RemoveStringRender(FontTypeRender ftr) {
assert(pk_bkt_arr_handle_validate(&ftd.fonts, ftr.font_type_handle) == PK_BKT_ARR_HANDLE_VALIDATION_VALID);
FontType *ft = &ftd.fonts[ftr.font_type_handle];
assert(pk_bkt_arr_handle_validate(&ft->renders, ftr.font_render_handle) == PK_BKT_ARR_HANDLE_VALIDATION_VALID);
- // hack, but works
- ft->gr.should_update_instance_buffer = true;
fr = &ft->renders[ftr.font_render_handle];
+
+ // 2025-12-03 JCB
+ // This prevents text from being seen THIS tick.
+ ft->gr.should_update_instance_buffer = true;
+ if (fr->text.reserved > 0 && fr->text.val != NULL) pk_delete_arr<char>(fr->text.val, fr->text.reserved);
+ fr->text.val = nullptr;
+ fr->text.length = 0;
+ fr->text.reserved = 0;
+
ECS_MarkForRemoval(fr);
}
diff --git a/src/static-ui.cpp b/src/static-ui.cpp
index 6858905..882a3dc 100644
--- a/src/static-ui.cpp
+++ b/src/static-ui.cpp
@@ -760,7 +760,7 @@ void pke_ui_tick(double delta) {
}
void pke_ui_teardown_box_recursive(pke_ui_box *box, uint8_t depth) {
- FontRender *fr;
+ FontRender *fr = nullptr;
pke_ui_graphics_bindings_texture *bindings = nullptr;
for (pke_ui_box_count_T i = 0; i < box->internal.h_children; ++i) {
pke_ui_teardown_box_recursive(box->internal.children[i], depth + 1);
@@ -771,20 +771,10 @@ void pke_ui_teardown_box_recursive(pke_ui_box *box, uint8_t depth) {
if (box->type_data != nullptr) {
switch (box->type) {
case PKE_UI_BOX_TYPE_TEXT:
- // 2025-09-16 JCB
- // If correctly parented, this is unnecessary, but serialization does
- // not construct text boxes in this way.
- // Handle to avoid memory leaks.
fr = FontType_GetFontRender(box->type_data->text.font_type_render);
- if (fr != nullptr && fr->parentHandle != box->handle) {
- FontType_RemoveStringRender(box->type_data->text.font_type_render);
- }
break;
case PKE_UI_BOX_TYPE_BUTTON_TEXT:
fr = FontType_GetFontRender(box->type_data->button_text.font_type_render);
- if (fr != nullptr && fr->parentHandle != box->handle) {
- FontType_RemoveStringRender(box->type_data->button_text.font_type_render);
- }
break;
case PKE_UI_BOX_TYPE_BUTTON_IMAGE:
if (box->type_data->button_image.gr_binds_bkt_arr_handle != pk_bkt_arr_handle_MAX) {
@@ -824,11 +814,19 @@ void pke_ui_teardown_box_recursive(pke_ui_box *box, uint8_t depth) {
box->type_data = nullptr;
}
pk_arr_append_t<pke_ui_box*>(&pke_ui_master.boxes_to_delete, box);
+ // 2025-09-16 JCB
+ // If correctly parented, this is unnecessary, but de/serialization does
+ // not construct text boxes in this way.
+ // Handle explicitly to avoid memory leaks.
+ if (fr != nullptr && fr->parentHandle != box->handle) {
+ FontType_RemoveStringRender(FontTypeRender{fr->font_type_handle, fr->font_render_handle});
+ }
/* 2025-09-25 JCB HACK
* I'd like this to be more elegant, this seems hacky.
* We need to skip the first (the one we marked for removal).
* If we are manually managing child boxes (like deleting in the editor),
* then this can get called when depth > 0 but the box is already marked.
+ * The box at depth==0 is already marked, so only mark children.
*/
if (depth != 0 && box->isMarkedForRemoval == false) {
ECS_MarkForRemoval(box);