Clean up UI stuff, More UI elements (WIP)

This commit is contained in:
MrLetsplay 2022-11-01 15:55:23 +01:00
parent 1d0869794b
commit cc006e7469
12 changed files with 242 additions and 68 deletions

View File

@ -1,17 +1,22 @@
#include "input.h" #include "input.h"
#include "ui.h"
#include "uielements.h"
#include "internal.h" #include "internal.h"
namespace kek::Defaults { namespace kek::Defaults {
static int static KeyBinding
keyForward, keyForward,
keyBackward, keyBackward,
keyLeft, keyLeft,
keyRight, keyRight,
keyUp, keyUp,
keyDown; keyDown,
keyOptions;
void defaultInput(GLFWwindow *window, void *data) { static ButtonElement *options;
static void defaultInput(GLFWwindow *window, void *data) {
if(Input::getKeyState(keyForward) == GLFW_PRESS) { if(Input::getKeyState(keyForward) == GLFW_PRESS) {
kekData.activeCamera->translate(kekData.activeCamera->direction * KEK_NOCLIP_SPEED * kekData.lastFrameTime); kekData.activeCamera->translate(kekData.activeCamera->direction * KEK_NOCLIP_SPEED * kekData.lastFrameTime);
} }
@ -39,6 +44,12 @@ void defaultInput(GLFWwindow *window, void *data) {
} }
} }
static void defaultKey(GLFWwindow *window, int key, int scancode, int action, int mods, void *data) {
if(key == Input::getKeyBinding(keyOptions).key && action == GLFW_PRESS) {
options->visible = !options->visible;
}
}
void init() { void init() {
keyForward = Input::createKeyBinding("Forward", GLFW_KEY_W); keyForward = Input::createKeyBinding("Forward", GLFW_KEY_W);
keyBackward = Input::createKeyBinding("Backward", GLFW_KEY_S); keyBackward = Input::createKeyBinding("Backward", GLFW_KEY_S);
@ -46,8 +57,13 @@ void init() {
keyRight = Input::createKeyBinding("Right", GLFW_KEY_D); keyRight = Input::createKeyBinding("Right", GLFW_KEY_D);
keyUp = Input::createKeyBinding("Up", GLFW_KEY_SPACE); keyUp = Input::createKeyBinding("Up", GLFW_KEY_SPACE);
keyDown = Input::createKeyBinding("Down", GLFW_KEY_LEFT_CONTROL); keyDown = Input::createKeyBinding("Down", GLFW_KEY_LEFT_CONTROL);
keyOptions = Input::createKeyBinding("Options", GLFW_KEY_Q);
Input::addPeriodicCallback(PeriodicCallback(defaultInput, nullptr)); Input::addPeriodicCallback(PeriodicCallback(defaultInput, nullptr));
Input::addKeyListener(KeyCallback(defaultKey, nullptr));
options = new ButtonElement(px(0), px(100), px(100), px(50));
UI::addElement(options);
} }
} }

View File

@ -180,9 +180,9 @@ int init() {
return KEK_ERROR; return KEK_ERROR;
} }
UIElement::init(); UI::init();
Defaults::init(); Defaults::init();
fpsText = new TextElement(px(0), px(0)); fpsText = new TextElement(px(0), px(0));
UI::addElement(fpsText); UI::addElement(fpsText);

View File

@ -32,8 +32,6 @@ constexpr UIValue operator-(const UIValue& lhs, const UIValue& rhs) {
return UIValue(lhs) -= rhs; return UIValue(lhs) -= rhs;
} }
Font *UIElement::defaultFont = nullptr;
UIElement::UIElement(UIValue x, UIValue y): x(x), y(y) { UIElement::UIElement(UIValue x, UIValue y): x(x), y(y) {
} }
@ -70,7 +68,7 @@ void UIElement::removeChild(UIElement *child) {
std::remove(children.begin(), children.end(), child); std::remove(children.begin(), children.end(), child);
} }
inline int UIElement::uiToScreen(UIValue val) { int UIElement::uiToScreen(UIValue val) {
float px = 0; float px = 0;
px += val.pixels; px += val.pixels;
if(parent) px += (int) (val.parentWidth * parent->getBounds().w); if(parent) px += (int) (val.parentWidth * parent->getBounds().w);
@ -92,11 +90,11 @@ void UIElement::drawAll(UIPoint screenPos, glm::mat4 projection) {
} }
} }
void UIElement::hoverAll(UIPoint pos, UIPoint screenPos) { bool UIElement::hoverAll(UIPoint pos, UIPoint screenPos) {
UIBounds bounds = getBounds(); UIBounds bounds = getBounds();
if(!bounds.contains(pos)) { // Only used by topmost parent UIElement if(!bounds.contains(pos)) { // Only used by topmost parent UIElement
if(hovering) hoverExitAll(); if(hovering) hoverExitAll();
return; return false;
} }
UIElement *hoveredChild = NULL; UIElement *hoveredChild = NULL;
@ -121,6 +119,7 @@ void UIElement::hoverAll(UIPoint pos, UIPoint screenPos) {
if(!hovering) hoverEnter(pos, screenPos); if(!hovering) hoverEnter(pos, screenPos);
hovering = true; hovering = true;
hover(pos, screenPos); hover(pos, screenPos);
return true;
} }
void UIElement::hoverExitAll() { void UIElement::hoverExitAll() {
@ -132,9 +131,9 @@ void UIElement::hoverExitAll() {
hoverExit(); hoverExit();
} }
void UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) { bool UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) {
UIBounds bounds = getBounds(); UIBounds bounds = getBounds();
if(!bounds.contains(pos)) return; // Only used by topmost parent UIElement if(!bounds.contains(pos)) return false; // Only used by topmost parent UIElement
UIElement *clickedChild = NULL; UIElement *clickedChild = NULL;
for(UIElement *child : children) { for(UIElement *child : children) {
@ -153,6 +152,8 @@ void UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button)
}else { }else {
click(pos, screenPos, button); click(pos, screenPos, button);
} }
return true;
} }
bool UIElement::focusEnterAll(UIPoint pos, UIPoint screenPos) { bool UIElement::focusEnterAll(UIPoint pos, UIPoint screenPos) {
@ -208,8 +209,14 @@ UIElement *UIElement::dragEnterAll(UIPoint pos, UIPoint screenPos) {
return nullptr; return nullptr;
} }
void UIElement::init() { void UI::init() {
defaultFont = new Font(KEK_DEFAULT_FONT); kekData.uiDefaultFont = new Font(KEK_DEFAULT_FONT);
kekData.uiRectangleShader = new Shader("shader/rectangle/vertex.glsl", "shader/rectangle/fragment.glsl");
}
void UI::destroy() {
delete kekData.uiDefaultFont;
delete kekData.uiRectangleShader;
} }
void UI::addElement(UIElement *element) { void UI::addElement(UIElement *element) {

View File

@ -1,5 +1,9 @@
#include "uielements.h" #include "uielements.h"
#include <glm/gtc/type_ptr.hpp>
#include "internal.h"
namespace kek { namespace kek {
static inline int offsetX(int w, Origin origin) { static inline int offsetX(int w, Origin origin) {
@ -56,7 +60,7 @@ TextElement::TextElement(UIValue x, UIValue y, Font *font): UIElement(x, y) {
this->textBounds = TextBounds::SMALLEST; this->textBounds = TextBounds::SMALLEST;
} }
TextElement::TextElement(UIValue x, UIValue y): TextElement(x, y, UIElement::defaultFont) {} TextElement::TextElement(UIValue x, UIValue y): TextElement(x, y, kekData.uiDefaultFont) {}
TextElement::~TextElement() { TextElement::~TextElement() {
delete text; delete text;
@ -97,22 +101,6 @@ void TextElement::setText(std::string text) {
this->text->setText(text); this->text->setText(text);
} }
void TextElement::setSizePixels(int sizePixels) {
this->sizePixels = sizePixels;
}
void TextElement::setColor(Color color) {
this->color = color;
}
void TextElement::setTextMode(TextMode textMode) {
this->textMode = textMode;
}
void TextElement::setTextBounds(TextBounds textBounds) {
this->textBounds = textBounds;
}
void TextElement::draw(UIPoint screenPos, glm::mat4 projection) { void TextElement::draw(UIPoint screenPos, glm::mat4 projection) {
UIBounds offset = getBounds(); UIBounds offset = getBounds();
@ -153,4 +141,101 @@ 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) {
}
} }

View File

@ -7,10 +7,10 @@
namespace kek { namespace kek {
typedef generic_callable_t<GLFWwindow *> PeriodicCallback; // periodicCallback(GLFWwindow *window) typedef GenericCallable<GLFWwindow *> PeriodicCallback; // periodicCallback(GLFWwindow *window)
typedef generic_callable_t<GLFWwindow *, int, int, int, int> KeyCallback; // keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) typedef GenericCallable<GLFWwindow *, int, int, int, int> KeyCallback; // keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
typedef generic_callable_t<GLFWwindow *, double, double> MouseCallback; // mouseCallback(GLFWwindow *window, double x, double y) typedef GenericCallable<GLFWwindow *, double, double> MouseCallback; // mouseCallback(GLFWwindow *window, double x, double y)
typedef generic_callable_t<GLFWwindow *, int, int, int> MouseButtonCallback; // void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) typedef GenericCallable<GLFWwindow *, int, int, int> MouseButtonCallback; // void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
typedef unsigned int InputListener; typedef unsigned int InputListener;
typedef int GLFWKey; typedef int GLFWKey;

View File

@ -36,6 +36,8 @@ struct KekData {
FT_Library freetype; FT_Library freetype;
std::vector<UIElement *> uiElements; std::vector<UIElement *> uiElements;
Font *uiDefaultFont;
Shader *uiRectangleShader;
}; };
extern KekData kekData; extern KekData kekData;

View File

@ -120,8 +120,6 @@ struct UIValue {
class UIElement { class UIElement {
protected: protected:
static Font *defaultFont;
UIElement *parent = nullptr; UIElement *parent = nullptr;
std::vector<UIElement *> children; std::vector<UIElement *> children;
@ -147,62 +145,50 @@ public:
UIPoint getScreenPosition(); UIPoint getScreenPosition();
std::vector<UIElement *> getChildren(); std::vector<UIElement *> getChildren();
void addChild(UIElement *child); void addChild(UIElement *child);
void removeChild(UIElement *child); void removeChild(UIElement *child);
protected: protected:
inline int uiToScreen(UIValue val); int uiToScreen(UIValue val);
public: public:
// Returns the bounds of the element relative to its origin (as returned by getX() and getY()) // Returns the bounds of the element relative to its origin (as returned by getX() and getY())
virtual UIBounds getBounds() = 0; virtual UIBounds getBounds() = 0;
void drawAll(UIPoint screenPos, glm::mat4 projection); void drawAll(UIPoint screenPos, glm::mat4 projection);
virtual void draw(UIPoint screenPos, glm::mat4 projection) = 0; virtual void draw(UIPoint screenPos, glm::mat4 projection) = 0;
void hoverAll(UIPoint pos, UIPoint screenPos); bool hoverAll(UIPoint pos, UIPoint screenPos);
void hoverExitAll(); void hoverExitAll();
virtual void hoverEnter(UIPoint pos, UIPoint screenPos) {}; virtual void hoverEnter(UIPoint pos, UIPoint screenPos) {};
virtual void hover(UIPoint pos, UIPoint screenPos) {}; virtual void hover(UIPoint pos, UIPoint screenPos) {};
virtual void hoverExit() {}; virtual void hoverExit() {};
void clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button); bool clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button);
virtual void click(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) {}; virtual void click(UIPoint pos, UIPoint screenPos, GLFWMouseButton button) {};
bool focusEnterAll(UIPoint pos, UIPoint screenPos); bool focusEnterAll(UIPoint pos, UIPoint screenPos);
virtual void focusEnter(UIPoint pos, UIPoint screenPos) {}; virtual void focusEnter(UIPoint pos, UIPoint screenPos) {};
virtual void focusExit() {}; virtual void focusExit() {};
UIElement *dragEnterAll(UIPoint pos, UIPoint screenPos); UIElement *dragEnterAll(UIPoint pos, UIPoint screenPos);
virtual void dragEnter(UIPoint pos, UIPoint screenPos) {}; virtual void dragEnter(UIPoint pos, UIPoint screenPos) {};
virtual void drag(UIPoint pos, UIPoint screenPos) {}; virtual void drag(UIPoint pos, UIPoint screenPos) {};
virtual void dragExit(UIPoint pos, UIPoint screenPos) {}; virtual void dragExit(UIPoint pos, UIPoint screenPos) {};
static void init();
}; };
namespace UI { namespace UI {
void addElement(UIElement *element); void init();
void destroy();
void removeElement(UIElement *element);
std::vector<UIElement *> getElements(); std::vector<UIElement *> getElements();
void addElement(UIElement *element);
void removeElement(UIElement *element);
}; };
} }
#include "uielements.h"

View File

@ -20,12 +20,13 @@ class TextElement: public UIElement {
protected: protected:
TextObject *text; TextObject *text;
public:
int sizePixels; int sizePixels;
Color color; Color color;
TextMode textMode; TextMode textMode;
TextBounds textBounds; TextBounds textBounds;
public:
TextElement(UIValue x, UIValue y, Font *font); TextElement(UIValue x, UIValue y, Font *font);
TextElement(UIValue x, UIValue y); TextElement(UIValue x, UIValue y);
@ -38,16 +39,62 @@ public:
void setText(std::string text); void setText(std::string text);
void setSizePixels(int sizePixels); virtual void draw(UIPoint screenPos, glm::mat4 projection);
void setColor(Color color); };
void setTextMode(TextMode textMode); class RectangleElement: public UIElement {
void setTextBounds(TextBounds textBounds); protected:
UIValue w, h;
Color color;
unsigned int vao;
unsigned int vbo;
public:
RectangleElement(UIValue x, UIValue y, UIValue w, UIValue h);
virtual ~RectangleElement();
virtual UIElementType getType();
virtual UIBounds getBounds();
virtual void setColor(Color color);
virtual void draw(UIPoint screenPos, glm::mat4 projection); virtual void draw(UIPoint screenPos, glm::mat4 projection);
}; };
class ButtonElement: public RectangleElement {
protected:
TextElement *text;
Color color;
Callable onClick;
public:
ButtonElement(UIValue x, UIValue y, UIValue w, UIValue h);
virtual ~ButtonElement();
virtual UIElementType getType();
TextElement *getText();
virtual void setColor(Color color);
void setOnClickCallback(Callable onClick);
virtual void hover(UIPoint pos, UIPoint screenPos);
virtual void hoverEnter();
virtual void hoverExit();
virtual void click(UIPoint pos, UIPoint screenPos, GLFWMouseButton button);
};
} }

View File

@ -9,21 +9,24 @@
namespace kek { namespace kek {
template<typename ...Args> template<typename ...Args>
using generic_function_t = void(*)(Args... args); using GenericFunction = void(*)(Args... args);
template<typename ...Args> template<typename ...Args>
struct generic_callable_t { struct GenericCallable {
generic_function_t<Args..., void *> function; GenericFunction<Args..., void *> function;
void *data; void *data;
generic_callable_t(generic_function_t<Args..., void *> function, void *data): function(function), data(data) {} GenericCallable(): function(nullptr), data(nullptr) {}
GenericCallable(GenericFunction<Args..., void *> function, void *data): function(function), data(data) {}
void operator()(Args... args) { void operator()(Args... args) {
if(function == nullptr) return;
function(args..., data); function(args..., data);
} }
}; };
typedef generic_callable_t<> callable_t; typedef GenericCallable<> Callable;
float clampCyclic(float value, float min, float max); float clampCyclic(float value, float min, float max);

View File

@ -0,0 +1,9 @@
#version 330 core
out vec4 color;
uniform vec4 rectColor;
void main() {
color = rectColor;
}

View File

@ -0,0 +1,10 @@
#version 330 core
layout (location = 0) in vec2 position;
uniform mat4 projection;
uniform vec4 bounds;
void main() {
gl_Position = projection * vec4(position * bounds.zw + bounds.xy, 0.0, 1.0);
}

View File

@ -17,6 +17,11 @@ void periodicCallback(GLFWwindow *window, void *data){
void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods, void *data){ void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods, void *data){
if(key == Input::getKeyBinding(keyWow).key && action == GLFW_PRESS) { if(key == Input::getKeyBinding(keyWow).key && action == GLFW_PRESS) {
std::cout << "WOW" << std::endl; std::cout << "WOW" << std::endl;
if(glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}else {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
}
} }
} }
@ -61,5 +66,9 @@ int main(int argc, char **argv) {
Input::addKeyListener(KeyCallback(keyCallback, nullptr)); Input::addKeyListener(KeyCallback(keyCallback, nullptr));
Input::addMouseButtonListener(MouseButtonCallback(mouseButtonCallback, nullptr)); Input::addMouseButtonListener(MouseButtonCallback(mouseButtonCallback, nullptr));
ButtonElement *btn = new ButtonElement(px(0), px(100), px(200), px(50));
btn->getText()->setText("Hello There!");
UI::addElement(btn);
Engine::start(); Engine::start();
} }