summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-07-24 12:38:28 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-07-24 12:38:28 -0400
commit8dbacba532e05d76325392d85a75906f2de12350 (patch)
treed7dd4e847af200ff407740ca1d3c26dfb1682098 /src
parent13bb74998afda740bf61df8ddd14c76539937a3b (diff)
pke: ui: update state on mouse hover
Diffstat (limited to 'src')
-rw-r--r--src/player-input.cpp43
-rw-r--r--src/player-input.hpp5
-rw-r--r--src/static-ui.cpp34
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) {