diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-07-31 15:15:16 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-07-31 15:15:16 -0400 |
| commit | f7d860cee74ad3b94e0d15ea157783b7760f6d55 (patch) | |
| tree | c2d37ae18a4ce1a63da4010516ecc588bfb7903a /src | |
| parent | 8dbacba532e05d76325392d85a75906f2de12350 (diff) | |
pke-ui: detect mouse clicks, other small refactors
Diffstat (limited to 'src')
| -rw-r--r-- | src/components.hpp | 6 | ||||
| -rw-r--r-- | src/ecs.cpp | 16 | ||||
| -rw-r--r-- | src/ecs.hpp | 8 | ||||
| -rw-r--r-- | src/font.hpp | 5 | ||||
| -rw-r--r-- | src/player-input.cpp | 23 | ||||
| -rw-r--r-- | src/serialization-static-ui.cpp | 4 | ||||
| -rw-r--r-- | src/static-ui.cpp | 263 | ||||
| -rw-r--r-- | src/static-ui.hpp | 28 |
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(®isteredInputSets, 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(); |
