summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-07-31 15:15:16 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-07-31 15:15:16 -0400
commitf7d860cee74ad3b94e0d15ea157783b7760f6d55 (patch)
treec2d37ae18a4ce1a63da4010516ecc588bfb7903a /src
parent8dbacba532e05d76325392d85a75906f2de12350 (diff)
pke-ui: detect mouse clicks, other small refactors
Diffstat (limited to 'src')
-rw-r--r--src/components.hpp6
-rw-r--r--src/ecs.cpp16
-rw-r--r--src/ecs.hpp8
-rw-r--r--src/font.hpp5
-rw-r--r--src/player-input.cpp23
-rw-r--r--src/serialization-static-ui.cpp4
-rw-r--r--src/static-ui.cpp263
-rw-r--r--src/static-ui.hpp28
8 files changed, 271 insertions, 82 deletions
diff --git a/src/components.hpp b/src/components.hpp
index f9a3b51..36c3785 100644
--- a/src/components.hpp
+++ b/src/components.hpp
@@ -17,7 +17,7 @@ struct EntityHandle : public pk_bkt_arr_handle { };
struct GenericEntityHandle : public pk_bkt_arr_handle { };
struct GrBindsHandle : public pk_bkt_arr_handle { };
struct InstanceHandle : public pk_bkt_arr_handle { };
-struct PkeEventMgrHandle : public pk_bkt_arr_handle { };
+struct PkeEventHandle : public pk_bkt_arr_handle { };
struct SceneHandle : public pk_bkt_arr_handle { };
struct LevelHandle : public pk_bkt_arr_handle { };
@@ -25,7 +25,7 @@ constexpr EntityHandle EntityHandle_MAX = EntityHandle{ pk_bkt_arr_handle_MAX_co
constexpr GenericEntityHandle GenericEntityHandle_MAX = GenericEntityHandle{ pk_bkt_arr_handle_MAX_constexpr };
constexpr GrBindsHandle GrBindsHandle_MAX = GrBindsHandle{ pk_bkt_arr_handle_MAX_constexpr };
constexpr InstanceHandle InstanceHandle_MAX = InstanceHandle{ pk_bkt_arr_handle_MAX_constexpr };
-constexpr PkeEventMgrHandle PkeEventMgrHandle_MAX = PkeEventMgrHandle{ pk_bkt_arr_handle_MAX_constexpr };
+constexpr PkeEventHandle PkeEventMgrHandle_MAX = PkeEventHandle{ pk_bkt_arr_handle_MAX_constexpr };
constexpr SceneHandle SceneHandle_MAX = SceneHandle{ pk_bkt_arr_handle_MAX_constexpr };
constexpr LevelHandle LevelHandle_MAX = LevelHandle{ pk_bkt_arr_handle_MAX_constexpr };
@@ -97,7 +97,7 @@ struct pke_component_event {
const pk_ev_mgr_id_T ev_mgr_id = 0;
pk_ev_id_T ev_id;
EntityHandle entity_handle;
- PkeEventMgrHandle pke_ev_mgr_handle;
+ PkeEventHandle pke_event_handle;
pk_uuid uuid = pk_uuid_max;
};
diff --git a/src/ecs.cpp b/src/ecs.cpp
index 1ffd9f2..de8b0cd 100644
--- a/src/ecs.cpp
+++ b/src/ecs.cpp
@@ -269,7 +269,7 @@ void ECS_Tick(double delta) {
Entity_Base *ent = ecs.bc.entityPtrs[arr_obj_data->entity_handle];
if (pk_arr_find_first_index(&entitiesYetToBeRemoved, ent, ecs_pk_arr_find_first_matching_pointer) != uint32_t(-1)) {
pk_ev_destroy_mgr(arr_obj_data->ev_mgr_id);
- pk_bkt_arr_free_handle(&ecs.bc.ev_mgrs, arr_obj_data->pke_ev_mgr_handle);
+ pk_bkt_arr_free_handle(&ecs.bc.ev_mgrs, arr_obj_data->pke_event_handle);
}
};
if (entityRemovalCount > 0) {
@@ -573,14 +573,14 @@ pk_bkt_arr *ECS_GetInstances() {
return &ecs.bc.instances;
}
-pke_component_event *ECS_CreateEvManager(Entity_Base *entity, pk_uuid uuid) {
+pke_component_event *ECS_CreateEv(Entity_Base *entity, pk_uuid uuid) {
assert(entity != nullptr && entity != CAFE_BABE(Entity_Base));
- PkeEventMgrHandle ev_mgr_handle { pk_bkt_arr_new_handle(&ecs.bc.ev_mgrs) };
- auto *comp = &ecs.bc.ev_mgrs[ev_mgr_handle];
+ PkeEventHandle pke_ev_handle { pk_bkt_arr_new_handle(&ecs.bc.ev_mgrs) };
+ auto *comp = &ecs.bc.ev_mgrs[pke_ev_handle];
new (comp) pke_component_event{};
comp->entity_handle = entity->handle;
- comp->pke_ev_mgr_handle = ev_mgr_handle;
+ comp->pke_event_handle = pke_ev_handle;
comp->uuid = uuid;
if (comp->uuid == pk_uuid_zed || comp->uuid == pk_uuid_max) {
comp->uuid = pk_uuid_new_v7();
@@ -591,7 +591,7 @@ pke_component_event *ECS_CreateEvManager(Entity_Base *entity, pk_uuid uuid) {
return comp;
}
-pke_component_event *ECS_GetEvManager(PkeEventMgrHandle handle) {
+pke_component_event *ECS_GetEv(PkeEventHandle handle) {
if (handle == PkeEventMgrHandle_MAX) return nullptr;
assert(pk_bkt_arr_handle_validate(&ecs.bc.ev_mgrs, handle) == PK_BKT_ARR_HANDLE_VALIDATION_VALID);
@@ -600,7 +600,7 @@ pke_component_event *ECS_GetEvManager(PkeEventMgrHandle handle) {
return ev_mgr;
}
-void ECS_GetEvManagers(Entity_Base *entity, pk_arr_t<pke_component_event *> &arr) {
+void ECS_GetEvs(Entity_Base *entity, pk_arr_t<pke_component_event *> &arr) {
if (entity == nullptr) return;
// 2025-05-29 JCB PERF
@@ -618,7 +618,7 @@ void ECS_GetEvManagers(Entity_Base *entity, pk_arr_t<pke_component_event *> &arr
pk_bkt_arr_iterate(&ecs.bc.ev_mgrs, &CompEvMgrIterFn::invoke, &inst_iter_cb);
}
-pk_bkt_arr *ECS_GetEvManagers() {
+pk_bkt_arr *ECS_GetEvs() {
return &ecs.bc.ev_mgrs;
}
diff --git a/src/ecs.hpp b/src/ecs.hpp
index e66bfb4..20f7444 100644
--- a/src/ecs.hpp
+++ b/src/ecs.hpp
@@ -35,9 +35,9 @@ void ECS_GetInstances(Entity_Base *entity, pk_arr_t<CompInstance *> &arr);
void ECS_UpdateInstance(CompInstance *instance, const InstPos &instPos, bool overridePhysics = false);
pk_bkt_arr *ECS_GetInstances();
-pke_component_event *ECS_CreateEvManager(Entity_Base *entity, pk_uuid uuid);
-pke_component_event *ECS_GetEvManager(PkeEventMgrHandle handle);
-void ECS_GetEvManagers(Entity_Base *entity, pk_arr_t<pke_component_event *> &arr);
-pk_bkt_arr *ECS_GetEvManagers();
+pke_component_event *ECS_CreateEv(Entity_Base *entity, pk_uuid uuid);
+pke_component_event *ECS_GetEv(PkeEventHandle handle);
+void ECS_GetEvs(Entity_Base *entity, pk_arr_t<pke_component_event *> &arr);
+pk_bkt_arr *ECS_GetEvs();
#endif /* PKE_ECS_HPP */
diff --git a/src/font.hpp b/src/font.hpp
index 9d766df..127feec 100644
--- a/src/font.hpp
+++ b/src/font.hpp
@@ -41,6 +41,11 @@ struct FontRenderHandle {
FontRenderIndex index_fr;
};
+constexpr struct FontRenderHandle FontRenderHandle_MAX = {
+ .index_ft = FontTypeIndex_MAX,
+ .index_fr = FontRenderIndex_MAX,
+};
+
struct FontGlyphChar {
double advance;
glm::vec2 sprite_region_min;
diff --git a/src/player-input.cpp b/src/player-input.cpp
index 2bf412c..29297ab 100644
--- a/src/player-input.cpp
+++ b/src/player-input.cpp
@@ -46,14 +46,6 @@ GLFWwindowfocusfun prevWindowFocusCallback;
TypeSafeInt_B(pke_input_action_set_handle);
pk_arr_t<pke_input_unhandled_event> unhandled_events;
-/* nocheckin
-pk_arr_t<CursorPosEvent> unhandledCursorPosEvents{};
-pk_arr_t<CursorEnterEvent> unhandledCursorEnterEvents{};
-pk_arr_t<KeyEvent> unhandledKeyEvents{};
-pk_arr_t<MouseButtonEvent> unhandledMouseButtonEvents{};
-pk_arr_t<ScrollEvent> unhandledScrollEvents{};
-pk_arr_t<WindowFocusEvent> unhandledWindowFocusEvents{};
-*/
pk_arr_t<pke_input_event> registeredCursorEnterEvents{};
bool lastCursorEntered = false;
@@ -75,6 +67,7 @@ pke_input_action *FindActionByName(const char *actionName) {
uint32_t count = activeInputSetStack.next;
for (uint32_t i = count; i > 0; --i) {
pke_input_action_set_handle handle = activeInputSetStack[i-1];
+ if (handle == pke_input_action_set_handle_MAX) continue;
pke_input_action_set_handle_T index = static_cast<pke_input_action_set_handle_T>(handle);
pke_input_set &set = registeredInputSets[index];
for (int64_t k = 0; k < set.actionCount; ++k) {
@@ -203,6 +196,7 @@ template<pke_input_event_hash T> pke_input_event_hash FindActivepke_input_action
count = activeInputSetStack.next;
for (i = count; i > 0; --i) {
pke_input_action_set_handle handle = activeInputSetStack[i-1];
+ if (handle == pke_input_action_set_handle_MAX) continue;
pke_input_action_set_handle_T index = static_cast<pke_input_action_set_handle_T>(handle);
pke_input_set &set = registeredInputSets[index];
for (int64_t k = 0; k < set.actionCount; ++k) {
@@ -309,7 +303,6 @@ void pke_input_tick(double delta) {
// handle unhandled events
// @performance cache action->event results
// 2025-07-23 JCB I'm not sure what this perf message means.
- // I am in the process of refactoring this.
pke_input_event *primary_event = nullptr;
for (i = 0; i < unhandled_events.next; ++i) {
pke_input_unhandled_event &uh_ev = unhandled_events[i];
@@ -670,8 +663,10 @@ void pke_input_deactivate_set(pke_input_action_set_handle handle) {
break;
}
}
- assert(index >= 0 && "pke_input_deactivate_set - expected InputActionSet to be active");
- assert(index == activeInputSetStack.next - 1 && "pke_input_unregister_set - expected InputActionSet to be the last set active");
+ if (index == 0) {
+ fprintf(stderr, "[pke_input] Attempt to deactivate a non-active set.\n");
+ return;
+ }
pke_input_action_set_handle_T handleIndex{static_cast<pke_input_action_set_handle_T>(handle)};
auto &set = registeredInputSets[handleIndex];
for (int64_t i = set.actionCount - 1; i >= 0; --i) {
@@ -698,7 +693,7 @@ void pke_input_deactivate_set(pke_input_action_set_handle handle) {
}
}
}
- pk_arr_remove_at(&activeInputSetStack, activeInputSetStack.next-1);
+ pk_arr_remove_at(&activeInputSetStack, index);
}
bool PkeInput_pke_arr_find_first_handle(void *search_handle, void *list_handle) {
@@ -712,7 +707,9 @@ void pke_input_unregister_set(pke_input_action_set_handle handle) {
if (pk_arr_find_first_index(&activeInputSetStack, &handle, PkeInput_pke_arr_find_first_handle) != uint32_t(-1)) {
pke_input_deactivate_set(handle);
}
- pk_delete_arr<pke_input_action>(set.actions, set.actionCount);
+ if (set.actions != nullptr) {
+ pk_delete_arr<pke_input_action>(set.actions, set.actionCount);
+ }
pk_arr_remove_at(&registeredInputSets, index);
}
diff --git a/src/serialization-static-ui.cpp b/src/serialization-static-ui.cpp
index 1495c61..9ed86a0 100644
--- a/src/serialization-static-ui.cpp
+++ b/src/serialization-static-ui.cpp
@@ -75,7 +75,7 @@ pk_handle pke_serialize_ui_box(srlztn_serialize_helper *h, pke_ui_box *box) {
kvec.children.bkt = h->bkt;
h->handle_head.itemIndex++;
- compt_a<192==sizeof(pke_ui_box)>();
+ compt_a<208==sizeof(pke_ui_box)>();
if (box->uuid != pk_uuid_zed && box->uuid != pk_uuid_max) {
kve.key = SRLZTN_UI_BOX_UUID;
s = pk_new_arr<char>(37, h->bkt);
@@ -216,7 +216,7 @@ void pke_deserialize_ui_box(srlztn_deserialize_helper *h, pke_kve_container *kve
pke_ui_box *parent_box = nullptr;
bx.type_data = nullptr;
- compt_a<192==sizeof(pke_ui_box)>();
+ compt_a<208==sizeof(pke_ui_box)>();
for (i = 0; i < kvec->arr.next; ++i) {
kve = &kvec->arr[i];
if (strstr(SRLZTN_UI_BOX_UUID, kve->key)) {
diff --git a/src/static-ui.cpp b/src/static-ui.cpp
index da5ab2b..1e0dffb 100644
--- a/src/static-ui.cpp
+++ b/src/static-ui.cpp
@@ -10,11 +10,16 @@
#include "vendor-glm-include.hpp"
#include "window.hpp"
+#include <GLFW/glfw3.h>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <vulkan/vulkan_core.h>
+const char *const ui_ux_mouse_left = "ui_ux_mouse_left";
+const char *const ui_ux_mouse_right = "ui_ux_mouse_right";
+const char *const ui_ux_mouse_middle = "ui_ux_mouse_middle";
+
TypeSafeInt_B(PKE_UI_BOX_TYPE);
TypeSafeInt_B(PKE_UI_BOX_FLAG);
TypeSafeInt_B(PKE_UI_BOX_STATE_FLAG);
@@ -34,20 +39,75 @@ struct pke_ui_master {
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;
+ bool should_update_buffer = false;
glm::vec2 px_scale;
+ pk_arr_t<pke_input_event> events_this_tick;
+ pke_input_action_set_handle input_action_set_handle;
+ struct pke_ui_master_state {
+ const pke_input_event *mouse_left = nullptr;
+ const pke_input_event *mouse_right = nullptr;
+ const pke_input_event *mouse_middle = nullptr;
+ pke_ui_box *deepest_pressed = nullptr;
+ } state;
} pke_ui_master;
+// typedef void(*pke_box_search)(pke_ui_box &box);
+typedef std::function<void(pke_ui_box &box)> pke_box_iterate ;
+
+
+/* 2025-07-28 JCB TODO
+ * Needs PERF? Consider separate searches by need (depth/breadth).
+ * With a depth-first, if the parent kept track of how deep its children are, we could short-cut the search (assuming we're searching for depth-most)
+ */
+void pke_ui_internal_box_iterate_top_down_recursive(pke_box_iterate *iters, int n_iters, pke_ui_box **boxes, pke_ui_box_count_T box_count) {
+ pke_ui_box_count_T i;
+ int k;
+
+ for (i = 0; i < box_count; ++i) {
+ for (k = 0; k < n_iters; ++k) {
+ iters[k](*boxes[i]);
+ }
+ }
+ for (i = 0; i < box_count; ++i) {
+ pke_ui_internal_box_iterate_top_down_recursive(iters, n_iters, boxes[i]->internal.children, boxes[i]->internal.h_children);
+ }
+}
+
void pke_ui_init() {
pke_ui_master.bkt = pk_mem_bucket_create("pke ui", PK_MEM_DEFAULT_BUCKET_SIZE, PK_MEMBUCKET_FLAG_NONE);
pke_ui_master.root_boxes = pk_new_arr<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 = {};
+
+ pke_input_set ui_controls_set{};
+ ui_controls_set.title = "debug-editor-controls";
+ ui_controls_set.actionCount = 3;
+ ui_controls_set.actions = pk_new_arr<pke_input_action>(ui_controls_set.actionCount);
+ ui_controls_set.flags = PKE_INPUT_ACTION_SET_FLAG_DO_NOT_SERIALIZE;
+
+ ui_controls_set.actions[0].name = ui_ux_mouse_left;
+ ui_controls_set.actions[0].masks[0] = pke_input_event_mask {
+ .computedHash = PKE_INPUT_HASH_ALL_MOUSE_BUTTON_EVENTS,
+ .button = GLFW_MOUSE_BUTTON_LEFT,
+ };
+ ui_controls_set.actions[1].name = ui_ux_mouse_right;
+ ui_controls_set.actions[1].masks[0] = pke_input_event_mask {
+ .computedHash = PKE_INPUT_HASH_ALL_MOUSE_BUTTON_EVENTS,
+ .button = GLFW_MOUSE_BUTTON_RIGHT,
+ };
+ ui_controls_set.actions[2].name = ui_ux_mouse_middle;
+ ui_controls_set.actions[2].masks[0] = pke_input_event_mask {
+ .computedHash = PKE_INPUT_HASH_ALL_MOUSE_BUTTON_EVENTS,
+ .button = GLFW_MOUSE_BUTTON_MIDDLE,
+ };
+
+ pke_ui_master.input_action_set_handle = pke_input_register_set(ui_controls_set);
+
}
void pke_ui_force_recalc() {
- pke_ui_master.should_recalc_ui = true;
+ pke_ui_master.should_update_buffer = true;
}
void pke_ui_init_bindings() {
@@ -95,6 +155,76 @@ Some restrictions:
- this means that tables or similar need to consist of rows of columns
*/
+void pke_ui_update_state(pke_ui_box &box) {
+ double mouse_x, mouse_y;
+
+ // update state
+ PKE_UI_BOX_STATE_FLAG old_state = box.state_flags;
+ PKE_UI_BOX_STATE_FLAG flgs;
+ box.state_flags = PKE_UI_BOX_STATE_FLAG_NONE;
+
+ if (pke_ui_master.state.mouse_left == nullptr || (pke_ui_master.state.mouse_left->data.mouse_button.isPressed == false && pke_ui_master.state.mouse_left->data.mouse_button.thisTick == false)) {
+ flgs = PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_RELEASE | PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESS | PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESSED;
+ box.state_flags_mem &= ~flgs;
+ }
+
+ if (pke_ui_master.state.mouse_right == nullptr || (pke_ui_master.state.mouse_right->data.mouse_button.isPressed == false && pke_ui_master.state.mouse_right->data.mouse_button.thisTick == false)) {
+ flgs = PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_RELEASE | PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_PRESS | PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_PRESSED;
+ box.state_flags_mem &= ~flgs;
+ }
+
+ if (pke_ui_master.state.mouse_middle == nullptr || (pke_ui_master.state.mouse_middle->data.mouse_button.isPressed == false && pke_ui_master.state.mouse_middle->data.mouse_button.thisTick == false)) {
+ flgs = PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_RELEASE | PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_PRESS | PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_PRESSED;
+ box.state_flags_mem &= ~flgs;
+ }
+
+ pke_input_query_mouse_pos(mouse_x, mouse_y);
+ if (mouse_x >= box.internal.px_corner.x + box.internal.px_padding_l
+ && mouse_y >= box.internal.px_corner.y + box.internal.px_padding_t
+ && mouse_x <= box.internal.px_corner.x + box.internal.px_size.x - box.internal.px_padding_r
+ && mouse_y <= box.internal.px_corner.y + box.internal.px_size.y - box.internal.px_padding_b) {
+ box.state_flags |= PKE_UI_BOX_STATE_FLAG_MOUSE_HOVER;
+ if (!PK_HAS_FLAG(old_state, PKE_UI_BOX_STATE_FLAG_MOUSE_HOVER)) {
+ box.state_flags |= PKE_UI_BOX_STATE_FLAG_MOUSE_ENTERED;
+ }
+
+ if (pke_ui_master.state.mouse_left != nullptr && pke_ui_master.state.mouse_left->data.mouse_button.thisTick) {
+ if (pke_ui_master.state.mouse_left->data.mouse_button.isPressed) {
+ box.state_flags |= PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESS;
+ box.state_flags_mem |= PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESS;
+ } else if (PK_HAS_FLAG(box.state_flags_mem, PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESS)) {
+ box.state_flags |= PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESSED;
+ if (box.type == PKE_UI_BOX_TYPE_BUTTON_TEXT || box.type == PKE_UI_BOX_TYPE_BUTTON_IMAGE) {
+ if (pke_ui_master.state.deepest_pressed == nullptr || pke_ui_master.state.deepest_pressed->internal.depth < box.internal.depth) {
+ pke_ui_master.state.deepest_pressed = &box;
+ }
+ }
+ }
+ }
+
+ if (pke_ui_master.state.mouse_right != nullptr && pke_ui_master.state.mouse_right->data.mouse_button.thisTick) {
+ if (pke_ui_master.state.mouse_right->data.mouse_button.isPressed) {
+ box.state_flags |= PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_PRESS;
+ box.state_flags_mem |= PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_PRESS;
+ } else if (PK_HAS_FLAG(box.state_flags_mem, PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_PRESS)) {
+ box.state_flags |= PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_PRESSED;
+ }
+ }
+
+ if (pke_ui_master.state.mouse_middle != nullptr && pke_ui_master.state.mouse_middle->data.mouse_button.thisTick) {
+ if (pke_ui_master.state.mouse_middle->data.mouse_button.isPressed) {
+ box.state_flags |= PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_PRESS;
+ box.state_flags_mem |= PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_PRESS;
+ } else if (PK_HAS_FLAG(box.state_flags_mem, PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_PRESS)) {
+ box.state_flags |= PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_PRESSED;
+ }
+ }
+
+ } else if (PK_HAS_FLAG(old_state, PKE_UI_BOX_STATE_FLAG_MOUSE_HOVER)) {
+ box.state_flags |= PKE_UI_BOX_STATE_FLAG_MOUSE_EXITED;
+ }
+}
+
struct pke_ui_flex_params {
float px_per_unit;
float unit_total;
@@ -117,6 +247,9 @@ void pke_ui_calc_px(pk_arr_t<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl
assert(box->min_size.x <= box->max_size.x);
assert(box->min_size.y <= box->max_size.y);
+ PKE_UI_BOX_STATE_FLAG prev_state_flags = box->state_flags;
+ PKE_UI_BOX_STATE_FLAG prev_state_flags_mem = box->state_flags_mem;
+
if (box->internal.parent != nullptr) {
parent_pos_and_offset.x = box->internal.parent->internal.px_corner.x
+ box->internal.parent->internal.px_padding_l;
@@ -218,6 +351,11 @@ void pke_ui_calc_px(pk_arr_t<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl
}
}
+ pke_ui_update_state(*box);
+ if (prev_state_flags != box->state_flags || prev_state_flags_mem != box->state_flags_mem) {
+ pke_ui_master.should_update_buffer = true;
+ }
+
if (PK_HAS_FLAG(box->flags, PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE)) {
return;
}
@@ -252,33 +390,7 @@ void pke_ui_calc_px(pk_arr_t<pke_ui_box_instance_buffer_item> &buffer, pke_ui_fl
pk_arr_append_t(&buffer, tmp);
}
-void pke_ui_update_state_recursive(pke_ui_box *box, uint8_t depth = 0) {
- (void)depth;
- double mouse_x, mouse_y;
-
- // update state
- PKE_UI_BOX_STATE_FLAG old_state = box->state_flags;
- box->state_flags = PKE_UI_BOX_STATE_FLAG_NONE;
-
- pke_input_query_mouse_pos(mouse_x, mouse_y);
- if (mouse_x >= box->internal.px_corner.x + box->internal.px_padding_l
- && mouse_y >= box->internal.px_corner.y + box->internal.px_padding_t
- && mouse_x <= box->internal.px_corner.x + box->internal.px_size.x - box->internal.px_padding_r
- && mouse_y <= box->internal.px_corner.y + box->internal.px_size.y - box->internal.px_padding_b) {
- box->state_flags |= PKE_UI_BOX_STATE_FLAG_MOUSE_HOVER;
- if (!PK_HAS_FLAG(old_state, PKE_UI_BOX_STATE_FLAG_MOUSE_HOVER)) {
- box->state_flags |= PKE_UI_BOX_STATE_FLAG_MOUSE_ENTERED;
- }
- } else if (PK_HAS_FLAG(old_state, PKE_UI_BOX_STATE_FLAG_MOUSE_HOVER)) {
- box->state_flags |= PKE_UI_BOX_STATE_FLAG_MOUSE_EXITED;
- }
-
- for (pke_ui_box_count_T i = 0; i < box->internal.h_children; ++i) {
- pke_ui_update_state_recursive(box->internal.children[i], depth + 1);
- }
-}
-
-void pke_ui_recalc_sizes_recursive(pk_arr_t<pke_ui_box_instance_buffer_item> &arr, pke_ui_box *box, uint8_t depth = 0) {
+void pke_ui_recalc_sizes_recursive(pk_arr_t<pke_ui_box_instance_buffer_item> &arr, pke_ui_box *box) {
PKE_UI_BOX_FLAG_T flags_masked;
uint8_t flex_count = 0;
pke_ui_flex_params flex_params{};
@@ -309,7 +421,7 @@ void pke_ui_recalc_sizes_recursive(pk_arr_t<pke_ui_box_instance_buffer_item> &ar
for (pke_ui_box_count_T i = 0; i < box->internal.h_children; ++i) {
pke_ui_calc_px(arr, &flex_params, box->internal.children[i]);
- pke_ui_recalc_sizes_recursive(arr, box->internal.children[i], depth + 1);
+ pke_ui_recalc_sizes_recursive(arr, box->internal.children[i]);
}
}
@@ -407,22 +519,44 @@ void pke_ui_tick(double delta) {
(void)delta;
pke_ui_box_count_T i;
if (pke_ui_master.h_root_boxes == 0) return;
- if (pke_ui_master.should_recalc_ui == true || pkeSettings.rt.was_framebuffer_resized == true) {
- pk_arr_t<pke_ui_box_instance_buffer_item> arr;
- 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 (i = 0; i < pke_ui_master.h_root_boxes; ++i) {
- pke_ui_box *box = pke_ui_master.root_boxes[i];
- pke_ui_calc_px(arr, nullptr, box);
- pke_ui_recalc_sizes_recursive(arr, box, 0);
- }
+
+ pke_ui_master.state.mouse_left = pke_input_query_by_action_name(ui_ux_mouse_left);
+ pke_ui_master.state.mouse_right = pke_input_query_by_action_name(ui_ux_mouse_right);
+ pke_ui_master.state.mouse_middle = pke_input_query_by_action_name(ui_ux_mouse_middle);
+ pke_ui_master.state.deepest_pressed = nullptr;
+
+ pk_arr_t<pke_ui_box_instance_buffer_item> arr;
+ pke_ui_master.px_scale = glm::vec2(
+ 2.0 / (float)Extent.width,
+ 2.0 / (float)Extent.height
+ );
+ for (i = 0; i < pke_ui_master.h_root_boxes; ++i) {
+ pke_ui_box *box = pke_ui_master.root_boxes[i];
+ pke_ui_calc_px(arr, nullptr, box);
+ pke_ui_recalc_sizes_recursive(arr, box);
+ }
+
+ if (pke_ui_master.should_update_buffer || pkeSettings.rt.was_framebuffer_resized) {
+ pke_ui_master.should_update_buffer = false;
pke_ui_update_instance_buffer(arr);
}
- for (i = 0; i < pke_ui_master.h_root_boxes; ++i) {
- pke_ui_update_state_recursive(pke_ui_master.root_boxes[i], 0);
+
+ if (pke_ui_master.state.deepest_pressed != NULL) {
+ // fprintf(stdout, "box: " pk_uuid_printf_format " pressed!\n", pk_uuid_printf_var(pke_ui_master.state.deepest_pressed->uuid));
+ struct pke_component_event *component_event = nullptr;
+ switch (pke_ui_master.state.deepest_pressed->type) {
+ case PKE_UI_BOX_TYPE_BUTTON_TEXT:
+ component_event = ECS_GetEv(pke_ui_master.state.deepest_pressed->type_data->button_text.pke_event_handle);
+ break;
+ case PKE_UI_BOX_TYPE_BUTTON_IMAGE:
+ component_event = ECS_GetEv(pke_ui_master.state.deepest_pressed->type_data->button_image.pke_event_handle);
+ break;
+ default:
+ fprintf(stderr, "[static-ui] Something was pressed but we didn't know the type and couldn't emit.");
+ }
+ if (component_event != nullptr) {
+ pk_ev_emit(component_event->ev_mgr_id, component_event->ev_id, nullptr);
+ }
}
}
@@ -433,6 +567,7 @@ void pke_ui_teardown_box_recursive(pke_ui_box *box) {
if (box->internal.children != nullptr) {
pk_delete_arr<pke_ui_box *>(box->internal.children, box->internal.r_children);
}
+ pke_ui_master.should_update_buffer = true;
}
void pke_ui_teardown() {
@@ -483,6 +618,8 @@ void pke_ui_teardown() {
if (pke_ui_master.bindings.deviceMemoryVert != VK_NULL_HANDLE)
vkFreeMemory(vkDevice, pke_ui_master.bindings.deviceMemoryVert, vkAllocator);
pke_ui_master.bindings.deviceMemoryVert = VK_NULL_HANDLE;
+
+ pke_input_unregister_set(pke_ui_master.input_action_set_handle);
}
pke_ui_box **pke_ui_get_root_boxes(pke_ui_box_count_T *count) {
@@ -493,22 +630,48 @@ pke_ui_box **pke_ui_get_root_boxes(pke_ui_box_count_T *count) {
void pke_ui_internal_new_typed_box(pke_ui_box *box, const PKE_UI_BOX_TYPE type) {
assert(box->type == type);
+ pke_ui_box_type_data *tp_data = nullptr;
+ pke_component_event *pressed_ev = nullptr;
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>(pke_ui_master.bkt);
+ tp_data = pk_new<pke_ui_box_type_data>(pke_ui_master.bkt);
box->flags |= PKE_UI_BOX_FLAG_VISIBILITY_INVISIBLE;
break;
case PKE_UI_BOX_TYPE_INPUT_TEXT:
break;
+ case PKE_UI_BOX_TYPE_BUTTON_TEXT:
+ tp_data = pk_new<pke_ui_box_type_data>(pke_ui_master.bkt);
+ tp_data->button_text.font_render_handle = FontRenderHandle_MAX;
+ pressed_ev = ECS_CreateEv(box, pk_uuid_max);
+ tp_data->button_text.pke_event_handle = pressed_ev->pke_event_handle;
+ tp_data->button_text.ev_id = pressed_ev->ev_id;
+ break;
+ case PKE_UI_BOX_TYPE_BUTTON_IMAGE:
+ tp_data = pk_new<pke_ui_box_type_data>(pke_ui_master.bkt);
+ tp_data->button_image.image_memory = VK_NULL_HANDLE;
+ tp_data->button_image.image_default = VK_NULL_HANDLE;
+ tp_data->button_image.image_view_default = VK_NULL_HANDLE;
+ tp_data->button_image.image_hovered = VK_NULL_HANDLE;
+ tp_data->button_image.image_view_hovered = VK_NULL_HANDLE;
+ tp_data->button_image.image_pressed = VK_NULL_HANDLE;
+ tp_data->button_image.image_view_pressed = VK_NULL_HANDLE;
+ pressed_ev = ECS_CreateEv(box, pk_uuid_max);
+ tp_data->button_image.pke_event_handle = pressed_ev->pke_event_handle;
+ tp_data->button_image.ev_id = pressed_ev->ev_id;
+ break;
default:
assert(true == false && "unknown pke_ui_box::type");
break;
}
+ box->type_data = tp_data;
}
pke_ui_box *pke_ui_box_new_root(const PKE_UI_BOX_TYPE type, pk_uuid uuid) {
+ if (pke_ui_master.h_root_boxes == 0) {
+ pke_input_activate_set(pke_ui_master.input_action_set_handle);
+ }
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;
@@ -523,11 +686,12 @@ pke_ui_box *pke_ui_box_new_root(const PKE_UI_BOX_TYPE type, pk_uuid uuid) {
*box = {};
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;
+ pke_ui_master.should_update_buffer = true;
box->type = type;
- pke_ui_internal_new_typed_box(box, type);
box->uuid = uuid;
+ box->internal.depth = 0;
ECS_CreateEntity(box, nullptr);
+ pke_ui_internal_new_typed_box(box, type);
return box;
}
@@ -559,10 +723,11 @@ pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent, const PKE_UI_BOX_TYPE type,
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);
+ box->internal.depth = parent->internal.depth + 1;
box->uuid = uuid;
ECS_CreateEntity(box, parent);
+ pke_ui_internal_new_typed_box(box, type);
+ pke_ui_master.should_update_buffer = true;
return box;
}
diff --git a/src/static-ui.hpp b/src/static-ui.hpp
index adc410a..3abfd26 100644
--- a/src/static-ui.hpp
+++ b/src/static-ui.hpp
@@ -82,6 +82,24 @@ const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_MOUSE_EXITED
= PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 1));
const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_MOUSE_HOVER
= PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 2));
+const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESS
+ = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 3));
+const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_RELEASE
+ = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 4));
+const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_PRIMARY_PRESSED
+ = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 5));
+const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_PRESS
+ = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 6));
+const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_RELEASE
+ = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 7));
+const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_SECONDARY_PRESSED
+ = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 8));
+const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_PRESS
+ = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 9));
+const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_RELEASE
+ = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 10));
+const PKE_UI_BOX_STATE_FLAG PKE_UI_BOX_STATE_FLAG_ON_BTN_MIDDLE_PRESSED
+ = PKE_UI_BOX_STATE_FLAG((PKE_UI_BOX_STATE_FLAG_T(1) << 11));
typedef uint16_t pke_ui_box_count_T;
@@ -100,6 +118,7 @@ struct pke_ui_box : public Entity_Base {
glm::vec4 color_background = glm::vec4(0.2, 0.3, 0.2, 0.5);
union pke_ui_box_type_data *type_data;
PKE_UI_BOX_STATE_FLAG state_flags;
+ PKE_UI_BOX_STATE_FLAG state_flags_mem;
struct pke_ui_box_internals {
// the exact px to translate (shader)
glm::vec2 px_corner;
@@ -112,6 +131,7 @@ struct pke_ui_box : public Entity_Base {
pke_ui_box **children;
pke_ui_box_count_T h_children;
pke_ui_box_count_T r_children;
+ uint8_t depth;
} internal;
};
@@ -122,7 +142,8 @@ union pke_ui_box_type_data {
} text;
struct pke_ui_box_type_data_button_text {
FontRenderHandle font_render_handle;
- pk_ev_id_T ev_mgr;
+ PkeEventHandle pke_event_handle;
+ pk_ev_id_T ev_id;
} button_text;
struct pke_ui_box_type_data_button_image {
VkDeviceMemory image_memory;
@@ -132,7 +153,8 @@ union pke_ui_box_type_data {
VkImageView image_view_hovered;
VkImage image_pressed;
VkImageView image_view_pressed;
- pk_ev_id_T ev_mgr;
+ PkeEventHandle pke_event_handle;
+ pk_ev_id_T ev_id;
} button_image;
};
@@ -161,7 +183,7 @@ pke_ui_box *pke_ui_box_new_child(pke_ui_box *parent, const PKE_UI_BOX_TYPE type
#ifdef PKE_TEST_EXPOSE
void pke_ui_calc_px(pk_arr_t<pke_ui_box_instance_buffer_item> &buffer, pke_ui_flex_params *flex_params, pke_ui_box *box);
-void pke_ui_recalc_sizes_recursive(pk_arr_t<pke_ui_box_instance_buffer_item> &arr, pke_ui_box *box, uint8_t depth = 0);
+void pke_ui_recalc_sizes_recursive(pk_arr_t<pke_ui_box_instance_buffer_item> &arr, pke_ui_box *box);
#endif
pke_ui_graphics_bindings *pke_ui_get_graphics_bindings();