Browse Source

text typing, remove at index for lists, stringbuffer supports unsigned
ints and unicode

Kajetan Johannes Hammerle 3 years ago
parent
commit
4d90e6c859
9 changed files with 155 additions and 10 deletions
  1. 59 0
      input/TextInput.cpp
  2. 29 0
      input/TextInput.h
  3. 2 1
      meson.build
  4. 21 1
      rendering/Window.cpp
  5. 8 1
      rendering/Window.h
  6. 3 3
      tests/ListTests.cpp
  7. 1 3
      utils/HashMap.h
  8. 9 1
      utils/List.h
  9. 23 0
      utils/StringBuffer.h

+ 59 - 0
input/TextInput.cpp

@@ -0,0 +1,59 @@
+#include <iostream>
+#include <utility>
+
+#include <GLFW/glfw3.h>
+
+#include "input/TextInput.h"
+
+TextInput::TextInput() : active(false) {
+}
+
+void TextInput::reset() {
+    input.clear();
+    cursor = 0;
+}
+
+void TextInput::setActive(bool b) {
+    active = b;
+}
+
+void TextInput::onKeyEvent(int key, int scancode, int action, int mods) {
+    if(!active || action == GLFW_RELEASE) {
+        return;
+    }
+    (void)scancode;
+    (void)mods;
+    switch(key) {
+        case GLFW_KEY_BACKSPACE:
+            if(input.getLength() > cursor - 1 && cursor > 0) {
+                input.remove(cursor - 1);
+                cursor--;
+            }
+            break;
+        case GLFW_KEY_LEFT:
+            if(cursor > 0) {
+                cursor--;
+            }
+            break;
+        case GLFW_KEY_RIGHT:
+            if(cursor < input.getLength()) {
+                cursor++;
+            }
+            break;
+    }
+}
+
+void TextInput::onCharEvent(unsigned int codepoint) {
+    if(!active) {
+        return;
+    }
+    input.add(codepoint);
+    for(int i = input.getLength() - 1; i > cursor; i--) {
+        std::swap(input[i], input[i - 1]);
+    }
+    cursor++;
+}
+
+int TextInput::getCursor() const {
+    return cursor;
+}

+ 29 - 0
input/TextInput.h

@@ -0,0 +1,29 @@
+#ifndef TEXT_INPUT_H
+#define TEXT_INPUT_H
+
+#include "utils/List.h"
+
+class TextInput final {
+    List<unsigned int> input;
+    int cursor;
+    bool active;
+
+public:
+    TextInput();
+
+    void reset();
+    void setActive(bool b);
+    void onKeyEvent(int key, int scancode, int action, int mods);
+    void onCharEvent(unsigned int codepoint);
+
+    template<int N>
+    void getInput(StringBuffer<N>& s) const {
+        for(unsigned int c : input) {
+            s.appendUnicode(c);
+        }
+    }
+
+    int getCursor() const;
+};
+
+#endif

+ 2 - 1
meson.build

@@ -54,7 +54,8 @@ sources = ['Main.cpp',
     'network/Packet.cpp',
     'network/Server.cpp',
     'network/Client.cpp',
-    'network/ENet.cpp',]
+    'network/ENet.cpp',
+    'input/TextInput.cpp']
 
 threadDep = dependency('threads')
 glewDep = dependency('glew')

+ 21 - 1
rendering/Window.cpp

@@ -2,7 +2,8 @@
 
 #include "rendering/Window.h"
 
-Window::Window(const WindowOptions& options) : window(nullptr) {
+Window::Window(TextInput& textInput, const WindowOptions& options)
+    : textInput(textInput), window(nullptr) {
     glfwDefaultWindowHints();
     glfwWindowHint(GLFW_VISIBLE, 0);
     glfwWindowHint(GLFW_RESIZABLE, 1);
@@ -25,6 +26,10 @@ Window::Window(const WindowOptions& options) : window(nullptr) {
         std::cout << "could not create window\n";
         return;
     }
+    glfwSetWindowUserPointer(window, this);
+    glfwSetKeyCallback(window, keyCallback);
+    glfwSetCharCallback(window, charCallback);
+
     glfwMakeContextCurrent(window);
     glfwSwapInterval(options.vsync);
 }
@@ -70,4 +75,19 @@ Size Window::getFramebufferSize() const {
 
 bool Window::isKeyDown(int key) const {
     return glfwGetKey(window, key) == GLFW_PRESS;
+}
+
+void Window::keyCallback(GLFWwindow* w, int key, int scancode, int action,
+                         int mods) {
+    void* p = glfwGetWindowUserPointer(w);
+    if(p != nullptr) {
+        static_cast<Window*>(p)->textInput.onKeyEvent(key, scancode, action,
+                                                      mods);
+    }
+}
+void Window::charCallback(GLFWwindow* w, unsigned int codepoint) {
+    void* p = glfwGetWindowUserPointer(w);
+    if(p != nullptr) {
+        static_cast<Window*>(p)->textInput.onCharEvent(codepoint);
+    }
 }

+ 8 - 1
rendering/Window.h

@@ -4,13 +4,15 @@
 #include <GL/glew.h>
 #include <GLFW/glfw3.h>
 
+#include "input/TextInput.h"
 #include "rendering/WindowOptions.h"
 
 class Window final {
+    TextInput& textInput;
     GLFWwindow* window;
 
 public:
-    Window(const WindowOptions& options);
+    Window(TextInput& textInput, const WindowOptions& options);
     ~Window();
 
     Window(const Window&) = delete;
@@ -27,6 +29,11 @@ public:
     Size getSize() const;
     Size getFramebufferSize() const;
     bool isKeyDown(int key) const;
+
+private:
+    static void keyCallback(GLFWwindow* w, int key, int scancode, int action,
+                            int mods);
+    static void charCallback(GLFWwindow* w, unsigned int codepoint);
 };
 
 #endif

+ 3 - 3
tests/ListTests.cpp

@@ -117,14 +117,14 @@ static void testToString3(Test& test) {
 static void testRemove(Test& test) {
     IntList list;
     list.add(4).add(3).add(2);
-    list.remove(0);
+    list.removeBySwap(0);
     test.checkEqual(2, list[0], "remove 1");
     test.checkEqual(3, list[1], "remove 2");
     test.checkEqual(2, list.getLength(), "remove 3");
-    list.remove(1);
+    list.removeBySwap(1);
     test.checkEqual(2, list[0], "remove 4");
     test.checkEqual(1, list.getLength(), "remove 5");
-    list.remove(0);
+    list.removeBySwap(0);
     test.checkEqual(0, list.getLength(), "remove 6");
 }
 

+ 1 - 3
utils/HashMap.h

@@ -7,8 +7,6 @@
 #include "utils/Types.h"
 #include "utils/Utils.h"
 
-#include <unordered_map>
-
 template<typename K, typename V>
 struct HashMap final {
     class Node {
@@ -130,7 +128,7 @@ public:
         List<Node>& list = nodes[hash(key)];
         for(int i = 0; i < list.getLength(); i++) {
             if(list[i].key == key) {
-                list.remove(i);
+                list.removeBySwap(i);
                 return true;
             }
         }

+ 9 - 1
utils/List.h

@@ -132,7 +132,7 @@ public:
         length = 0;
     }
 
-    void remove(int index) {
+    void removeBySwap(int index) {
         length--;
         if(index != length) {
             data[index] = std::move(data[length]);
@@ -140,6 +140,14 @@ public:
         data[length].~T();
     }
 
+    void remove(int index) {
+        length--;
+        for(int i = index; i < length; i++) {
+            data[i] = std::move(data[i + 1]);
+        }
+        data[length].~T();
+    }
+
     template<int L>
     void toString(StringBuffer<L>& s) const {
         s.append("[");

+ 23 - 0
utils/StringBuffer.h

@@ -104,6 +104,10 @@ public:
         return append("%d", i);
     }
 
+    StringBuffer& append(unsigned int i) {
+        return append("%u", i);
+    }
+
     StringBuffer& append(float i) {
         return append("%.2f", i);
     }
@@ -118,6 +122,25 @@ public:
         return *this;
     }
 
+    StringBuffer& appendUnicode(unsigned int c) {
+        if(c < (1 << 7)) {
+            append(static_cast<char>(c & 0x7F));
+        } else if(c < (1 << 11)) {
+            append(static_cast<char>(((c >> 6) & 0x1F) | 0xC0));
+            append(static_cast<char>(((c >> 0) & 0x3F) | 0x80));
+        } else if(c < (1 << 16)) {
+            append(static_cast<char>(((c >> 12) & 0x0F) | 0xE0));
+            append(static_cast<char>(((c >> 6) & 0x3F) | 0x80));
+            append(static_cast<char>(((c >> 0) & 0x3F) | 0x80));
+        } else if(c < (1 << 21)) {
+            append(static_cast<char>(((c >> 18) & 0x07) | 0xF0));
+            append(static_cast<char>(((c >> 12) & 0x3F) | 0x80));
+            append(static_cast<char>(((c >> 6) & 0x3F) | 0x80));
+            append(static_cast<char>(((c >> 0) & 0x3F) | 0x80));
+        }
+        return *this;
+    }
+
     StringBuffer& clear() {
         length = 0;
         hash = 0;