Pārlūkot izejas kodu

Add glfw, partial window port

Kajetan Johannes Hammerle 11 mēneši atpakaļ
vecāks
revīzija
2f541e08a6
6 mainītis faili ar 249 papildinājumiem un 218 dzēšanām
  1. 3 0
      .gitmodules
  2. 5 2
      CMakeLists.txt
  3. 1 0
      glfw
  4. 70 106
      include/core/Window.h
  5. 142 90
      src/Window.c
  6. 28 20
      test/Main.c

+ 3 - 0
.gitmodules

@@ -4,3 +4,6 @@
 [submodule "stb"]
 	path = stb
 	url = https://github.com/nothings/stb.git
+[submodule "glfw"]
+	path = glfw
+	url = https://github.com/glfw/glfw.git

+ 5 - 2
CMakeLists.txt

@@ -1,6 +1,8 @@
 cmake_minimum_required(VERSION 3.25)
 project(gaming_core)
 
+add_subdirectory(glfw SYSTEM)
+
 set(CMAKE_C_STANDARD 23)
 
 set(SRC
@@ -19,7 +21,7 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
     set(COMPILE_OPTIONS "")
     set(LINK_OPTIONS "")
     set(LOG_LEVEL 2)
-    set(DEFINITIONS "")
+    set(DEFINITIONS CORE_CHECK_MEMORY)
 else()
     set(DEFINITIONS ERROR_SIMULATOR CORE_CHECK_MEMORY)
     if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
@@ -57,12 +59,13 @@ target_compile_definitions(gaming_core
     PRIVATE ${DEFINITIONS}
 )
 target_link_libraries(gaming_core 
-    PRIVATE m core ${LINK_OPTIONS}
+    PRIVATE m core glfw ${LINK_OPTIONS}
 )
 target_include_directories(gaming_core SYSTEM 
     PUBLIC ${CMAKE_INSTALL_PREFIX}/include
     PUBLIC enet/include
     PUBLIC stb
+    PUBLIC glfw/include
 )
 target_link_directories(gaming_core SYSTEM 
     PUBLIC ${CMAKE_INSTALL_PREFIX}/lib

+ 1 - 0
glfw

@@ -0,0 +1 @@
+Subproject commit b35641f4a3c62aa86a0b3c983d163bc0fe36026d

+ 70 - 106
include/core/Window.h

@@ -1,111 +1,75 @@
 #ifndef CORE_WINDOW_H
 #define CORE_WINDOW_H
 
-void window(void);
-/*namespace Window {
-    typedef bool (*ShouldRun)();
-    typedef void (*Tick)();
-    typedef void (*Render)(float);
-
-    struct Options final {
-        int majorVersion;
-        int minorVersion;
-        const IntVector2& size;
-        bool fullscreen;
-        bool es;
-        bool vsync;
-        const char* name;
-
-        Options(int majorVersion, int minorVersion, const IntVector2& size,
-                bool es, const char* name);
-    };
-
-    Error open(const Options& options);
-    void close();
-
-    float getTicksPerSecond();
-    float getFramesPerSecond();
-
-    void trapCursor();
-    void freeCursor();
-    bool isCursorTrapped();
-
-    const IntVector2& getSize();
-    bool hasSizeChanged();
-
-    void show();
-    bool shouldClose();
-
-    Error startFrame(Clock::Nanos& n);
-    void endFrame();
-    Error tick();
-    void postTick();
-
-    template<ShouldRun SR, Tick T, Render R>
-    Error run(Clock::Nanos nanosPerTick) {
-        Clock::Nanos lag = 0;
-        while(SR()) {
-            Clock::Nanos passedTime = 0;
-            Error e = startFrame(passedTime);
-            if(e.has()) {
-                return e;
-            }
-            lag += passedTime;
-            while(lag >= nanosPerTick) {
-                lag -= nanosPerTick;
-                e = tick();
-                if(e.has()) {
-                    return e;
-                }
-                T();
-                postTick();
-            }
-            R(static_cast<float>(lag) / static_cast<float>(nanosPerTick));
-            endFrame();
-        }
-        return Error();
-    }
-
-    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);
-            }
-        }
-    }
-
-    namespace Controls {
-        typedef StringBuffer<32> ButtonName;
-        typedef int ButtonId;
-
-        ButtonId add(const ButtonName& name);
-        void bindKey(ButtonId id, int key);
-        void bindGamepad(ButtonId id, int gamepadButton);
-        void bindMouse(ButtonId id, int mouseButton);
-
-        Vector2 getLastMousePosition();
-        Vector2 getMousePosition();
-        Vector2 getLeftGamepadAxis();
-        Vector2 getRightGamepadAxis();
-        float getLeftGamepadTrigger();
-        float getRightGamepadTrigger();
-
-        bool isDown(ButtonId id);
-        int getDownTime(ButtonId id);
-        bool wasReleased(ButtonId id);
-        const ButtonName& getName(ButtonId id);
-    }
-}*/
+#include <core/Vector.h>
+
+typedef bool (*CoreWindowRunHandler)(void* data);
+typedef void (*CoreWindowTickHandler)(void* data);
+typedef void (*CoreWindowRenderHandler)(void* data, float lag);
+
+typedef struct {
+    CoreIntVector2 size;
+    bool fullscreen;
+    const char* name;
+} CoreWindowOptions;
+
+bool coreWindowOpen(const CoreWindowOptions* options);
+void coreWindowClose(void);
+void coreWindowShow(void);
+void coreWindowTrapCursor(void);
+void coreWindowFreeCursor(void);
+bool coreWindowIsCursorTrapped(void);
+const CoreIntVector2* coreWindowGetSize(void);
+bool CoreWindowSizeChanged(void);
+bool coreWindowShouldClose(void);
+
+void coreWindowRunHandler(CoreWindowRunHandler wr, void* data);
+void coreWindowTickHandler(CoreWindowTickHandler t, void* data);
+void coreWindowRenderHandler(CoreWindowRenderHandler r, void* data);
+void coreWindowNanosPerTick(i64 nanos);
+void coreWindowRun(void);
+float coreWindowTicksPerSecond(void);
+float coreWindowFramesPerSecond(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);
+//         }
+//     }
+// }
+
+// namespace Controls {
+//     typedef StringBuffer<32> ButtonName;
+//     typedef int ButtonId;
+//
+//     ButtonId add(const ButtonName& name);
+//     void bindKey(ButtonId id, int key);
+//     void bindGamepad(ButtonId id, int gamepadButton);
+//     void bindMouse(ButtonId id, int mouseButton);
+//
+//     Vector2 getLastMousePosition();
+//     Vector2 getMousePosition();
+//     Vector2 getLeftGamepadAxis();
+//     Vector2 getRightGamepadAxis();
+//     float getLeftGamepadTrigger();
+//     float getRightGamepadTrigger();
+//
+//     bool isDown(ButtonId id);
+//     int getDownTime(ButtonId id);
+//     bool wasReleased(ButtonId id);
+//     const ButtonName& getName(ButtonId id);
+// }
 
 #endif

+ 142 - 90
src/Window.c

@@ -1,12 +1,43 @@
 #include "core/Window.h"
 
-/*static GLFWwindow* window = nullptr;
-static Clock fps;
-static Clock tps;
-static IntVector2 size{0, 0};
-static bool sizeChanged = false;
+#include <GLFW/glfw3.h>
+#include <core/Logger.h>
+#include <core/Utility.h>
+#include <stdio.h>
+
+static bool dummyWindowRunHandler(void*) {
+    return !coreWindowShouldClose();
+}
+
+static void dummyWindowTickHandler(void*) {
+}
+
+static void dummyWindowRenderHandler(void*, float) {
+}
 
-static List<uint32> input;
+static GLFWwindow* window = nullptr;
+static CoreIntVector2 size = {0, 0};
+static bool sizeChanged = false;
+static CoreWindowRunHandler runHandler = dummyWindowRunHandler;
+static CoreWindowTickHandler tickHandler = dummyWindowTickHandler;
+static CoreWindowRenderHandler renderHandler = dummyWindowRenderHandler;
+static void* runHandlerData = nullptr;
+static void* tickHandlerData = nullptr;
+static void* renderHandlerData = nullptr;
+static i64 nanosPerTick = 1;
+
+#define CLOCK_SIZE 16
+typedef struct {
+    i64 last;
+    i64 sum;
+    i64 values[CLOCK_SIZE];
+    size_t index;
+} Clock;
+
+static Clock fps = {0};
+static Clock tps = {0};
+
+/*static List<uint32> input;
 static int inputCursor = 0;
 static int inputLimit = 256;
 static bool inputActive = false;
@@ -142,58 +173,39 @@ static void onMouse(GLFWwindow*, int button, int action, int mods) {
 
 static void onMouseMove(GLFWwindow*, double x, double y) {
     mousePosition = Vector<2, double>(x, y).toFloat();
-}
+}*/
 
-Error Window::open(const Options& o) {
+bool coreWindowOpen(const CoreWindowOptions* o) {
     if(!glfwInit()) {
-        Error e{"could not initialize GLFW"};
-        addError(e);
-        return e;
+        CORE_LOG_ERROR("could not initialize GLFW");
+        return true;
     }
 
     glfwDefaultWindowHints();
     glfwWindowHint(GLFW_VISIBLE, false);
     glfwWindowHint(GLFW_RESIZABLE, true);
-    glfwWindowHint(GLFW_DECORATED, !o.fullscreen);
+    glfwWindowHint(GLFW_DECORATED, !o->fullscreen);
     glfwWindowHint(GLFW_DOUBLEBUFFER, true);
 
-    if(o.es) {
-        glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
-    } else {
-        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-    }
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, o.majorVersion);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, o.minorVersion);
-
-    GLFWmonitor* m = o.fullscreen ? glfwGetPrimaryMonitor() : nullptr;
-    window = glfwCreateWindow(o.size[0], o.size[1], o.name, m, nullptr);
+    GLFWmonitor* m = o->fullscreen ? glfwGetPrimaryMonitor() : nullptr;
+    window =
+        glfwCreateWindow(o->size.data[0], o->size.data[1], o->name, m, nullptr);
     if(window == nullptr) {
-        Error e{"could not create window"};
-        addError(e);
-        close();
-        return e;
+        CORE_LOG_ERROR("could not create window");
+        coreWindowClose();
+        return true;
     }
-    size = o.size;
-    glfwSetKeyCallback(window, onKey);
-    glfwSetCharCallback(window, onChar);
-    glfwSetFramebufferSizeCallback(window, onResize);
-    glfwSetMouseButtonCallback(window, onMouse);
-    glfwSetCursorPosCallback(window, onMouseMove);
+    size = o->size;
+    // glfwSetKeyCallback(window, onKey);
+    // glfwSetCharCallback(window, onChar);
+    // glfwSetFramebufferSizeCallback(window, onResize);
+    // glfwSetMouseButtonCallback(window, onMouse);
+    // glfwSetCursorPosCallback(window, onMouseMove);
 
-    glfwMakeContextCurrent(window);
-    glfwSwapInterval(o.vsync);
-
-    GLenum err = glewInit();
-    if(err != GLEW_OK) {
-        Error e{"could not initialize GLEW: "};
-        e.message.append(glewGetErrorString(err));
-        close();
-        return e;
-    }
-    return {};
+    return false;
 }
 
-void Window::close() {
+void coreWindowClose(void) {
     if(window != nullptr) {
         glfwDestroyWindow(window);
         window = nullptr;
@@ -201,47 +213,111 @@ void Window::close() {
     glfwTerminate();
 }
 
-float Window::getTicksPerSecond() {
-    return tps.getUpdatesPerSecond();
+void coreWindowShow(void) {
+    glfwShowWindow(window);
+}
+
+void coreWindowTrapCursor(void) {
+    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+}
+
+void coreWindowFreeCursor(void) {
+    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
 }
 
-float Window::getFramesPerSecond() {
-    return fps.getUpdatesPerSecond();
+bool coreWindowIsCursorTrapped(void) {
+    return glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED;
 }
 
-const IntVector2& Window::getSize() {
-    return size;
+const CoreIntVector2* coreWindowGetSize(void) {
+    return &size;
 }
 
-bool Window::hasSizeChanged() {
+bool CoreWindowSizeChanged(void) {
     return sizeChanged;
 }
 
-void Window::trapCursor() {
-    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+bool coreWindowShouldClose(void) {
+    return glfwWindowShouldClose(window);
 }
 
-void Window::freeCursor() {
-    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+void coreWindowRunHandler(CoreWindowRunHandler wr, void* data) {
+    runHandlerData = data;
+    runHandler = wr == nullptr ? dummyWindowRunHandler : wr;
 }
 
-bool Window::isCursorTrapped() {
-    return glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED;
+void coreWindowTickHandler(CoreWindowTickHandler t, void* data) {
+    tickHandlerData = data;
+    tickHandler = t == nullptr ? dummyWindowTickHandler : t;
 }
 
-void Window::show() {
-    glfwShowWindow(window);
+void coreWindowRenderHandler(CoreWindowRenderHandler r, void* data) {
+    renderHandlerData = data;
+    renderHandler = r == nullptr ? dummyWindowRenderHandler : r;
 }
 
-bool Window::shouldClose() {
-    return glfwWindowShouldClose(window);
+void coreWindowNanosPerTick(i64 nanos) {
+    nanosPerTick = nanos <= 0 ? 1 : nanos;
 }
 
-Error Window::startFrame(Clock::Nanos& n) {
-    return fps.update(n);
+static i64 updateClock(Clock* c) {
+    i64 nanos = coreNanos();
+    if(nanos < 0) {
+        CORE_LOG_WARNING("Cannot get nanos, using default");
+        nanos = 10000000 + c->last;
+    }
+    i64 diff = nanos - c->last;
+    c->last = nanos;
+    c->sum -= c->values[c->index];
+    c->values[c->index] = diff;
+    c->sum += diff;
+    c->index = (c->index + 1) % CLOCK_SIZE;
+    return diff;
+}
+
+static void endFrame(void) {
+    sizeChanged = false;
+    glfwSwapBuffers(window);
+    glfwPollEvents();
+    // if(searchForGamepad()) {
+    //     checkGamepad();
+    // }
+}
+
+static void tick() {
+    updateClock(&tps);
+    // for(Button& b : buttons) {
+    //     b.tick();
+    // }
+    tickHandler(tickHandlerData);
+    // lastMousePosition = mousePosition;
 }
 
-static bool searchForGamepad() {
+void coreWindowRun(void) {
+    glfwMakeContextCurrent(window);
+    tps.last = coreNanos();
+    fps.last = coreNanos();
+    i64 lag = 0;
+    while(runHandler(runHandlerData)) {
+        lag += updateClock(&fps);
+        while(lag >= nanosPerTick) {
+            lag -= nanosPerTick;
+            tick();
+        }
+        renderHandler(renderHandlerData, (float)lag / (float)nanosPerTick);
+        endFrame();
+    }
+}
+
+float coreWindowTicksPerSecond(void) {
+    return (1000000000.0f * CLOCK_SIZE) / (float)tps.sum;
+}
+
+float coreWindowFramesPerSecond(void) {
+    return (1000000000.0f * CLOCK_SIZE) / (float)fps.sum;
+}
+
+/*static bool searchForGamepad() {
     if(activeController != -1) {
         return true;
     }
@@ -278,31 +354,6 @@ static void checkGamepad() {
     lastControllerState = state;
 }
 
-void Window::endFrame() {
-    glfwSwapBuffers(window);
-    sizeChanged = false;
-    glfwPollEvents();
-    if(searchForGamepad()) {
-        checkGamepad();
-    }
-}
-
-Error Window::tick() {
-    Clock::Nanos n = 0;
-    Error e = tps.update(n);
-    if(e.has()) {
-        return e;
-    }
-    for(Button& b : buttons) {
-        b.tick();
-    }
-    return Error();
-}
-
-void Window::postTick() {
-    lastMousePosition = mousePosition;
-}
-
 void Window::Input::setLimit(int l) {
     inputLimit = l;
     while(input.getLength() > inputLimit) {
@@ -444,4 +495,5 @@ bool Window::Controls::wasReleased(ButtonId id) {
 
 const Window::Controls::ButtonName& Window::Controls::getName(ButtonId id) {
     return getButton(id).name;
-}*/
+}
+*/

+ 28 - 20
test/Main.c

@@ -1,22 +1,39 @@
+#include <GLFW/glfw3.h>
 #include <core/Logger.h>
 #include <core/Utility.h>
+#include <stdio.h>
 
 #include "Tests.h"
-// #include "core/Window.h"
+#include "core/Window.h"
 
-/*static int ticks = 40;
+static int ticks = 40;
 
-static bool isRunning() {
-    return true;
-    // return !Window::shouldClose() && ticks > 0;
+static bool isRunning(void*) {
+    return !coreWindowShouldClose() && ticks > 0;
 }
 
-static void tick() {
+static void tick(void*) {
     ticks -= ticks > 0;
+    printf("TPS: %.3f\nFPS: %.3f\n", (double)coreWindowTicksPerSecond(),
+           (double)coreWindowFramesPerSecond());
 }
 
-static void render(float) {
-}*/
+static void render(void*, float) {
+}
+
+static void testWindow(void) {
+    CoreWindowOptions options = {{800, 480}, false, "Test"};
+    if(coreWindowOpen(&options)) {
+        return;
+    }
+    coreWindowShow();
+    coreWindowRunHandler(isRunning, nullptr);
+    coreWindowTickHandler(tick, nullptr);
+    coreWindowRenderHandler(render, nullptr);
+    coreWindowNanosPerTick(50000000);
+    coreWindowRun();
+    coreWindowClose();
+}
 
 int main(int argAmount, char** args) {
     (void)args;
@@ -24,19 +41,10 @@ int main(int argAmount, char** args) {
         CORE_LOG_ERROR("missing path to images");
         return 0;
     }
-    coreTestImageReader(args[1]);
-    coreTestNetwork();
+    // coreTestImageReader(args[1]);
+    // coreTestNetwork();
+    testWindow();
     coreFinalizeTests();
-
-    // Window::Options options(4, 3, {800, 480}, false, "Test");
-    // Error error = Window::open(options);
-    // if(error.has()) {
-    //     LOG_ERROR(error.message);
-    //     return 0;
-    // }
-    // Window::show();
-    // Window::run<isRunning, tick, render>(50'000'000);
-    // Window::close();
     corePrintMemoryReport();
     return 0;
 }