From 299b1b57735ca582151516e9f3051b6100eed51f Mon Sep 17 00:00:00 2001 From: MrLetsplay2003 Date: Tue, 18 Oct 2022 18:48:54 +0200 Subject: [PATCH] More UI basics (WIP) --- src/kekengine/cpp/ui.cpp | 183 +++++++++++++++++++++++++++++++++++++ src/kekengine/include/ui.h | 2 +- 2 files changed, 184 insertions(+), 1 deletion(-) diff --git a/src/kekengine/cpp/ui.cpp b/src/kekengine/cpp/ui.cpp index 3fab951..f495be3 100644 --- a/src/kekengine/cpp/ui.cpp +++ b/src/kekengine/cpp/ui.cpp @@ -1 +1,184 @@ #include "ui.h" + +#include + +#include "internal.h" + +namespace kek { + +UIElement::UIElement(UIValue x, UIValue y): x(x), y(y) { + +} + +UIElement::~UIElement() { + +} + +// Returns the element's position relative to its parent in pixels +UIPoint UIElement::getPosition() { + return UIPoint(uiToScreen(x), uiToScreen(y)); +} + +// Returns the element's position on the screen in pixels +UIPoint UIElement::getScreenPosition() { + UIPoint pos = getPosition(); + if(parent) { + UIPoint parentPos = parent->getPosition(); + pos.x += parentPos.x; + pos.y += parentPos.y; + } + return pos; +} + +void UIElement::addChild(UIElement *child) { + children.push_back(child); +} + +void UIElement::removeChild(UIElement *child) { + std::remove(children.begin(), children.end(), child); +} + +inline int UIElement::uiToScreen(UIValue val) { + float px = 0; + px += val.pixels; + if(parent) px += (int) (val.parentWidth * parent->getBounds().w); + px += val.screenWidth * kekData.screenWidth; + if(!parent) px += val.parentWidth * kekData.screenWidth; + if(parent) px += (int) (val.parentHeight * parent->getBounds().h); + px += val.screenHeight * kekData.screenHeight; + if(!parent) px += val.parentHeight * kekData.screenHeight; + return px; +} + +/*void UIElement::drawAll(int x, int y, glm::mat4 projection) { + if(!isVisible()) return; + draw(x, y, projection); + + for(UIElement *child : children) { + UIPoint pos = child->getPosition(); + child->drawAll(x + pos.x, y + pos.y, projection); + } +} + +void UIElement::hoverAll(int x, int y, int absX, int absY) { + UIBounds bounds = getBounds(); + if(x < bounds.x || y < bounds.y || x >= bounds.x + bounds.w || y >= bounds.y + bounds.h) { // Only used by topmost parent UIElement + if(hovering) hoverExitAll(); + return; + } + + UIElement *hoveredChild = NULL; + for(UIElement *child : children) { + UIPoint pos = child->getPosition(); + int relX = x - pos.x; + int relY = y - pos.y; + UIBounds b = child->getBounds(); + if(relX < b.x || relY < b.y || relX > b.x + b.w || relY > b.y + b.h) continue; + hoveredChild = child; + } + + for(UIElement *child : children) { + if(child != hoveredChild && child->hovering) child->hoverExitAll(); + } + + if(hoveredChild) { + UIPoint pos = hoveredChild->getPosition(); + hoveredChild->hoverAll(x - pos.x, y - pos.y, absX, absY); + } + + if(!hovering) hoverEnter(); + hovering = true; + hover(x, y, absX, absY); +} + +void UIElement::hoverExitAll() { + if(!hovering) return; + hovering = false; + for(UIElement *child : children) { + if(child->hovering) child->hoverExitAll(); + } + hoverExit(); +} + +void UIElement::clickAll(int x, int y, int absX, int absY, MouseButton button) { + UIBounds bounds = getBounds(); + if(x < bounds.x || y < bounds.y || x >= bounds.x + bounds.w || y >= bounds.y + bounds.h) return; // Only used by topmost parent UIElement + + UIElement *clickedChild = NULL; + for(UIElement *child : children) { + if(!child->clickable) continue; + UIPoint pos = child->getPosition(); + int relX = x - pos.x; + int relY = y - pos.y; + UIBounds b = child->getBounds(); + if(relX < b.x || relY < b.y || relX > b.x + b.w || relY > b.y + b.h) continue; + clickedChild = child; + } + + if(clickedChild != NULL) { + UIPoint pos = clickedChild->getPosition(); + clickedChild->clickAll(x - pos.x, y - pos.y, absX, absY, button); + }else { + click(x, y, absX, absY, button); + } +} + +bool UIElement::focusEnterAll(UIPoint pos, UIPoint screenPos) { + UIBounds bounds = getBounds(); + if(pos.x < bounds.x || pos.y < bounds.y || pos.x >= bounds.x + bounds.w || pos.y >= bounds.y + bounds.h) return false; + + UIElement *focusedChild = nullptr; + for(UIElement *child : children) { + UIPoint childPos = child->getPosition(); + int relX = pos.x - childPos.x; + int relY = pos.y - childPos.y; + UIBounds b = child->getBounds(); + if(relX < b.x || relY < b.y || relX > b.x + b.w || relY > b.y + b.h) continue; + focusedChild = child; + } + + if(focusedChild) { + UIPoint childPos = focusedChild->getPosition(); + bool focusable = focusedChild->focusEnterAll(pos.x - childPos.x, pos.y - childPos.y); + if(focusable) return true; + } + + if(focusable) { + //UI::focusElement(this); FIXME + return true; + } + + return false; +} + +UIElement *UIElement::dragEnterAll(UIPoint pos, UIPoint screenPos) { + UIBounds bounds = getBounds(); + if(x < bounds.x || y < bounds.y || x >= bounds.x + bounds.w || y >= bounds.y + bounds.h) return nullptr; // Only used by topmost parent UIElement + + UIElement *draggedChild = nullptr; + for(UIElement *child : children) { + UIPoint pos = child->getPosition(); + int relX = x - pos.x; + int relY = y - pos.y; + UIBounds b = child->getBounds(); + if(relX < b.x || relY < b.y || relX > b.x + b.w || relY > b.y + b.h) continue; + draggedChild = child; + } + + if(draggedChild) { + UIPoint pos = draggedChild->getPosition(); + UIElement *dragged = draggedChild->dragEnterAll(x - pos.x, y - pos.y, absX, absY); + if(dragged) return dragged; + } + + if(draggable) return this; + + return nullptr; +} + +void UIElement::init() { + defaultFont = new Font("fonts/DejaVuSans.ttf"); +} +*/ + +} diff --git a/src/kekengine/include/ui.h b/src/kekengine/include/ui.h index 5de9a08..760f4f0 100644 --- a/src/kekengine/include/ui.h +++ b/src/kekengine/include/ui.h @@ -177,7 +177,7 @@ public: virtual void click(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) {}; - bool focusEnterAll(UIPoint pos); + bool focusEnterAll(UIPoint pos, UIPoint screenPos); virtual void focusEnter(UIPoint pos, UIPoint screenPos) {};