KekEngine/src/kekengine/cpp/uielements.cpp

242 lines
5.4 KiB
C++

#include "uielements.h"
#include <glm/gtc/type_ptr.hpp>
#include "internal.h"
namespace kek {
static inline int offsetX(int w, Origin origin) {
switch(origin) {
case Origin::TOP_LEFT:
case Origin::BOTTOM_LEFT:
case Origin::LEFT_CENTER:
return 0;
case Origin::TOP_RIGHT:
case Origin::BOTTOM_RIGHT:
case Origin::RIGHT_CENTER:
return -w;
case Origin::TOP_CENTER:
case Origin::BOTTOM_CENTER:
case Origin::CENTER:
return -w / 2;
}
return 0;
}
static inline int offsetY(int h, Origin origin) {
switch(origin) {
case Origin::TOP_LEFT:
case Origin::TOP_CENTER:
case Origin::TOP_RIGHT:
return 0;
case Origin::BOTTOM_LEFT:
case Origin::BOTTOM_CENTER:
case Origin::BOTTOM_RIGHT:
return -h;
case Origin::LEFT_CENTER:
case Origin::RIGHT_CENTER:
case Origin::CENTER:
return -h / 2;
}
return 0;
}
static inline UIBounds offsetUIBounds(int w, int h, Origin origin) {
return UIBounds(offsetX(w, origin), offsetY(h, origin), w, h);
}
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.uiDefaultFont) {}
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);
}
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;
this->color = Colors::BLACK;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(rectangleVerts), rectangleVerts, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
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::setColor(Color color) {
this->color = color;
}
void RectangleElement::draw(UIPoint screenPos, glm::mat4 projection) {
kekData.uiRectangleShader->use();
UIBounds offset = getBounds();
glUniformMatrix4fv(glGetUniformLocation(kekData.uiRectangleShader->id, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glm::vec4 bounds = glm::vec4(offset.x + screenPos.x, offset.y + screenPos.y, uiToScreen(w), uiToScreen(h));
glUniform4fv(glGetUniformLocation(kekData.uiRectangleShader->id, "bounds"), 1, glm::value_ptr(bounds));
glUniform4fv(glGetUniformLocation(kekData.uiRectangleShader->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) {
this->text = new TextElement(px(0), px(0));
}
ButtonElement::~ButtonElement() {
delete text;
}
UIElementType ButtonElement::getType() {
return UIElementType::BUTTON;
}
TextElement *ButtonElement::getText() {
return text;
}
void ButtonElement::setColor(Color color) {
}
void ButtonElement::setOnClickCallback(Callable onClick) {
this->onClick = onClick;
}
void ButtonElement::hover(UIPoint pos, UIPoint screenPos) {
}
void ButtonElement::hoverEnter() {
RectangleElement::setColor(Colors::RED);
}
void ButtonElement::hoverExit() {
}
void ButtonElement::click(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) {
}
}