Implement UI drag

This commit is contained in:
MrLetsplay 2024-08-25 21:41:54 +02:00
parent d9cfcba0ba
commit bc0cab870b
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
5 changed files with 57 additions and 37 deletions

View File

@ -41,36 +41,55 @@ static void doUIMouseHover(double x, double y) {
} }
if(hoveredElement) { if(hoveredElement) {
IntPoint2 childPos = hoveredElement->getPosition(); IntPoint2 childPos = hoveredElement->getScreenPosition();
hoveredElement->hoverAll(mousePosition - childPos, mousePosition); 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) { static void doUIMouseDrag(double x, double y) {
IntPoint2 mousePosition = IntPoint2((int) x, (int) y);
if(Input::getMouseButtonState(GLFWMouseButton::LEFT) != GLFWMouseButtonState::PRESSED) { if(Input::getMouseButtonState(GLFWMouseButton::LEFT) != GLFWMouseButtonState::PRESSED) {
kekData.input->mouseDown = false; kekData.input->mouseDown = false;
stopUIMouseDrag();
return; return;
} }
if(!kekData.input->mouseDown) { if(!kekData.input->mouseDown) {
kekData.input->mouseDownPosition = IntPoint2((int) x, (int) y); kekData.input->mouseDownPosition = mousePosition;
} }
int deltaX = (int) x - kekData.input->mouseDownPosition.x; if(!kekData.ui->draggedElement) {
int deltaY = (int) y - kekData.input->mouseDownPosition.y; IntPoint2 mouseDownPosition = kekData.input->mouseDownPosition;
if(deltaX * deltaX + deltaY * deltaY >= KEK_UI_MIN_DRAG_DISTANCE_SQUARED) { int deltaX = (int) x - mouseDownPosition.x;
// Initiate drag int deltaY = (int) y - mouseDownPosition.y;
IntPoint2 mousePosition = IntPoint2((int) x, (int) y); if(deltaX * deltaX + deltaY * deltaY >= KEK_UI_MIN_DRAG_DISTANCE_SQUARED) {
UIElement *draggedElement = UI::findElementAt(mousePosition); // Initiate drag
UIElement *draggedElement = UI::findElementAt(mousePosition);
if(draggedElement) { if(draggedElement) {
IntPoint2 childPos = draggedElement->getPosition(); IntPoint2 childPos = draggedElement->getScreenPosition();
draggedElement->dragEnterAll(mousePosition - childPos, mousePosition); 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; kekData.input->mouseDown = true;
} }
@ -79,7 +98,7 @@ static void doUIMouseClick(double x, double y, GLFWMouseButton button) {
UIElement *clickedElement = UI::findElementAt(mousePosition); UIElement *clickedElement = UI::findElementAt(mousePosition);
if(clickedElement) { if(clickedElement) {
IntPoint2 childPos = clickedElement->getPosition(); IntPoint2 childPos = clickedElement->getScreenPosition();
IntPoint2 clickedAt = mousePosition - childPos; IntPoint2 clickedAt = mousePosition - childPos;
if(button == GLFWMouseButton::LEFT) { if(button == GLFWMouseButton::LEFT) {
@ -175,6 +194,9 @@ static void defaultMouseButtonCallback(MouseButtonEvent event, void *data) {
case GLFW_PRESS: case GLFW_PRESS:
break; break;
case GLFW_RELEASE: { case GLFW_RELEASE: {
kekData.input->mouseDown = false;
stopUIMouseDrag();
double x, y; double x, y;
glfwGetCursorPos(event.window, &x, &y); glfwGetCursorPos(event.window, &x, &y);
doUIMouseClick(x, y, (GLFWMouseButton) event.button); doUIMouseClick(x, y, (GLFWMouseButton) event.button);

View File

@ -224,21 +224,21 @@ bool UIElement::focusEnterAll(IntPoint2 pos, IntPoint2 screenPos) {
return false; return false;
} }
UIElement *UIElement::dragEnterAll(IntPoint2 pos, IntPoint2 screenPos) { bool UIElement::dragEnterAll(IntPoint2 pos, IntPoint2 screenPos) {
UIElement *draggedChild = findChildAtRelativePos(this, pos); UIElement *draggedChild = findChildAtRelativePos(this, pos);
if(draggedChild) { if(draggedChild) {
IntPoint2 childPos = draggedChild->getPosition(); IntPoint2 childPos = draggedChild->getPosition();
UIElement *dragged = draggedChild->dragEnterAll(pos - childPos, screenPos); if(draggedChild->dragEnterAll(pos - childPos, screenPos)) return true;
if(dragged) return dragged;
} }
if(draggable) { if(draggable) {
// TODO: start drag dragEnter(pos, screenPos);
return this; kekData.ui->draggedElement = this;
return true;
} }
return nullptr; return false;
} }
void UI::init() { void UI::init() {
@ -272,16 +272,17 @@ std::vector<UIElement *> UI::getElements() {
} }
void UI::focusElement(UIElement *element) { void UI::focusElement(UIElement *element) {
if(kekData.ui->focusedElement != element) { if(!element->focusable) return;
if(kekData.ui->focusedElement != nullptr) { if(kekData.ui->focusedElement == element) return;
unfocusElement(kekData.ui->focusedElement);
}
kekData.ui->focusedElement = element; if(kekData.ui->focusedElement != nullptr) {
if(element != nullptr) { unfocusElement(kekData.ui->focusedElement);
element->focused = true; }
element->focusEnter();
} kekData.ui->focusedElement = element;
if(element != nullptr) {
element->focused = true;
element->focusEnter();
} }
} }

View File

@ -357,20 +357,16 @@ UIWindowTitleBar::~UIWindowTitleBar() {
} }
void UIWindowTitleBar::dragEnter(IntPoint2 pos, IntPoint2 screenPos) { void UIWindowTitleBar::dragEnter(IntPoint2 pos, IntPoint2 screenPos) {
// TODO
std::cout << "Drag start" << std::endl;
this->dragDownPos = pos; this->dragDownPos = pos;
} }
void UIWindowTitleBar::drag(IntPoint2 pos, IntPoint2 screenPos) { void UIWindowTitleBar::drag(IntPoint2 pos, IntPoint2 screenPos) {
// TODO if(!this->parent) return;
std::cout << "Drag" << std::endl; this->parent->x = uiPx(screenPos.x - dragDownPos.x);
this->x = uiPx(screenPos.x + dragDownPos.x); this->parent->y = uiPx(screenPos.y - dragDownPos.y);
this->y = uiPx(screenPos.y + dragDownPos.y);
} }
void UIWindowTitleBar::dragExit(IntPoint2 pos, IntPoint2 screenPos) { void UIWindowTitleBar::dragExit(IntPoint2 pos, IntPoint2 screenPos) {
// TODO
} }
UIWindow::UIWindow(UIValue x, UIValue y, UIValue w, UIValue h) UIWindow::UIWindow(UIValue x, UIValue y, UIValue w, UIValue h)

View File

@ -7,6 +7,7 @@ namespace kek {
struct UIData { struct UIData {
std::vector<UIElement *> elements; std::vector<UIElement *> elements;
UIElement *focusedElement; UIElement *focusedElement;
UIElement *draggedElement;
std::shared_ptr<Font> defaultFont; std::shared_ptr<Font> defaultFont;
Shader *rectangleShader; Shader *rectangleShader;
}; };

View File

@ -193,7 +193,7 @@ class UIElement {
virtual void focusEnter(){}; virtual void focusEnter(){};
virtual void focusExit(){}; virtual void focusExit(){};
UIElement *dragEnterAll(IntPoint2 pos, IntPoint2 screenPos); bool dragEnterAll(IntPoint2 pos, IntPoint2 screenPos);
virtual void dragEnter(IntPoint2 pos, IntPoint2 screenPos){}; virtual void dragEnter(IntPoint2 pos, IntPoint2 screenPos){};
virtual void drag(IntPoint2 pos, IntPoint2 screenPos){}; virtual void drag(IntPoint2 pos, IntPoint2 screenPos){};
virtual void dragExit(IntPoint2 pos, IntPoint2 screenPos){}; virtual void dragExit(IntPoint2 pos, IntPoint2 screenPos){};