diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-07-24 12:38:28 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-07-24 12:38:28 -0400 |
| commit | 8dbacba532e05d76325392d85a75906f2de12350 (patch) | |
| tree | d7dd4e847af200ff407740ca1d3c26dfb1682098 /src | |
| parent | 13bb74998afda740bf61df8ddd14c76539937a3b (diff) | |
pke: ui: update state on mouse hover
Diffstat (limited to 'src')
| -rw-r--r-- | src/player-input.cpp | 43 | ||||
| -rw-r--r-- | src/player-input.hpp | 5 | ||||
| -rw-r--r-- | src/static-ui.cpp | 34 |
3 files changed, 81 insertions, 1 deletions
diff --git a/src/player-input.cpp b/src/player-input.cpp index 412be75..2bf412c 100644 --- a/src/player-input.cpp +++ b/src/player-input.cpp @@ -441,6 +441,49 @@ const pke_input_event *pke_input_query_by_action_name(const char *actionName) { return ev; } +void pke_input_query_by_mask(pke_input_event_mask mask, pke_input_event &ev) { + pke_input_event_hash type = mask.computedHash & PKE_INPUT_HASH_ALL_EVENTS; + switch (type) { + case PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER: + /* no-op */ + break; + case PKE_INPUT_HASH_EVENT_TYPE_CURSOR_POS: + /* no-op */ + break; + case PKE_INPUT_HASH_EVENT_TYPE_KEY: + ev.type = PKE_INPUT_HASH_EVENT_TYPE_KEY; + ev.sourceSet = pke_input_action_set_handle_MAX; + ev.data.key.button = mask.button; + ev.data.key.isPressed = bool(glfwGetKey(window, mask.button)); + ev.data.key.mods = 0; + ev.data.key.thisTick = false; + break; + case PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON: + ev.type = PKE_INPUT_HASH_EVENT_TYPE_MOUSE_BUTTON; + ev.sourceSet = pke_input_action_set_handle_MAX; + ev.data.mouse_button.button = mask.button; + ev.data.mouse_button.isPressed = bool(glfwGetMouseButton(window, mask.button)); + ev.data.mouse_button.mods = 0; + ev.data.mouse_button.thisTick = false; + break; + case PKE_INPUT_HASH_EVENT_TYPE_SCROLL: + /* no-op */ + break; + case PKE_INPUT_HASH_EVENT_TYPE_WINDOW_FOCUS: + /* no-op */ + break; + default: + fprintf(stderr, "[pke_input_query_by_mask] unhandled input type: %i", pke_input_event_hash_T(type)); + break; + } + return; +} + +void pke_input_query_mouse_pos(double &x, double &y) { + x = lastMousePos.x; + y = lastMousePos.y; +} + void CursorEnterCallback(GLFWwindow *window, int entered) { if (registeredCursorEnterEvents.next) { pk_arr_append_t(&unhandled_events, { .type = PKE_INPUT_HASH_EVENT_TYPE_CURSOR_ENTER, .data = { .cursor_enter = { .entered = bool(entered) } } }); diff --git a/src/player-input.hpp b/src/player-input.hpp index 2e8517c..6145a22 100644 --- a/src/player-input.hpp +++ b/src/player-input.hpp @@ -114,6 +114,11 @@ struct pke_input_set { void pke_input_tick(double delta); const pke_input_event *pke_input_query_by_action_name(const char *actionName); +// note: must be called from main thread (per glfw) +// note: does not return `mods` nor `thisTick` +// note: only supports keyboard and mouse buttons +void pke_input_query_by_mask(pke_input_event_mask mask, pke_input_event &ev); +void pke_input_query_mouse_pos(double &x, double &y); void pke_input_init(); pke_input_action_set_handle pke_input_register_set(const pke_input_set &set); void pke_input_activate_set(pke_input_action_set_handle handle); diff --git a/src/static-ui.cpp b/src/static-ui.cpp index 1abd6b2..da5ab2b 100644 --- a/src/static-ui.cpp +++ b/src/static-ui.cpp @@ -5,6 +5,7 @@ #include "font.hpp" #include "game-settings.hpp" #include "pk.h" +#include "player-input.hpp" #include "static-plane.hpp" #include "vendor-glm-include.hpp" #include "window.hpp" @@ -16,6 +17,7 @@ TypeSafeInt_B(PKE_UI_BOX_TYPE); TypeSafeInt_B(PKE_UI_BOX_FLAG); +TypeSafeInt_B(PKE_UI_BOX_STATE_FLAG); struct pke_ui_box_instance_buffer_item { glm::mat4 pos_scale; @@ -250,6 +252,32 @@ 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) { PKE_UI_BOX_FLAG_T flags_masked; uint8_t flex_count = 0; @@ -377,6 +405,7 @@ void pke_ui_update_instance_buffer(pk_arr_t<pke_ui_box_instance_buffer_item> &ar 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; @@ -385,13 +414,16 @@ void pke_ui_tick(double delta) { 2.0 / (float)Extent.width, 2.0 / (float)Extent.height ); - for (pke_ui_box_count_T i = 0; i < pke_ui_master.h_root_boxes; ++i) { + 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_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); + } } void pke_ui_teardown_box_recursive(pke_ui_box *box) { |
