From 9a89ab3bbc52f0dff57a406d0cce8497dcc4d2f3 Mon Sep 17 00:00:00 2001 From: Nathan Date: Sat, 7 Feb 2026 11:45:43 -0600 Subject: [PATCH] start template refactor --- include/utils/Objects/Object.h | 0 .../Renderer/RendererImpl/RendererImpl.h | 36 ++++ .../RendererOpenGL/RendererOpenGL.h | 36 ++++ .../RendererImpl/RendererSDL3/RendererSDL3.h | 41 +++++ include/utils/Renderer/concepts.h | 21 +++ .../Window/WindowImpl/WindowGLFW/WindowGLFW.h | 143 +++++++++++++++ .../Window/WindowImpl/WindowSDL3/WindowSDL3.h | 173 ++++++++++++++++++ include/utils/Window/concepts.h | 25 +++ 8 files changed, 475 insertions(+) create mode 100644 include/utils/Objects/Object.h create mode 100644 include/utils/Renderer/RendererImpl/RendererImpl.h create mode 100644 include/utils/Renderer/RendererImpl/RendererOpenGL/RendererOpenGL.h create mode 100644 include/utils/Renderer/RendererImpl/RendererSDL3/RendererSDL3.h create mode 100644 include/utils/Renderer/concepts.h create mode 100644 include/utils/Window/WindowImpl/WindowGLFW/WindowGLFW.h create mode 100644 include/utils/Window/WindowImpl/WindowSDL3/WindowSDL3.h create mode 100644 include/utils/Window/concepts.h diff --git a/include/utils/Objects/Object.h b/include/utils/Objects/Object.h new file mode 100644 index 0000000..e69de29 diff --git a/include/utils/Renderer/RendererImpl/RendererImpl.h b/include/utils/Renderer/RendererImpl/RendererImpl.h new file mode 100644 index 0000000..dd9cc0a --- /dev/null +++ b/include/utils/Renderer/RendererImpl/RendererImpl.h @@ -0,0 +1,36 @@ +#ifndef RENDERER_IMPL +#define RENDERER_IMPL + + +#include "pch.hpp" + + +namespace Archimedes { + + template + class RendererImpl { + + public: + typedef void renderCmd(); + + RendererImpl() {}; + + ~RendererImpl() {}; + + bool init(void* p) { + return false; + }; + + void render(std::list> cmdList, int& w, int& h) { + + + for(auto f : cmdList) + f(); + } + + private: + T rendererImpl; + }; + +} +#endif diff --git a/include/utils/Renderer/RendererImpl/RendererOpenGL/RendererOpenGL.h b/include/utils/Renderer/RendererImpl/RendererOpenGL/RendererOpenGL.h new file mode 100644 index 0000000..3227ab0 --- /dev/null +++ b/include/utils/Renderer/RendererImpl/RendererOpenGL/RendererOpenGL.h @@ -0,0 +1,36 @@ +#ifndef RENDERER_OPENGL +#define RENDERER_OPENGL + +#include "pch.hpp" + +#define GLEW_STATIC +#include + + +namespace Archimedes { + + class RendererOpenGL { + + public: + typedef void renderCmd(); + + RendererOpenGL() {}; + ~RendererOpenGL() {}; + + bool init(void* p) { + return glewInit() == GLEW_OK; + }; + + void render(std::list> cmdList, int& w, int& h) { + + glViewport(0, 0, w, h); + glClearColor(0.2, 0.2, 0.4, 1); + glClear(GL_COLOR_BUFFER_BIT); + + for(auto f : cmdList) + f(); + } + }; +} + +#endif diff --git a/include/utils/Renderer/RendererImpl/RendererSDL3/RendererSDL3.h b/include/utils/Renderer/RendererImpl/RendererSDL3/RendererSDL3.h new file mode 100644 index 0000000..2fd3de8 --- /dev/null +++ b/include/utils/Renderer/RendererImpl/RendererSDL3/RendererSDL3.h @@ -0,0 +1,41 @@ +#ifndef RENDERER_SDL3 +#define RENDERER_SDL3 + +#include "pch.hpp" + +#include + + +namespace Archimedes { + + class RendererSDL3 { + + public: + typedef void renderCmd(); + + RendererSDL3() {}; + ~RendererSDL3() { SDL_DestroyRenderer(renderer); }; + + bool init(void* window) { + renderer = SDL_CreateRenderer((SDL_Window*) window, nullptr); + SDL_SetRenderVSync(renderer, 1); + return renderer != nullptr; + }; + + void render(std::list> cmdList, int& w, int& h) { + + //SDL_SetRenderScale(renderer, w, h); + + SDL_RenderClear(renderer); + + for(auto f : cmdList) + f(); + + SDL_RenderPresent(renderer); + } + + SDL_Renderer* renderer = nullptr; + }; +} + +#endif diff --git a/include/utils/Renderer/concepts.h b/include/utils/Renderer/concepts.h new file mode 100644 index 0000000..2b2b5f9 --- /dev/null +++ b/include/utils/Renderer/concepts.h @@ -0,0 +1,21 @@ +#ifndef RENDERER_CONCEPTS +#define RENDERER_CONCEPTS + +#include "pch.hpp" + +namespace Archimedes { + + class RendererOpenGL; + + class RendererSDL3; + + template + concept allowed_renderers = requires (RendererImpl r) { +#ifndef CUSTOM_RENDERER + requires std::same_as + || std::same_as; +#endif + }; +} + +#endif diff --git a/include/utils/Window/WindowImpl/WindowGLFW/WindowGLFW.h b/include/utils/Window/WindowImpl/WindowGLFW/WindowGLFW.h new file mode 100644 index 0000000..32542d2 --- /dev/null +++ b/include/utils/Window/WindowImpl/WindowGLFW/WindowGLFW.h @@ -0,0 +1,143 @@ +#ifndef WINDOW_GLFW +#define WINDOW_GLFW + +#include "pch.hpp" + +#include "utils/Window/WindowEvents.h" + +#define GLFW_INCLUDE_NONE +#include + + +namespace Archimedes { + + template + requires allowed_windows + && allowed_renderers + class Window; + + template + class WindowGLFW { + + public: + + WindowGLFW(Window, R>* p, const std::function& sendEvent) { + + /*if(glfwPlatformSupported(GLFW_PLATFORM_WAYLAND)) { + glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_WAYLAND); + }*/ + + + data.window = p; + data.sendEvent = sendEvent; + + glfwSetErrorCallback([](int e, const char* m){ + std::cout << "GLFW Error " << e << ": " << m << std::endl; + }); + + if(!glfwInit()) { + std::cout << "glfwInit failed!\n"; + std::abort(); + } +#if RENDRER == 1 + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +#endif + w = glfwCreateWindow(640, 480, "Archimedes", NULL, NULL); + + if(!w) { + std::cout << "glfwCreateWindow failed!\n"; + glfwTerminate(); + std::abort(); + } + glfwMakeContextCurrent(w); + glfwSwapInterval(1); + + glfwSetWindowUserPointer(w, &data); + + glfwSetWindowSizeCallback(w, [](GLFWwindow* window, int w, int h){ + WindowData, R>& d = *(WindowData, R>*) glfwGetWindowUserPointer(window); + + d.sendEvent(new ResizeWindowEvent(w, h)); + }); + + glfwSetWindowCloseCallback(w, [](GLFWwindow* window){ + WindowData, R>& d = *(WindowData, R>*) glfwGetWindowUserPointer(window); + + d.sendEvent(new CloseWindowEvent(d.window)); + }); + + glfwSetKeyCallback(w, [](GLFWwindow* window, int key, int scancode, int action, int mods){ + WindowData, R>& d = *(WindowData, R>*) glfwGetWindowUserPointer(window); + + switch(action) { + case GLFW_PRESS: + d.sendEvent(new KeyPressedWindowEvent(key, 0)); + break; + case GLFW_RELEASE: + d.sendEvent(new KeyReleasedWindowEvent(key)); + break; + case GLFW_REPEAT: + d.sendEvent(new KeyPressedWindowEvent(key, 1)); + break; + } + }); + + glfwSetMouseButtonCallback(w, [](GLFWwindow* window, int button, int action, int mods){ + WindowData, R>& d = *(WindowData, R>*) glfwGetWindowUserPointer(window); + + switch(action) { + case GLFW_PRESS: + d.sendEvent(new MouseButtonPressedWindowEvent(button)); + break; + case GLFW_RELEASE: + d.sendEvent(new MouseButtonReleasedWindowEvent(button)); + break; + } + }); + + glfwSetScrollCallback(w, [](GLFWwindow* window, double dx, double dy){ + WindowData, R>& d = *(WindowData, R>*) glfwGetWindowUserPointer(window); + + d.sendEvent(new ScrollWindowEvent(dx, dy)); + }); + + glfwSetCursorPosCallback(w, [](GLFWwindow* window, double dx, double dy){ + WindowData, R>& d = *(WindowData, R>*) glfwGetWindowUserPointer(window); + + d.sendEvent(new MouseMovedWindowEvent(dx, dy)); + }); + } + + ~WindowGLFW() { + glfwTerminate(); + } + + + bool shouldClose() { + return glfwWindowShouldClose(w); + } + + void doFrame() { restoreContext(); glfwSwapBuffers(w); } + + void pollEvents() { glfwPollEvents(); } + + void restoreContext() { glfwMakeContextCurrent(w); } + + void getSize(int& w, int& h) { + glfwGetFramebufferSize(this->w, &w, &h); + } + + GLFWwindow* getWindow() { return w; } + + WindowData, R> data; + + private: + GLFWwindow* w; + + }; + +} + +#endif diff --git a/include/utils/Window/WindowImpl/WindowSDL3/WindowSDL3.h b/include/utils/Window/WindowImpl/WindowSDL3/WindowSDL3.h new file mode 100644 index 0000000..771d924 --- /dev/null +++ b/include/utils/Window/WindowImpl/WindowSDL3/WindowSDL3.h @@ -0,0 +1,173 @@ +#ifndef WINDOW_SDL3 +#define WINDOW_SDL3 + +#include "pch.hpp" + +#include "utils/Window/WindowEvents.h" + +#include + +#if RENDERER == 2 + +#include + +#endif + +namespace Archimedes { + + template + requires allowed_windows + && allowed_renderers + class Window; + + template + static bool EventCallback(void* ptr, SDL_Event* e) { + + WindowData& data = *(WindowData*) ptr; + + switch(e->type) { + + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + case SDL_EVENT_QUIT: + data.sendEvent(new CloseWindowEvent(data.window, e)); + break; + case SDL_EVENT_WINDOW_RESIZED: + data.sendEvent(new ResizeWindowEvent(e->window.data1, e->window.data2, e)); + break; + case SDL_EVENT_WINDOW_MOUSE_ENTER: + case SDL_EVENT_WINDOW_FOCUS_GAINED: + data.sendEvent(new FocusedWindowEvent(data.window, e)); + break; + case SDL_EVENT_WINDOW_MOUSE_LEAVE: + case SDL_EVENT_WINDOW_FOCUS_LOST: + data.sendEvent(new FocusLostWindowEvent(data.window, e)); + break; + case SDL_EVENT_KEY_DOWN: + data.sendEvent(new KeyPressedWindowEvent(e->key.key, e->key.repeat ? 1 : 0, e)); + break; + case SDL_EVENT_KEY_UP: + data.sendEvent(new KeyReleasedWindowEvent(e->key.key, e)); + break; + case SDL_EVENT_MOUSE_MOTION: + data.sendEvent(new MouseMovedWindowEvent(e->motion.x, e->motion.y, e)); + break; + case SDL_EVENT_MOUSE_BUTTON_DOWN: + data.sendEvent(new MouseButtonPressedWindowEvent(e->button.button, e)); + break; + case SDL_EVENT_MOUSE_BUTTON_UP: + data.sendEvent(new MouseButtonReleasedWindowEvent(e->button.button, e)); + break; + case SDL_EVENT_MOUSE_WHEEL: + data.sendEvent(new ScrollWindowEvent(e->wheel.x, e->wheel.y, e)); + break; + default: + data.sendEvent(new AnonymousEvent(e)); + break; + } + + return true; + } + + template + class WindowSDL3 { + + public: + + WindowSDL3(Window, R>* p, const std::function& sendEvent) { + + data.window = p; + data.sendEvent = sendEvent; + + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { + std::cerr << "Error: SDL_Init(): " << SDL_GetError() << std::flush; + std::abort(); + } + +#if RENDERER == 1 + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + + SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; +#elif RENDERER == 2 + SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY; +#endif + + w = SDL_CreateWindow("Archimedes", 1280, 720, window_flags); + if (w == nullptr) + { + std::cerr << "Error: SDL_CreateWindow(): " << SDL_GetError() << std::endl; + std::abort(); + } + SDL_SetWindowPosition(w, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + +#if RENDERER == 1 + gl_context = SDL_GL_CreateContext(w); + + if (gl_context == nullptr) + { + std::cerr << "Error: SDL_GL_CreateContext(): " << SDL_GetError() << std::endl; + std::abort(); + } + + SDL_GL_MakeCurrent(w, gl_context); + SDL_GL_SetSwapInterval(1); // Enable vsync +#endif + SDL_AddEventWatch(EventCallback, &data); + + SDL_ShowWindow(w); + } + + ~WindowSDL3() { +#if RENDERER == 1 + SDL_GL_DestroyContext(gl_context); +#endif + SDL_RemoveEventWatch(EventCallback, &data); + SDL_DestroyWindow(w); + SDL_Quit(); + } + + bool shouldClose() { return false; } + + void doFrame() { +#if RENDERER == 1 + restoreContext(); + SDL_GL_SwapWindow(w); +#endif + } + + void pollEvents() { + static SDL_Event e; + while(SDL_PollEvent(&e)) {} + } +#if RENDERER == 1 + void restoreContext() { SDL_GL_MakeCurrent(w, gl_context); } +#endif + void getSize(int& w, int& h) { + w = this->width; + h = this->height; + } + + void setSize(int& w, int& h) { + this->width = w; + this->height = h; + } + + SDL_Window* getWindow() { return w; } +#if RENDERER == 1 + SDL_GLContext getContext() { return gl_context; } +#endif + WindowData, R> data; + + private: + SDL_Window* w; + int width = 0, height = 0; +#if RENDERER == 1 + SDL_GLContext gl_context; +#endif + + }; + +} + +#endif diff --git a/include/utils/Window/concepts.h b/include/utils/Window/concepts.h new file mode 100644 index 0000000..dff5edb --- /dev/null +++ b/include/utils/Window/concepts.h @@ -0,0 +1,25 @@ +#ifndef WINDOW_CONCEPTS +#define WINDOW_CONCEPTS + +#include "pch.hpp" + +#include "utils/Renderer/concepts.h" + +namespace Archimedes { + + template + class WindowGLFW; + + template + class WindowSDL3; + + template + concept allowed_windows = requires (WindowImpl a, R b) { +#ifndef CUSTOM_WINDOW + requires std::same_as> + || std::same_as>; +#endif + }; +} + +#endif