Fix UI rendering
This commit is contained in:
parent
b087ccad1e
commit
bbee789593
@ -32,7 +32,7 @@ static void doUIMouseHover(double x, double y) {
|
|||||||
UIPoint hoveredAt = UIPoint((int) x - childPos.x, (int) y - childPos.y);
|
UIPoint hoveredAt = UIPoint((int) x - childPos.x, (int) y - childPos.y);
|
||||||
|
|
||||||
UIBounds bounds = element->getBounds();
|
UIBounds bounds = element->getBounds();
|
||||||
if(!bounds.contains(hoveredAt)) continue;
|
if(!bounds.containsOffset(hoveredAt)) continue;
|
||||||
|
|
||||||
hoveredElement = element;
|
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);
|
UIPoint clickedAt = UIPoint((int) x - childPos.x, (int) y - childPos.y);
|
||||||
|
|
||||||
UIBounds bounds = element->getBounds();
|
UIBounds bounds = element->getBounds();
|
||||||
if(!bounds.contains(clickedAt)) continue;
|
if(!bounds.containsOffset(clickedAt)) continue;
|
||||||
|
|
||||||
clickedElement = element;
|
clickedElement = element;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
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()) {
|
if(offset != 0 || length != str.length()) {
|
||||||
length = std::min(length, (unsigned int) (str.length() - offset));
|
length = std::min(length, (unsigned int) (str.length() - offset));
|
||||||
str = str.substr(offset, length);
|
str = str.substr(offset, length);
|
||||||
|
@ -20,14 +20,20 @@ UIElement::~UIElement() {
|
|||||||
UI::unfocusElement(this);
|
UI::unfocusElement(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 UIElement::getPosition() {
|
UIPoint UIElement::getOriginPosition() {
|
||||||
return UIPoint(uiToScreen(x), uiToScreen(y));
|
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())
|
// Returns the element's origin position on the screen in pixels (not offset by getBounds())
|
||||||
UIPoint UIElement::getScreenOriginPosition() {
|
UIPoint UIElement::getScreenOriginPosition() {
|
||||||
UIPoint pos = getPosition();
|
UIPoint pos = getOriginPosition();
|
||||||
if(parent) {
|
if(parent) {
|
||||||
UIPoint parentPos = parent->getScreenPosition();
|
UIPoint parentPos = parent->getScreenPosition();
|
||||||
pos.x += parentPos.x;
|
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) {
|
void UIElement::drawAll(UIPoint screenPos, glm::mat4 projection) {
|
||||||
if(!visible) return;
|
if(!visible) return;
|
||||||
|
|
||||||
|
UIBounds bounds = getBounds();
|
||||||
|
|
||||||
if(enableClipping) {
|
if(enableClipping) {
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
UIPoint pos = getScreenPosition();
|
glScissor(screenPos.x, kekData.screenHeight - (screenPos.y + bounds.h), bounds.w, bounds.h);
|
||||||
UIBounds bounds = getBounds();
|
|
||||||
glScissor(pos.x, kekData.screenHeight - (pos.y + bounds.h), bounds.w, bounds.h);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(screenPos, projection);
|
draw(screenPos, projection);
|
||||||
@ -145,7 +151,7 @@ void UIElement::hoverAll(UIPoint pos, UIPoint screenPos) {
|
|||||||
int relX = pos.x - childPos.x;
|
int relX = pos.x - childPos.x;
|
||||||
int relY = pos.y - childPos.y;
|
int relY = pos.y - childPos.y;
|
||||||
UIBounds b = child->getBounds();
|
UIBounds b = child->getBounds();
|
||||||
if(!b.contains(UIPoint(relX, relY))) continue;
|
if(!b.containsOffset(UIPoint(relX, relY))) continue;
|
||||||
hoveredChild = child;
|
hoveredChild = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +185,7 @@ bool UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button)
|
|||||||
int relX = pos.x - childPos.x;
|
int relX = pos.x - childPos.x;
|
||||||
int relY = pos.y - childPos.y;
|
int relY = pos.y - childPos.y;
|
||||||
UIBounds b = child->getBounds();
|
UIBounds b = child->getBounds();
|
||||||
if(!b.contains(UIPoint(relX, relY))) continue;
|
if(!b.containsOffset(UIPoint(relX, relY))) continue;
|
||||||
clickedChild = child;
|
clickedChild = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +209,7 @@ bool UIElement::focusEnterAll(UIPoint pos, UIPoint screenPos) {
|
|||||||
int relX = pos.x - childPos.x;
|
int relX = pos.x - childPos.x;
|
||||||
int relY = pos.y - childPos.y;
|
int relY = pos.y - childPos.y;
|
||||||
UIBounds b = child->getBounds();
|
UIBounds b = child->getBounds();
|
||||||
if(!b.contains(UIPoint(relX, relY))) continue;
|
if(!b.containsOffset(UIPoint(relX, relY))) continue;
|
||||||
focusedChild = child;
|
focusedChild = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +236,7 @@ UIElement *UIElement::dragEnterAll(UIPoint pos, UIPoint screenPos) {
|
|||||||
int relX = pos.x - childPos.x;
|
int relX = pos.x - childPos.x;
|
||||||
int relY = pos.y - childPos.y;
|
int relY = pos.y - childPos.y;
|
||||||
UIBounds b = child->getBounds();
|
UIBounds b = child->getBounds();
|
||||||
if(!b.contains(UIPoint(relX, relY))) continue;
|
if(!b.containsOffset(UIPoint(relX, relY))) continue;
|
||||||
draggedChild = child;
|
draggedChild = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,23 +39,21 @@ UIElementType TextElement::getType() {
|
|||||||
UIBounds TextElement::getBounds() {
|
UIBounds TextElement::getBounds() {
|
||||||
TextMetrics metrics = text->getMetrics(sizePixels);
|
TextMetrics metrics = text->getMetrics(sizePixels);
|
||||||
|
|
||||||
int w = metrics.width, h, offsetY = 0;
|
int w = metrics.width, h;
|
||||||
switch(textBounds) {
|
switch(textBounds) {
|
||||||
case TextBounds::SMALLEST:
|
case TextBounds::SMALLEST:
|
||||||
default:
|
default:
|
||||||
h = metrics.height;
|
h = metrics.height;
|
||||||
offsetY = metrics.offsetY;
|
|
||||||
break;
|
break;
|
||||||
case TextBounds::LINE:
|
case TextBounds::LINE:
|
||||||
FontMetrics metrics = text->getFont()->getMetrics(sizePixels);
|
FontMetrics metrics = text->getFont()->getMetrics(sizePixels);
|
||||||
h = metrics.lineHeight;
|
h = metrics.lineHeight;
|
||||||
offsetY = metrics.ascender;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(textMode) {
|
switch(textMode) {
|
||||||
case TextMode::BASELINE:
|
case TextMode::BASELINE:
|
||||||
return UIBounds(offsetX(w, origin), -offsetY, w, h);
|
return UIBounds(offsetX(w, origin), 0, w, h);
|
||||||
case TextMode::ORIGIN:
|
case TextMode::ORIGIN:
|
||||||
default:
|
default:
|
||||||
return offsetUIBounds(w, h, origin);
|
return offsetUIBounds(w, h, origin);
|
||||||
@ -71,22 +69,20 @@ std::string TextElement::getText() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextElement::draw(UIPoint screenPos, glm::mat4 projection) {
|
void TextElement::draw(UIPoint screenPos, glm::mat4 projection) {
|
||||||
UIBounds offset = getBounds();
|
|
||||||
|
|
||||||
switch(textMode) {
|
switch(textMode) {
|
||||||
case TextMode::BASELINE:
|
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;
|
break;
|
||||||
case TextMode::ORIGIN:
|
case TextMode::ORIGIN:
|
||||||
switch(textBounds) {
|
switch(textBounds) {
|
||||||
case TextBounds::SMALLEST:
|
case TextBounds::SMALLEST:
|
||||||
default:
|
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;
|
break;
|
||||||
case TextBounds::LINE:
|
case TextBounds::LINE:
|
||||||
FontMetrics metrics = text->getFont()->getMetrics(sizePixels);
|
FontMetrics metrics = text->getFont()->getMetrics(sizePixels);
|
||||||
int offsetY = metrics.ascender;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +31,15 @@ struct UIBounds {
|
|||||||
w(w),
|
w(w),
|
||||||
h(h) {}
|
h(h) {}
|
||||||
|
|
||||||
|
// Checks if a point is contained in the bounds
|
||||||
inline bool contains(UIPoint pos) {
|
inline bool contains(UIPoint pos) {
|
||||||
return pos.x > x && pos.y > y && pos.x < x + w && pos.y < y + h;
|
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 {
|
enum class UIElementType {
|
||||||
@ -149,7 +155,10 @@ class UIElement {
|
|||||||
|
|
||||||
virtual UIElementType getType() = 0;
|
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();
|
UIPoint getPosition();
|
||||||
|
|
||||||
// Returns the element's origin position on the screen in pixels (not offset by getBounds())
|
// Returns the element's origin position on the screen in pixels (not offset by getBounds())
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "color.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "kekengine.h"
|
#include "kekengine.h"
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
@ -128,7 +129,13 @@ int main(int argc, char **argv) {
|
|||||||
button3->addChild(rect);
|
button3->addChild(rect);
|
||||||
UI::addElement(button3);
|
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->color = Colors::GREEN;
|
||||||
textField->focusColor = Colors::RED;
|
textField->focusColor = Colors::RED;
|
||||||
textField->textElement->color = Colors::WHITE;
|
textField->textElement->color = Colors::WHITE;
|
||||||
@ -152,11 +159,18 @@ int main(int argc, char **argv) {
|
|||||||
ep->t->onSubmit = SubmitCallback();
|
ep->t->onSubmit = SubmitCallback();
|
||||||
},
|
},
|
||||||
&e);
|
&e);
|
||||||
UI::addElement(textField);
|
rect2->addChild(textField);
|
||||||
|
|
||||||
TextElement *text = new TextElement(uiPx(10), uiPx(260));
|
TextElement *text = new TextElement(uiPx(0), uiPx(0));
|
||||||
text->setText("Lorem ipsum\ndolor sit amet\nsussy amogus, KekEngine sample text\nWhen the impostor is\nAmogus");
|
text->setText("Lorem ipsum dolorg");
|
||||||
UI::addElement(text);
|
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;
|
if(Engine::start() != KEK_SUCCESS) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user