Browse Source

Input and import for it

Kajetan Johannes Hammerle 1 year ago
parent
commit
28796a675b
6 changed files with 139 additions and 129 deletions
  1. 1 0
      .clangd
  2. 18 18
      include/core/Window.h
  3. 89 97
      src/Window.c
  4. 2 1
      test/Main.c
  5. 1 1
      test/Tests.h
  6. 28 12
      test/modules/WindowTests.c

+ 1 - 0
.clangd

@@ -1,2 +1,3 @@
 CompileFlags:
+  Add: [-ferror-limit=0]
   CompilationDatabase: ./build_debug/

+ 18 - 18
include/core/Window.h

@@ -31,24 +31,15 @@ void coreRunWindow(void);
 float coreGetWindowTicksPerSecond(void);
 float coreGetWindowFramesPerSecond(void);
 
-// namespace Input {
-//     void setLimit(int limit);
-//     void reset();
-//     void enable();
-//     void disable();
-//     bool isEnabled();
-//     void fill(const char* s);
-//     int getCursor();
-//     void setCursor(int index);
-//     const List<uint32>& getUnicode();
-//
-//     template<int N>
-//     void toString(StringBuffer<N>& s) {
-//         for(uint32 c : getUnicode()) {
-//             s.appendUnicode(c);
-//         }
-//     }
-// }
+void coreSetInputLimit(size_t limit);
+void coreResetInput(void);
+void coreEnableInput(void);
+void coreDisableInput(void);
+bool coreIsInputEnabled(void);
+void coreFillInput(const char* s);
+size_t coreGetInputCursor(void);
+void coreSetInputCursor(size_t index);
+const char* coreGetInputString(void);
 
 typedef size_t CoreButton;
 
@@ -90,6 +81,15 @@ const char* coreGetButtonName(CoreButton b);
 #define runWindow coreRunWindow
 #define getWindowTicksPerSecond coreGetWindowTicksPerSecond
 #define getWindowFramesPerSecond coreGetWindowFramesPerSecond
+#define setInputLimit coreSetInputLimit
+#define resetInput coreResetInput
+#define enableInput coreEnableInput
+#define disableInput coreDisableInput
+#define isInputEnabled coreIsInputEnabled
+#define fillInput coreFillInput
+#define getInputCursor coreGetInputCursor
+#define setInputCursor coreSetInputCursor
+#define getInputString coreGetInputString
 #define Button CoreButton
 #define addButton coreAddButton
 #define bindKeyToButton coreBindKeyToButton

+ 89 - 97
src/Window.c

@@ -5,7 +5,9 @@
 #include <core/HashMap.h>
 #include <core/Logger.h>
 #include <core/Utility.h>
+#include <limits.h>
 #include <stdio.h>
+#include <uchar.h>
 
 static bool dummyWindowRunHandler(void*) {
     return !shouldWindowClose();
@@ -38,10 +40,12 @@ typedef struct {
 static Clock fps = {0};
 static Clock tps = {0};
 
-// static List<uint32> input;
-// static int inputCursor = 0;
-// static int inputLimit = 256;
-// static bool inputActive = false;
+#define INPUT_SIZE 2048
+static char input[INPUT_SIZE] = {0};
+static size_t inputLength = 0;
+static size_t inputCursor = 0;
+static size_t inputLimit = INPUT_SIZE - 1;
+static bool inputActive = false;
 
 typedef struct {
     char name[31];
@@ -82,13 +86,8 @@ static void onButton(Button* map, int n, int key, int action) {
     }
 }
 
-/*static void addError(Error& e) {
-    const char* description = nullptr;
-    int errorCode = glfwGetError(&description);
-    if(errorCode == GLFW_NO_ERROR) {
-        return;
-    }
-    e.message.append(": ").append(description);
+static bool isCharSequence(size_t i) {
+    return (input[i] & 0xC0) == 0x80;
 }
 
 static void handleInputKey(int key, int action) {
@@ -97,43 +96,66 @@ static void handleInputKey(int key, int action) {
     }
     switch(key) {
         case GLFW_KEY_BACKSPACE:
-            if(input.getLength() > inputCursor - 1 && inputCursor > 0) {
-                input.remove(inputCursor - 1);
+            if(inputLength >= inputCursor && inputCursor > 0) {
+                size_t w = 1;
+                while(inputCursor - w > 0 && isCharSequence(inputCursor - w)) {
+                    w++;
+                }
+                for(size_t i = inputCursor - w; i < inputLength; i++) {
+                    input[i] = input[i + w];
+                }
+                inputLength -= w;
+                inputCursor -= w;
+            }
+            break;
+        case GLFW_KEY_LEFT: {
+            inputCursor -= inputCursor > 0;
+            while(inputCursor > 0 && isCharSequence(inputCursor)) {
                 inputCursor--;
             }
             break;
-        case GLFW_KEY_LEFT: inputCursor -= inputCursor > 0; break;
-        case GLFW_KEY_RIGHT:
-            inputCursor += inputCursor < input.getLength();
+        }
+        case GLFW_KEY_RIGHT: {
+            inputCursor += inputCursor < inputLength;
+            while(inputCursor < inputLength && isCharSequence(inputCursor)) {
+                inputCursor++;
+            }
             break;
+        }
     }
-}*/
+}
 
 static void onKey(GLFWwindow*, int key, int scancode, int action, int mods) {
     (void)scancode;
     (void)mods;
-    // if(inputActive) {
-    //     handleInputKey(key, action);
-    // }
+    if(inputActive) {
+        handleInputKey(key, action);
+    }
     onButton(keyToButton, KEYS, key, action);
 }
 
-/*static void addUnicode(uint32 codepoint) {
-    if(input.getLength() >= inputLimit) {
+static void addUnicode(u32 c) {
+    char buffer[MB_LEN_MAX + 1] = {0};
+    mbstate_t state = {0};
+    size_t w = c32rtomb(buffer, c, &state);
+    if(w >= MB_LEN_MAX || inputLength + w >= inputLimit) {
         return;
     }
-    input.add(codepoint);
-    for(int i = input.getLength() - 1; i > inputCursor; i--) {
-        ::swap(input[i], input[i - 1]);
+    if(inputLength > 0) {
+        for(size_t i = inputLength - 1; i >= inputCursor; i--) {
+            swap(input + (i + w), input + i);
+        }
     }
-    inputCursor++;
+    memcpy(input + inputCursor, buffer, w);
+    inputLength += w;
+    inputCursor += w;
 }
 
-static void onChar(GLFWwindow*, uint32 codepoint) {
+static void onChar(GLFWwindow*, u32 codepoint) {
     if(inputActive) {
         addUnicode(codepoint);
     }
-}*/
+}
 
 static void onResize(GLFWwindow*, int width, int height) {
     sizeChanged = true;
@@ -153,7 +175,7 @@ static void onMouseMove(GLFWwindow*, double x, double y) {
 
 bool openWindow(const WindowOptions* o) {
     if(!glfwInit()) {
-        CORE_LOG_ERROR("could not initialize GLFW");
+        LOG_ERROR("could not initialize GLFW");
         return true;
     }
 
@@ -167,13 +189,13 @@ bool openWindow(const WindowOptions* o) {
     window =
         glfwCreateWindow(o->size.data[0], o->size.data[1], o->name, m, nullptr);
     if(window == nullptr) {
-        CORE_LOG_ERROR("could not create window");
+        LOG_ERROR("could not create window");
         closeWindow();
         return true;
     }
     size = o->size;
     glfwSetKeyCallback(window, onKey);
-    // glfwSetCharCallback(window, onChar);
+    glfwSetCharCallback(window, onChar);
     glfwSetFramebufferSizeCallback(window, onResize);
     glfwSetMouseButtonCallback(window, onMouse);
     glfwSetCursorPosCallback(window, onMouseMove);
@@ -238,7 +260,7 @@ void setWindowNanosPerTick(i64 nanos) {
 static i64 updateClock(Clock* c) {
     i64 nanos = getNanos();
     if(nanos < 0) {
-        CORE_LOG_WARNING("Cannot get nanos, using default");
+        LOG_WARNING("Cannot get nanos, using default");
         nanos = 10000000 + c->last;
     }
     i64 diff = nanos - c->last;
@@ -343,85 +365,55 @@ float getWindowFramesPerSecond(void) {
     return (1000000000.0f * CLOCK_SIZE) / (float)fps.sum;
 }
 
-/*
-
-void Window::Input::setLimit(int l) {
-    inputLimit = l;
-    while(input.getLength() > inputLimit) {
-        input.removeBySwap(inputLimit);
+void setInputLimit(size_t limit) {
+    inputLimit = limit >= INPUT_SIZE ? INPUT_SIZE - 1 : limit;
+    if(inputLength > inputLimit) {
+        inputLength = inputLimit;
+    }
+    if(inputCursor > inputLimit) {
+        inputCursor = inputLimit;
     }
 }
 
-void Window::Input::reset() {
-    input.clear();
+void resetInput() {
+    inputLength = 0;
     inputCursor = 0;
 }
 
-void Window::Input::enable() {
+void enableInput() {
     inputActive = true;
 }
 
-void Window::Input::disable() {
+void disableInput() {
     inputActive = false;
 }
 
-bool Window::Input::isEnabled() {
+bool isInputEnabled() {
     return inputActive;
 }
 
-static uint32 read(int& index, const char* s) {
-    if(s[index] == '\0') {
-        return '\0';
-    }
-    return static_cast<uint32>(s[index++]);
-}
-
-static uint32 readUnicode(int& index, const char* s) {
-    uint32 c = read(index, s);
-    if((c & 0xE0) == 0xC0) {
-        c = ((c & 0x1F) << 6) | (read(index, s) & 0x3F);
-    } else if((c & 0xF0) == 0xE0) {
-        c = ((c & 0xF) << 12) | ((read(index, s) & 0x3F) << 6);
-        c |= read(index, s) & 0x3F;
-    } else if((c & 0xF8) == 0xF0) {
-        c = ((c & 0x7) << 18) | ((read(index, s) & 0x3F) << 12);
-        c |= (read(index, s) & 0x3F) << 6;
-        c |= read(index, s) & 0x3F;
-    }
-    return c;
+void fillInput(const char* s) {
+    resetInput();
+    snprintf(input, inputLength, "%s", s);
 }
 
-void Window::Input::fill(const char* s) {
-    int index = 0;
-    reset();
-    while(true) {
-        uint32 c = readUnicode(index, s);
-        if(c == '\0') {
-            break;
-        }
-        addUnicode(c);
-    }
-}
-
-int Window::Input::getCursor() {
+size_t getInputCursor() {
     return inputCursor;
 }
 
-void Window::Input::setCursor(int index) {
-    if(index < 0) {
-        inputCursor = 0;
-    } else if(index > input.getLength()) {
-        inputCursor = input.getLength();
+void setInputCursor(size_t index) {
+    if(index > inputLength) {
+        inputCursor = inputLength;
     } else {
         inputCursor = index;
     }
 }
 
-const List<uint32>& Window::Input::getUnicode() {
+const char* getInputString(void) {
     return input;
-}*/
+}
 
-Button coreAddButton(const char* name) {
+Button addButton(const char* name) {
     if(buttonIndex >= BUTTONS) {
         return 0;
     }
@@ -430,47 +422,47 @@ Button coreAddButton(const char* name) {
     return b;
 }
 
-void coreBindKeyToButton(Button b, int key) {
+void bindKeyToButton(Button b, int key) {
     if(key >= 0 && key < KEYS) {
         keyToButton[key] = b;
     }
 }
 
-void coreBindGamepadToButton(Button b, int gamepadButton) {
+void bindGamepadToButton(Button b, int gamepadButton) {
     if(gamepadButton >= 0 && gamepadButton < GAMEPAD_BUTTONS) {
         gamepadToButton[gamepadButton] = b;
     }
 }
 
-void coreBindMouseToButton(Button b, int mouseButton) {
+void bindMouseToButton(Button b, int mouseButton) {
     if(mouseButton >= 0 && mouseButton < MOUSE_BUTTONS) {
         mouseToButton[mouseButton] = b;
     }
 }
 
-Vector2 coreGetLastMousePosition(void) {
+Vector2 getLastMousePosition(void) {
     return lastMousePosition;
 }
 
-Vector2 coreGetMousePosition(void) {
+Vector2 getMousePosition(void) {
     return mousePosition;
 }
 
-Vector2 coreGetLeftGamepadAxis(void) {
+Vector2 getLeftGamepadAxis(void) {
     return (Vector2){{lastControllerState.axes[GLFW_GAMEPAD_AXIS_LEFT_X],
                       lastControllerState.axes[GLFW_GAMEPAD_AXIS_LEFT_Y]}};
 }
 
-Vector2 coreGetRightGamepadAxis(void) {
+Vector2 getRightGamepadAxis(void) {
     return (Vector2){{lastControllerState.axes[GLFW_GAMEPAD_AXIS_RIGHT_X],
                       lastControllerState.axes[GLFW_GAMEPAD_AXIS_RIGHT_Y]}};
 }
 
-float coreGetLeftGamepadTrigger(void) {
+float getLeftGamepadTrigger(void) {
     return lastControllerState.axes[GLFW_GAMEPAD_AXIS_LEFT_TRIGGER];
 }
 
-float coreGetRightGamepadTrigger(void) {
+float getRightGamepadTrigger(void) {
     return lastControllerState.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER];
 }
 
@@ -478,18 +470,18 @@ static const ButtonData* getButton(Button id) {
     return buttons + (id >= buttonIndex ? 0 : id);
 }
 
-bool coreIsButtonDown(Button b) {
+bool isButtonDown(Button b) {
     return getButton(b)->downTime > 0;
 }
 
-int coreGetButtonDownTime(Button b) {
+int getButtonDownTime(Button b) {
     return getButton(b)->downTime;
 }
 
-bool coreWasButtonReleased(Button b) {
+bool wasButtonReleased(Button b) {
     return getButton(b)->released;
 }
 
-const char* coreGetButtonName(Button b) {
+const char* getButtonName(Button b) {
     return getButton(b)->name;
 }

+ 2 - 1
test/Main.c

@@ -1,12 +1,13 @@
 #define IMPORT_CORE
 #include <core/Logger.h>
 #include <core/Utility.h>
+#include <locale.h>
 #include <string.h>
 
 #include "Tests.h"
 
 int main(int argAmount, char** args) {
-    (void)args;
+    setlocale(LC_ALL, "en_US.utf8");
     if(argAmount < 3) {
         LOG_ERROR("missing path to images and/or mode");
         return 0;

+ 1 - 1
test/Tests.h

@@ -1,7 +1,7 @@
 #ifndef CORE_TESTS_H
 #define CORE_TESTS_H
 
-#include "core/Test.h"
+#include <core/Test.h>
 
 void testImageReader(const char* path);
 void testNetwork(void);

+ 28 - 12
test/modules/WindowTests.c

@@ -6,9 +6,10 @@
 #include "../Tests.h"
 #include "core/Window.h"
 
-static int ticks = 200;
+static int ticks = 2000;
 static Button closeButton = 0;
 static Button testButton = 0;
+static Button textButton = 0;
 
 static bool isRunning(void*) {
     return !shouldWindowClose() && ticks > 0 && !isButtonDown(closeButton);
@@ -16,17 +17,30 @@ static bool isRunning(void*) {
 
 static void tick(void*) {
     ticks -= ticks > 0;
-    printf("TPS: %.3f\nFPS: %.3f\n", (double)getWindowTicksPerSecond(),
-           (double)getWindowFramesPerSecond());
-    printf("%12s | Down: %d | DownTime: %3d | Released: %d\n",
-           getButtonName(closeButton), isButtonDown(closeButton),
-           getButtonDownTime(closeButton), wasButtonReleased(closeButton));
-    printf("%12s | Down: %d | DownTime: %3d | Released: %d\n",
-           getButtonName(testButton), isButtonDown(testButton),
-           getButtonDownTime(testButton), wasButtonReleased(testButton));
-
-    Vector2 mouse = getLastMousePosition();
-    printf("Mouse: %.2f %.2f\n", (double)mouse.data[0], (double)mouse.data[1]);
+    if(!isInputEnabled()) {
+        printf("TPS: %.3f\nFPS: %.3f\n", (double)getWindowTicksPerSecond(),
+               (double)getWindowFramesPerSecond());
+        printf("%12s | Down: %d | DownTime: %3d | Released: %d\n",
+               getButtonName(closeButton), isButtonDown(closeButton),
+               getButtonDownTime(closeButton), wasButtonReleased(closeButton));
+        printf("%12s | Down: %d | DownTime: %3d | Released: %d\n",
+               getButtonName(testButton), isButtonDown(testButton),
+               getButtonDownTime(testButton), wasButtonReleased(testButton));
+        Vector2 mouse = getLastMousePosition();
+        printf("Mouse: %.2f %.2f\n", (double)mouse.data[0],
+               (double)mouse.data[1]);
+    }
+    if(getButtonDownTime(textButton) == 1) {
+        if(isInputEnabled()) {
+            disableInput();
+        } else {
+            enableInput();
+        }
+    }
+    if(isInputEnabled()) {
+        printf("Input: '%s'\n", getInputString());
+        printf("Cursor: %zu\n", getInputCursor());
+    }
 }
 
 static void render(void*, float) {
@@ -42,6 +56,8 @@ void testWindow(void) {
     bindKeyToButton(closeButton, GLFW_KEY_Q);
     testButton = addButton("Test Button");
     bindKeyToButton(testButton, GLFW_KEY_T);
+    textButton = addButton("Text Button");
+    bindKeyToButton(textButton, GLFW_KEY_C);
 
     showWindow();
     setWindowRunHandler(isRunning, nullptr);