KekEngine/src/kekengine/cpp/ui/uielements.cpp
2023-09-13 20:42:01 +02:00

193 lines
4.7 KiB
C++

#include "uielements.h"
#include <glm/gtc/type_ptr.hpp>
#include "internal.h"
#include "internal/ui.h"
namespace kek {
TextElement::TextElement(UIValue x, UIValue y, Font *font)
: UIElement(x, y) {
this->text = new TextObject(font, "Text");
this->sizePixels = KEK_DEFAULT_FONT_SIZE_PIXELS;
this->color = Colors::WHITE;
this->textMode = TextMode::ORIGIN;
this->textBounds = TextBounds::SMALLEST;
}
TextElement::TextElement(UIValue x, UIValue y)
: TextElement(x, y, kekData.ui->defaultFont) {}
TextElement::~TextElement() {
delete text;
}
UIElementType TextElement::getType() {
return UIElementType::TEXT;
}
UIBounds TextElement::getBounds() {
TextMetrics metrics = text->getMetrics(sizePixels);
int w = metrics.width, h, offsetY = 0;
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);
case TextMode::ORIGIN:
default:
return offsetUIBounds(w, h, origin);
}
}
void TextElement::setText(std::string text) {
this->text->setText(text);
}
std::string TextElement::getText() {
return text->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);
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);
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);
break;
}
break;
}
}
UIWindow::UIWindow(UIValue x, UIValue y)
: UIElement(x, y) {
addChild(new TextElement(x, y));
}
UIWindow::~UIWindow() {
}
UIElementType UIWindow::getType() {
return UIElementType::WINDOW;
}
void UIWindow::draw(UIPoint screenPos, glm::mat4 projection) {
}
static float rectangleVerts[] = {
0.0f,
1.0f,
1.0f,
1.0f,
1.0f,
0.0f,
1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
1.0f,
};
RectangleElement::RectangleElement(UIValue x, UIValue y, UIValue w, UIValue h)
: UIElement(x, y) {
this->w = w;
this->h = h;
color = Colors::BLACK;
glCreateVertexArrays(1, &vao);
glCreateBuffers(1, &vbo);
glNamedBufferData(vbo, sizeof(rectangleVerts), rectangleVerts, GL_STATIC_DRAW);
glVertexArrayVertexBuffer(vao, KEK_UI_VERTEX_BUFFER_BINDING, vbo, 0, 2 * sizeof(float));
glEnableVertexArrayAttrib(vao, KEK_UI_RECT_VERTEX_SHADER_IN_POSITION);
glVertexArrayAttribFormat(vao, KEK_UI_RECT_VERTEX_SHADER_IN_POSITION, 2, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(vao, KEK_UI_RECT_VERTEX_SHADER_IN_POSITION, KEK_UI_VERTEX_BUFFER_BINDING);
}
RectangleElement::~RectangleElement() {
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
}
UIElementType RectangleElement::getType() {
return UIElementType::RECTANGLE;
}
UIBounds RectangleElement::getBounds() {
return offsetUIBounds(uiToScreen(w), uiToScreen(h), origin);
}
void RectangleElement::draw(UIPoint screenPos, glm::mat4 projection) {
kekData.ui->rectangleShader->use();
UIBounds offset = getBounds();
glUniformMatrix4fv(glGetUniformLocation(kekData.ui->rectangleShader->id, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glm::vec4 bounds = glm::vec4(screenPos.x, screenPos.y, offset.w, offset.h);
glUniform4fv(glGetUniformLocation(kekData.ui->rectangleShader->id, "bounds"), 1, glm::value_ptr(bounds));
glUniform4fv(glGetUniformLocation(kekData.ui->rectangleShader->id, "rectColor"), 1, color.valuePointer());
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
ButtonElement::ButtonElement(UIValue x, UIValue y, UIValue w, UIValue h)
: RectangleElement(x, y, w, h) {
clickable = true;
color = Colors::CYAN;
hoverColor = Colors::CYAN.darker();
text = new TextElement(uiPw(0.5), uiPh(0.5));
text->origin = Origin::CENTER;
addChild(text);
}
ButtonElement::~ButtonElement() {
delete text;
}
UIElementType ButtonElement::getType() {
return UIElementType::BUTTON;
}
void ButtonElement::click(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) {
onClick();
}
void ButtonElement::draw(UIPoint screenPos, glm::mat4 projection) {
RectangleElement::color = hovering ? hoverColor : color;
RectangleElement::draw(screenPos, projection);
}
}