From bc0cab870babecade97de1ad683d674329d1f76b Mon Sep 17 00:00:00 2001 From: MrLetsplay Date: Sun, 25 Aug 2024 21:41:54 +0200 Subject: [PATCH] Implement UI drag --- src/kekengine/cpp/common/defaults.cpp | 50 +++++++++++++++++++-------- src/kekengine/cpp/ui/ui.cpp | 31 +++++++++-------- src/kekengine/cpp/ui/uielements.cpp | 10 ++---- src/kekengine/include/internal/ui.h | 1 + src/kekengine/include/ui.h | 2 +- 5 files changed, 57 insertions(+), 37 deletions(-) diff --git a/src/kekengine/cpp/common/defaults.cpp b/src/kekengine/cpp/common/defaults.cpp index f03440b..7182f8e 100644 --- a/src/kekengine/cpp/common/defaults.cpp +++ b/src/kekengine/cpp/common/defaults.cpp @@ -41,36 +41,55 @@ static void doUIMouseHover(double x, double y) { } if(hoveredElement) { - IntPoint2 childPos = hoveredElement->getPosition(); + IntPoint2 childPos = hoveredElement->getScreenPosition(); hoveredElement->hoverAll(mousePosition - childPos, mousePosition); } } +static void stopUIMouseDrag() { + if(!kekData.ui->draggedElement) return; + + double x, y; + glfwGetCursorPos(kekData.window, &x, &y); + IntPoint2 mousePosition = IntPoint2((int) x, (int) y); + + IntPoint2 childPos = kekData.ui->draggedElement->getScreenPosition(); + kekData.ui->draggedElement->dragExit(mousePosition - childPos, mousePosition); + kekData.ui->draggedElement = nullptr; +} + static void doUIMouseDrag(double x, double y) { + IntPoint2 mousePosition = IntPoint2((int) x, (int) y); + if(Input::getMouseButtonState(GLFWMouseButton::LEFT) != GLFWMouseButtonState::PRESSED) { kekData.input->mouseDown = false; + stopUIMouseDrag(); return; } if(!kekData.input->mouseDown) { - kekData.input->mouseDownPosition = IntPoint2((int) x, (int) y); + kekData.input->mouseDownPosition = mousePosition; } - int deltaX = (int) x - kekData.input->mouseDownPosition.x; - int deltaY = (int) y - kekData.input->mouseDownPosition.y; - if(deltaX * deltaX + deltaY * deltaY >= KEK_UI_MIN_DRAG_DISTANCE_SQUARED) { - // Initiate drag - IntPoint2 mousePosition = IntPoint2((int) x, (int) y); - UIElement *draggedElement = UI::findElementAt(mousePosition); + if(!kekData.ui->draggedElement) { + IntPoint2 mouseDownPosition = kekData.input->mouseDownPosition; + int deltaX = (int) x - mouseDownPosition.x; + int deltaY = (int) y - mouseDownPosition.y; + if(deltaX * deltaX + deltaY * deltaY >= KEK_UI_MIN_DRAG_DISTANCE_SQUARED) { + // Initiate drag + UIElement *draggedElement = UI::findElementAt(mousePosition); - if(draggedElement) { - IntPoint2 childPos = draggedElement->getPosition(); - draggedElement->dragEnterAll(mousePosition - childPos, mousePosition); + if(draggedElement) { + IntPoint2 childPos = draggedElement->getScreenPosition(); + draggedElement->dragEnterAll(mouseDownPosition - childPos, mouseDownPosition); + } } + } else { + // Element is being dragged + IntPoint2 childPos = kekData.ui->draggedElement->getScreenPosition(); + kekData.ui->draggedElement->drag(mousePosition - childPos, mousePosition); } - // TODO: drag dragged element, exit drag - kekData.input->mouseDown = true; } @@ -79,7 +98,7 @@ static void doUIMouseClick(double x, double y, GLFWMouseButton button) { UIElement *clickedElement = UI::findElementAt(mousePosition); if(clickedElement) { - IntPoint2 childPos = clickedElement->getPosition(); + IntPoint2 childPos = clickedElement->getScreenPosition(); IntPoint2 clickedAt = mousePosition - childPos; if(button == GLFWMouseButton::LEFT) { @@ -175,6 +194,9 @@ static void defaultMouseButtonCallback(MouseButtonEvent event, void *data) { case GLFW_PRESS: break; case GLFW_RELEASE: { + kekData.input->mouseDown = false; + stopUIMouseDrag(); + double x, y; glfwGetCursorPos(event.window, &x, &y); doUIMouseClick(x, y, (GLFWMouseButton) event.button); diff --git a/src/kekengine/cpp/ui/ui.cpp b/src/kekengine/cpp/ui/ui.cpp index e9eeec8..bd1b5f1 100644 --- a/src/kekengine/cpp/ui/ui.cpp +++ b/src/kekengine/cpp/ui/ui.cpp @@ -224,21 +224,21 @@ bool UIElement::focusEnterAll(IntPoint2 pos, IntPoint2 screenPos) { return false; } -UIElement *UIElement::dragEnterAll(IntPoint2 pos, IntPoint2 screenPos) { +bool UIElement::dragEnterAll(IntPoint2 pos, IntPoint2 screenPos) { UIElement *draggedChild = findChildAtRelativePos(this, pos); if(draggedChild) { IntPoint2 childPos = draggedChild->getPosition(); - UIElement *dragged = draggedChild->dragEnterAll(pos - childPos, screenPos); - if(dragged) return dragged; + if(draggedChild->dragEnterAll(pos - childPos, screenPos)) return true; } if(draggable) { - // TODO: start drag - return this; + dragEnter(pos, screenPos); + kekData.ui->draggedElement = this; + return true; } - return nullptr; + return false; } void UI::init() { @@ -272,16 +272,17 @@ std::vector UI::getElements() { } void UI::focusElement(UIElement *element) { - if(kekData.ui->focusedElement != element) { - if(kekData.ui->focusedElement != nullptr) { - unfocusElement(kekData.ui->focusedElement); - } + if(!element->focusable) return; + if(kekData.ui->focusedElement == element) return; - kekData.ui->focusedElement = element; - if(element != nullptr) { - element->focused = true; - element->focusEnter(); - } + if(kekData.ui->focusedElement != nullptr) { + unfocusElement(kekData.ui->focusedElement); + } + + kekData.ui->focusedElement = element; + if(element != nullptr) { + element->focused = true; + element->focusEnter(); } } diff --git a/src/kekengine/cpp/ui/uielements.cpp b/src/kekengine/cpp/ui/uielements.cpp index 4e3f0d1..8a0492d 100644 --- a/src/kekengine/cpp/ui/uielements.cpp +++ b/src/kekengine/cpp/ui/uielements.cpp @@ -357,20 +357,16 @@ UIWindowTitleBar::~UIWindowTitleBar() { } void UIWindowTitleBar::dragEnter(IntPoint2 pos, IntPoint2 screenPos) { - // TODO - std::cout << "Drag start" << std::endl; this->dragDownPos = pos; } void UIWindowTitleBar::drag(IntPoint2 pos, IntPoint2 screenPos) { - // TODO - std::cout << "Drag" << std::endl; - this->x = uiPx(screenPos.x + dragDownPos.x); - this->y = uiPx(screenPos.y + dragDownPos.y); + if(!this->parent) return; + this->parent->x = uiPx(screenPos.x - dragDownPos.x); + this->parent->y = uiPx(screenPos.y - dragDownPos.y); } void UIWindowTitleBar::dragExit(IntPoint2 pos, IntPoint2 screenPos) { - // TODO } UIWindow::UIWindow(UIValue x, UIValue y, UIValue w, UIValue h) diff --git a/src/kekengine/include/internal/ui.h b/src/kekengine/include/internal/ui.h index b9aa74b..6dffaef 100644 --- a/src/kekengine/include/internal/ui.h +++ b/src/kekengine/include/internal/ui.h @@ -7,6 +7,7 @@ namespace kek { struct UIData { std::vector elements; UIElement *focusedElement; + UIElement *draggedElement; std::shared_ptr defaultFont; Shader *rectangleShader; }; diff --git a/src/kekengine/include/ui.h b/src/kekengine/include/ui.h index 37c5a07..71f6b99 100644 --- a/src/kekengine/include/ui.h +++ b/src/kekengine/include/ui.h @@ -193,7 +193,7 @@ class UIElement { virtual void focusEnter(){}; virtual void focusExit(){}; - UIElement *dragEnterAll(IntPoint2 pos, IntPoint2 screenPos); + bool dragEnterAll(IntPoint2 pos, IntPoint2 screenPos); virtual void dragEnter(IntPoint2 pos, IntPoint2 screenPos){}; virtual void drag(IntPoint2 pos, IntPoint2 screenPos){}; virtual void dragExit(IntPoint2 pos, IntPoint2 screenPos){};