Keyboard captures

This commit is contained in:
MrLetsplay 2022-11-05 22:07:53 +01:00
parent 04df1078b4
commit f15e895af5
12 changed files with 126 additions and 18 deletions

View File

@ -13,11 +13,14 @@ static KeyBinding
keyUp, keyUp,
keyDown, keyDown,
keyOptions, keyOptions,
keyToggleCursorMode; keyToggleCursorMode,
keyExit;
static ButtonElement *options; static ButtonElement *options;
static void defaultInput(GLFWwindow *window, void *data) { static void defaultInput(GLFWwindow *window, void *data) {
if(Input::isKeyboardCaptured()) return;
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);
} }
@ -46,6 +49,10 @@ static void defaultInput(GLFWwindow *window, void *data) {
} }
static void defaultKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods, void *data) { static void defaultKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods, void *data) {
if(key == Input::getKeyBinding(keyExit).key && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true);
}
if(key == Input::getKeyBinding(keyOptions).key && action == GLFW_PRESS) { if(key == Input::getKeyBinding(keyOptions).key && action == GLFW_PRESS) {
options->visible = !options->visible; options->visible = !options->visible;
} }
@ -128,6 +135,7 @@ void init() {
keyDown = Input::createKeyBinding("Down", GLFW_KEY_LEFT_CONTROL); keyDown = Input::createKeyBinding("Down", GLFW_KEY_LEFT_CONTROL);
keyOptions = Input::createKeyBinding("Options", GLFW_KEY_Q); keyOptions = Input::createKeyBinding("Options", GLFW_KEY_Q);
keyToggleCursorMode = Input::createKeyBinding("Toggle Cursor Mode", GLFW_KEY_TAB); keyToggleCursorMode = Input::createKeyBinding("Toggle Cursor Mode", GLFW_KEY_TAB);
keyExit = Input::createKeyBinding("Exit", GLFW_KEY_ESCAPE);
Input::addPeriodicCallback(PeriodicCallback(defaultInput, nullptr)); Input::addPeriodicCallback(PeriodicCallback(defaultInput, nullptr));
Input::addKeyListener(KeyCallback(defaultKeyCallback, nullptr)); Input::addKeyListener(KeyCallback(defaultKeyCallback, nullptr));

View File

@ -50,11 +50,27 @@ static void onCursorPosCallback(GLFWwindow *window, double x, double y) {
} }
static void onKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) { static void onKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) {
if(Input::isKeyboardCaptured()) {
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) Input::uncaptureKeyboardInput(kekData.activeKeyboardCapture.id);
return;
}
for(auto cb : kekData.keyCallbacks) { for(auto cb : kekData.keyCallbacks) {
cb.second(window, key, scancode, action, mods); cb.second(window, key, scancode, action, mods);
} }
} }
static void onKeyCharCallback(GLFWwindow *window, unsigned int codepoint) {
if(Input::isKeyboardCaptured()) {
kekData.activeKeyboardCapture.callback(window, codepoint);
return;
}
for(auto cb : kekData.keyCharCallbacks) {
cb.second(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.mouseButtonCallbacks) { for(auto cb : kekData.mouseButtonCallbacks) {
cb.second(window, button, action, mods); cb.second(window, button, action, mods);
@ -159,6 +175,7 @@ int init() {
glfwSetCursorPosCallback(kekData.window, onCursorPosCallback); glfwSetCursorPosCallback(kekData.window, onCursorPosCallback);
Input::setCursorMode(GLFWCursorMode::CAPTURE); Input::setCursorMode(GLFWCursorMode::CAPTURE);
glfwSetKeyCallback(kekData.window, onKeyCallback); glfwSetKeyCallback(kekData.window, onKeyCallback);
glfwSetCharCallback(kekData.window, onKeyCharCallback);
glfwSetMouseButtonCallback(kekData.window, onMouseButtonCallback); glfwSetMouseButtonCallback(kekData.window, onMouseButtonCallback);
glClearColor(0.1f, 0.3f, 0.1f, 0.0f); glClearColor(0.1f, 0.3f, 0.1f, 0.0f);
@ -195,10 +212,6 @@ int start() {
cb.second(kekData.window); cb.second(kekData.window);
} }
if(glfwGetKey(kekData.window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
break;
}
kekData.shader->use(); kekData.shader->use();
glm::mat4 view = kekData.activeCamera->transformationMatrix(); glm::mat4 view = kekData.activeCamera->transformationMatrix();

View File

@ -29,6 +29,16 @@ void removeKeyListener(InputListener listener) {
kekData.keyCallbacks.erase(listener); kekData.keyCallbacks.erase(listener);
} }
InputListener addKeyCharListener(KeyCharCallback callback) {
InputListener id = nextID++;
kekData.keyCharCallbacks.emplace(id, callback);
return id;
}
void removeKeyCharListener(InputListener listener) {
kekData.keyCharCallbacks.erase(listener);
}
InputListener addMouseListener(MouseCallback callback) { InputListener addMouseListener(MouseCallback callback) {
InputListener id = nextID++; InputListener id = nextID++;
kekData.mouseCallbacks.emplace(id, callback); kekData.mouseCallbacks.emplace(id, callback);
@ -50,7 +60,7 @@ void removeMouseButtonListener(InputListener listener) {
} }
KeyBinding createKeyBinding(std::string name, GLFWKey defaultKey) { KeyBinding createKeyBinding(std::string name, GLFWKey defaultKey) {
if(name == KEK_INVALID_KEY_BINDING_NAME) return KEK_INVALID_KEY_BINDING; if(name == KEK_INVALID_KEY_BINDING_NAME) return KEK_INVALID_ID;
KeyBinding id = nextID++; KeyBinding id = nextID++;
KeyBindingData d; KeyBindingData d;
d.name = name; d.name = name;
@ -60,7 +70,7 @@ KeyBinding createKeyBinding(std::string name, GLFWKey defaultKey) {
} }
void reassignKeyBinding(KeyBinding binding, GLFWKey key) { void reassignKeyBinding(KeyBinding binding, GLFWKey key) {
if(binding == KEK_INVALID_KEY_BINDING) return; if(binding == KEK_INVALID_ID) return;
auto it = kekData.keyBindings.find(binding); auto it = kekData.keyBindings.find(binding);
if(it == kekData.keyBindings.end()) return; if(it == kekData.keyBindings.end()) return;
KeyBindingData d = it->second; KeyBindingData d = it->second;
@ -89,4 +99,24 @@ GLFWCursorMode getCursorMode() {
return kekData.uiCursorMode; return kekData.uiCursorMode;
} }
KeyboardCapture captureKeyboardInput(KeyCharCallback callback, Callable uncaptureCallback) {
KeyboardCapture id = nextID++;
kekData.activeKeyboardCapture.id = id;
kekData.activeKeyboardCapture.callback = callback;
kekData.activeKeyboardCapture.uncaptureCallback = uncaptureCallback;
return id;
}
bool uncaptureKeyboardInput(KeyboardCapture capture) {
if(capture == KEK_INVALID_ID || capture != kekData.activeKeyboardCapture.id) return false;
kekData.activeKeyboardCapture.id = KEK_INVALID_ID;
kekData.activeKeyboardCapture.callback = KeyCharCallback();
kekData.activeKeyboardCapture.uncaptureCallback = Callable();
return true;
}
bool isKeyboardCaptured() {
return kekData.activeKeyboardCapture.id != KEK_INVALID_ID;
}
} }

View File

@ -55,6 +55,10 @@ void TextElement::setText(std::string text) {
this->text->setText(text); this->text->setText(text);
} }
std::string TextElement::getText() {
return text->getText();
}
void TextElement::draw(UIPoint screenPos, glm::mat4 projection) { void TextElement::draw(UIPoint screenPos, glm::mat4 projection) {
UIBounds offset = getBounds(); UIBounds offset = getBounds();

View File

@ -0,0 +1,17 @@
#include "unicode.h"
#include <locale>
namespace kek::Unicode {
static std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> utf32cvt;
std::u32string convertStdToU32(std::string string) {
return utf32cvt.from_bytes(string);
}
std::string convertU32ToStd(std::u32string string) {
return utf32cvt.to_bytes(string);
}
}

View File

@ -27,14 +27,14 @@
#define KEK_LIGHT_MAX_DISTANCE_SQUARED (KEK_LIGHT_MAX_DISTANCE * KEK_LIGHT_MAX_DISTANCE) #define KEK_LIGHT_MAX_DISTANCE_SQUARED (KEK_LIGHT_MAX_DISTANCE * KEK_LIGHT_MAX_DISTANCE)
#define KEK_INVALID_KEY_BINDING_NAME "INVALID" #define KEK_INVALID_KEY_BINDING_NAME "INVALID"
#define KEK_INVALID_KEY_BINDING -1u #define KEK_INVALID_ID -1u
#define KEK_FONT_RESOLUTION 64 #define KEK_FONT_RESOLUTION 64
#define KEK_FONT_BITMAP_WIDTH_BLOCKS 16 #define KEK_FONT_BITMAP_WIDTH_BLOCKS 16
#define KEK_FONT_BITMAP_HEIGHT_BLOCKS 16 #define KEK_FONT_BITMAP_HEIGHT_BLOCKS 16
#define KEK_FONT_BITMAP_WIDTH (KEK_FONT_BITMAP_WIDTH_BLOCKS * KEK_FONT_RESOLUTION) #define KEK_FONT_BITMAP_WIDTH (KEK_FONT_BITMAP_WIDTH_BLOCKS * KEK_FONT_RESOLUTION)
#define KEK_FONT_BITMAP_HEIGHT (KEK_FONT_BITMAP_HEIGHT_BLOCKS * KEK_FONT_RESOLUTION) #define KEK_FONT_BITMAP_HEIGHT (KEK_FONT_BITMAP_HEIGHT_BLOCKS * KEK_FONT_RESOLUTION)
#define KEK_FONT_BITMAP_CHAR_BITS 8 // = log2(KEK_FONT_BITMAP_WIDTH_BLOCKS * KEK_FONT_BITMAP_HEIGHT_BLOCKS) #define KEK_FONT_BITMAP_CHAR_BITS 8 // = ceil(log2(KEK_FONT_BITMAP_WIDTH_BLOCKS * KEK_FONT_BITMAP_HEIGHT_BLOCKS))
#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

View File

@ -9,6 +9,7 @@ namespace kek {
typedef GenericCallable<GLFWwindow *> PeriodicCallback; // periodicCallback(GLFWwindow *window) typedef GenericCallable<GLFWwindow *> PeriodicCallback; // periodicCallback(GLFWwindow *window)
typedef GenericCallable<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 GenericCallable<GLFWwindow *, unsigned int> KeyCharCallback; // keyCharCallback(GLFWwindow *window, unsigned int codepoint)
typedef GenericCallable<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 GenericCallable<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)
@ -16,6 +17,7 @@ typedef unsigned int InputListener;
typedef int GLFWKey; typedef int GLFWKey;
typedef int GLFWKeyState; typedef int GLFWKeyState;
typedef unsigned int KeyBinding; typedef unsigned int KeyBinding;
typedef unsigned int KeyboardCapture;
struct KeyBindingData { struct KeyBindingData {
std::string name; std::string name;
@ -44,6 +46,9 @@ void removePeriodicCallback(InputListener listener);
InputListener addKeyListener(KeyCallback callback); InputListener addKeyListener(KeyCallback callback);
void removeKeyListener(InputListener listener); void removeKeyListener(InputListener listener);
InputListener addKeyCharListener(KeyCharCallback callback);
void removeKeyCharListener(InputListener listener);
InputListener addMouseListener(MouseCallback callback); InputListener addMouseListener(MouseCallback callback);
void removeMouseListener(InputListener listener); void removeMouseListener(InputListener listener);
@ -58,4 +63,8 @@ GLFWKeyState getKeyState(KeyBinding mapping);
void setCursorMode(GLFWCursorMode mode); void setCursorMode(GLFWCursorMode mode);
GLFWCursorMode getCursorMode(); GLFWCursorMode getCursorMode();
KeyboardCapture captureKeyboardInput(KeyCharCallback callback, Callable uncaptureCallback);
bool uncaptureKeyboardInput(KeyboardCapture capture);
bool isKeyboardCaptured();
} }

View File

@ -13,9 +13,16 @@
namespace kek { namespace kek {
struct ActiveKeyboardCapture {
KeyboardCapture id = KEK_INVALID_ID;
KeyCharCallback callback;
Callable uncaptureCallback;
};
struct KekData { struct KekData {
std::map<InputListener, PeriodicCallback> periodicCallbacks; std::map<InputListener, PeriodicCallback> periodicCallbacks;
std::map<InputListener, KeyCallback> keyCallbacks; std::map<InputListener, KeyCallback> keyCallbacks;
std::map<InputListener, KeyCharCallback> keyCharCallbacks;
std::map<InputListener, MouseCallback> mouseCallbacks; std::map<InputListener, MouseCallback> mouseCallbacks;
std::map<InputListener, MouseButtonCallback> mouseButtonCallbacks; std::map<InputListener, MouseButtonCallback> mouseButtonCallbacks;
std::map<KeyBinding, KeyBindingData> keyBindings; std::map<KeyBinding, KeyBindingData> keyBindings;
@ -39,6 +46,7 @@ struct KekData {
Font *uiDefaultFont; Font *uiDefaultFont;
Shader *uiRectangleShader; Shader *uiRectangleShader;
GLFWCursorMode uiCursorMode; GLFWCursorMode uiCursorMode;
ActiveKeyboardCapture activeKeyboardCapture;
}; };
extern KekData kekData; extern KekData kekData;

View File

@ -13,6 +13,7 @@
#include "scene.h" #include "scene.h"
#include "shader.h" #include "shader.h"
#include "types.h" #include "types.h"
#include "utils.h"
#include "ui.h" #include "ui.h"
#include "unicode.h"
#include "uielements.h" #include "uielements.h"
#include "utils.h"

View File

@ -51,6 +51,8 @@ public:
void setText(std::string text); void setText(std::string text);
std::string getText();
virtual void draw(UIPoint screenPos, glm::mat4 projection); virtual void draw(UIPoint screenPos, glm::mat4 projection);
}; };

View File

@ -0,0 +1,10 @@
#pragma once
#include <codecvt>
namespace kek::Unicode {
std::u32string convertStdToU32(std::string string);
std::string convertU32ToStd(std::u32string string);
}

View File

@ -6,6 +6,8 @@
using namespace kek; using namespace kek;
static ButtonElement *button;
void periodicCallback(GLFWwindow *window, void *data){ void periodicCallback(GLFWwindow *window, void *data){
} }
@ -19,7 +21,11 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods, v
} }
void onButtonClick(void *data) { void onButtonClick(void *data) {
std::cout << "Clicked!" << std::endl; Input::captureKeyboardInput(KeyCharCallback([](GLFWwindow *window, unsigned int codepoint, void *data) {
std::u32string str = Unicode::convertStdToU32(button->text->getText());
str.push_back(codepoint);
button->text->setText(Unicode::convertU32ToStd(str));
}, nullptr), Callable());
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -58,13 +64,13 @@ 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(10), px(100), px(200), px(50)); button = new ButtonElement(px(10), px(100), px(200), px(50));
btn->text->color = Colors::BLACK; button->text->color = Colors::BLACK;
btn->color = Colors::WHITE; button->color = Colors::WHITE;
btn->hoverColor = Colors::GRAY; button->hoverColor = Colors::GRAY;
btn->text->setText("Hello There!"); button->text->setText("Hello There!");
btn->onClick = Callable(onButtonClick, nullptr); button->onClick = Callable(onButtonClick, nullptr);
UI::addElement(btn); UI::addElement(button);
Engine::start(); Engine::start();
} }