From 8ce8f8a0dd755298e8ced40cc3911d4a20f54366 Mon Sep 17 00:00:00 2001 From: MrLetsplay2003 Date: Tue, 12 Sep 2023 17:53:56 +0200 Subject: [PATCH] Fix UI click/hover --- src/kekengine/cpp/common/defaults.cpp | 52 ++++++++++++++++++++++----- src/kekengine/cpp/ui/ui.cpp | 16 ++------- src/kekengine/include/ui.h | 4 +-- src/kekgame/cpp/kekgame.cpp | 9 +++++ 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/src/kekengine/cpp/common/defaults.cpp b/src/kekengine/cpp/common/defaults.cpp index 37d2d63..0f20cda 100644 --- a/src/kekengine/cpp/common/defaults.cpp +++ b/src/kekengine/cpp/common/defaults.cpp @@ -27,10 +27,49 @@ static void defaultInput(GLFWwindow *window, void *data) { kekData.player->controller->update(); } -static void doUIMouse(double x, double y) { +static void doUIMouseHover(double x, double y) { + UIElement *hoveredElement = nullptr; + for(UIElement *element : kekData.ui->elements) { UIPoint childPos = element->getPosition(); - if(element->hoverAll(UIPoint((int) x - childPos.x, (int) y - childPos.y), UIPoint((int) x, (int) y))) break; + UIPoint hoveredAt = UIPoint((int) x - childPos.x, (int) y - childPos.y); + + UIBounds bounds = element->getBounds(); + if(!bounds.contains(hoveredAt)) continue; + + hoveredElement = element; + } + + for(UIElement *element : kekData.ui->elements) { + if(element->hovering && element != hoveredElement) { + element->hoverExitAll(); + } + } + + if(hoveredElement) { + UIPoint childPos = hoveredElement->getPosition(); + UIPoint hoveredAt = UIPoint((int) x - childPos.x, (int) y - childPos.y); + hoveredElement->hoverAll(hoveredAt, UIPoint((int) x, (int) y)); + } +} + +static void doUIMouseClick(double x, double y, GLFWMouseButton button) { + UIElement *clickedElement = nullptr; + + for(UIElement *element : kekData.ui->elements) { + UIPoint childPos = element->getPosition(); + UIPoint clickedAt = UIPoint((int) x - childPos.x, (int) y - childPos.y); + + UIBounds bounds = element->getBounds(); + if(!bounds.contains(clickedAt)) continue; + + clickedElement = element; + } + + if(clickedElement) { + UIPoint childPos = clickedElement->getPosition(); + UIPoint clickedAt = UIPoint((int) x - childPos.x, (int) y - childPos.y); + clickedElement->clickAll(clickedAt, UIPoint((int) x, (int) y), button); } } @@ -48,7 +87,7 @@ static void defaultKeyCallback(GLFWwindow *window, int key, int scancode, int ac Input::setCursorMode(GLFWCursorMode::FREE); double x, y; glfwGetCursorPos(kekData.window, &x, &y); - doUIMouse(x, y); + doUIMouseHover(x, y); }else { Input::setCursorMode(GLFWCursorMode::CAPTURE); @@ -96,7 +135,7 @@ static void defaultMouseCallback(GLFWwindow *window, double x, double y, void *d case GLFWCursorMode::FREE: case GLFWCursorMode::HIDDEN: { - doUIMouse(x, y); + doUIMouseHover(x, y); break; } } @@ -119,10 +158,7 @@ static void defaultMouseButtonCallback(GLFWwindow* window, int button, int actio { double x, y; glfwGetCursorPos(window, &x, &y); - for(UIElement *element : kekData.ui->elements) { - UIPoint childPos = element->getPosition(); - if(element->clickAll(UIPoint((int) x - childPos.x, (int) y - childPos.y), UIPoint((int) x, (int) y), (GLFWMouseButton) button)) break; - } + doUIMouseClick(x, y, (GLFWMouseButton) button); } } diff --git a/src/kekengine/cpp/ui/ui.cpp b/src/kekengine/cpp/ui/ui.cpp index 25c9d7a..97fd15e 100644 --- a/src/kekengine/cpp/ui/ui.cpp +++ b/src/kekengine/cpp/ui/ui.cpp @@ -139,13 +139,7 @@ void UIElement::drawAll(UIPoint screenPos, glm::mat4 projection) { } } -bool UIElement::hoverAll(UIPoint pos, UIPoint screenPos) { - UIBounds bounds = getBounds(); - if(!bounds.contains(pos)) { // Only used by topmost parent UIElement - if(hovering) hoverExitAll(); - return false; - } - +void UIElement::hoverAll(UIPoint pos, UIPoint screenPos) { UIElement *hoveredChild = nullptr; for(UIElement *child : children) { UIPoint childPos = child->getPosition(); @@ -168,7 +162,6 @@ bool UIElement::hoverAll(UIPoint pos, UIPoint screenPos) { if(!hovering) hoverEnter(pos, screenPos); hovering = true; hover(pos, screenPos); - return true; } void UIElement::hoverExitAll() { @@ -180,10 +173,7 @@ void UIElement::hoverExitAll() { hoverExit(); } -bool UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) { - UIBounds bounds = getBounds(); - if(!bounds.contains(pos)) return false; // Only used by topmost parent UIElement - +void UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) { UIElement *clickedChild = nullptr; for(UIElement *child : children) { if(!child->clickable) continue; @@ -201,8 +191,6 @@ bool UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) }else { click(pos, screenPos, button); } - - return true; } bool UIElement::focusEnterAll(UIPoint pos, UIPoint screenPos) { diff --git a/src/kekengine/include/ui.h b/src/kekengine/include/ui.h index 6c32cc9..79a75dc 100644 --- a/src/kekengine/include/ui.h +++ b/src/kekengine/include/ui.h @@ -144,13 +144,13 @@ public: void drawAll(UIPoint screenPos, glm::mat4 projection); virtual void draw(UIPoint screenPos, glm::mat4 projection) = 0; - bool hoverAll(UIPoint pos, UIPoint screenPos); + void hoverAll(UIPoint pos, UIPoint screenPos); void hoverExitAll(); virtual void hoverEnter(UIPoint pos, UIPoint screenPos) {}; virtual void hover(UIPoint pos, UIPoint screenPos) {}; virtual void hoverExit() {}; - bool clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button); + void clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button); virtual void click(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) {}; bool focusEnterAll(UIPoint pos, UIPoint screenPos); diff --git a/src/kekgame/cpp/kekgame.cpp b/src/kekgame/cpp/kekgame.cpp index 56ed577..1dce2f7 100644 --- a/src/kekgame/cpp/kekgame.cpp +++ b/src/kekgame/cpp/kekgame.cpp @@ -30,6 +30,7 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods, v void onButtonClick(void *data) { button->color = Colors::RED; + button->hoverColor = Colors::ORANGE; capture = Input::captureKeyboardInput(KeyCharCallback([](GLFWwindow *window, unsigned int codepoint, void *data) { std::u32string str = Unicode::convertStdToU32(button->text->getText()); if(codepoint == KEK_INPUT_DELETE) { @@ -44,6 +45,7 @@ void onButtonClick(void *data) { } }, nullptr), Callable([](void *data) { button->color = Colors::WHITE; + button->hoverColor = Colors::GRAY; }, nullptr)); } @@ -122,6 +124,13 @@ int main(int argc, char **argv) { button->onClick = Callable(onButtonClick, nullptr); UI::addElement(button); + ButtonElement *button2 = new ButtonElement(uiPx(10), uiPx(125), uiPx(200), uiPx(50)); + button2->text->color = Colors::WHITE; + button2->color = Colors::ORANGE; + button2->hoverColor = Colors::RED; + button2->text->setText("Hi there!"); + UI::addElement(button2); + if(Engine::start() != KEK_SUCCESS) return 1; return 0; }