#include "uielements.h" #include #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) { } }