Update UI, more fonts & configs, Use C++20

This commit is contained in:
MrLetsplay 2023-10-14 23:35:56 +02:00
parent f9041ffc28
commit 3b03637cd4
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
24 changed files with 275 additions and 119 deletions

29
.clang-format Normal file
View File

@ -0,0 +1,29 @@
Language: Cpp
BasedOnStyle: LLVM
IndentWidth: 4
UseTab: Always
TabWidth: 4
ColumnLimit: 0
IndentCaseLabels: true
AllowShortIfStatementsOnASingleLine: true
FixNamespaceComments: false
SpaceBeforeParens: Never
SpaceAfterCStyleCast: true
SeparateDefinitionBlocks: Always
PackConstructorInitializers: Never
IncludeBlocks: Preserve
SpaceBeforeInheritanceColon: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignTrailingComments: false
AlignOperands: false
AlignEscapedNewlines: false
AlignConsecutiveMacros: false
AllowShortCaseLabelsOnASingleLine: false
SpaceBeforeCtorInitializerColon: false
SpaceBeforeAssignmentOperators: true
AllowShortLoopsOnASingleLine: true
AlignAfterOpenBracket: DontAlign
LambdaBodyIndentation: Signature
LineEnding: LF
ContinuationIndentWidth: 4

2
.clangd Normal file
View File

@ -0,0 +1,2 @@
CompileFlags:
Add: [-std=c++20]

View File

@ -37,9 +37,9 @@ file(GLOB_RECURSE KEKGAME_RELATIVE_RESOURCE_FILES RELATIVE ${KEKGAME_RESOURCE_DI
add_compile_definitions(FT_CONFIG_OPTION_ERROR_STRINGS) # Freetype error strings add_compile_definitions(FT_CONFIG_OPTION_ERROR_STRINGS) # Freetype error strings
if(${KEKENGINE_DEBUG}) if(${KEKENGINE_DEBUG})
add_compile_options(-Wall -g) add_compile_options(-Wall -std=c++20 -g)
else() else()
add_compile_options(-Wall -O3) add_compile_options(-Wall -std=c++20 -O3)
endif() endif()
block() block()

View File

@ -20,10 +20,7 @@ static KeyBinding
static ButtonElement *options; static ButtonElement *options;
static void defaultInput(GLFWwindow *window, void *data) { static void defaultPeriodic(PeriodicEvent event, void *data) {
if(Input::isKeyboardCaptured()) return;
// TODO: move input handling to controller class, add NoclipController
kekData.player->controller->update(); kekData.player->controller->update();
} }
@ -55,6 +52,7 @@ static void doUIMouseHover(double x, double y) {
static void doUIMouseClick(double x, double y, GLFWMouseButton button) { static void doUIMouseClick(double x, double y, GLFWMouseButton button) {
UIElement *clickedElement = nullptr; UIElement *clickedElement = nullptr;
UIElement *focusedElement = nullptr;
for(UIElement *element : kekData.ui->elements) { for(UIElement *element : kekData.ui->elements) {
UIPoint childPos = element->getPosition(); UIPoint childPos = element->getPosition();
@ -63,34 +61,41 @@ static void doUIMouseClick(double x, double y, GLFWMouseButton button) {
UIBounds bounds = element->getBounds(); UIBounds bounds = element->getBounds();
if(!bounds.contains(clickedAt)) continue; if(!bounds.contains(clickedAt)) continue;
clickedElement = element; if(element->clickable) clickedElement = element;
if(element->focusable) focusedElement = element;
} }
if(clickedElement) { if(clickedElement) {
/*if(clickedElement != kekData.ui->focusedElement) { // TODO: check for focusable on children etc
if(kekData.ui->focusedElement != nullptr) {
kekData.ui->focusedElement->focusExit();
}
clickedElement->focusEnter();
}*/
UIPoint childPos = clickedElement->getPosition(); UIPoint childPos = clickedElement->getPosition();
UIPoint clickedAt = UIPoint((int) x - childPos.x, (int) y - childPos.y); UIPoint clickedAt = UIPoint((int) x - childPos.x, (int) y - childPos.y);
clickedElement->clickAll(clickedAt, UIPoint((int) x, (int) y), button); clickedElement->clickAll(clickedAt, UIPoint((int) x, (int) y), button);
} }
if(button == GLFWMouseButton::LEFT && focusedElement != kekData.ui->focusedElement) {
if(kekData.ui->focusedElement != nullptr) {
kekData.ui->focusedElement->focusExit();
}
if(focusedElement) {
UIPoint childPos = focusedElement->getPosition();
UIPoint clickedAt = UIPoint((int) x - childPos.x, (int) y - childPos.y);
focusedElement->focusEnterAll(clickedAt, UIPoint((int) x, (int) y));
}
kekData.ui->focusedElement = focusedElement;
}
} }
static void defaultKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods, void *data) { static void defaultKeyCallback(KeyEvent event, void *data) {
if(key == Input::getKeyBinding(keyExit).key && action == GLFW_PRESS) { if(event.key == Input::getKeyBinding(keyExit).key && event.action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true); glfwSetWindowShouldClose(event.window, true);
} }
if(key == Input::getKeyBinding(keyOptions).key && action == GLFW_PRESS) { if(event.key == Input::getKeyBinding(keyOptions).key && event.action == GLFW_PRESS) {
options->visible = !options->visible; options->visible = !options->visible;
} }
if(key == Input::getKeyBinding(keyToggleCursorMode).key && action == GLFW_PRESS) { if(event.key == Input::getKeyBinding(keyToggleCursorMode).key && event.action == GLFW_PRESS) {
if(Input::getCursorMode() == GLFWCursorMode::CAPTURE) { if(Input::getCursorMode() == GLFWCursorMode::CAPTURE) {
Input::setCursorMode(GLFWCursorMode::FREE); Input::setCursorMode(GLFWCursorMode::FREE);
double x, y; double x, y;
@ -105,7 +110,7 @@ static void defaultKeyCallback(GLFWwindow *window, int key, int scancode, int ac
} }
} }
if(key == Input::getKeyBinding(keyToggleNoclip).key && action == GLFW_PRESS) { if(event.key == Input::getKeyBinding(keyToggleNoclip).key && event.action == GLFW_PRESS) {
kekData.player->noclip = !kekData.player->noclip; kekData.player->noclip = !kekData.player->noclip;
kekData.player->controller = kekData.player->noclip ? (PlayerController *) noclipController : (PlayerController *) defaultController; kekData.player->controller = kekData.player->noclip ? (PlayerController *) noclipController : (PlayerController *) defaultController;
if(kekData.player->noclip) { if(kekData.player->noclip) {
@ -116,19 +121,19 @@ static void defaultKeyCallback(GLFWwindow *window, int key, int scancode, int ac
} }
} }
static void defaultMouseCallback(GLFWwindow *window, double x, double y, void *data) { static void defaultMouseCallback(MouseEvent event, void *data) {
static bool firstMouse = true; static bool firstMouse = true;
static double lastX = 0, lastY = 0; static double lastX = 0, lastY = 0;
if(firstMouse) { if(firstMouse) {
lastX = x; lastX = event.x;
lastY = y; lastY = event.y;
firstMouse = false; firstMouse = false;
} }
switch(Input::getCursorMode()) { switch(Input::getCursorMode()) {
case GLFWCursorMode::CAPTURE: { case GLFWCursorMode::CAPTURE: {
float xoff = lastX - x; float xoff = lastX - event.x;
float yoff = lastY - y; float yoff = lastY - event.y;
xoff *= 0.1f; xoff *= 0.1f;
yoff *= 0.1f; yoff *= 0.1f;
@ -139,16 +144,16 @@ static void defaultMouseCallback(GLFWwindow *window, double x, double y, void *d
} }
case GLFWCursorMode::FREE: case GLFWCursorMode::FREE:
case GLFWCursorMode::HIDDEN: { case GLFWCursorMode::HIDDEN: {
doUIMouseHover(x, y); doUIMouseHover(event.x, event.y);
break; break;
} }
} }
lastX = x; lastX = event.x;
lastY = y; lastY = event.y;
} }
static void defaultMouseButtonCallback(GLFWwindow *window, int button, int action, int mods, void *data) { static void defaultMouseButtonCallback(MouseButtonEvent event, void *data) {
switch(Input::getCursorMode()) { switch(Input::getCursorMode()) {
case GLFWCursorMode::CAPTURE: { case GLFWCursorMode::CAPTURE: {
// TODO // TODO
@ -156,13 +161,13 @@ static void defaultMouseButtonCallback(GLFWwindow *window, int button, int actio
} }
case GLFWCursorMode::FREE: case GLFWCursorMode::FREE:
case GLFWCursorMode::HIDDEN: { case GLFWCursorMode::HIDDEN: {
switch(action) { switch(event.action) {
case GLFW_PRESS: case GLFW_PRESS:
break; break;
case GLFW_RELEASE: { case GLFW_RELEASE: {
double x, y; double x, y;
glfwGetCursorPos(window, &x, &y); glfwGetCursorPos(event.window, &x, &y);
doUIMouseClick(x, y, (GLFWMouseButton) button); doUIMouseClick(x, y, (GLFWMouseButton) event.button);
} }
} }
@ -185,7 +190,7 @@ void init() {
keyToggleNoclip = Input::createKeyBinding("Toggle Noclip", GLFW_KEY_N); keyToggleNoclip = Input::createKeyBinding("Toggle Noclip", GLFW_KEY_N);
keyExit = Input::createKeyBinding("Exit", GLFW_KEY_ESCAPE); keyExit = Input::createKeyBinding("Exit", GLFW_KEY_ESCAPE);
Input::addPeriodicCallback(PeriodicCallback(defaultInput, nullptr)); Input::addPeriodicCallback(PeriodicCallback(defaultPeriodic, nullptr));
Input::addKeyListener(KeyCallback(defaultKeyCallback, nullptr)); Input::addKeyListener(KeyCallback(defaultKeyCallback, nullptr));
Input::addMouseListener(MouseCallback(defaultMouseCallback, nullptr)); Input::addMouseListener(MouseCallback(defaultMouseCallback, nullptr));
Input::addMouseButtonListener(MouseButtonCallback(defaultMouseButtonCallback, nullptr)); Input::addMouseButtonListener(MouseButtonCallback(defaultMouseButtonCallback, nullptr));

View File

@ -1,5 +1,6 @@
#include "engine.h" #include "engine.h"
#include <algorithm>
#include <chrono> #include <chrono>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
@ -183,7 +184,7 @@ int start() {
Physics::step(kekData.lastFrameTime); Physics::step(kekData.lastFrameTime);
for(auto cb : kekData.input->periodicCallbacks) { for(auto cb : kekData.input->periodicCallbacks) {
cb.second(kekData.window); cb.second(PeriodicEvent{kekData.window});
} }
if(kekData.activeScene) { if(kekData.activeScene) {

View File

@ -20,7 +20,7 @@ void destroy() {
void onCursorPosCallback(GLFWwindow *window, double x, double y) { void onCursorPosCallback(GLFWwindow *window, double x, double y) {
for(auto cb : kekData.input->mouseCallbacks) { for(auto cb : kekData.input->mouseCallbacks) {
cb.second(window, x, y); cb.second(MouseEvent{window, x, y});
} }
} }
@ -32,32 +32,32 @@ void onKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mo
} }
if(key == GLFW_KEY_BACKSPACE && (action == GLFW_PRESS || action == GLFW_REPEAT)) { if(key == GLFW_KEY_BACKSPACE && (action == GLFW_PRESS || action == GLFW_REPEAT)) {
kekData.input->activeKeyboardCapture.charCallback(window, KEK_INPUT_DELETE); kekData.input->activeKeyboardCapture.charCallback(KeyCharEvent{window, KEK_INPUT_DELETE});
} }
kekData.input->activeKeyboardCapture.keyCallback(window, key, scancode, action, mods); kekData.input->activeKeyboardCapture.keyCallback(KeyEvent{window, key, scancode, action, mods});
return; return;
} }
for(auto cb : kekData.input->keyCallbacks) { for(auto cb : kekData.input->keyCallbacks) {
cb.second(window, key, scancode, action, mods); cb.second(KeyEvent{window, key, scancode, action, mods});
} }
} }
void onKeyCharCallback(GLFWwindow *window, unsigned int codepoint) { void onKeyCharCallback(GLFWwindow *window, unsigned int codepoint) {
if(Input::isKeyboardCaptured()) { if(Input::isKeyboardCaptured()) {
kekData.input->activeKeyboardCapture.charCallback(window, codepoint); kekData.input->activeKeyboardCapture.charCallback(KeyCharEvent{window, codepoint});
return; return;
} }
for(auto cb : kekData.input->keyCharCallbacks) { for(auto cb : kekData.input->keyCharCallbacks) {
cb.second(window, codepoint); cb.second(KeyCharEvent{window, codepoint});
} }
} }
void onMouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { void onMouseButtonCallback(GLFWwindow *window, int button, int action, int mods) {
for(auto cb : kekData.input->mouseButtonCallbacks) { for(auto cb : kekData.input->mouseButtonCallbacks) {
cb.second(window, button, action, mods); cb.second(MouseButtonEvent{window, button, action, mods});
} }
} }
@ -163,12 +163,13 @@ KeyboardCapture captureKeyboardInput(KeyCharCallback charCallback, KeyCallback k
bool uncaptureKeyboardInput(KeyboardCapture capture) { bool uncaptureKeyboardInput(KeyboardCapture capture) {
if(capture == KEK_INVALID_ID || capture != kekData.input->activeKeyboardCapture.id) return false; if(capture == KEK_INVALID_ID || capture != kekData.input->activeKeyboardCapture.id) return false;
kekData.input->activeKeyboardCapture.uncaptureCallback(); ActiveKeyboardCapture oldCapture = kekData.input->activeKeyboardCapture;
kekData.input->activeKeyboardCapture = { kekData.input->activeKeyboardCapture = {
KEK_INVALID_ID, KEK_INVALID_ID,
KeyCharCallback(), KeyCharCallback(),
KeyCallback(), KeyCallback(),
Callable()}; Callable()};
oldCapture.uncaptureCallback();
return true; return true;
} }
@ -176,4 +177,8 @@ bool isKeyboardCaptured() {
return kekData.input->activeKeyboardCapture.id != KEK_INVALID_ID; return kekData.input->activeKeyboardCapture.id != KEK_INVALID_ID;
} }
KeyboardCapture getActiveKeyboardCapture() {
return kekData.input->activeKeyboardCapture.id;
}
} }

View File

@ -1,5 +1,6 @@
#include "defaultplayercontroller.h" #include "defaultplayercontroller.h"
#include "input.h"
#include "internal.h" #include "internal.h"
#include "internal/physics.h" #include "internal/physics.h"
@ -100,31 +101,33 @@ void DefaultPlayerController::update() {
glm::vec3 direction = glm::vec3(0); glm::vec3 direction = glm::vec3(0);
if(Input::getKeyState(keyForward) == GLFW_PRESS) { if(!Input::isKeyboardCaptured()) {
direction += kekData.activeCamera->direction; if(Input::getKeyState(keyForward) == GLFW_PRESS) {
} direction += kekData.activeCamera->direction;
}
if(Input::getKeyState(keyBackward) == GLFW_PRESS) { if(Input::getKeyState(keyBackward) == GLFW_PRESS) {
direction += -kekData.activeCamera->direction; direction += -kekData.activeCamera->direction;
} }
if(Input::getKeyState(keyLeft) == GLFW_PRESS) { if(Input::getKeyState(keyLeft) == GLFW_PRESS) {
direction += -glm::normalize(glm::cross(kekData.activeCamera->direction, glm::vec3(0.0f, 1.0f, 0.0f))); direction += -glm::normalize(glm::cross(kekData.activeCamera->direction, glm::vec3(0.0f, 1.0f, 0.0f)));
} }
if(Input::getKeyState(keyRight) == GLFW_PRESS) { if(Input::getKeyState(keyRight) == GLFW_PRESS) {
direction += glm::normalize(glm::cross(kekData.activeCamera->direction, glm::vec3(0.0f, 1.0f, 0.0f))); direction += glm::normalize(glm::cross(kekData.activeCamera->direction, glm::vec3(0.0f, 1.0f, 0.0f)));
} }
if(Input::getKeyState(keyJump) == GLFW_PRESS && kekData.player->onGround) { if(Input::getKeyState(keyJump) == GLFW_PRESS && kekData.player->onGround) {
velocity += glm::vec3(0, jumpVelocity, 0); velocity += glm::vec3(0, jumpVelocity, 0);
} }
direction = glm::vec3(direction.x, 0, direction.z); direction = glm::vec3(direction.x, 0, direction.z);
if(onGround) { if(onGround) {
// Project movement onto ground // Project movement onto ground
direction = glm::normalize(glm::cross(groundNormal, glm::cross(direction, groundNormal))); direction = glm::normalize(glm::cross(groundNormal, glm::cross(direction, groundNormal)));
}
} }
glm::vec3 move = velocity; glm::vec3 move = velocity;

View File

@ -1,5 +1,6 @@
#include "noclipplayercontroller.h" #include "noclipplayercontroller.h"
#include "input.h"
#include "internal.h" #include "internal.h"
namespace kek { namespace kek {
@ -16,6 +17,8 @@ glm::vec3 NoclipPlayerController::move(glm::vec3 movement) {
} }
void NoclipPlayerController::update() { void NoclipPlayerController::update() {
if(Input::isKeyboardCaptured()) return;
glm::vec3 direction = glm::vec3(0); glm::vec3 direction = glm::vec3(0);
if(Input::getKeyState(keyForward) == GLFW_PRESS) { if(Input::getKeyState(keyForward) == GLFW_PRESS) {

View File

@ -1,7 +1,11 @@
#include "ui.h" #include "ui.h"
#include <bits/stdc++.h> #include <iostream>
#include <numeric>
#include <string_view>
#include <vector>
#include "input.h"
#include "internal.h" #include "internal.h"
#include "internal/ui.h" #include "internal/ui.h"
@ -13,6 +17,7 @@ UIElement::UIElement(UIValue x, UIValue y)
} }
UIElement::~UIElement() { UIElement::~UIElement() {
UI::unfocusElement(this);
} }
// Returns the element's position relative to its parent in pixels // Returns the element's position relative to its parent in pixels
@ -50,7 +55,7 @@ void UIElement::addChild(UIElement *child) {
void UIElement::removeChild(UIElement *child) { void UIElement::removeChild(UIElement *child) {
child->parent = nullptr; child->parent = nullptr;
std::remove(children.begin(), children.end(), child); std::erase(children, child);
} }
int UIElement::uiToScreen(UIValue val) { int UIElement::uiToScreen(UIValue val) {
@ -188,9 +193,6 @@ void UIElement::clickAll(UIPoint pos, UIPoint screenPos, GLFWMouseButton button)
} }
bool UIElement::focusEnterAll(UIPoint pos, UIPoint screenPos) { bool UIElement::focusEnterAll(UIPoint pos, UIPoint screenPos) {
UIBounds bounds = getBounds();
if(!bounds.contains(pos)) return false;
UIElement *focusedChild = nullptr; UIElement *focusedChild = nullptr;
for(UIElement *child : children) { for(UIElement *child : children) {
UIPoint childPos = child->getPosition(); UIPoint childPos = child->getPosition();
@ -271,21 +273,26 @@ std::vector<UIElement *> UI::getElements() {
} }
void UI::focusElement(UIElement *element) { void UI::focusElement(UIElement *element) {
if(kekData.ui->focusedElement != nullptr) { if(kekData.ui->focusedElement != element) {
unfocusElement(); if(kekData.ui->focusedElement != nullptr) {
} unfocusElement(kekData.ui->focusedElement);
}
kekData.ui->focusedElement = element; kekData.ui->focusedElement = element;
if(element != nullptr) { if(element != nullptr) {
element->focusEnter(); element->focused = true;
element->focusEnter();
}
} }
} }
void UI::unfocusElement() { void UI::unfocusElement(UIElement *element) {
if(kekData.ui->focusedElement == nullptr) return; if(kekData.ui->focusedElement == nullptr || element != kekData.ui->focusedElement) return;
kekData.ui->focusedElement->focusExit(); UIElement *oldFocus = kekData.ui->focusedElement;
kekData.ui->focusedElement = nullptr; kekData.ui->focusedElement = nullptr;
oldFocus->focused = false;
oldFocus->focusExit();
} }
} }

View File

@ -1,10 +1,15 @@
#include "uielements.h" #include "uielements.h"
#include <GLFW/glfw3.h>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include "constants.h"
#include "input.h"
#include "internal.h" #include "internal.h"
#include "internal/ui.h" #include "internal/ui.h"
#include "ui.h" #include "ui.h"
#include "unicode.h"
#include "utils.h"
namespace kek { namespace kek {
@ -195,17 +200,25 @@ TextFieldElement::TextFieldElement(UIValue x, UIValue y, UIValue w, Font *font)
this->enableClipping = true; this->enableClipping = true;
this->focusable = true; this->focusable = true;
this->color = Colors::WHITE; this->color = Colors::WHITE;
this->text = "Hello World"; this->focusColor = Colors::GRAY;
this->text = "";
RectangleElement::color = color;
this->textElement = new TextElement(uiPx(0), uiPx(0)); this->textElement = new TextElement(uiPx(0), uiPx(0));
textElement->textBounds = TextBounds::LINE; textElement->textBounds = TextBounds::LINE;
textElement->color = Colors::RED; textElement->color = Colors::BLACK;
textElement->setText(text); textElement->setText(text);
addChild(textElement); addChild(textElement);
int textH = textElement->getBounds().h; int textH = textElement->getBounds().h;
std::cout << "TEXTH" << textH << std::endl;
h = uiPx(textH); h = uiPx(textH);
this->cursor = new RectangleElement(uiPx(0), uiPx(2), uiPx(1), uiPx(textH - 4));
cursor->color = Colors::BLACK;
addChild(cursor);
this->capture = KEK_INVALID_ID;
} }
TextFieldElement::TextFieldElement(UIValue x, UIValue y, UIValue w) TextFieldElement::TextFieldElement(UIValue x, UIValue y, UIValue w)
@ -213,15 +226,72 @@ TextFieldElement::TextFieldElement(UIValue x, UIValue y, UIValue w)
} }
TextFieldElement::~TextFieldElement() { TextFieldElement::~TextFieldElement() {
Input::uncaptureKeyboardInput(capture);
capture = KEK_INVALID_ID;
delete textElement; delete textElement;
delete cursor;
} }
UIElementType TextFieldElement::getType() { UIElementType TextFieldElement::getType() {
return UIElementType::TEXT_FIELD; return UIElementType::TEXT_FIELD;
} }
void TextFieldElement::focusEnter() {
RectangleElement::color = focusColor;
cursor->visible = true;
capture = Input::captureKeyboardInput(
KeyCharCallback([](KeyCharEvent event, void *data) {
TextFieldElement *_this = (TextFieldElement *) data;
std::u32string str = Unicode::convertStdToU32(_this->text);
if(event.codepoint == KEK_INPUT_DELETE) {
if(str.length() == 0) return;
str = str.substr(0, str.length() - 1);
} else {
str.push_back(event.codepoint);
}
_this->text = Unicode::convertU32ToStd(str);
_this->textElement->setText(_this->text);
_this->lastCharTyped = glfwGetTime();
_this->cursor->x = uiPx(_this->textElement->getBounds().w);
},
this),
KeyCallback([](KeyEvent event, void *data) {
TextFieldElement *_this = (TextFieldElement *) data;
if(event.key == GLFW_KEY_ENTER && event.action == GLFW_PRESS) {
Input::uncaptureKeyboardInput(_this->capture);
}
},
this),
Callable([](void *data) {
TextFieldElement *_this = (TextFieldElement *) data;
UI::unfocusElement(_this);
},
this));
}
void TextFieldElement::focusExit() {
RectangleElement::color = color;
cursor->visible = false;
Input::uncaptureKeyboardInput(capture);
capture = KEK_INVALID_ID;
}
void TextFieldElement::draw(UIPoint screenPos, glm::mat4 projection) { void TextFieldElement::draw(UIPoint screenPos, glm::mat4 projection) {
RectangleElement::draw(screenPos, projection); RectangleElement::draw(screenPos, projection);
double time = glfwGetTime();
cursor->visible = focused ? (time - lastCharTyped < 0.5 || (int) time % 2 == 0) : false;
}
void TextFieldElement::setText(std::string text) {
this->text = text;
this->textElement->setText(text);
} }
} }

View File

@ -28,6 +28,10 @@ struct Color {
constexpr Color brighter(float factor = 0.7) const { constexpr Color brighter(float factor = 0.7) const {
return Color(r / factor, g / factor, b / factor, a); return Color(r / factor, g / factor, b / factor, a);
} }
constexpr bool operator==(const Color &other) {
return r == other.r && g == other.g && b == other.g;
}
}; };
class Colors { class Colors {

View File

@ -38,7 +38,7 @@
#define KEK_FONT_BITMAP_CHAR_MASK 0xFF // = KEK_FONT_BITMAP_CHAR_BITS 1s in binary #define KEK_FONT_BITMAP_CHAR_MASK 0xFF // = KEK_FONT_BITMAP_CHAR_BITS 1s in binary
#define KEK_TEXT_BLOCK_SIZE 8 #define KEK_TEXT_BLOCK_SIZE 8
#define KEK_DEFAULT_FONT "font/MaredivRegular-yeg3.ttf" #define KEK_DEFAULT_FONT "font/JupiteroidRegular.ttf"
#define KEK_DEFAULT_FONT_SIZE_PIXELS 24 #define KEK_DEFAULT_FONT_SIZE_PIXELS 24
#define KEK_INPUT_DELETE -1u #define KEK_INPUT_DELETE -1u

View File

@ -7,11 +7,41 @@
namespace kek { namespace kek {
typedef GenericCallable<GLFWwindow *> PeriodicCallback; // periodicCallback(GLFWwindow *window) typedef struct {
typedef GenericCallable<GLFWwindow *, int, int, int, int> KeyCallback; // keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) GLFWwindow *window;
typedef GenericCallable<GLFWwindow *, unsigned int> KeyCharCallback; // keyCharCallback(GLFWwindow *window, unsigned int codepoint) } PeriodicEvent;
typedef GenericCallable<GLFWwindow *, double, double> MouseCallback; // mouseCallback(GLFWwindow *window, double x, double y)
typedef GenericCallable<GLFWwindow *, int, int, int> MouseButtonCallback; // void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) typedef struct {
GLFWwindow *window;
int key;
int scancode;
int action;
int mods;
} KeyEvent;
typedef struct {
GLFWwindow *window;
unsigned int codepoint;
} KeyCharEvent;
typedef struct {
GLFWwindow *window;
double x;
double y;
} MouseEvent;
typedef struct {
GLFWwindow *window;
int button;
int action;
int mods;
} MouseButtonEvent;
typedef GenericCallable<PeriodicEvent> PeriodicCallback; // periodicCallback(GLFWwindow *window)
typedef GenericCallable<KeyEvent> KeyCallback; // keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
typedef GenericCallable<KeyCharEvent> KeyCharCallback; // keyCharCallback(GLFWwindow *window, unsigned int codepoint)
typedef GenericCallable<MouseEvent> MouseCallback; // mouseCallback(GLFWwindow *window, double x, double y)
typedef GenericCallable<MouseButtonEvent> 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;
@ -69,5 +99,6 @@ GLFWCursorMode getCursorMode();
KeyboardCapture captureKeyboardInput(KeyCharCallback charCallback, KeyCallback keyCallback, Callable uncaptureCallback); KeyboardCapture captureKeyboardInput(KeyCharCallback charCallback, KeyCallback keyCallback, Callable uncaptureCallback);
bool uncaptureKeyboardInput(KeyboardCapture capture); bool uncaptureKeyboardInput(KeyboardCapture capture);
bool isKeyboardCaptured(); bool isKeyboardCaptured();
KeyboardCapture getActiveKeyboardCapture();
} }

View File

@ -136,11 +136,13 @@ class UIElement {
bool enableClipping = false; bool enableClipping = false;
bool clickable = false; bool clickable = false;
bool hovering = false;
bool visible = true; bool visible = true;
bool focusable = false; bool focusable = false;
bool draggable = false; bool draggable = false;
bool hovering = false;
bool focused = false;
UIElement(UIValue x, UIValue y); UIElement(UIValue x, UIValue y);
virtual ~UIElement(); virtual ~UIElement();
@ -202,7 +204,7 @@ void addElement(UIElement *element);
void removeElement(UIElement *element); void removeElement(UIElement *element);
void focusElement(UIElement *element); void focusElement(UIElement *element);
void unfocusElement(); void unfocusElement(UIElement *element);
}; };

View File

@ -101,7 +101,14 @@ class TextFieldElement: public RectangleElement {
protected: protected:
std::string text; std::string text;
Color color;
Color focusColor;
TextElement *textElement; TextElement *textElement;
RectangleElement *cursor;
KeyboardCapture capture;
float lastCharTyped = 0;
public: public:
TextFieldElement(UIValue x, UIValue y, UIValue w, Font *font); TextFieldElement(UIValue x, UIValue y, UIValue w, Font *font);
@ -112,7 +119,12 @@ class TextFieldElement: public RectangleElement {
virtual UIElementType getType(); virtual UIElementType getType();
virtual void focusEnter();
virtual void focusExit();
virtual void draw(UIPoint screenPos, glm::mat4 projection); virtual void draw(UIPoint screenPos, glm::mat4 projection);
void setText(std::string text);
}; };
} }

View File

@ -20,9 +20,8 @@ struct GenericCallable {
: function(nullptr), : function(nullptr),
data(nullptr) {} data(nullptr) {}
GenericCallable(GenericFunction<Args..., void *> function) GenericCallable(GenericFunction<Args...> function)
: function(function), : GenericCallable([](void *f) { ((GenericFunction<Args...>) f)(); }, (void *) function) {}
data(nullptr){};
GenericCallable(GenericFunction<Args..., void *> function, void *data) GenericCallable(GenericFunction<Args..., void *> function, void *data)
: function(function), : function(function),

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,6 @@
#include <iostream> #include <iostream>
#include "input.h"
#include "kekengine.h" #include "kekengine.h"
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
@ -16,42 +17,24 @@
using namespace kek; using namespace kek;
static ButtonElement *button; static ButtonElement *button;
static KeyboardCapture capture = KEK_INVALID_ID;
void periodicCallback(GLFWwindow *window, void *data) { void periodicCallback(PeriodicEvent event, void *data) {
} }
void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods, void *data) { void keyCallback(KeyEvent event, void *data) {
} }
void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods, void *data) { void mouseButtonCallback(MouseButtonEvent event, void *data) {
} }
void onButtonClick(void *data) { void onButtonClick(void *data) {
button->color = Colors::RED; if(button->color == Colors::RED) {
button->hoverColor = Colors::ORANGE; button->color = Colors::GREEN;
capture = Input::captureKeyboardInput( button->hoverColor = Colors::GREEN.darker();
KeyCharCallback([](GLFWwindow *window, unsigned int codepoint, void *data) { } else {
std::u32string str = Unicode::convertStdToU32(button->text->getText()); button->color = Colors::RED;
if(codepoint == KEK_INPUT_DELETE) { button->hoverColor = Colors::RED.darker();
str = str.substr(0, str.length() - 1); }
} else {
str.push_back(codepoint);
}
button->text->setText(Unicode::convertU32ToStd(str));
},
nullptr),
KeyCallback([](GLFWwindow *window, int key, int scancode, int action, int mods, void *data) {
if(key == GLFW_KEY_ENTER && action == GLFW_PRESS) {
Input::uncaptureKeyboardInput(capture);
}
},
nullptr),
Callable([](void *data) {
button->color = Colors::WHITE;
button->hoverColor = Colors::GRAY;
},
nullptr));
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -142,7 +125,7 @@ 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(50)); TextFieldElement *textField = new TextFieldElement(uiPx(10), uiPx(200), uiPx(500));
UI::addElement(textField); UI::addElement(textField);
if(Engine::start() != KEK_SUCCESS) return 1; if(Engine::start() != KEK_SUCCESS) return 1;