Fix UI rendering

This commit is contained in:
MrLetsplay 2023-10-16 20:43:42 +02:00
parent b087ccad1e
commit bbee789593
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
6 changed files with 54 additions and 27 deletions

View File

@ -32,7 +32,7 @@ static void doUIMouseHover(double x, double y) {
UIPoint hoveredAt = UIPoint((int) x - childPos.x, (int) y - childPos.y);
UIBounds bounds = element->getBounds();
if(!bounds.contains(hoveredAt)) continue;
if(!bounds.containsOffset(hoveredAt)) continue;
hoveredElement = element;
}
@ -58,7 +58,7 @@ static void doUIMouseClick(double x, double y, GLFWMouseButton button) {
UIPoint clickedAt = UIPoint((int) x - childPos.x, (int) y - childPos.y);
UIBounds bounds = element->getBounds();
if(!bounds.contains(clickedAt)) continue;
if(!bounds.containsOffset(clickedAt)) continue;
clickedElement = element;
}

View File

@ -100,6 +100,8 @@ void TextObject::allocateBuffer(TextBlock *block, int numChars) {
}
TextMetrics TextObject::measureChars(std::u32string str, unsigned int offset, unsigned int length, std::map<unsigned int, std::vector<RenderChar>> *chars) {
// TODO: returned metrics are incorrect when there are multiple lines of text
if(offset != 0 || length != str.length()) {
length = std::min(length, (unsigned int) (str.length() - offset));
str = str.substr(offset, length);

View File

@ -20,14 +20,20 @@ UIElement::~UIElement() {
UI::unfocusElement(this);
}
// Returns the element's position relative to its parent in pixels
UIPoint UIElement::getPosition() {
// Returns the element's origin position relative to its parent in pixels (not offset by getBounds())
UIPoint UIElement::getOriginPosition() {
return UIPoint(uiToScreen(x), uiToScreen(y));
}
// Returns the element's position relative to its parent in pixels (offset by getBounds())
UIPoint UIElement::getPosition() {
UIBounds bounds = getBounds();
return UIPoint(uiToScreen(x) + bounds.x, uiToScreen(y) + bounds.y);
}
// Returns the element's origin position on the screen in pixels (not offset by getBounds())
UIPoint UIElement::getScreenOriginPosition() {
UIPoint pos = getPosition();
UIPoint pos = getOriginPosition();
if(parent) {
UIPoint parentPos = parent->getScreenPosition();
pos.x += parentPos.x;
@ -119,11 +125,11 @@ UIBounds UIElement::offsetUIBounds(int w, int h, Origin origin) {
void UIElement::drawAll(UIPoint screenPos, glm::mat4 projection) {
if(!visible) return;
UIBounds bounds = getBounds();
if(enableClipping) {
glEnable(GL_SCISSOR_TEST);
UIPoint pos = getScreenPosition();
UIBounds bounds = getBounds();
glScissor(pos.x, kekData.screenHeight - (pos.y + bounds.h), bounds.w, bounds.h);
glScissor(screenPos.x, kekData.screenHeight - (screenPos.y + bounds.h), bounds.w, bounds.h);
}
draw(screenPos, projection);
@ -145,7 +151,7 @@ void UIElement::hoverAll(UIPoint pos, UIPoint screenPos) {
int relX = pos.x - childPos.x;
int relY = pos.y - childPos.y;
UIBounds b = child->getBounds();
if(!b.contains(UIPoint(relX, relY))) continue;
if(!b.containsOffset(UIPoint(relX, relY))) continue;
hoveredChild = child;
}
@ -179,7 +185,7 @@ bool UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button)
int relX = pos.x - childPos.x;
int relY = pos.y - childPos.y;
UIBounds b = child->getBounds();
if(!b.contains(UIPoint(relX, relY))) continue;
if(!b.containsOffset(UIPoint(relX, relY))) continue;
clickedChild = child;
}
@ -203,7 +209,7 @@ bool UIElement::focusEnterAll(UIPoint pos, UIPoint screenPos) {
int relX = pos.x - childPos.x;
int relY = pos.y - childPos.y;
UIBounds b = child->getBounds();
if(!b.contains(UIPoint(relX, relY))) continue;
if(!b.containsOffset(UIPoint(relX, relY))) continue;
focusedChild = child;
}
@ -230,7 +236,7 @@ UIElement *UIElement::dragEnterAll(UIPoint pos, UIPoint screenPos) {
int relX = pos.x - childPos.x;
int relY = pos.y - childPos.y;
UIBounds b = child->getBounds();
if(!b.contains(UIPoint(relX, relY))) continue;
if(!b.containsOffset(UIPoint(relX, relY))) continue;
draggedChild = child;
}

View File

@ -39,23 +39,21 @@ UIElementType TextElement::getType() {
UIBounds TextElement::getBounds() {
TextMetrics metrics = text->getMetrics(sizePixels);
int w = metrics.width, h, offsetY = 0;
int w = metrics.width, h;
switch(textBounds) {
case TextBounds::SMALLEST:
default:
h = metrics.height;
offsetY = metrics.offsetY;
break;
case TextBounds::LINE:
FontMetrics metrics = text->getFont()->getMetrics(sizePixels);
h = metrics.lineHeight;
offsetY = metrics.ascender;
break;
}
switch(textMode) {
case TextMode::BASELINE:
return UIBounds(offsetX(w, origin), -offsetY, w, h);
return UIBounds(offsetX(w, origin), 0, w, h);
case TextMode::ORIGIN:
default:
return offsetUIBounds(w, h, origin);
@ -71,22 +69,20 @@ std::string TextElement::getText() {
}
void TextElement::draw(UIPoint screenPos, glm::mat4 projection) {
UIBounds offset = getBounds();
switch(textMode) {
case TextMode::BASELINE:
text->getFont()->drawText(text, projection, offset.x + screenPos.x, screenPos.y, sizePixels, color);
text->getFont()->drawText(text, projection, screenPos.x, screenPos.y, sizePixels, color);
break;
case TextMode::ORIGIN:
switch(textBounds) {
case TextBounds::SMALLEST:
default:
text->getFont()->drawTextFromOrigin(text, projection, offset.x + screenPos.x, offset.y + screenPos.y, sizePixels, color);
text->getFont()->drawTextFromOrigin(text, projection, screenPos.x, screenPos.y, sizePixels, color);
break;
case TextBounds::LINE:
FontMetrics metrics = text->getFont()->getMetrics(sizePixels);
int offsetY = metrics.ascender;
text->getFont()->drawText(text, projection, offset.x + screenPos.x, offset.y + screenPos.y + offsetY, sizePixels, color);
text->getFont()->drawText(text, projection, screenPos.x, screenPos.y + offsetY, sizePixels, color);
break;
}

View File

@ -31,9 +31,15 @@ struct UIBounds {
w(w),
h(h) {}
// Checks if a point is contained in the bounds
inline bool contains(UIPoint pos) {
return pos.x > x && pos.y > y && pos.x < x + w && pos.y < y + h;
}
// Checks if an already offset point is contained in the bounds
inline bool containsOffset(UIPoint pos) {
return pos.x > 0 && pos.y > 0 && pos.x < w && pos.y < h;
}
};
enum class UIElementType {
@ -149,7 +155,10 @@ class UIElement {
virtual UIElementType getType() = 0;
// Returns the element's position relative to its parent in pixels
// Returns the element's origin position relative to its parent in pixels (not offset by getBounds())
UIPoint getOriginPosition();
// Returns the element's position relative to its parent in pixels (offset by getBounds())
UIPoint getPosition();
// Returns the element's origin position on the screen in pixels (not offset by getBounds())

View File

@ -1,5 +1,6 @@
#include <iostream>
#include "color.h"
#include "input.h"
#include "kekengine.h"
#include <GL/glew.h>
@ -128,7 +129,13 @@ int main(int argc, char **argv) {
button3->addChild(rect);
UI::addElement(button3);
TextFieldElement *textField = new TextFieldElement(uiPx(10), uiPx(200), uiPx(500));
RectangleElement *rect2 = new RectangleElement(uiPx(0), uiSh(0.5), uiPx(500), uiPx(250));
rect2->origin = Origin::LEFT_CENTER;
rect2->enableClipping = true;
UI::addElement(rect2);
TextFieldElement *textField = new TextFieldElement(uiPx(0), uiPh(1) - uiPx(10), uiPx(500));
textField->origin = kek::Origin::BOTTOM_LEFT;
textField->color = Colors::GREEN;
textField->focusColor = Colors::RED;
textField->textElement->color = Colors::WHITE;
@ -152,11 +159,18 @@ int main(int argc, char **argv) {
ep->t->onSubmit = SubmitCallback();
},
&e);
UI::addElement(textField);
rect2->addChild(textField);
TextElement *text = new TextElement(uiPx(10), uiPx(260));
text->setText("Lorem ipsum\ndolor sit amet\nsussy amogus, KekEngine sample text\nWhen the impostor is\nAmogus");
UI::addElement(text);
TextElement *text = new TextElement(uiPx(0), uiPx(0));
text->setText("Lorem ipsum dolorg");
text->textMode = TextMode::ORIGIN;
text->textBounds = TextBounds::SMALLEST;
UIBounds bounds = text->getBounds();
RectangleElement *box = new RectangleElement(uiPx(bounds.x), uiPx(bounds.y), uiPx(bounds.w), uiPx(bounds.h));
box->color = Colors::GRAY;
rect2->addChild(box);
rect2->addChild(text);
if(Engine::start() != KEK_SUCCESS) return 1;
return 0;