From 26114b9a59b26ce2dc1af8d9b94122c9068dbc21 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sat, 4 Oct 2025 14:52:26 +0300 Subject: [PATCH 01/41] First iteration. Window create successfull --- .gitignore | 1 + CMakeLists.txt | 2 +- src/CMakeLists.txt | 4 +- src/graphics/core/Shader.cpp | 10 - .../detail/{GLFWWindow.cpp => SDLWindow.cpp} | 460 ++++++++---------- src/window/input.cpp | 271 +++++------ 6 files changed, 355 insertions(+), 393 deletions(-) rename src/window/detail/{GLFWWindow.cpp => SDLWindow.cpp} (58%) diff --git a/.gitignore b/.gitignore index 9056cce5b..a6379cced 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ Debug/voxel_engine /export /config /out +/compile_commands.json /misc /world diff --git a/CMakeLists.txt b/CMakeLists.txt index 6966e81fd..1723ae29c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.11) project(VoxelEngine) set(CMAKE_CXX_STANDARD 17) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5e8fc44bb..77c1f0195 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,7 +18,7 @@ endif() find_package(ZLIB REQUIRED) find_package(PNG REQUIRED) find_package(CURL REQUIRED) -find_package(glfw3 REQUIRED) +find_package(SDL3 REQUIRED) if(NOT APPLE) find_package(EnTT REQUIRED) endif() @@ -65,7 +65,7 @@ target_include_directories(VoxelEngineSrc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries( VoxelEngineSrc - PRIVATE glfw + PRIVATE SDL3::SDL3 OpenGL::GL GLEW::GLEW ZLIB::ZLIB diff --git a/src/graphics/core/Shader.cpp b/src/graphics/core/Shader.cpp index da6ea342c..5a70e3091 100644 --- a/src/graphics/core/Shader.cpp +++ b/src/graphics/core/Shader.cpp @@ -1,23 +1,13 @@ #include "Shader.hpp" -#include -#include -#include -#include -#include - #include - #include -#include #include "coders/GLSLExtension.hpp" #include "debug/Logger.hpp" static debug::Logger logger("gl-shader"); -namespace fs = std::filesystem; - GLSLExtension* Shader::preprocessor = new GLSLExtension(); Shader* Shader::used = nullptr; diff --git a/src/window/detail/GLFWWindow.cpp b/src/window/detail/SDLWindow.cpp similarity index 58% rename from src/window/detail/GLFWWindow.cpp rename to src/window/detail/SDLWindow.cpp index accd969ff..f6f4366a7 100644 --- a/src/window/detail/GLFWWindow.cpp +++ b/src/window/detail/SDLWindow.cpp @@ -1,25 +1,29 @@ #include "window/Window.hpp" #include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include -#include -#include +#include #include +#include #include "debug/Logger.hpp" #include "graphics/core/ImageData.hpp" #include "graphics/core/Texture.hpp" #include "settings.hpp" -#include "util/ObjectsKeeper.hpp" #include "util/platform.hpp" #include "window/input.hpp" static debug::Logger logger("window"); static std::unordered_set supported_gl_extensions; -static void window_size_callback(GLFWwindow* window, int width, int height); static void init_gl_extensions_list() { GLint numExtensions = 0; @@ -118,54 +122,15 @@ static bool initialize_gl(int width, int height) { const GLubyte* renderer = glGetString(GL_RENDERER); logger.info() << "GL Vendor: " << reinterpret_cast(vendor); logger.info() << "GL Renderer: " << reinterpret_cast(renderer); - logger.info() << "GLFW: " << glfwGetVersionString(); + logger.info() << "SDL: " << SDL_GetVersion(); return false; } -static const char* glfw_error_name(int error) { - switch (error) { - case GLFW_NO_ERROR: - return "no error"; - case GLFW_NOT_INITIALIZED: - return "not initialized"; - case GLFW_NO_CURRENT_CONTEXT: - return "no current context"; - case GLFW_INVALID_ENUM: - return "invalid enum"; - case GLFW_INVALID_VALUE: - return "invalid value"; - case GLFW_OUT_OF_MEMORY: - return "out of memory"; - case GLFW_API_UNAVAILABLE: - return "api unavailable"; - case GLFW_VERSION_UNAVAILABLE: - return "version unavailable"; - case GLFW_PLATFORM_ERROR: - return "platform error"; - case GLFW_FORMAT_UNAVAILABLE: - return "format unavailable"; - case GLFW_NO_WINDOW_CONTEXT: - return "no window context"; - default: - return "unknown error"; - } -} - -static void glfw_error_callback(int error, const char* description) { - auto logline = logger.error(); - logline << "GLFW error [0x" << std::hex << error << " - " - << glfw_error_name(error) << "]"; - if (description) { - logline << ": " << description; - } -} inline constexpr short KEYS_BUFFER_SIZE = 1036; inline constexpr short MOUSE_KEYS_OFFSET = 1024; -static GLFWcursor* standard_cursors[static_cast(CursorShape::LAST) + 1] = {}; - -class GLFWInput : public Input { +class SDLInput : public Input { public: int scroll = 0; uint currentFrame = 0; @@ -176,7 +141,7 @@ public: bool keys[KEYS_BUFFER_SIZE] {}; std::unordered_map> keyCallbacks; - GLFWInput(GLFWwindow* window) + SDLInput(SDL_Window* window) : window(window) { } @@ -184,40 +149,55 @@ public: delta.x = 0.0f; delta.y = 0.0f; scroll = 0; - currentFrame++; codepoints.clear(); pressedKeys.clear(); - glfwPollEvents(); - for (auto& [_, binding] : bindings.getAll()) { - if (!binding.enabled) { - binding.state = false; - continue; - } - binding.justChanged = false; - - bool newstate = false; - switch (binding.type) { - case InputType::KEYBOARD: - newstate = pressed(static_cast(binding.code)); + SDL_Event event; + + while(SDL_PollEvent(&event)) + { + switch (event.type) { + case SDL_EVENT_QUIT: + // window->setShouldClose(true); break; - case InputType::MOUSE: - newstate = clicked(static_cast(binding.code)); + case SDL_EVENT_KEY_DOWN: + break; + case SDL_EVENT_KEY_UP: + break; + case SDL_EVENT_MOUSE_BUTTON_DOWN: + break; + case SDL_EVENT_MOUSE_MOTION: break; } + // for (auto& [_, binding] : bindings.getAll()) { + // if (!binding.enabled) { + // binding.state = false; + // continue; + // } + // binding.justChanged = false; - if (newstate) { - if (!binding.state) { - binding.state = true; - binding.justChanged = true; - binding.onactived.notify(); - } - } else { - if (binding.state) { - binding.state = false; - binding.justChanged = true; - } - } + // bool newstate = false; + // switch (binding.type) { + // case InputType::KEYBOARD: + // newstate = pressed(static_cast(binding.code)); + // break; + // case InputType::MOUSE: + // newstate = clicked(static_cast(binding.code)); + // break; + // } + + // if (newstate) { + // if (!binding.state) { + // binding.state = true; + // binding.justChanged = true; + // binding.onactived.notify(); + // } + // } else { + // if (binding.state) { + // binding.state = false; + // binding.justChanged = true; + // } + // } } } @@ -242,11 +222,12 @@ public: } const char* getClipboardText() const override { - return glfwGetClipboardString(window); + /*todo free*/ + return SDL_GetClipboardText(); } void setClipboardText(const char* text) override { - glfwSetClipboardString(window, text); + SDL_SetClipboardText(text); } int getScroll() override { @@ -286,11 +267,7 @@ public: void toggleCursor() override { cursorDrag = false; - if (cursorLocked) { - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); - } else { - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - } + SDL_SetWindowMouseGrab(window, cursorLocked); cursorLocked = !cursorLocked; } @@ -325,22 +302,24 @@ public: return codepoints; } private: - GLFWwindow* window; + SDL_Window* window; bool cursorLocked = false; bool cursorDrag = false; glm::vec2 delta; glm::vec2 cursor; }; -static_assert(!std::is_abstract()); +static_assert(!std::is_abstract()); -class GLFWWindow : public Window { +class WindowSdlImpl final : public Window { public: - GLFWInput& input; + SDLInput& input; + DisplaySettings* settings; - GLFWWindow( - GLFWInput& glfwInput, - GLFWwindow* window, + WindowSdlImpl( + SDLInput& glfwInput, + SDL_Window* window, + SDL_GLContext context, DisplaySettings* settings, int width, int height @@ -348,22 +327,20 @@ public: : Window({width, height}), input(glfwInput), settings(settings), - window(window) { + window(window), + glcontext(context) { } - ~GLFWWindow() { - for (int i = 0; i <= static_cast(CursorShape::LAST); i++) { - glfwDestroyCursor(standard_cursors[i]); - } - glfwTerminate(); + ~WindowSdlImpl() override { + SDL_GL_DestroyContext(glcontext); } double time() override { - return glfwGetTime(); + return SDL_GetTicks(); } void swapBuffers() override { - glfwSwapBuffers(window); + SDL_GL_SwapWindow(window); resetScissor(); if (framerate > 0) { auto elapsedTime = time() - prevSwap; @@ -378,65 +355,44 @@ public: } bool isMaximized() const override { - return glfwGetWindowAttrib(window, GLFW_MAXIMIZED); + return (SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) != 0; } bool isFocused() const override { - return glfwGetWindowAttrib(window, GLFW_FOCUSED); + Uint32 flags = SDL_GetWindowFlags(window); + return (flags & SDL_WINDOW_INPUT_FOCUS) != 0 || (flags & SDL_WINDOW_MOUSE_FOCUS) != 0; } bool isIconified() const override { - return glfwGetWindowAttrib(window, GLFW_ICONIFIED); + return (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) != 0; } - bool isShouldClose() const override { - return glfwWindowShouldClose(window); + + bool isShouldClose() const override + { + return toClose; } - void setShouldClose(bool flag) override { - glfwSetWindowShouldClose(window, flag); + void setShouldClose(bool flag) override + { + toClose = flag; } void setCursor(CursorShape shape) override { - if (cursor == shape) { - return; - } - cursor = shape; - // NULL cursor is valid for GLFW - glfwSetCursor(window, standard_cursors[static_cast(shape)]); + // if (cursor == shape) { + // return; + // } + // cursor = shape; + // // NULL cursor is valid for GLFW + // glfwSetCursor(window, standard_cursors[static_cast(shape)]); } void toggleFullscreen() override { fullscreen = !fullscreen; - - GLFWmonitor* monitor = glfwGetPrimaryMonitor(); - const GLFWvidmode* mode = glfwGetVideoMode(monitor); - - if (input.isCursorLocked()){ - input.toggleCursor(); + + if (!SDL_SetWindowFullscreen(window, fullscreen)) { + // SDL_Log("Failed to toggle fullscreen: %s", SDL_GetError()); } - - if (fullscreen) { - glfwGetWindowPos(window, &posX, &posY); - glfwSetWindowMonitor( - window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate - ); - } else { - glfwSetWindowMonitor( - window, - nullptr, - posX, - posY, - settings->width.get(), - settings->height.get(), - GLFW_DONT_CARE - ); - window_size_callback(window, settings->width.get(), settings->height.get()); - } - - double xPos, yPos; - glfwGetCursorPos(window, &xPos, &yPos); - input.setCursorPosition(xPos, yPos); } bool isFullscreen() const override { @@ -445,16 +401,33 @@ public: void setIcon(const ImageData* image) override { if (image == nullptr) { - glfwSetWindowIcon(window, 0, nullptr); + SDL_SetWindowIcon(window, nullptr); return; } - GLFWimage icon { - static_cast(image->getWidth()), - static_cast(image->getHeight()), - image->getData()}; - glfwSetWindowIcon(window, 1, &icon); + + // Create SDL_Surface from ImageData + SDL_Surface* iconSurface = SDL_CreateSurface( + image->getWidth(), + image->getHeight(), + SDL_PIXELFORMAT_RGBA32 // Adjust format based on your ImageData + ); + + if (!iconSurface) { + // SDL_Log("Failed to create surface for window icon: %s", SDL_GetError()); + return; + } + + memcpy(iconSurface->pixels, image->getData(), + image->getWidth() * image->getHeight() * 4); + + if (!SDL_SetWindowIcon(window, iconSurface)) { + // SDL_Log("Failed to set window icon: %s", SDL_GetError()); + } + + SDL_DestroySurface(iconSurface); } + void setSize(int width, int height) { glViewport(0, 0, width, height); size = {width, height}; @@ -534,15 +507,17 @@ public: void setFramerate(int framerate) override { if ((framerate != -1) != (this->framerate != -1)) { - glfwSwapInterval(framerate == -1); + SDL_GL_SetSwapInterval(framerate == -1); } this->framerate = framerate; } private: - GLFWwindow* window; + SDL_Window* window; + SDL_GLContext glcontext; CursorShape cursor = CursorShape::ARROW; bool fullscreen = false; + bool toClose = false; int framerate = -1; std::stack scissorStack; glm::vec4 scissorArea; @@ -550,86 +525,85 @@ private: int posX = 0; int posY = 0; }; -static_assert(!std::is_abstract()); -static void mouse_button_callback(GLFWwindow* window, int button, int action, int) { - auto handler = static_cast(glfwGetWindowUserPointer(window)); - handler->input.onMouseCallback(button, action == GLFW_PRESS); -} +// static void mouse_button_callback(GLFWwindow* window, int button, int action, int) { +// auto handler = static_cast(glfwGetWindowUserPointer(window)); +// handler->input.onMouseCallback(button, action == GLFW_PRESS); +// } -static void character_callback(GLFWwindow* window, unsigned int codepoint) { - auto handler = static_cast(glfwGetWindowUserPointer(window)); - handler->input.codepoints.push_back(codepoint); -} +// static void character_callback(GLFWwindow* window, unsigned int codepoint) { +// auto handler = static_cast(glfwGetWindowUserPointer(window)); +// handler->input.codepoints.push_back(codepoint); +// } -static void key_callback( - GLFWwindow* window, int key, int /*scancode*/, int action, int /*mode*/ -) { - auto handler = static_cast(glfwGetWindowUserPointer(window)); - auto& input = handler->input; - if (key == GLFW_KEY_UNKNOWN) { - return; - } - if (action == GLFW_PRESS) { - input.onKeyCallback(key, true); +// static void key_callback( +// GLFWwindow* window, int key, int /*scancode*/, int action, int /*mode*/ +// ) { +// auto handler = static_cast(glfwGetWindowUserPointer(window)); +// auto& input = handler->input; +// if (key == GLFW_KEY_UNKNOWN) { +// return; +// } +// if (action == GLFW_PRESS) { +// input.onKeyCallback(key, true); - } else if (action == GLFW_RELEASE) { - input.onKeyCallback(key, false); - } else if (action == GLFW_REPEAT) { - input.onKeyCallback(key, true); - } -} +// } else if (action == GLFW_RELEASE) { +// input.onKeyCallback(key, false); +// } else if (action == GLFW_REPEAT) { +// input.onKeyCallback(key, true); +// } +// } -static void window_size_callback(GLFWwindow* window, int width, int height) { - auto handler = static_cast(glfwGetWindowUserPointer(window)); - if (width && height) { - handler->setSize(width, height); - } - handler->resetScissor(); -} +// static void window_size_callback(GLFWwindow* window, int width, int height) { +// auto handler = static_cast(glfwGetWindowUserPointer(window)); +// if (width && height) { +// handler->setSize(width, height); +// } +// handler->resetScissor(); +// } -static void scroll_callback(GLFWwindow* window, double, double yoffset) { - auto handler = static_cast(glfwGetWindowUserPointer(window)); - handler->input.scroll += yoffset; -} +// static void scroll_callback(GLFWwindow* window, double, double yoffset) { +// auto handler = static_cast(glfwGetWindowUserPointer(window)); +// handler->input.scroll += yoffset; +// } -static void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) { - auto handler = static_cast(glfwGetWindowUserPointer(window)); - handler->input.setCursorPosition(xpos, ypos); -} +// static void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) { +// auto handler = static_cast(glfwGetWindowUserPointer(window)); +// handler->input.setCursorPosition(xpos, ypos); +// } -static void iconify_callback(GLFWwindow* window, int iconified) { - auto handler = static_cast(glfwGetWindowUserPointer(window)); - if (handler->isFullscreen() && iconified == 0) { - GLFWmonitor* monitor = glfwGetPrimaryMonitor(); - const GLFWvidmode* mode = glfwGetVideoMode(monitor); - glfwSetWindowMonitor( - window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate - ); - } -} +// static void iconify_callback(GLFWwindow* window, int iconified) { +// auto handler = static_cast(glfwGetWindowUserPointer(window)); +// if (handler->isFullscreen() && iconified == 0) { +// GLFWmonitor* monitor = glfwGetPrimaryMonitor(); +// const GLFWvidmode* mode = glfwGetVideoMode(monitor); +// glfwSetWindowMonitor( +// window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate +// ); +// } +// } -static void create_standard_cursors() { - for (int i = 0; i <= static_cast(CursorShape::LAST); i++) { - int cursor = GLFW_ARROW_CURSOR + i; - // GLFW 3.3 does not support some cursors - if (GLFW_VERSION_MAJOR <= 3 && GLFW_VERSION_MINOR <= 3 && - cursor > GLFW_VRESIZE_CURSOR) { - break; - } - standard_cursors[i] = glfwCreateStandardCursor(cursor); - } -} +// static void create_standard_cursors() { +// for (int i = 0; i <= static_cast(CursorShape::LAST); i++) { +// int cursor = GLFW_ARROW_CURSOR + i; +// // GLFW 3.3 does not support some cursors +// if (GLFW_VERSION_MAJOR <= 3 && GLFW_VERSION_MINOR <= 3 && +// cursor > GLFW_VRESIZE_CURSOR) { +// break; +// } +// standard_cursors[i] = glfwCreateStandardCursor(cursor); +// } +// } -static void setup_callbacks(GLFWwindow* window) { - glfwSetKeyCallback(window, key_callback); - glfwSetMouseButtonCallback(window, mouse_button_callback); - glfwSetCursorPosCallback(window, cursor_pos_callback); - glfwSetWindowSizeCallback(window, window_size_callback); - glfwSetCharCallback(window, character_callback); - glfwSetScrollCallback(window, scroll_callback); - glfwSetWindowIconifyCallback(window, iconify_callback); -} +// static void setup_callbacks(GLFWwindow* window) { +// glfwSetKeyCallback(window, key_callback); +// glfwSetMouseButtonCallback(window, mouse_button_callback); +// glfwSetCursorPosCallback(window, cursor_pos_callback); +// glfwSetWindowSizeCallback(window, window_size_callback); +// glfwSetCharCallback(window, character_callback); +// glfwSetScrollCallback(window, scroll_callback); +// glfwSetWindowIconifyCallback(window, iconify_callback); +// } std::tuple< std::unique_ptr, @@ -638,35 +612,34 @@ std::tuple< int width = settings->width.get(); int height = settings->height.get(); - glfwSetErrorCallback(glfw_error_callback); - if (glfwInit() == GLFW_FALSE) { - logger.error() << "failed to initialize GLFW"; + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS)) { + logger.error() << "failed to initialize SDL"; return {nullptr, nullptr}; } - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); -#if GLFW_VERSION_MAJOR >= 3 && GLFW_VERSION_MINOR >= 4 - // see issue #465 - glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GL_FALSE); -#endif + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); +// #if GLFW_VERSION_MAJOR >= 3 && GLFW_VERSION_MINOR >= 4 +// // see issue #465 +// // glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GL_FALSE); +// #endif #ifdef __APPLE__ - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE); + // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + // glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE); #else - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); + // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); #endif - glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); - glfwWindowHint(GLFW_SAMPLES, settings->samples.get()); + // glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); + // glfwWindowHint(GLFW_SAMPLES, settings->samples.get()); - auto window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); + auto window = SDL_CreateWindow(title.c_str(), width, height, SDL_WINDOW_OPENGL); if (window == nullptr) { logger.error() << "failed to create GLFW window"; - glfwTerminate(); return {nullptr, nullptr}; } - glfwMakeContextCurrent(window); + SDL_GLContext glcontext = SDL_GL_CreateContext(window); + SDL_GL_MakeCurrent(window, glcontext); glewExperimental = GL_TRUE; @@ -679,7 +652,7 @@ std::tuple< } else { logger.error() << "failed to initialize GLEW:\n" << glewGetErrorString(glewErr); - glfwTerminate(); + SDL_DestroyWindow(window); return {nullptr, nullptr}; } } @@ -704,26 +677,25 @@ std::tuple< Texture::MAX_RESOLUTION = maxTextureSize[0]; logger.info() << "max texture size is " << Texture::MAX_RESOLUTION; } - setup_callbacks(window); + // setup_callbacks(window); - glfwSwapInterval(1); + SDL_GL_SetSwapInterval(1); input_util::initialize(); - create_standard_cursors(); + // create_standard_cursors(); glm::vec2 scale; - glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &scale.x, &scale.y); + // SDL_SetDisplayContentScale(SDL_GetPrimaryDisplay(), &scale.x, &scale.y); logger.info() << "monitor content scale: " << scale.x << "x" << scale.y; if (initialize_gl(width, height)) { - glfwTerminate(); return {nullptr, nullptr}; } - auto inputPtr = std::make_unique(window); - auto windowPtr = std::make_unique( - *inputPtr, window, settings, width, height + auto inputPtr = std::make_unique(window); + auto windowPtr = std::make_unique( + *inputPtr, window, glcontext, settings, width, height ); - glfwSetWindowUserPointer(window, windowPtr.get()); + // glfwSetWindowUserPointer(window, windowPtr.get()); return {std::move(windowPtr), std::move(inputPtr)}; } diff --git a/src/window/input.cpp b/src/window/input.cpp index 6feaddb3f..f3dbea53c 100644 --- a/src/window/input.cpp +++ b/src/window/input.cpp @@ -1,56 +1,60 @@ #include "input.hpp" -#include "debug/Logger.hpp" -#include "util/stringutil.hpp" -#include "data/dv.hpp" - -#include - #include +#include +#include +#include +#include +#include + +#include "debug/Logger.hpp" +#include "data/dv.hpp" +#include "util/stringutil.hpp" + #ifdef _WIN32 #include #endif // _WIN32 static debug::Logger logger("input"); -static std::unordered_map keycodes { - {"enter", GLFW_KEY_ENTER}, - {"space", GLFW_KEY_SPACE}, - {"backspace", GLFW_KEY_BACKSPACE}, - {"caps-lock", GLFW_KEY_CAPS_LOCK}, - {"escape", GLFW_KEY_ESCAPE}, - {"delete", GLFW_KEY_DELETE}, - {"home", GLFW_KEY_HOME}, - {"end", GLFW_KEY_END}, - {"tab", GLFW_KEY_TAB}, - {"insert", GLFW_KEY_INSERT}, - {"page-down", GLFW_KEY_PAGE_DOWN}, - {"page-up", GLFW_KEY_PAGE_UP}, - {"left-shift", GLFW_KEY_LEFT_SHIFT}, - {"right-shift", GLFW_KEY_RIGHT_SHIFT}, - {"left-ctrl", GLFW_KEY_LEFT_CONTROL}, - {"right-ctrl", GLFW_KEY_RIGHT_CONTROL}, - {"left-alt", GLFW_KEY_LEFT_ALT}, - {"right-alt", GLFW_KEY_RIGHT_ALT}, - {"left-super", GLFW_KEY_LEFT_SUPER}, - {"right-super", GLFW_KEY_RIGHT_SUPER}, - {"grave-accent", GLFW_KEY_GRAVE_ACCENT}, - {"left", GLFW_KEY_LEFT}, - {"right", GLFW_KEY_RIGHT}, - {"down", GLFW_KEY_DOWN}, - {"up", GLFW_KEY_UP}, +static std::unordered_map keycodes { + {"enter", SDLK_RETURN }, + {"space", SDLK_SPACE }, + {"backspace", SDLK_BACKSPACE }, + {"caps-lock", SDLK_CAPSLOCK }, + {"escape", SDLK_ESCAPE }, + {"delete", SDLK_DELETE }, + {"home", SDLK_HOME }, + {"end", SDLK_END }, + {"tab", SDLK_TAB }, + {"insert", SDLK_INSERT }, + {"page-down", SDLK_PAGEDOWN }, + {"page-up", SDLK_PAGEUP }, + {"left-shift", SDLK_LSHIFT }, + {"right-shift", SDLK_RSHIFT }, + {"left-ctrl", SDLK_LCTRL }, + {"right-ctrl", SDLK_RCTRL}, + {"left-alt", SDLK_LALT }, + {"right-alt", SDLK_RALT }, + {"left-super", 0 /*todo*/ }, + {"right-super", 0 /*todo*/ }, + {"grave-accent", SDLK_GRAVE }, + {"left", SDLK_LEFT }, + {"right", SDLK_RIGHT }, + {"down", SDLK_DOWN }, + {"up", SDLK_UP }, }; - -static std::unordered_map mousecodes { - {"left", GLFW_MOUSE_BUTTON_1}, - {"right", GLFW_MOUSE_BUTTON_2}, - {"middle", GLFW_MOUSE_BUTTON_3}, - {"side1", GLFW_MOUSE_BUTTON_4}, - {"side2", GLFW_MOUSE_BUTTON_5}, - {"side3", GLFW_MOUSE_BUTTON_6}, - {"side4", GLFW_MOUSE_BUTTON_7}, - {"side5", GLFW_MOUSE_BUTTON_8}, +SDL_Event s; +static std::unordered_map mousecodes { + {"left", SDL_BUTTON_LEFT }, + {"right", SDL_BUTTON_RIGHT }, + {"middle", SDL_BUTTON_MIDDLE }, + {"side1", SDL_BUTTON_MASK(4) /*todo*/}, + {"side2", SDL_BUTTON_MASK(5) /*todo*/}, + {"side3", SDL_BUTTON_MASK(6) /*todo*/}, + {"side4", SDL_BUTTON_MASK(7) /*todo*/}, + {"side5", SDL_BUTTON_MASK(8) /*todo*/}, }; static std::unordered_map keynames {}; @@ -86,14 +90,14 @@ void Binding::reset(Mousecode code) { } void input_util::initialize() { - for (int i = 0; i <= 9; i++) { - keycodes[std::to_string(i)] = GLFW_KEY_0 + i; + for (std::uint32_t i = 0; i <= 9; i++) { + keycodes[std::to_string(i)] = SDLK_0 + i; } - for (int i = 0; i < 25; i++) { - keycodes["f" + std::to_string(i + 1)] = GLFW_KEY_F1 + i; + for (std::uint32_t i = 0; i < 25; i++) { + keycodes["f" + std::to_string(i + 1)] = SDLK_F1 + i; } for (char i = 'a'; i <= 'z'; i++) { - keycodes[std::string({i})] = GLFW_KEY_A - 'a' + i; + keycodes[std::string({i})] = SDLK_A - 'a' + i; } for (const auto& entry : keycodes) { keynames[entry.second] = entry.first; @@ -120,96 +124,91 @@ Mousecode input_util::mousecode_from(const std::string& name) { } std::string input_util::to_string(Keycode code) { - int icode_repr = static_cast(code); - const char* name = - glfwGetKeyName(icode_repr, glfwGetKeyScancode(icode_repr)); - if (name == nullptr) { - switch (icode_repr) { - case GLFW_KEY_TAB: - return "Tab"; - case GLFW_KEY_LEFT_CONTROL: - return "Left Ctrl"; - case GLFW_KEY_RIGHT_CONTROL: - return "Right Ctrl"; - case GLFW_KEY_LEFT_ALT: - return "Left Alt"; - case GLFW_KEY_RIGHT_ALT: - return "Right Alt"; - case GLFW_KEY_LEFT_SHIFT: - return "Left Shift"; - case GLFW_KEY_RIGHT_SHIFT: - return "Right Shift"; - case GLFW_KEY_CAPS_LOCK: - return "Caps-Lock"; - case GLFW_KEY_SPACE: - return "Space"; - case GLFW_KEY_ESCAPE: - return "Esc"; - case GLFW_KEY_ENTER: - return "Enter"; - case GLFW_KEY_UP: - return "Up"; - case GLFW_KEY_DOWN: - return "Down"; - case GLFW_KEY_LEFT: - return "Left"; - case GLFW_KEY_RIGHT: - return "Right"; - case GLFW_KEY_BACKSPACE: - return "Backspace"; - case GLFW_KEY_F1: - return "F1"; - case GLFW_KEY_F2: - return "F2"; - case GLFW_KEY_F3: - return "F3"; - case GLFW_KEY_F4: - return "F4"; - case GLFW_KEY_F5: - return "F5"; - case GLFW_KEY_F6: - return "F6"; - case GLFW_KEY_F7: - return "F7"; - case GLFW_KEY_F8: - return "F8"; - case GLFW_KEY_F9: - return "F9"; - case GLFW_KEY_F10: - return "F10"; - case GLFW_KEY_F11: - return "F11"; - case GLFW_KEY_F12: - return "F12"; - case GLFW_KEY_DELETE: - return "Delete"; - case GLFW_KEY_HOME: - return "Home"; - case GLFW_KEY_END: - return "End"; - case GLFW_KEY_LEFT_SUPER: - return "Left Super"; - case GLFW_KEY_RIGHT_SUPER: - return "Right Super"; - case GLFW_KEY_PAGE_UP: - return "Page Up"; - case GLFW_KEY_PAGE_DOWN: - return "Page Down"; - case GLFW_KEY_INSERT: - return "Insert"; - case GLFW_KEY_PRINT_SCREEN: - return "Print Screen"; - case GLFW_KEY_NUM_LOCK: - return "Num Lock"; - case GLFW_KEY_MENU: - return "Menu"; - case GLFW_KEY_PAUSE: - return "Pause"; - default: - return "Unknown"; - } + SDL_Scancode scancode = static_cast(code); + switch (scancode) { + case SDLK_TAB: + return "Tab"; + case SDL_SCANCODE_LCTRL: + return "Left Ctrl"; + case SDL_SCANCODE_RCTRL: + return "Right Ctrl"; + case SDL_SCANCODE_LALT: + return "Left Alt"; + case SDL_SCANCODE_RALT: + return "Right Alt"; + case SDL_SCANCODE_LSHIFT: + return "Left Shift"; + case SDL_SCANCODE_RSHIFT: + return "Right Shift"; + case SDL_SCANCODE_CAPSLOCK: + return "Caps-Lock"; + case SDL_SCANCODE_SPACE: + return "Space"; + case SDL_SCANCODE_ESCAPE: + return "Esc"; + case SDL_SCANCODE_RETURN: + return "Enter"; + case SDL_SCANCODE_UP: + return "Up"; + case SDL_SCANCODE_DOWN: + return "Down"; + case SDL_SCANCODE_LEFT: + return "Left"; + case SDL_SCANCODE_RIGHT: + return "Right"; + case SDL_SCANCODE_BACKSPACE: + return "Backspace"; + case SDL_SCANCODE_F1: + return "F1"; + case SDL_SCANCODE_F2: + return "F2"; + case SDL_SCANCODE_F3: + return "F3"; + case SDL_SCANCODE_F4: + return "F4"; + case SDL_SCANCODE_F5: + return "F5"; + case SDL_SCANCODE_F6: + return "F6"; + case SDL_SCANCODE_F7: + return "F7"; + case SDL_SCANCODE_F8: + return "F8"; + case SDL_SCANCODE_F9: + return "F9"; + case SDL_SCANCODE_F10: + return "F10"; + case SDL_SCANCODE_F11: + return "F11"; + case SDL_SCANCODE_F12: + return "F12"; + case SDL_SCANCODE_DELETE: + return "Delete"; + case SDL_SCANCODE_HOME: + return "Home"; + case SDL_SCANCODE_END: + return "End"; + case SDL_SCANCODE_LGUI: + return "Left Super"; + case SDL_SCANCODE_RGUI: + return "Right Super"; + case SDL_SCANCODE_PAGEUP: + return "Page Up"; + case SDL_SCANCODE_PAGEDOWN: + return "Page Down"; + case SDL_SCANCODE_INSERT: + return "Insert"; + case SDL_SCANCODE_PRINTSCREEN: + return "Print Screen"; + case SDL_SCANCODE_NUMLOCKCLEAR: + return "Num Lock"; + case SDL_SCANCODE_APPLICATION: + return "Menu"; + case SDL_SCANCODE_PAUSE: + return "Pause"; + default: + return "Unknown"; } - return std::string(name); } std::string input_util::to_string(Mousecode code) { From f62bd09fb21e62a073ec68707a3ffbd0d7c48c08 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sat, 4 Oct 2025 21:08:03 +0300 Subject: [PATCH 02/41] Unimpl gl --- src/CMakeLists.txt | 4 +- src/engine/Engine.cpp | 2 +- src/engine/Mainloop.cpp | 2 +- src/frontend/hud.cpp | 2 +- src/frontend/screens/LevelScreen.cpp | 2 +- src/frontend/screens/MenuScreen.cpp | 2 +- src/graphics/core/DrawContext.cpp | 2 +- src/graphics/render/BlocksPreview.cpp | 2 +- src/graphics/render/Skybox.cpp | 2 +- src/graphics/render/WorldRenderer.cpp | 2 +- src/graphics/ui/GUI.cpp | 4 +- src/graphics/ui/elements/ModelViewer.cpp | 2 +- src/graphics/ui/elements/TextBox.cpp | 2 +- src/logic/PlayerController.cpp | 2 +- src/window/detail/SDLWindow.cpp | 716 ----------------------- src/window/detail/input_sdl.cpp | 125 ++++ src/window/detail/input_sdl.hpp | 39 ++ src/window/detail/window_sdl.cpp | 290 +++++++++ src/window/detail/window_sdl.hpp | 51 ++ src/window/input.cpp | 201 +------ src/window/input.hpp | 10 +- src/window/{Window.hpp => window.hpp} | 15 +- 22 files changed, 547 insertions(+), 932 deletions(-) delete mode 100644 src/window/detail/SDLWindow.cpp create mode 100644 src/window/detail/input_sdl.cpp create mode 100644 src/window/detail/input_sdl.hpp create mode 100644 src/window/detail/window_sdl.cpp create mode 100644 src/window/detail/window_sdl.hpp rename src/window/{Window.hpp => window.hpp} (78%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 77c1f0195..38d00b63c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ project(VoxelEngineSrc) -file(GLOB_RECURSE headers ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) -file(GLOB_RECURSE sources ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +file(GLOB_RECURSE headers CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) +file(GLOB_RECURSE sources CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) list(REMOVE_ITEM sources ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) add_library(VoxelEngineSrc STATIC ${sources} ${headers}) diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index 6596733f0..a3eec44da 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -34,7 +34,7 @@ #include "util/platform.hpp" #include "window/Camera.hpp" #include "window/input.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "world/Level.hpp" #include "Mainloop.hpp" #include "ServerMainloop.hpp" diff --git a/src/engine/Mainloop.cpp b/src/engine/Mainloop.cpp index ecfd17bca..547fc79cb 100644 --- a/src/engine/Mainloop.cpp +++ b/src/engine/Mainloop.cpp @@ -4,7 +4,7 @@ #include "debug/Logger.hpp" #include "frontend/screens/MenuScreen.hpp" #include "frontend/screens/LevelScreen.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "world/Level.hpp" static debug::Logger logger("mainloop"); diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 08dfcf401..e853b6da5 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -41,7 +41,7 @@ #include "voxels/GlobalChunks.hpp" #include "window/Camera.hpp" #include "window/input.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "world/Level.hpp" #include "world/World.hpp" #include "debug/Logger.hpp" diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index ca80ed11e..6bbbd6676 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -29,7 +29,7 @@ #include "util/stringutil.hpp" #include "voxels/Chunks.hpp" #include "window/Camera.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "world/Level.hpp" #include "world/World.hpp" diff --git a/src/frontend/screens/MenuScreen.cpp b/src/frontend/screens/MenuScreen.cpp index be114ed3c..6420966ac 100644 --- a/src/frontend/screens/MenuScreen.cpp +++ b/src/frontend/screens/MenuScreen.cpp @@ -8,7 +8,7 @@ #include "graphics/core/Texture.hpp" #include "assets/Assets.hpp" #include "maths/UVRegion.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "window/Camera.hpp" #include "engine/Engine.hpp" diff --git a/src/graphics/core/DrawContext.cpp b/src/graphics/core/DrawContext.cpp index fc37fd46d..67814de02 100644 --- a/src/graphics/core/DrawContext.cpp +++ b/src/graphics/core/DrawContext.cpp @@ -6,7 +6,7 @@ #include "Batch2D.hpp" #include "Framebuffer.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" static void set_blend_mode(BlendMode mode) { switch (mode) { diff --git a/src/graphics/render/BlocksPreview.cpp b/src/graphics/render/BlocksPreview.cpp index 9a1bf97dd..971748436 100644 --- a/src/graphics/render/BlocksPreview.cpp +++ b/src/graphics/render/BlocksPreview.cpp @@ -6,7 +6,7 @@ #include "frontend/ContentGfxCache.hpp" #include "voxels/Block.hpp" #include "window/Camera.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "graphics/core/Atlas.hpp" #include "graphics/core/Batch3D.hpp" #include "graphics/core/Framebuffer.hpp" diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index eb90feef8..64bbf71db 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -7,7 +7,7 @@ #include "graphics/core/Cubemap.hpp" #include "graphics/core/Framebuffer.hpp" #include "graphics/core/DrawContext.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "window/Camera.hpp" #include "maths/UVRegion.hpp" diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index e8511fa5a..a3cfb1985 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -27,7 +27,7 @@ #include "voxels/Block.hpp" #include "voxels/Chunk.hpp" #include "voxels/Chunks.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "world/Level.hpp" #include "world/LevelEvents.hpp" #include "world/World.hpp" diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index 0cea8a663..828c0a8c8 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -20,7 +20,7 @@ #include "graphics/core/Shader.hpp" #include "gui_util.hpp" #include "window/Camera.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "window/input.hpp" #include @@ -166,7 +166,7 @@ void GUI::actMouse(float delta, const CursorState& cursor) { } if (hover) { - for (Mousecode code : MOUSECODES_ALL) { + for (Mousecode code : mousecodes_all) { if (input.jclicked(code)) { hover->clicked(code); } diff --git a/src/graphics/ui/elements/ModelViewer.cpp b/src/graphics/ui/elements/ModelViewer.cpp index acc8170c1..4dd514ab9 100644 --- a/src/graphics/ui/elements/ModelViewer.cpp +++ b/src/graphics/ui/elements/ModelViewer.cpp @@ -10,7 +10,7 @@ #include "graphics/core/Shader.hpp" #include "graphics/core/Framebuffer.hpp" #include "graphics/core/DrawContext.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "../GUI.hpp" // TODO: remove diff --git a/src/graphics/ui/elements/TextBox.cpp b/src/graphics/ui/elements/TextBox.cpp index 0ed758823..fbd4b3d29 100644 --- a/src/graphics/ui/elements/TextBox.cpp +++ b/src/graphics/ui/elements/TextBox.cpp @@ -16,7 +16,7 @@ #include "graphics/core/Font.hpp" #include "graphics/ui/markdown.hpp" #include "util/stringutil.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "devtools/actions.hpp" #include "../markdown.hpp" diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index df471c36d..f69049d79 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -23,7 +23,7 @@ #include "voxels/Chunks.hpp" #include "voxels/voxel.hpp" #include "window/Camera.hpp" -#include "window/Window.hpp" +#include "window/window.hpp" #include "window/input.hpp" #include "world/Level.hpp" diff --git a/src/window/detail/SDLWindow.cpp b/src/window/detail/SDLWindow.cpp deleted file mode 100644 index f6f4366a7..000000000 --- a/src/window/detail/SDLWindow.cpp +++ /dev/null @@ -1,716 +0,0 @@ -#include "window/Window.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "debug/Logger.hpp" -#include "graphics/core/ImageData.hpp" -#include "graphics/core/Texture.hpp" -#include "settings.hpp" -#include "util/platform.hpp" -#include "window/input.hpp" - -static debug::Logger logger("window"); - -static std::unordered_set supported_gl_extensions; - -static void init_gl_extensions_list() { - GLint numExtensions = 0; - glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); - - for (GLint i = 0; i < numExtensions; ++i) { - const char *ext = reinterpret_cast(glGetStringi(GL_EXTENSIONS, i)); - if (ext) { - supported_gl_extensions.insert(ext); - } - } -} - -static bool is_gl_extension_supported(const char *extension) { - if (!extension || !*extension) { - return false; - } - return supported_gl_extensions.find(extension) != supported_gl_extensions.end(); -} - -static const char* gl_error_name(int error) { - switch (error) { - case GL_DEBUG_TYPE_ERROR: return "ERROR"; - case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "DEPRECATED_BEHAVIOR"; - case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "UNDEFINED_BEHAVIOR"; - case GL_DEBUG_TYPE_PORTABILITY: return "PORTABILITY"; - case GL_DEBUG_TYPE_PERFORMANCE: return "PERFORMANCE"; - case GL_DEBUG_TYPE_OTHER: return "OTHER"; - } - return "UNKNOWN"; -} - -static const char* gl_severity_name(int severity) { - switch (severity) { - case GL_DEBUG_SEVERITY_LOW: return "LOW"; - case GL_DEBUG_SEVERITY_MEDIUM: return "MEDIUM"; - case GL_DEBUG_SEVERITY_HIGH: return "HIGH"; - case GL_DEBUG_SEVERITY_NOTIFICATION: return "NOTIFICATION"; - } - return "UNKNOWN"; -} - -static void GLAPIENTRY gl_message_callback( - GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar* message, - const void* userParam -) { - if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) { - return; - } - if (!ENGINE_DEBUG_BUILD && severity != GL_DEBUG_SEVERITY_HIGH) { - return; - } - logger.warning() << "GL:" << gl_error_name(type) << ":" - << gl_severity_name(severity) << ": " << message; -} - -static bool initialize_gl(int width, int height) { - glewExperimental = GL_TRUE; - - GLenum glewErr = glewInit(); - if (glewErr != GLEW_OK) { - if (glewErr == GLEW_ERROR_NO_GLX_DISPLAY) { - // see issue #240 - logger.warning() - << "glewInit() returned GLEW_ERROR_NO_GLX_DISPLAY; ignored"; - } else { - logger.error() << "failed to initialize GLEW:\n" - << glewGetErrorString(glewErr); - return true; - } - } - -#ifndef __APPLE__ - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(gl_message_callback, 0); -#endif - - glViewport(0, 0, width, height); - glClearColor(0.0f, 0.0f, 0.0f, 1); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - GLint maxTextureSize[1] {static_cast(Texture::MAX_RESOLUTION)}; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize); - if (maxTextureSize[0] > 0) { - Texture::MAX_RESOLUTION = maxTextureSize[0]; - logger.info() << "max texture size is " << Texture::MAX_RESOLUTION; - } - - const GLubyte* vendor = glGetString(GL_VENDOR); - const GLubyte* renderer = glGetString(GL_RENDERER); - logger.info() << "GL Vendor: " << reinterpret_cast(vendor); - logger.info() << "GL Renderer: " << reinterpret_cast(renderer); - logger.info() << "SDL: " << SDL_GetVersion(); - return false; -} - - -inline constexpr short KEYS_BUFFER_SIZE = 1036; -inline constexpr short MOUSE_KEYS_OFFSET = 1024; - -class SDLInput : public Input { -public: - int scroll = 0; - uint currentFrame = 0; - uint frames[KEYS_BUFFER_SIZE] {}; - std::vector codepoints; - std::vector pressedKeys; - Bindings bindings; - bool keys[KEYS_BUFFER_SIZE] {}; - std::unordered_map> keyCallbacks; - - SDLInput(SDL_Window* window) - : window(window) { - } - - void pollEvents() override { - delta.x = 0.0f; - delta.y = 0.0f; - scroll = 0; - codepoints.clear(); - pressedKeys.clear(); - - SDL_Event event; - - while(SDL_PollEvent(&event)) - { - switch (event.type) { - case SDL_EVENT_QUIT: - // window->setShouldClose(true); - break; - case SDL_EVENT_KEY_DOWN: - break; - case SDL_EVENT_KEY_UP: - break; - case SDL_EVENT_MOUSE_BUTTON_DOWN: - break; - case SDL_EVENT_MOUSE_MOTION: - break; - } - // for (auto& [_, binding] : bindings.getAll()) { - // if (!binding.enabled) { - // binding.state = false; - // continue; - // } - // binding.justChanged = false; - - // bool newstate = false; - // switch (binding.type) { - // case InputType::KEYBOARD: - // newstate = pressed(static_cast(binding.code)); - // break; - // case InputType::MOUSE: - // newstate = clicked(static_cast(binding.code)); - // break; - // } - - // if (newstate) { - // if (!binding.state) { - // binding.state = true; - // binding.justChanged = true; - // binding.onactived.notify(); - // } - // } else { - // if (binding.state) { - // binding.state = false; - // binding.justChanged = true; - // } - // } - } - } - - void onKeyCallback(int key, bool pressed) { - bool prevPressed = keys[key]; - keys[key] = pressed; - frames[key] = currentFrame; - if (pressed && !prevPressed) { - const auto& callbacks = keyCallbacks.find(static_cast(key)); - if (callbacks != keyCallbacks.end()) { - callbacks->second.notify(); - } - } - if (pressed && key < MOUSE_KEYS_OFFSET) { - pressedKeys.push_back(static_cast(key)); - } - } - - void onMouseCallback(int button, bool pressed) { - int key = button + MOUSE_KEYS_OFFSET; - onKeyCallback(key, pressed); - } - - const char* getClipboardText() const override { - /*todo free*/ - return SDL_GetClipboardText(); - } - - void setClipboardText(const char* text) override { - SDL_SetClipboardText(text); - } - - int getScroll() override { - return scroll; - } - - bool pressed(Keycode key) const override { - int keycode = static_cast(key); - if (keycode < 0 || keycode >= KEYS_BUFFER_SIZE) { - return false; - } - return keys[keycode]; - } - bool jpressed(Keycode keycode) const override { - return pressed(keycode) && - frames[static_cast(keycode)] == currentFrame; - } - - bool clicked(Mousecode code) const override { - return pressed( - static_cast(MOUSE_KEYS_OFFSET + static_cast(code)) - ); - } - bool jclicked(Mousecode code) const override { - return clicked(code) && - frames[static_cast(code) + MOUSE_KEYS_OFFSET] == - currentFrame; - } - - CursorState getCursor() const override { - return {isCursorLocked(), cursor, delta}; - } - - bool isCursorLocked() const override { - return cursorLocked; - } - - void toggleCursor() override { - cursorDrag = false; - SDL_SetWindowMouseGrab(window, cursorLocked); - cursorLocked = !cursorLocked; - } - - void setCursorPosition(double xpos, double ypos) { - if (cursorDrag) { - delta.x += xpos - cursor.x; - delta.y += ypos - cursor.y; - } else { - cursorDrag = true; - } - cursor.x = xpos; - cursor.y = ypos; - } - - Bindings& getBindings() override { - return bindings; - } - - const Bindings& getBindings() const override { - return bindings; - } - - ObserverHandler addKeyCallback(Keycode key, KeyCallback callback) override { - return keyCallbacks[key].add(std::move(callback)); - } - - const std::vector& getPressedKeys() const override { - return pressedKeys; - } - - const std::vector& getCodepoints() const override { - return codepoints; - } -private: - SDL_Window* window; - bool cursorLocked = false; - bool cursorDrag = false; - glm::vec2 delta; - glm::vec2 cursor; -}; -static_assert(!std::is_abstract()); - -class WindowSdlImpl final : public Window { -public: - SDLInput& input; - - DisplaySettings* settings; - - WindowSdlImpl( - SDLInput& glfwInput, - SDL_Window* window, - SDL_GLContext context, - DisplaySettings* settings, - int width, - int height - ) - : Window({width, height}), - input(glfwInput), - settings(settings), - window(window), - glcontext(context) { - } - - ~WindowSdlImpl() override { - SDL_GL_DestroyContext(glcontext); - } - - double time() override { - return SDL_GetTicks(); - } - - void swapBuffers() override { - SDL_GL_SwapWindow(window); - resetScissor(); - if (framerate > 0) { - auto elapsedTime = time() - prevSwap; - auto frameTime = 1.0 / framerate; - if (elapsedTime < frameTime) { - platform::sleep( - static_cast((frameTime - elapsedTime) * 1000) - ); - } - } - prevSwap = time(); - } - - bool isMaximized() const override { - return (SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) != 0; - } - - bool isFocused() const override { - Uint32 flags = SDL_GetWindowFlags(window); - return (flags & SDL_WINDOW_INPUT_FOCUS) != 0 || (flags & SDL_WINDOW_MOUSE_FOCUS) != 0; - } - - bool isIconified() const override { - return (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) != 0; - } - - - bool isShouldClose() const override - { - return toClose; - } - - void setShouldClose(bool flag) override - { - toClose = flag; - } - - void setCursor(CursorShape shape) override { - // if (cursor == shape) { - // return; - // } - // cursor = shape; - // // NULL cursor is valid for GLFW - // glfwSetCursor(window, standard_cursors[static_cast(shape)]); - } - - void toggleFullscreen() override { - fullscreen = !fullscreen; - - if (!SDL_SetWindowFullscreen(window, fullscreen)) { - // SDL_Log("Failed to toggle fullscreen: %s", SDL_GetError()); - } - } - - bool isFullscreen() const override { - return fullscreen; - } - - void setIcon(const ImageData* image) override { - if (image == nullptr) { - SDL_SetWindowIcon(window, nullptr); - return; - } - - // Create SDL_Surface from ImageData - SDL_Surface* iconSurface = SDL_CreateSurface( - image->getWidth(), - image->getHeight(), - SDL_PIXELFORMAT_RGBA32 // Adjust format based on your ImageData - ); - - if (!iconSurface) { - // SDL_Log("Failed to create surface for window icon: %s", SDL_GetError()); - return; - } - - memcpy(iconSurface->pixels, image->getData(), - image->getWidth() * image->getHeight() * 4); - - if (!SDL_SetWindowIcon(window, iconSurface)) { - // SDL_Log("Failed to set window icon: %s", SDL_GetError()); - } - - SDL_DestroySurface(iconSurface); - } - - - void setSize(int width, int height) { - glViewport(0, 0, width, height); - size = {width, height}; - - if (!isFullscreen() && !isMaximized()) { - settings->width.set(width); - settings->height.set(height); - } - } - - void pushScissor(glm::vec4 area) override { - if (scissorStack.empty()) { - glEnable(GL_SCISSOR_TEST); - } - scissorStack.push(scissorArea); - - area.z += glm::ceil(area.x); - area.w += glm::ceil(area.y); - - area.x = glm::max(area.x, scissorArea.x); - area.y = glm::max(area.y, scissorArea.y); - - area.z = glm::min(area.z, scissorArea.z); - area.w = glm::min(area.w, scissorArea.w); - - if (area.z < 0.0f || area.w < 0.0f) { - glScissor(0, 0, 0, 0); - } else { - glScissor( - area.x, - size.y - area.w, - std::max(0, static_cast(glm::ceil(area.z - area.x))), - std::max(0, static_cast(glm::ceil(area.w - area.y))) - ); - } - scissorArea = area; - } - - void resetScissor() override { - scissorArea = glm::vec4(0.0f, 0.0f, size.x, size.y); - scissorStack = std::stack(); - glDisable(GL_SCISSOR_TEST); - } - - void popScissor() override { - if (scissorStack.empty()) { - logger.warning() << "extra Window::popScissor call"; - return; - } - glm::vec4 area = scissorStack.top(); - scissorStack.pop(); - if (area.z < 0.0f || area.w < 0.0f) { - glScissor(0, 0, 0, 0); - } else { - glScissor( - area.x, - size.y - area.w, - std::max(0, static_cast(area.z - area.x)), - std::max(0, static_cast(area.w - area.y)) - ); - } - if (scissorStack.empty()) { - glDisable(GL_SCISSOR_TEST); - } - scissorArea = area; - } - - std::unique_ptr takeScreenshot() override { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - auto data = std::make_unique(size.x * size.y * 3); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(0, 0, size.x, size.y, GL_RGB, GL_UNSIGNED_BYTE, data.get()); - return std::make_unique( - ImageFormat::rgb888, size.x, size.y, data.release() - ); - } - - void setFramerate(int framerate) override { - if ((framerate != -1) != (this->framerate != -1)) { - SDL_GL_SetSwapInterval(framerate == -1); - } - this->framerate = framerate; - } - -private: - SDL_Window* window; - SDL_GLContext glcontext; - CursorShape cursor = CursorShape::ARROW; - bool fullscreen = false; - bool toClose = false; - int framerate = -1; - std::stack scissorStack; - glm::vec4 scissorArea; - double prevSwap = 0.0; - int posX = 0; - int posY = 0; -}; - -// static void mouse_button_callback(GLFWwindow* window, int button, int action, int) { -// auto handler = static_cast(glfwGetWindowUserPointer(window)); -// handler->input.onMouseCallback(button, action == GLFW_PRESS); -// } - -// static void character_callback(GLFWwindow* window, unsigned int codepoint) { -// auto handler = static_cast(glfwGetWindowUserPointer(window)); -// handler->input.codepoints.push_back(codepoint); -// } - -// static void key_callback( -// GLFWwindow* window, int key, int /*scancode*/, int action, int /*mode*/ -// ) { -// auto handler = static_cast(glfwGetWindowUserPointer(window)); -// auto& input = handler->input; -// if (key == GLFW_KEY_UNKNOWN) { -// return; -// } -// if (action == GLFW_PRESS) { -// input.onKeyCallback(key, true); - -// } else if (action == GLFW_RELEASE) { -// input.onKeyCallback(key, false); -// } else if (action == GLFW_REPEAT) { -// input.onKeyCallback(key, true); -// } -// } - -// static void window_size_callback(GLFWwindow* window, int width, int height) { -// auto handler = static_cast(glfwGetWindowUserPointer(window)); -// if (width && height) { -// handler->setSize(width, height); -// } -// handler->resetScissor(); -// } - -// static void scroll_callback(GLFWwindow* window, double, double yoffset) { -// auto handler = static_cast(glfwGetWindowUserPointer(window)); -// handler->input.scroll += yoffset; -// } - -// static void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) { -// auto handler = static_cast(glfwGetWindowUserPointer(window)); -// handler->input.setCursorPosition(xpos, ypos); -// } - -// static void iconify_callback(GLFWwindow* window, int iconified) { -// auto handler = static_cast(glfwGetWindowUserPointer(window)); -// if (handler->isFullscreen() && iconified == 0) { -// GLFWmonitor* monitor = glfwGetPrimaryMonitor(); -// const GLFWvidmode* mode = glfwGetVideoMode(monitor); -// glfwSetWindowMonitor( -// window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate -// ); -// } -// } - -// static void create_standard_cursors() { -// for (int i = 0; i <= static_cast(CursorShape::LAST); i++) { -// int cursor = GLFW_ARROW_CURSOR + i; -// // GLFW 3.3 does not support some cursors -// if (GLFW_VERSION_MAJOR <= 3 && GLFW_VERSION_MINOR <= 3 && -// cursor > GLFW_VRESIZE_CURSOR) { -// break; -// } -// standard_cursors[i] = glfwCreateStandardCursor(cursor); -// } -// } - -// static void setup_callbacks(GLFWwindow* window) { -// glfwSetKeyCallback(window, key_callback); -// glfwSetMouseButtonCallback(window, mouse_button_callback); -// glfwSetCursorPosCallback(window, cursor_pos_callback); -// glfwSetWindowSizeCallback(window, window_size_callback); -// glfwSetCharCallback(window, character_callback); -// glfwSetScrollCallback(window, scroll_callback); -// glfwSetWindowIconifyCallback(window, iconify_callback); -// } - -std::tuple< - std::unique_ptr, - std::unique_ptr -> Window::initialize(DisplaySettings* settings, std::string title) { - int width = settings->width.get(); - int height = settings->height.get(); - - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS)) { - logger.error() << "failed to initialize SDL"; - return {nullptr, nullptr}; - } - - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); -// #if GLFW_VERSION_MAJOR >= 3 && GLFW_VERSION_MINOR >= 4 -// // see issue #465 -// // glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GL_FALSE); -// #endif -#ifdef __APPLE__ - // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - // glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE); -#else - // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); -#endif - // glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); - // glfwWindowHint(GLFW_SAMPLES, settings->samples.get()); - - auto window = SDL_CreateWindow(title.c_str(), width, height, SDL_WINDOW_OPENGL); - if (window == nullptr) { - logger.error() << "failed to create GLFW window"; - return {nullptr, nullptr}; - } - SDL_GLContext glcontext = SDL_GL_CreateContext(window); - SDL_GL_MakeCurrent(window, glcontext); - - glewExperimental = GL_TRUE; - - GLenum glewErr = glewInit(); - if (glewErr != GLEW_OK) { - if (glewErr == GLEW_ERROR_NO_GLX_DISPLAY) { - // see issue #240 - logger.warning() - << "glewInit() returned GLEW_ERROR_NO_GLX_DISPLAY; ignored"; - } else { - logger.error() << "failed to initialize GLEW:\n" - << glewGetErrorString(glewErr); - SDL_DestroyWindow(window); - return {nullptr, nullptr}; - } - } - - init_gl_extensions_list(); - - #ifndef __APPLE__ - if (is_gl_extension_supported("GL_KHR_debug")) { - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(gl_message_callback, nullptr); - } - #endif - - glViewport(0, 0, width, height); - glClearColor(0.0f, 0.0f, 0.0f, 1); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - GLint maxTextureSize[1] {static_cast(Texture::MAX_RESOLUTION)}; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize); - if (maxTextureSize[0] > 0) { - Texture::MAX_RESOLUTION = maxTextureSize[0]; - logger.info() << "max texture size is " << Texture::MAX_RESOLUTION; - } - // setup_callbacks(window); - - SDL_GL_SetSwapInterval(1); - input_util::initialize(); - // create_standard_cursors(); - - glm::vec2 scale; - // SDL_SetDisplayContentScale(SDL_GetPrimaryDisplay(), &scale.x, &scale.y); - logger.info() << "monitor content scale: " << scale.x << "x" << scale.y; - - if (initialize_gl(width, height)) { - return {nullptr, nullptr}; - } - - auto inputPtr = std::make_unique(window); - auto windowPtr = std::make_unique( - *inputPtr, window, glcontext, settings, width, height - ); - // glfwSetWindowUserPointer(window, windowPtr.get()); - return {std::move(windowPtr), std::move(inputPtr)}; -} - -void display::clear() { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -} - -void display::clearDepth() { - glClear(GL_DEPTH_BUFFER_BIT); -} - -void display::setBgColor(glm::vec3 color) { - glClearColor(color.r, color.g, color.b, 1.0f); -} - -void display::setBgColor(glm::vec4 color) { - glClearColor(color.r, color.g, color.b, color.a); -} diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp new file mode 100644 index 000000000..826ad8df6 --- /dev/null +++ b/src/window/detail/input_sdl.cpp @@ -0,0 +1,125 @@ +#include "window/detail/input_sdl.hpp" + +#include +#include +#include +#include +#include + +#include + +#include "debug/Logger.hpp" + +static debug::Logger logger("input"); + +std::string input_util::to_string(Keycode code) { + return {}; +} + +input_sdl::input_sdl() { +} + +void input_sdl::pollEvents() { + // delta.x = 0.0f; + // delta.y = 0.0f; + // scroll = 0; + // currentFrame++; + // codepoints.clear(); + // pressedKeys.clear(); + // glfwPollEvents(); + + // for (auto& [_, binding] : bindings.getAll()) { + // if (!binding.enabled) { + // binding.state = false; + // continue; + // } + // binding.justChanged = false; + + // bool newstate = false; + // switch (binding.type) { + // case InputType::KEYBOARD: + // newstate = pressed(static_cast(binding.code)); + // break; + // case InputType::MOUSE: + // newstate = clicked(static_cast(binding.code)); + // break; + // } + + // if (newstate) { + // if (!binding.state) { + // binding.state = true; + // binding.justChanged = true; + // binding.onactived.notify(); + // } + // } else { + // if (binding.state) { + // binding.state = false; + // binding.justChanged = true; + // } + // } + // } +} + +const char* input_sdl::getClipboardText() const { + return SDL_GetClipboardText(); +} + +void input_sdl::setClipboardText(const char* text) { + SDL_SetClipboardText(text); +} + +int input_sdl::getScroll() { + return {}; +} + +bool input_sdl::pressed(Keycode key) const { + return {}; +} +bool input_sdl::jpressed(Keycode keycode) const { + return {}; +} + +bool input_sdl::clicked(Mousecode code) const { + return {}; +} +bool input_sdl::jclicked(Mousecode code) const { + return {}; +} + +CursorState input_sdl::getCursor() const { + return {isCursorLocked(), {}, {}}; +} + +bool input_sdl::isCursorLocked() const { + return {}; +} + +void input_sdl::toggleCursor() { + // cursorDrag = false; + // if (cursorLocked) { + // glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + // } else { + // glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + // } + // cursorLocked = !cursorLocked; +} + +Bindings& input_sdl::getBindings() { + return bindings; +} + +const Bindings& input_sdl::getBindings() const { + return bindings; +} + +ObserverHandler input_sdl::addKeyCallback(Keycode key, KeyCallback callback) { + return {}; +} + +const std::vector& input_sdl::getPressedKeys() const { + return pressedKeys; +} + +const std::vector& input_sdl::getCodepoints() const { + return codepoints; +} diff --git a/src/window/detail/input_sdl.hpp b/src/window/detail/input_sdl.hpp new file mode 100644 index 000000000..3d9caa6f0 --- /dev/null +++ b/src/window/detail/input_sdl.hpp @@ -0,0 +1,39 @@ +#include "window/input.hpp" + +struct SDL_Window; + +class input_sdl final : public Input { +public: + input_sdl(); + + void pollEvents() override; + + const char* getClipboardText() const override; + void setClipboardText(const char* str) override; + + int getScroll() override; + + bool pressed(Keycode keycode) const override; + bool jpressed(Keycode keycode) const override; + + bool clicked(Mousecode mousecode) const override; + bool jclicked(Mousecode mousecode) const override; + + CursorState getCursor() const override; + + bool isCursorLocked() const override; + void toggleCursor() override; + + Bindings& getBindings() override; + + const Bindings& getBindings() const override; + + ObserverHandler addKeyCallback(Keycode key, KeyCallback callback) override; + + const std::vector& getPressedKeys() const override; + const std::vector& getCodepoints() const override; +private: + Bindings bindings; + std::vector codepoints; + std::vector pressedKeys; +}; \ No newline at end of file diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp new file mode 100644 index 000000000..ffa7c8962 --- /dev/null +++ b/src/window/detail/window_sdl.cpp @@ -0,0 +1,290 @@ +#include "window/detail/window_sdl.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "debug/Logger.hpp" +#include "graphics/core/ImageData.hpp" +#include "graphics/core/Texture.hpp" +#include "settings.hpp" +#include "window/detail/input_sdl.hpp" + +static debug::Logger logger("window"); + +static std::unordered_set supported_gl_extensions; +static void init_gl_extensions_list() { + GLint numExtensions = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); + + for (GLint i = 0; i < numExtensions; ++i) { + const char *ext = + reinterpret_cast(glGetStringi(GL_EXTENSIONS, i)); + if (ext) { + supported_gl_extensions.insert(ext); + } + } +} + +static bool is_gl_extension_supported(const char *extension) { + if (!extension || !*extension) { + return false; + } + return supported_gl_extensions.find(extension) != + supported_gl_extensions.end(); +} + +static const char *gl_error_name(int error) { + switch (error) { + case GL_DEBUG_TYPE_ERROR: + return "ERROR"; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + return "DEPRECATED_BEHAVIOR"; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + return "UNDEFINED_BEHAVIOR"; + case GL_DEBUG_TYPE_PORTABILITY: + return "PORTABILITY"; + case GL_DEBUG_TYPE_PERFORMANCE: + return "PERFORMANCE"; + case GL_DEBUG_TYPE_OTHER: + return "OTHER"; + } + return "UNKNOWN"; +} + +static const char *gl_severity_name(int severity) { + switch (severity) { + case GL_DEBUG_SEVERITY_LOW: + return "LOW"; + case GL_DEBUG_SEVERITY_MEDIUM: + return "MEDIUM"; + case GL_DEBUG_SEVERITY_HIGH: + return "HIGH"; + case GL_DEBUG_SEVERITY_NOTIFICATION: + return "NOTIFICATION"; + } + return "UNKNOWN"; +} + +static void GLAPIENTRY gl_message_callback( + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar *message, + const void *userParam +) { + if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) { + return; + } + if (!ENGINE_DEBUG_BUILD && severity != GL_DEBUG_SEVERITY_HIGH) { + return; + } + logger.warning() << "GL:" << gl_error_name(type) << ":" + << gl_severity_name(severity) << ": " << message; +} + +static bool initialize_gl(int width, int height) { + glewExperimental = GL_TRUE; + + GLenum glewErr = glewInit(); + if (glewErr != GLEW_OK) { + if (glewErr == GLEW_ERROR_NO_GLX_DISPLAY) { + // see issue #240 + logger.warning() + << "glewInit() returned GLEW_ERROR_NO_GLX_DISPLAY; ignored"; + } else { + logger.error() << "failed to initialize GLEW:\n" + << glewGetErrorString(glewErr); + return true; + } + } + +#ifndef __APPLE__ + glEnable(GL_DEBUG_OUTPUT); + // glDebugMessageCallback(gl_message_callback, 0); +#endif + + glViewport(0, 0, width, height); + glClearColor(0.0f, 0.0f, 0.0f, 1); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + GLint maxTextureSize[1] {static_cast(Texture::MAX_RESOLUTION)}; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize); + if (maxTextureSize[0] > 0) { + Texture::MAX_RESOLUTION = maxTextureSize[0]; + logger.info() << "max texture size is " << Texture::MAX_RESOLUTION; + } + + const GLubyte *vendor = glGetString(GL_VENDOR); + const GLubyte *renderer = glGetString(GL_RENDERER); + logger.info() << "GL Vendor: " << reinterpret_cast(vendor); + logger.info() << "GL Renderer: " + << reinterpret_cast(renderer); + logger.info() << "SDL: " << SDL_GetVersion(); + return false; +} + +window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS)) { + logger.error() << "failed to initialize SDL: " << SDL_GetError(); + isSuccessfull = false; + return; + } + + SDL_WindowFlags flags = SDL_WINDOW_OPENGL; + + if (settings->fullscreen.get()) { + flags |= SDL_WINDOW_FULLSCREEN; + } + + window = SDL_CreateWindow( + title.c_str(), settings->width.get(), settings->height.get(), flags + ); + if (!window) { + logger.error() << "failed to create SDL Window: " << SDL_GetError(); + isSuccessfull = false; + return; + } + context = SDL_GL_CreateContext(window); + if (!context) { + logger.error() << "failed to create GL context: " << SDL_GetError(); + isSuccessfull = false; + return; + } +} +window_sdl::~window_sdl() { + SDL_DestroyWindow(window); + if (!SDL_GL_DestroyContext(context)) { + logger.error() << "Cant destroy gl context: " << SDL_GetError(); + } +} + +void window_sdl::swapBuffers() const noexcept { + if (!SDL_GL_SwapWindow(window)) [[unlikely]] { + logger.error() << "Cant swap buffer: " << SDL_GetError(); + } +} +bool window_sdl::isMaximized() const { + return maximized; +} +bool window_sdl::isFocused() const { + return focused; +} +bool window_sdl::isIconified() const { + return iconified; +} + +bool window_sdl::isShouldClose() const { + return toClose; +} +void window_sdl::setShouldClose(bool flag) { + toClose = flag; +} + +void window_sdl::setCursor(CursorShape shape) { +} +void window_sdl::toggleFullscreen() { + fullscreen = !fullscreen; + if (SDL_SetWindowFullscreen(window, fullscreen)) { + logger.error() << "Cant toggle fullscreen window: " << SDL_GetError(); + } +} +bool window_sdl::isFullscreen() const { + return fullscreen; +} + +void window_sdl::setIcon(const ImageData *image) { + if (image == nullptr) { + logger.error() << "Image is nullptr"; + return; + } + + SDL_Surface *iconSurface = SDL_CreateSurface( + image->getWidth(), image->getHeight(), SDL_PIXELFORMAT_RGBA32 + ); + + if (!iconSurface) { + logger.error() << "Failed to create surface for app icon: " + << SDL_GetError(); + return; + } + + memcpy( + iconSurface->pixels, + image->getData(), + image->getWidth() * image->getHeight() * 4 + ); + + if (!SDL_SetWindowIcon(window, iconSurface)) { + logger.error() << "Failed to set icon: " << SDL_GetError(); + } + + SDL_DestroySurface(iconSurface); +} + +void window_sdl::pushScissor(glm::vec4 area) { +} +void window_sdl::popScissor() { +} +void window_sdl::resetScissor() { +} + +double window_sdl::time() { + return static_cast(SDL_GetTicks()) / 1000; +} + +void window_sdl::setFramerate(int framerate) { + /*todo*/ + if (!SDL_GL_SetSwapInterval(framerate)) { + logger.error() << "Failed to set framerate: " + << SDL_GetError(); +} +} + +// todo: move somewhere +std::unique_ptr window_sdl::takeScreenshot() { + return {}; +} + +[[nodiscard]] bool window_sdl::isValid() const { + return isSuccessfull; +} + +std::tuple, std::unique_ptr> Window::initialize( + DisplaySettings *settings, std::string title +) { + auto window = std::make_unique(settings, title); + if (!window->isValid()) { + return {nullptr, nullptr}; + } + auto input = std::make_unique(); + + return {std::move(window), std::move(input)}; +} + +void display::clear() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void display::clearDepth() { + glClear(GL_DEPTH_BUFFER_BIT); +} + +void display::setBgColor(glm::vec3 color) { + glClearColor(color.r, color.g, color.b, 1.0f); +} + +void display::setBgColor(glm::vec4 color) { + glClearColor(color.r, color.g, color.b, color.a); +} diff --git a/src/window/detail/window_sdl.hpp b/src/window/detail/window_sdl.hpp new file mode 100644 index 000000000..368e2698f --- /dev/null +++ b/src/window/detail/window_sdl.hpp @@ -0,0 +1,51 @@ +#include +#include "window/window.hpp" + +struct SDL_Window; + +class window_sdl final : public Window { +public: + window_sdl(DisplaySettings *settings, std::string title) noexcept; + ~window_sdl(); + window_sdl(const window_sdl &) = delete; + window_sdl(window_sdl &&) = default; + window_sdl &operator=(const window_sdl &) = delete; + window_sdl &operator=(window_sdl &&) = default; + + void swapBuffers() const noexcept override; + bool isMaximized() const override; + bool isFocused() const override; + bool isIconified() const override; + + bool isShouldClose() const override; + void setShouldClose(bool flag) override; + + void setCursor(CursorShape shape) override; + void toggleFullscreen() override; + bool isFullscreen() const override; + + void setIcon(const ImageData *image) override; + + void pushScissor(glm::vec4 area) override; + void popScissor() override; + void resetScissor() override; + + double time() override; + + void setFramerate(int framerate) override; + + // todo: move somewhere + std::unique_ptr takeScreenshot() override; + + [[nodiscard]] bool isValid() const override; +private: + bool isSuccessfull = true; + bool maximized = false; + bool focused = false; + bool iconified = false; + bool toClose = false; + bool fullscreen = false; + + SDL_Window *window; + SDL_GLContext context; +}; \ No newline at end of file diff --git a/src/window/input.cpp b/src/window/input.cpp index f3dbea53c..73bbe6327 100644 --- a/src/window/input.cpp +++ b/src/window/input.cpp @@ -1,79 +1,17 @@ -#include "input.hpp" - -#include - -#include -#include -#include -#include -#include +#include "window/input.hpp" +#include "coders/toml.hpp" #include "debug/Logger.hpp" -#include "data/dv.hpp" #include "util/stringutil.hpp" -#ifdef _WIN32 -#include -#endif // _WIN32 - -static debug::Logger logger("input"); - -static std::unordered_map keycodes { - {"enter", SDLK_RETURN }, - {"space", SDLK_SPACE }, - {"backspace", SDLK_BACKSPACE }, - {"caps-lock", SDLK_CAPSLOCK }, - {"escape", SDLK_ESCAPE }, - {"delete", SDLK_DELETE }, - {"home", SDLK_HOME }, - {"end", SDLK_END }, - {"tab", SDLK_TAB }, - {"insert", SDLK_INSERT }, - {"page-down", SDLK_PAGEDOWN }, - {"page-up", SDLK_PAGEUP }, - {"left-shift", SDLK_LSHIFT }, - {"right-shift", SDLK_RSHIFT }, - {"left-ctrl", SDLK_LCTRL }, - {"right-ctrl", SDLK_RCTRL}, - {"left-alt", SDLK_LALT }, - {"right-alt", SDLK_RALT }, - {"left-super", 0 /*todo*/ }, - {"right-super", 0 /*todo*/ }, - {"grave-accent", SDLK_GRAVE }, - {"left", SDLK_LEFT }, - {"right", SDLK_RIGHT }, - {"down", SDLK_DOWN }, - {"up", SDLK_UP }, -}; -SDL_Event s; -static std::unordered_map mousecodes { - {"left", SDL_BUTTON_LEFT }, - {"right", SDL_BUTTON_RIGHT }, - {"middle", SDL_BUTTON_MIDDLE }, - {"side1", SDL_BUTTON_MASK(4) /*todo*/}, - {"side2", SDL_BUTTON_MASK(5) /*todo*/}, - {"side3", SDL_BUTTON_MASK(6) /*todo*/}, - {"side4", SDL_BUTTON_MASK(7) /*todo*/}, - {"side5", SDL_BUTTON_MASK(8) /*todo*/}, -}; - -static std::unordered_map keynames {}; -static std::unordered_map buttonsnames{}; +debug::Logger logger("input"); std::string input_util::get_name(Mousecode code) { - const auto found = buttonsnames.find(static_cast(code)); - if (found == buttonsnames.end()) { - return "unknown"; - } - return found->second; + return {}; } std::string input_util::get_name(Keycode code) { - const auto found = keynames.find(static_cast(code)); - if (found == keynames.end()) { - return "unknown"; - } - return found->second; + return {}; } void Binding::reset(InputType type, int code) { @@ -90,125 +28,15 @@ void Binding::reset(Mousecode code) { } void input_util::initialize() { - for (std::uint32_t i = 0; i <= 9; i++) { - keycodes[std::to_string(i)] = SDLK_0 + i; - } - for (std::uint32_t i = 0; i < 25; i++) { - keycodes["f" + std::to_string(i + 1)] = SDLK_F1 + i; - } - for (char i = 'a'; i <= 'z'; i++) { - keycodes[std::string({i})] = SDLK_A - 'a' + i; - } - for (const auto& entry : keycodes) { - keynames[entry.second] = entry.first; - } - for (const auto& entry : mousecodes) { - buttonsnames[entry.second] = entry.first; - } + } Keycode input_util::keycode_from(const std::string& name) { - const auto& found = keycodes.find(name); - if (found == keycodes.end()) { - return Keycode::UNKNOWN; - } - return static_cast(found->second); + return {}; } Mousecode input_util::mousecode_from(const std::string& name) { - const auto& found = mousecodes.find(name); - if (found == mousecodes.end()) { - return Mousecode::UNKNOWN; - } - return static_cast(found->second); -} - -std::string input_util::to_string(Keycode code) { - SDL_Scancode scancode = static_cast(code); - switch (scancode) { - case SDLK_TAB: - return "Tab"; - case SDL_SCANCODE_LCTRL: - return "Left Ctrl"; - case SDL_SCANCODE_RCTRL: - return "Right Ctrl"; - case SDL_SCANCODE_LALT: - return "Left Alt"; - case SDL_SCANCODE_RALT: - return "Right Alt"; - case SDL_SCANCODE_LSHIFT: - return "Left Shift"; - case SDL_SCANCODE_RSHIFT: - return "Right Shift"; - case SDL_SCANCODE_CAPSLOCK: - return "Caps-Lock"; - case SDL_SCANCODE_SPACE: - return "Space"; - case SDL_SCANCODE_ESCAPE: - return "Esc"; - case SDL_SCANCODE_RETURN: - return "Enter"; - case SDL_SCANCODE_UP: - return "Up"; - case SDL_SCANCODE_DOWN: - return "Down"; - case SDL_SCANCODE_LEFT: - return "Left"; - case SDL_SCANCODE_RIGHT: - return "Right"; - case SDL_SCANCODE_BACKSPACE: - return "Backspace"; - case SDL_SCANCODE_F1: - return "F1"; - case SDL_SCANCODE_F2: - return "F2"; - case SDL_SCANCODE_F3: - return "F3"; - case SDL_SCANCODE_F4: - return "F4"; - case SDL_SCANCODE_F5: - return "F5"; - case SDL_SCANCODE_F6: - return "F6"; - case SDL_SCANCODE_F7: - return "F7"; - case SDL_SCANCODE_F8: - return "F8"; - case SDL_SCANCODE_F9: - return "F9"; - case SDL_SCANCODE_F10: - return "F10"; - case SDL_SCANCODE_F11: - return "F11"; - case SDL_SCANCODE_F12: - return "F12"; - case SDL_SCANCODE_DELETE: - return "Delete"; - case SDL_SCANCODE_HOME: - return "Home"; - case SDL_SCANCODE_END: - return "End"; - case SDL_SCANCODE_LGUI: - return "Left Super"; - case SDL_SCANCODE_RGUI: - return "Right Super"; - case SDL_SCANCODE_PAGEUP: - return "Page Up"; - case SDL_SCANCODE_PAGEDOWN: - return "Page Down"; - case SDL_SCANCODE_INSERT: - return "Insert"; - case SDL_SCANCODE_PRINTSCREEN: - return "Print Screen"; - case SDL_SCANCODE_NUMLOCKCLEAR: - return "Num Lock"; - case SDL_SCANCODE_APPLICATION: - return "Menu"; - case SDL_SCANCODE_PAUSE: - return "Pause"; - default: - return "Unknown"; - } + return {}; } std::string input_util::to_string(Mousecode code) { @@ -224,8 +52,10 @@ std::string input_util::to_string(Mousecode code) { case Mousecode::BUTTON_6: case Mousecode::BUTTON_7: case Mousecode::BUTTON_8: - return "XButton " + std::to_string(static_cast(code) - - static_cast(Mousecode::BUTTON_3)); + return "XButton " + std::to_string( + static_cast(code) - + static_cast(Mousecode::BUTTON_3) + ); default: return "unknown button"; } @@ -259,9 +89,8 @@ void Bindings::read(const dv::value& map, BindType bindType) { type = InputType::MOUSE; code = static_cast(input_util::mousecode_from(codename)); } else { - logger.error() - << "unknown input type: " << prefix << " (binding " - << util::quote(key) << ")"; + logger.error() << "unknown input type: " << prefix + << " (binding " << util::quote(key) << ")"; continue; } if (bindType == BindType::BIND) { @@ -273,8 +102,6 @@ void Bindings::read(const dv::value& map, BindType bindType) { } } -#include "coders/toml.hpp" - std::string Bindings::write() const { auto obj = dv::object(); for (auto& entry : bindings) { diff --git a/src/window/input.hpp b/src/window/input.hpp index 2edfe4c78..c7ffa791b 100644 --- a/src/window/input.hpp +++ b/src/window/input.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -14,8 +15,8 @@ enum class BindType { REBIND = 1 }; -/// @brief Represents glfw3 keycode values. -enum class Keycode : int { +/// @brief Represents sdl scancode values. +enum class Keycode : std::int32_t { SPACE = 32, APOSTROPHE = 39, COMMA = 44, @@ -120,7 +121,7 @@ enum class Mousecode : int { UNKNOWN = -1, }; -inline Mousecode MOUSECODES_ALL[] { +inline Mousecode mousecodes_all[] { Mousecode::BUTTON_1, Mousecode::BUTTON_2, Mousecode::BUTTON_3, @@ -128,7 +129,8 @@ inline Mousecode MOUSECODES_ALL[] { Mousecode::BUTTON_5, Mousecode::BUTTON_6, Mousecode::BUTTON_7, - Mousecode::BUTTON_8}; + Mousecode::BUTTON_8 +}; namespace input_util { void initialize(); diff --git a/src/window/Window.hpp b/src/window/window.hpp similarity index 78% rename from src/window/Window.hpp rename to src/window/window.hpp index 8800be8c8..d19ab5087 100644 --- a/src/window/Window.hpp +++ b/src/window/window.hpp @@ -4,7 +4,6 @@ #include #include "graphics/core/commons.hpp" -#include "typedefs.hpp" class ImageData; class Input; @@ -12,10 +11,8 @@ struct DisplaySettings; class Window { public: - Window(glm::ivec2 size) : size(std::move(size)) {} - virtual ~Window() = default; - virtual void swapBuffers() = 0; + virtual void swapBuffers() const noexcept = 0; virtual bool isMaximized() const = 0; virtual bool isFocused() const = 0; @@ -41,14 +38,14 @@ public: // todo: move somewhere virtual std::unique_ptr takeScreenshot() = 0; - const glm::ivec2& getSize() const { + [[nodiscard]] virtual bool isValid() const = 0; + + virtual const glm::ivec2& getSize() const { return size; } - static std::tuple< - std::unique_ptr, - std::unique_ptr - > initialize(DisplaySettings* settings, std::string title); + static std::tuple, std::unique_ptr> + initialize(DisplaySettings* settings, std::string title); protected: glm::ivec2 size; }; From 2293f6f5fac14e3424d5543da7769c1374ab9b69 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 01:00:22 +0300 Subject: [PATCH 03/41] refactoring --- .gitignore | 1 + src/window/detail/input_sdl.cpp | 4 ++ src/window/detail/window_sdl.cpp | 77 +++++++++++++++++++++++++------- 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index c0b0e1c9d..92e754729 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ Debug/voxel_engine /export /config /out +/compile_commands.json /projects /misc diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp index 826ad8df6..476245b6c 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/input_sdl.cpp @@ -20,6 +20,10 @@ input_sdl::input_sdl() { } void input_sdl::pollEvents() { + /* static */ SDL_Event event; + while (SDL_PollEvent(&event)) { + + } // delta.x = 0.0f; // delta.y = 0.0f; // scroll = 0; diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index ffa7c8962..080caed96 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -1,6 +1,5 @@ #include "window/detail/window_sdl.hpp" -#include #include #include #include @@ -105,13 +104,17 @@ static bool initialize_gl(int width, int height) { } else { logger.error() << "failed to initialize GLEW:\n" << glewGetErrorString(glewErr); - return true; + return false; } } + init_gl_extensions_list(); + #ifndef __APPLE__ - glEnable(GL_DEBUG_OUTPUT); - // glDebugMessageCallback(gl_message_callback, 0); + if (is_gl_extension_supported("GL_KHR_debug")) { + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(gl_message_callback, nullptr); + } #endif glViewport(0, 0, width, height); @@ -132,7 +135,7 @@ static bool initialize_gl(int width, int height) { logger.info() << "GL Renderer: " << reinterpret_cast(renderer); logger.info() << "SDL: " << SDL_GetVersion(); - return false; + return true; } window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { @@ -142,7 +145,7 @@ window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { return; } - SDL_WindowFlags flags = SDL_WINDOW_OPENGL; + SDL_WindowFlags flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; if (settings->fullscreen.get()) { flags |= SDL_WINDOW_FULLSCREEN; @@ -156,17 +159,58 @@ window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { isSuccessfull = false; return; } + + int width = 0; + int height = 0; + + if (!SDL_GetWindowSize(window, &width, &height)) { + logger.error() << "failed to get window size: " << SDL_GetError(); + isSuccessfull = false; + return; + } + + size = {width, height}; + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); +#ifdef __APPLE__ + SDL_GL_SetAttribute( + SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE + ); + SDL_GL_SetAttribute( + SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG + ); + // ?? + // SDL_GL_SetAttribute(SDL_WINDOW_ALLOW_HIGHDPI, false); +#endif + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, settings->samples.get()); + context = SDL_GL_CreateContext(window); if (!context) { logger.error() << "failed to create GL context: " << SDL_GetError(); isSuccessfull = false; return; } + + if (!initialize_gl(width, height)) { + logger.error() << "failed to init GL: " << SDL_GetError(); + return; + } + + if (!SDL_GL_SetSwapInterval(1)) { + logger.error() << "failed to set vsync: " << SDL_GetError(); + isSuccessfull = false; + return; + } } window_sdl::~window_sdl() { - SDL_DestroyWindow(window); - if (!SDL_GL_DestroyContext(context)) { - logger.error() << "Cant destroy gl context: " << SDL_GetError(); + if (window) { + SDL_DestroyWindow(window); + } + if (context) { + if (!SDL_GL_DestroyContext(context)) { + logger.error() << "Cant destroy gl context: " << SDL_GetError(); + } } } @@ -176,13 +220,15 @@ void window_sdl::swapBuffers() const noexcept { } } bool window_sdl::isMaximized() const { - return maximized; + return (SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) != 0; } bool window_sdl::isFocused() const { - return focused; + Uint32 flags = SDL_GetWindowFlags(window); + return (flags & SDL_WINDOW_INPUT_FOCUS) != 0 || + (flags & SDL_WINDOW_MOUSE_FOCUS) != 0; } bool window_sdl::isIconified() const { - return iconified; + return (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) != 0; } bool window_sdl::isShouldClose() const { @@ -246,10 +292,9 @@ double window_sdl::time() { void window_sdl::setFramerate(int framerate) { /*todo*/ - if (!SDL_GL_SetSwapInterval(framerate)) { - logger.error() << "Failed to set framerate: " - << SDL_GetError(); -} + if (!SDL_GL_SetSwapInterval(1)) { + logger.error() << "Failed to set framerate: " << SDL_GetError(); + } } // todo: move somewhere From 433a2eae15b096eb950aa2ee36547c686386862b Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 02:51:05 +0300 Subject: [PATCH 04/41] Fix mouse pos detect --- src/window/detail/input_sdl.cpp | 161 ++++++++++++++++++-------- src/window/detail/input_sdl.hpp | 15 +++ src/window/input.cpp | 54 ++++++--- src/window/input.hpp | 199 +++++++++++++++----------------- 4 files changed, 264 insertions(+), 165 deletions(-) diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp index 476245b6c..4ed84e415 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/input_sdl.cpp @@ -3,65 +3,119 @@ #include #include #include +#include #include #include -#include - #include "debug/Logger.hpp" +#include "window/input.hpp" static debug::Logger logger("input"); std::string input_util::to_string(Keycode code) { - return {}; + int icode_repr = static_cast(code); + const char* name = SDL_GetKeyName(icode_repr); + logger.info() << icode_repr << ": " << name; + return std::string(name); +} + +Keycode input_util::keycode_from(const std::string& name) { + logger.info() << name << ": " << SDL_GetKeyFromName(name.c_str()); + return static_cast(SDL_GetKeyFromName(name.c_str())); } input_sdl::input_sdl() { + input_util::initialize(); } void input_sdl::pollEvents() { - /* static */ SDL_Event event; + delta.x = 0.0f; + delta.y = 0.0f; + scroll = 0; + currentFrame++; + codepoints.clear(); + pressedKeys.clear(); + + bool prevPressed = false; + + static SDL_Event event; while (SDL_PollEvent(&event)) { - + switch (event.type) { + case SDL_EVENT_QUIT: + break; + case SDL_EVENT_KEY_DOWN: + logger.info() << "Keyboard button: " << event.key.key; + if (event.key.key >= keys_buffer_size) { + // Win key return 1073742051 + break; + } + prevPressed = keys[event.key.key]; + keys[event.key.key] = true; + frames[event.key.key] = currentFrame; + if (!prevPressed) { + keyCallbacks[static_cast(event.key.key)].notify(); + } + pressedKeys.push_back(static_cast(event.key.key)); + break; + case SDL_EVENT_KEY_UP: + if (event.key.key >= keys_buffer_size) { + // Win key return 1073742051 + break; + } + keys[event.key.key] = false; + frames[event.key.key] = currentFrame; + break; + case SDL_EVENT_MOUSE_BUTTON_DOWN: + prevPressed = keys[event.button.button + mouse_keys_offset]; + keys[event.button.button + mouse_keys_offset] = true; + frames[event.button.button + mouse_keys_offset] = currentFrame; + if (!prevPressed) { + keyCallbacks[static_cast( + event.button.button + mouse_keys_offset + )] + .notify(); + } + break; + case SDL_EVENT_MOUSE_BUTTON_UP: + keys[event.button.button + mouse_keys_offset] = false; + frames[event.button.button + mouse_keys_offset] = currentFrame; + break; + case SDL_EVENT_MOUSE_MOTION: + cursor = {event.motion.x, event.motion.y}; + delta = {event.motion.xrel, event.motion.yrel}; + break; + } } - // delta.x = 0.0f; - // delta.y = 0.0f; - // scroll = 0; - // currentFrame++; - // codepoints.clear(); - // pressedKeys.clear(); - // glfwPollEvents(); + for (auto& [_, binding] : bindings.getAll()) { + if (!binding.enabled) { + binding.state = false; + continue; + } + binding.justChanged = false; - // for (auto& [_, binding] : bindings.getAll()) { - // if (!binding.enabled) { - // binding.state = false; - // continue; - // } - // binding.justChanged = false; + bool newstate = false; + switch (binding.type) { + case InputType::KEYBOARD: + newstate = pressed(static_cast(binding.code)); + break; + case InputType::MOUSE: + newstate = clicked(static_cast(binding.code)); + break; + } - // bool newstate = false; - // switch (binding.type) { - // case InputType::KEYBOARD: - // newstate = pressed(static_cast(binding.code)); - // break; - // case InputType::MOUSE: - // newstate = clicked(static_cast(binding.code)); - // break; - // } - - // if (newstate) { - // if (!binding.state) { - // binding.state = true; - // binding.justChanged = true; - // binding.onactived.notify(); - // } - // } else { - // if (binding.state) { - // binding.state = false; - // binding.justChanged = true; - // } - // } - // } + if (newstate) { + if (!binding.state) { + binding.state = true; + binding.justChanged = true; + binding.onactived.notify(); + } + } else { + if (binding.state) { + binding.state = false; + binding.justChanged = true; + } + } + } } const char* input_sdl::getClipboardText() const { @@ -73,29 +127,38 @@ void input_sdl::setClipboardText(const char* text) { } int input_sdl::getScroll() { - return {}; + return scroll; } bool input_sdl::pressed(Keycode key) const { - return {}; + int keycode = static_cast(key); + if (keycode < 0 || keycode >= keys_buffer_size) { + return false; + } + if (keys[keycode]) logger.info() << "lol"; + return keys[keycode]; } bool input_sdl::jpressed(Keycode keycode) const { - return {}; + return pressed(keycode) && + frames[static_cast(keycode)] == currentFrame; } bool input_sdl::clicked(Mousecode code) const { - return {}; + return pressed( + static_cast(mouse_keys_offset + static_cast(code)) + ); } bool input_sdl::jclicked(Mousecode code) const { - return {}; + return clicked(code) && + frames[static_cast(code) + mouse_keys_offset] == currentFrame; } CursorState input_sdl::getCursor() const { - return {isCursorLocked(), {}, {}}; + return {isCursorLocked(), cursor, delta}; } bool input_sdl::isCursorLocked() const { - return {}; + return cursorLocked; } void input_sdl::toggleCursor() { @@ -117,7 +180,7 @@ const Bindings& input_sdl::getBindings() const { } ObserverHandler input_sdl::addKeyCallback(Keycode key, KeyCallback callback) { - return {}; + return keyCallbacks[key].add(std::move(callback)); } const std::vector& input_sdl::getPressedKeys() const { diff --git a/src/window/detail/input_sdl.hpp b/src/window/detail/input_sdl.hpp index 3d9caa6f0..9bc5c8415 100644 --- a/src/window/detail/input_sdl.hpp +++ b/src/window/detail/input_sdl.hpp @@ -1,9 +1,15 @@ +#include #include "window/input.hpp" +#include "window/window.hpp" + struct SDL_Window; class input_sdl final : public Input { public: + inline static constexpr short keys_buffer_size = 1036; + inline static constexpr short mouse_keys_offset = 1024; + input_sdl(); void pollEvents() override; @@ -33,7 +39,16 @@ public: const std::vector& getPressedKeys() const override; const std::vector& getCodepoints() const override; private: + glm::vec2 delta; + glm::vec2 cursor; + std::int32_t scroll = 0; + std::uint32_t currentFrame = 0; + std::uint32_t frames[keys_buffer_size] {}; + bool keys[keys_buffer_size] {}; + bool cursorLocked = false; + bool cursorDrag = false; Bindings bindings; std::vector codepoints; std::vector pressedKeys; + std::unordered_map> keyCallbacks; }; \ No newline at end of file diff --git a/src/window/input.cpp b/src/window/input.cpp index 73bbe6327..c774c6209 100644 --- a/src/window/input.cpp +++ b/src/window/input.cpp @@ -4,14 +4,35 @@ #include "debug/Logger.hpp" #include "util/stringutil.hpp" +#include + debug::Logger logger("input"); +static std::unordered_map keynames {}; +static std::unordered_map buttonsnames {}; + +static std::unordered_map mousecodes { + {"left", SDL_BUTTON_LEFT}, + {"right", SDL_BUTTON_RIGHT}, + {"middle", SDL_BUTTON_MIDDLE}, + {"side1", SDL_BUTTON_X1}, + {"side2", SDL_BUTTON_X2}, +}; + std::string input_util::get_name(Mousecode code) { - return {}; + const auto found = buttonsnames.find(static_cast(code)); + if (found == buttonsnames.end()) { + return "unknown"; + } + return found->second; } std::string input_util::get_name(Keycode code) { - return {}; + const auto found = keynames.find(static_cast(code)); + if (found == keynames.end()) { + return "unknown"; + } + return found->second; } void Binding::reset(InputType type, int code) { @@ -27,18 +48,28 @@ void Binding::reset(Mousecode code) { reset(InputType::MOUSE, static_cast(code)); } -void input_util::initialize() { - -} - -Keycode input_util::keycode_from(const std::string& name) { - return {}; -} - Mousecode input_util::mousecode_from(const std::string& name) { return {}; } +void input_util::initialize() { + // for (int i = 0; i <= 9; i++) { + // keycodes[std::to_string(i)] = GLFW_KEY_0 + i; + // } + // for (int i = 0; i < 25; i++) { + // keycodes["f" + std::to_string(i + 1)] = GLFW_KEY_F1 + i; + // } + // for (char i = 'a'; i <= 'z'; i++) { + // keycodes[std::string({i})] = GLFW_KEY_A - 'a' + i; + // } + // for (const auto& entry : keycodes) { + // keynames[entry.second] = entry.first; + // } + for (const auto& entry : mousecodes) { + buttonsnames[entry.second] = entry.first; + } +} + std::string input_util::to_string(Mousecode code) { switch (code) { case Mousecode::BUTTON_1: @@ -49,9 +80,6 @@ std::string input_util::to_string(Mousecode code) { return "MMB"; case Mousecode::BUTTON_4: case Mousecode::BUTTON_5: - case Mousecode::BUTTON_6: - case Mousecode::BUTTON_7: - case Mousecode::BUTTON_8: return "XButton " + std::to_string( static_cast(code) - static_cast(Mousecode::BUTTON_3) diff --git a/src/window/input.hpp b/src/window/input.hpp index c7ffa791b..a3b21f6ba 100644 --- a/src/window/input.hpp +++ b/src/window/input.hpp @@ -1,123 +1,118 @@ #pragma once #include -#include #include +#include #include "util/HandlersList.hpp" + namespace dv { class value; } -enum class BindType { - BIND = 0, - REBIND = 1 -}; +enum class BindType { BIND = 0, REBIND = 1 }; /// @brief Represents sdl scancode values. enum class Keycode : std::int32_t { - SPACE = 32, - APOSTROPHE = 39, - COMMA = 44, - MINUS = 45, - PERIOD = 46, - SLASH = 47, - NUM_0 = 48, - NUM_1 = 49, - NUM_2 = 50, - NUM_3 = 51, - NUM_4 = 52, - NUM_5 = 53, - NUM_6 = 54, - NUM_7 = 55, - NUM_8 = 56, - NUM_9 = 57, - SEMICOLON = 59, - EQUAL = 61, - A = 65, - B = 66, - C = 67, - D = 68, - E = 69, - F = 70, - G = 71, - H = 72, - I = 73, - J = 74, - K = 75, - L = 76, - M = 77, - N = 78, - O = 79, - P = 80, - Q = 81, - R = 82, - S = 83, - T = 84, - U = 85, - V = 86, - W = 87, - X = 88, - Y = 89, - Z = 90, - LEFT_BRACKET = 91, - BACKSLASH = 92, - RIGHT_BRACKET = 93, - GRAVE_ACCENT = 96, - ESCAPE = 256, - ENTER = 257, - TAB = 258, - BACKSPACE = 259, - INSERT = 260, - DELETE = 261, - LEFT = 263, - RIGHT = 262, - DOWN = 264, - UP = 265, - PAGE_UP = 266, - PAGE_DOWN = 267, - HOME = 268, - END = 269, - CAPS_LOCK = 280, - NUM_LOCK = 282, - PRINT_SCREEN = 283, - PAUSE = 284, - F1 = 290, - F2 = 291, - F3 = 292, - F4 = 293, - F5 = 294, - F6 = 295, - F7 = 296, - F8 = 297, - F9 = 298, - F10 = 299, - F11 = 300, - F12 = 301, - LEFT_SHIFT = 340, - LEFT_CONTROL = 341, - LEFT_ALT = 342, - LEFT_SUPER = 343, - RIGHT_SHIFT = 344, - RIGHT_CONTROL = 345, - RIGHT_ALT = 346, - RIGHT_SUPER = 347, - MENU = 348, - UNKNOWN = -1 + SPACE = 0x00000020u, + APOSTROPHE = 0x00000027u, + COMMA = 0x0000002cu, + MINUS = 0x0000002du, + PERIOD = 0x0000002eu, + SLASH = 0x0000002fu, + NUM_0 = 0x40000059u, + NUM_1, + NUM_2, + NUM_3, + NUM_4, + NUM_5, + NUM_6, + NUM_7, + NUM_8, + NUM_9, + SEMICOLON = 0x0000003bu, + EQUAL = 0x0000003du, + A = 0x00000061u, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + LEFT_BRACKET = 0x0000005bu, + BACKSLASH = 0x0000005cu, + RIGHT_BRACKET = 0x0000005du, + GRAVE_ACCENT = 0x00000060u, + ESCAPE = 0x0000001bu, + ENTER = 0x0000000du, + TAB = 0x00000009u, + BACKSPACE = 0x00000008u, + INSERT = 0x40000049u, + DELETE = 0x0000007fu, + LEFT = 0x40000050u, + RIGHT = 0x4000004fu, + DOWN = 0x40000051u, + UP = 0x40000052u, + PAGE_UP = 0x4000004bu, + PAGE_DOWN = 0x4000004eu, + HOME = 0x4000004au, + END = 0x4000004du, + CAPS_LOCK = 0x40000039u, + NUM_LOCK = 0x40000053u, + PRINT_SCREEN = 0x40000046u, + PAUSE = 0x40000048u, + F1 = 0x4000003au, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + LEFT_SHIFT = 0x400000e1u, + LEFT_CONTROL = 0x400000e0u, + LEFT_ALT = 0x400000e2u, + // LEFT_SUPER = 343, + RIGHT_SHIFT = 0x400000e5u, + RIGHT_CONTROL = 0x400000e4u, + RIGHT_ALT = 0x400000e6u, + // RIGHT_SUPER = 347, + MENU = 0x40000076u, + UNKNOWN = 0x00000000u }; -/// @brief Represents glfw3 mouse button IDs. -/// @details There is a subset of glfw3 mouse button IDs. +/// @brief Represents sdl mouse button IDs. +/// @details There is a subset of sdl mouse button IDs. enum class Mousecode : int { BUTTON_1 = 0, // Left mouse button BUTTON_2 = 1, // Right mouse button BUTTON_3 = 2, // Middle mouse button BUTTON_4 = 3, // Side mouse button 1 BUTTON_5 = 4, // Side mouse button 2 - BUTTON_6 = 5, // Side mouse button 3 - BUTTON_7 = 6, // Side mouse button 4 - BUTTON_8 = 7, // Side mouse button 5 UNKNOWN = -1, }; @@ -127,14 +122,10 @@ inline Mousecode mousecodes_all[] { Mousecode::BUTTON_3, Mousecode::BUTTON_4, Mousecode::BUTTON_5, - Mousecode::BUTTON_6, - Mousecode::BUTTON_7, - Mousecode::BUTTON_8 }; namespace input_util { void initialize(); - Keycode keycode_from(const std::string& name); Mousecode mousecode_from(const std::string& name); @@ -285,7 +276,9 @@ public: virtual const Bindings& getBindings() const = 0; - virtual ObserverHandler addKeyCallback(Keycode key, KeyCallback callback) = 0; + virtual ObserverHandler addKeyCallback( + Keycode key, KeyCallback callback + ) = 0; virtual const std::vector& getPressedKeys() const = 0; virtual const std::vector& getCodepoints() const = 0; From 51927ee3500813038f6fd483a8031ccc65ca860e Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 12:16:09 +0300 Subject: [PATCH 05/41] Mouse work --- src/window/detail/input_sdl.cpp | 43 +++++++------ src/window/detail/input_sdl.hpp | 13 ++-- src/window/detail/window_sdl.cpp | 62 ++++++++++++++++++- src/window/detail/window_sdl.hpp | 2 + src/window/input.hpp | 100 +++++++++++++++---------------- 5 files changed, 141 insertions(+), 79 deletions(-) diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp index 4ed84e415..e37eb8763 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/input_sdl.cpp @@ -6,8 +6,10 @@ #include #include #include +#include #include "debug/Logger.hpp" +#include "window/detail/window_sdl.hpp" #include "window/input.hpp" static debug::Logger logger("input"); @@ -24,7 +26,7 @@ Keycode input_util::keycode_from(const std::string& name) { return static_cast(SDL_GetKeyFromName(name.c_str())); } -input_sdl::input_sdl() { +input_sdl::input_sdl(window_sdl& window) : window(window) { input_util::initialize(); } @@ -42,28 +44,26 @@ void input_sdl::pollEvents() { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_EVENT_QUIT: + window.setShouldClose(true); break; case SDL_EVENT_KEY_DOWN: - logger.info() << "Keyboard button: " << event.key.key; - if (event.key.key >= keys_buffer_size) { - // Win key return 1073742051 - break; - } - prevPressed = keys[event.key.key]; - keys[event.key.key] = true; - frames[event.key.key] = currentFrame; + logger.info() << "Keyboard button: " << event.key.scancode; + prevPressed = keys[event.key.scancode]; + keys[event.key.scancode] = true; + frames[event.key.scancode] = currentFrame; if (!prevPressed) { - keyCallbacks[static_cast(event.key.key)].notify(); + keyCallbacks[static_cast(event.key.scancode)] + .notify(); } - pressedKeys.push_back(static_cast(event.key.key)); + pressedKeys.push_back(static_cast(event.key.scancode)); break; case SDL_EVENT_KEY_UP: - if (event.key.key >= keys_buffer_size) { + if (event.key.scancode >= keys_buffer_size) { // Win key return 1073742051 break; } - keys[event.key.key] = false; - frames[event.key.key] = currentFrame; + keys[event.key.scancode] = false; + frames[event.key.scancode] = currentFrame; break; case SDL_EVENT_MOUSE_BUTTON_DOWN: prevPressed = keys[event.button.button + mouse_keys_offset]; @@ -84,6 +84,8 @@ void input_sdl::pollEvents() { cursor = {event.motion.x, event.motion.y}; delta = {event.motion.xrel, event.motion.yrel}; break; + case SDL_EVENT_WINDOW_RESIZED: + break; } } for (auto& [_, binding] : bindings.getAll()) { @@ -102,7 +104,6 @@ void input_sdl::pollEvents() { newstate = clicked(static_cast(binding.code)); break; } - if (newstate) { if (!binding.state) { binding.state = true; @@ -135,7 +136,7 @@ bool input_sdl::pressed(Keycode key) const { if (keycode < 0 || keycode >= keys_buffer_size) { return false; } - if (keys[keycode]) logger.info() << "lol"; + if (keys[keycode]) logger.info() << "kek"; return keys[keycode]; } bool input_sdl::jpressed(Keycode keycode) const { @@ -162,13 +163,9 @@ bool input_sdl::isCursorLocked() const { } void input_sdl::toggleCursor() { - // cursorDrag = false; - // if (cursorLocked) { - // glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); - // } else { - // glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - // } - // cursorLocked = !cursorLocked; + cursorDrag = false; + SDL_SetWindowMouseGrab(window.getSdlWindow(), cursorLocked); + cursorLocked = !cursorLocked; } Bindings& input_sdl::getBindings() { diff --git a/src/window/detail/input_sdl.hpp b/src/window/detail/input_sdl.hpp index 9bc5c8415..99f476470 100644 --- a/src/window/detail/input_sdl.hpp +++ b/src/window/detail/input_sdl.hpp @@ -1,16 +1,17 @@ #include -#include "window/input.hpp" +#include "window/input.hpp" #include "window/window.hpp" -struct SDL_Window; +struct window_sdl; class input_sdl final : public Input { public: - inline static constexpr short keys_buffer_size = 1036; - inline static constexpr short mouse_keys_offset = 1024; + inline static constexpr short mouse_keys_offset = 512; + inline static constexpr short keys_buffer_size = + mouse_keys_offset + sizeof(mousecodes_all) / sizeof(mousecodes_all[0]); - input_sdl(); + input_sdl(window_sdl& window); void pollEvents() override; @@ -51,4 +52,6 @@ private: std::vector codepoints; std::vector pressedKeys; std::unordered_map> keyCallbacks; + + window_sdl& window; }; \ No newline at end of file diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index 080caed96..3059b6f62 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -239,6 +240,62 @@ void window_sdl::setShouldClose(bool flag) { } void window_sdl::setCursor(CursorShape shape) { + SDL_Cursor* cursor; + switch (shape) { + case CursorShape::ARROW: + cursor = SDL_CreateSystemCursor( + SDL_SystemCursor::SDL_SYSTEM_CURSOR_DEFAULT + ); + break; + case CursorShape::TEXT: + cursor = SDL_CreateSystemCursor( + SDL_SystemCursor::SDL_SYSTEM_CURSOR_TEXT + ); + break; + case CursorShape::CROSSHAIR: + cursor = SDL_CreateSystemCursor( + SDL_SystemCursor::SDL_SYSTEM_CURSOR_CROSSHAIR + ); + break; + case CursorShape::POINTER: + cursor = SDL_CreateSystemCursor( + SDL_SystemCursor::SDL_SYSTEM_CURSOR_POINTER + ); + break; + case CursorShape::EW_RESIZE: + cursor = SDL_CreateSystemCursor( + SDL_SystemCursor::SDL_SYSTEM_CURSOR_EW_RESIZE + ); + break; + case CursorShape::NS_RESIZE: + cursor = SDL_CreateSystemCursor( + SDL_SystemCursor::SDL_SYSTEM_CURSOR_NS_RESIZE + ); + break; + case CursorShape::NWSE_RESIZE: + cursor = SDL_CreateSystemCursor( + SDL_SystemCursor::SDL_SYSTEM_CURSOR_NWSE_RESIZE + ); + break; + case CursorShape::NESW_RESIZE: + cursor = SDL_CreateSystemCursor( + SDL_SystemCursor::SDL_SYSTEM_CURSOR_NESW_RESIZE + ); + break; + case CursorShape::ALL_RESIZE: + // ?? + cursor = SDL_CreateSystemCursor( + SDL_SystemCursor::SDL_SYSTEM_CURSOR_NWSE_RESIZE + ); + break; + case CursorShape::NOT_ALLOWED: + cursor = SDL_CreateSystemCursor( + SDL_SystemCursor::SDL_SYSTEM_CURSOR_NOT_ALLOWED + ); + break; + SDL_SetCursor(cursor); + SDL_DestroyCursor(cursor); + } } void window_sdl::toggleFullscreen() { fullscreen = !fullscreen; @@ -305,6 +362,9 @@ std::unique_ptr window_sdl::takeScreenshot() { [[nodiscard]] bool window_sdl::isValid() const { return isSuccessfull; } +[[nodiscard]] SDL_Window *window_sdl::getSdlWindow() const { + return window; +} std::tuple, std::unique_ptr> Window::initialize( DisplaySettings *settings, std::string title @@ -313,7 +373,7 @@ std::tuple, std::unique_ptr> Window::initialize( if (!window->isValid()) { return {nullptr, nullptr}; } - auto input = std::make_unique(); + auto input = std::make_unique(*window); return {std::move(window), std::move(input)}; } diff --git a/src/window/detail/window_sdl.hpp b/src/window/detail/window_sdl.hpp index 368e2698f..523b23929 100644 --- a/src/window/detail/window_sdl.hpp +++ b/src/window/detail/window_sdl.hpp @@ -13,6 +13,7 @@ public: window_sdl &operator=(window_sdl &&) = default; void swapBuffers() const noexcept override; + bool isMaximized() const override; bool isFocused() const override; bool isIconified() const override; @@ -38,6 +39,7 @@ public: std::unique_ptr takeScreenshot() override; [[nodiscard]] bool isValid() const override; + [[nodiscard]] SDL_Window* getSdlWindow() const; private: bool isSuccessfull = true; bool maximized = false; diff --git a/src/window/input.hpp b/src/window/input.hpp index a3b21f6ba..9f65f6d69 100644 --- a/src/window/input.hpp +++ b/src/window/input.hpp @@ -15,14 +15,14 @@ enum class BindType { BIND = 0, REBIND = 1 }; /// @brief Represents sdl scancode values. enum class Keycode : std::int32_t { - SPACE = 0x00000020u, - APOSTROPHE = 0x00000027u, - COMMA = 0x0000002cu, - MINUS = 0x0000002du, - PERIOD = 0x0000002eu, - SLASH = 0x0000002fu, - NUM_0 = 0x40000059u, - NUM_1, + SPACE = 44, + APOSTROPHE = 52, + COMMA = 54, + MINUS = 45, + PERIOD = 55, + SLASH = 56, + NUM_0 = 39, + NUM_1 = 30, NUM_2, NUM_3, NUM_4, @@ -31,9 +31,9 @@ enum class Keycode : std::int32_t { NUM_7, NUM_8, NUM_9, - SEMICOLON = 0x0000003bu, - EQUAL = 0x0000003du, - A = 0x00000061u, + SEMICOLON = 51, + EQUAL = 46, + A = 4, B, C, D, @@ -59,29 +59,29 @@ enum class Keycode : std::int32_t { X, Y, Z, - LEFT_BRACKET = 0x0000005bu, - BACKSLASH = 0x0000005cu, - RIGHT_BRACKET = 0x0000005du, - GRAVE_ACCENT = 0x00000060u, - ESCAPE = 0x0000001bu, - ENTER = 0x0000000du, - TAB = 0x00000009u, - BACKSPACE = 0x00000008u, - INSERT = 0x40000049u, - DELETE = 0x0000007fu, - LEFT = 0x40000050u, - RIGHT = 0x4000004fu, - DOWN = 0x40000051u, - UP = 0x40000052u, - PAGE_UP = 0x4000004bu, - PAGE_DOWN = 0x4000004eu, - HOME = 0x4000004au, - END = 0x4000004du, - CAPS_LOCK = 0x40000039u, - NUM_LOCK = 0x40000053u, - PRINT_SCREEN = 0x40000046u, - PAUSE = 0x40000048u, - F1 = 0x4000003au, + LEFT_BRACKET = 47, + BACKSLASH = 49, + RIGHT_BRACKET = 48, + GRAVE_ACCENT = 53, + ESCAPE = 41, + ENTER = 40, + TAB = 43, + BACKSPACE = 42, + INSERT = 73, + DELETE = 76, + LEFT = 80, + RIGHT = 79, + DOWN = 81, + UP = 82, + PAGE_UP = 75, + PAGE_DOWN = 78, + HOME = 74, + END = 77, + CAPS_LOCK = 57, + NUM_LOCK = 83, + PRINT_SCREEN = 70, + PAUSE = 72, + F1 = 58, F2, F3, F4, @@ -93,27 +93,27 @@ enum class Keycode : std::int32_t { F10, F11, F12, - LEFT_SHIFT = 0x400000e1u, - LEFT_CONTROL = 0x400000e0u, - LEFT_ALT = 0x400000e2u, - // LEFT_SUPER = 343, - RIGHT_SHIFT = 0x400000e5u, - RIGHT_CONTROL = 0x400000e4u, - RIGHT_ALT = 0x400000e6u, - // RIGHT_SUPER = 347, - MENU = 0x40000076u, - UNKNOWN = 0x00000000u + LEFT_SHIFT = 225, + LEFT_CONTROL = 224, + LEFT_ALT = 226, + LEFT_SUPER = 227, + RIGHT_SHIFT = 229, + RIGHT_CONTROL = 228, + RIGHT_ALT = 230, + RIGHT_SUPER = 231, + MENU = 118, + UNKNOWN = 0 }; /// @brief Represents sdl mouse button IDs. /// @details There is a subset of sdl mouse button IDs. enum class Mousecode : int { - BUTTON_1 = 0, // Left mouse button - BUTTON_2 = 1, // Right mouse button - BUTTON_3 = 2, // Middle mouse button - BUTTON_4 = 3, // Side mouse button 1 - BUTTON_5 = 4, // Side mouse button 2 - UNKNOWN = -1, + BUTTON_1 = 1, // Left mouse button + BUTTON_2 = 2, // Right mouse button + BUTTON_3 = 3, // Middle mouse button + BUTTON_4 = 4, // Side mouse button 1 + BUTTON_5 = 5, // Side mouse button 2 + UNKNOWN = 0, }; inline Mousecode mousecodes_all[] { From 6a7335900f564f6b8b3978f310985b91a1256fc6 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 13:20:52 +0300 Subject: [PATCH 06/41] Mouse move work --- src/window/detail/input_sdl.cpp | 30 +++++++++++++++++++----------- src/window/detail/input_sdl.hpp | 4 ++-- src/window/input.hpp | 2 +- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp index e37eb8763..75af5bbba 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/input_sdl.cpp @@ -8,6 +8,8 @@ #include #include +#include + #include "debug/Logger.hpp" #include "window/detail/window_sdl.hpp" #include "window/input.hpp" @@ -17,17 +19,17 @@ static debug::Logger logger("input"); std::string input_util::to_string(Keycode code) { int icode_repr = static_cast(code); const char* name = SDL_GetKeyName(icode_repr); - logger.info() << icode_repr << ": " << name; return std::string(name); } Keycode input_util::keycode_from(const std::string& name) { - logger.info() << name << ": " << SDL_GetKeyFromName(name.c_str()); return static_cast(SDL_GetKeyFromName(name.c_str())); } input_sdl::input_sdl(window_sdl& window) : window(window) { input_util::initialize(); + // We should always get char stream (maybe) + SDL_StartTextInput(window.getSdlWindow()); } void input_sdl::pollEvents() { @@ -47,7 +49,6 @@ void input_sdl::pollEvents() { window.setShouldClose(true); break; case SDL_EVENT_KEY_DOWN: - logger.info() << "Keyboard button: " << event.key.scancode; prevPressed = keys[event.key.scancode]; keys[event.key.scancode] = true; frames[event.key.scancode] = currentFrame; @@ -58,10 +59,6 @@ void input_sdl::pollEvents() { pressedKeys.push_back(static_cast(event.key.scancode)); break; case SDL_EVENT_KEY_UP: - if (event.key.scancode >= keys_buffer_size) { - // Win key return 1073742051 - break; - } keys[event.key.scancode] = false; frames[event.key.scancode] = currentFrame; break; @@ -81,11 +78,23 @@ void input_sdl::pollEvents() { frames[event.button.button + mouse_keys_offset] = currentFrame; break; case SDL_EVENT_MOUSE_MOTION: + if (cursorDrag) { + delta += glm::vec2{event.motion.xrel, event.motion.yrel}; + } else { + cursorDrag = true; + } cursor = {event.motion.x, event.motion.y}; - delta = {event.motion.xrel, event.motion.yrel}; break; case SDL_EVENT_WINDOW_RESIZED: break; + case SDL_EVENT_TEXT_INPUT: + std::vector vec( + event.text.text, + event.text.text + std::strlen(event.text.text) + ); + std::copy( + vec.begin(), vec.end(), std::back_inserter(codepoints) + ); } } for (auto& [_, binding] : bindings.getAll()) { @@ -136,7 +145,6 @@ bool input_sdl::pressed(Keycode key) const { if (keycode < 0 || keycode >= keys_buffer_size) { return false; } - if (keys[keycode]) logger.info() << "kek"; return keys[keycode]; } bool input_sdl::jpressed(Keycode keycode) const { @@ -164,8 +172,8 @@ bool input_sdl::isCursorLocked() const { void input_sdl::toggleCursor() { cursorDrag = false; - SDL_SetWindowMouseGrab(window.getSdlWindow(), cursorLocked); cursorLocked = !cursorLocked; + SDL_SetWindowRelativeMouseMode(window.getSdlWindow(), cursorLocked); } Bindings& input_sdl::getBindings() { @@ -184,6 +192,6 @@ const std::vector& input_sdl::getPressedKeys() const { return pressedKeys; } -const std::vector& input_sdl::getCodepoints() const { +const std::vector& input_sdl::getCodepoints() const { return codepoints; } diff --git a/src/window/detail/input_sdl.hpp b/src/window/detail/input_sdl.hpp index 99f476470..6e1f055c0 100644 --- a/src/window/detail/input_sdl.hpp +++ b/src/window/detail/input_sdl.hpp @@ -38,7 +38,7 @@ public: ObserverHandler addKeyCallback(Keycode key, KeyCallback callback) override; const std::vector& getPressedKeys() const override; - const std::vector& getCodepoints() const override; + const std::vector& getCodepoints() const override; private: glm::vec2 delta; glm::vec2 cursor; @@ -49,7 +49,7 @@ private: bool cursorLocked = false; bool cursorDrag = false; Bindings bindings; - std::vector codepoints; + std::vector codepoints; std::vector pressedKeys; std::unordered_map> keyCallbacks; diff --git a/src/window/input.hpp b/src/window/input.hpp index 9f65f6d69..c8a100f21 100644 --- a/src/window/input.hpp +++ b/src/window/input.hpp @@ -281,7 +281,7 @@ public: ) = 0; virtual const std::vector& getPressedKeys() const = 0; - virtual const std::vector& getCodepoints() const = 0; + virtual const std::vector& getCodepoints() const = 0; ObserverHandler addCallback(const std::string& name, KeyCallback callback) { return getBindings().require(name).onactived.add(callback); From 82562300ffd1651657779bc528497200796c0382 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 13:35:00 +0300 Subject: [PATCH 07/41] half keyboard is work --- src/window/detail/input_sdl.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp index 75af5bbba..410fdc02b 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/input_sdl.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -17,13 +18,15 @@ static debug::Logger logger("input"); std::string input_util::to_string(Keycode code) { - int icode_repr = static_cast(code); - const char* name = SDL_GetKeyName(icode_repr); + auto icode_repr = static_cast(code); + const char* name = SDL_GetKeyName( + SDL_GetKeyFromScancode(icode_repr, SDL_KMOD_NONE, false) + ); return std::string(name); } Keycode input_util::keycode_from(const std::string& name) { - return static_cast(SDL_GetKeyFromName(name.c_str())); + return static_cast(SDL_GetScancodeFromName(name.c_str())); } input_sdl::input_sdl(window_sdl& window) : window(window) { @@ -79,7 +82,7 @@ void input_sdl::pollEvents() { break; case SDL_EVENT_MOUSE_MOTION: if (cursorDrag) { - delta += glm::vec2{event.motion.xrel, event.motion.yrel}; + delta += glm::vec2 {event.motion.xrel, event.motion.yrel}; } else { cursorDrag = true; } From 5e19c6807ca017228e85bcba60c8161d347c9827 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 19:09:24 +0300 Subject: [PATCH 08/41] final, but buuugs --- src/window/detail/input_sdl.cpp | 1 + src/window/detail/window_sdl.cpp | 4 ++-- src/window/input.cpp | 27 +++++++-------------------- src/window/input.hpp | 5 ----- src/window/window.hpp | 3 +++ 5 files changed, 13 insertions(+), 27 deletions(-) diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp index 410fdc02b..673b1d690 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/input_sdl.cpp @@ -89,6 +89,7 @@ void input_sdl::pollEvents() { cursor = {event.motion.x, event.motion.y}; break; case SDL_EVENT_WINDOW_RESIZED: + window.setSize({event.window.data1, event.window.data2}); break; case SDL_EVENT_TEXT_INPUT: std::vector vec( diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index 3059b6f62..93af4f514 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -344,12 +344,12 @@ void window_sdl::resetScissor() { } double window_sdl::time() { - return static_cast(SDL_GetTicks()) / 1000; + return static_cast(SDL_GetTicksNS()) / 1'000'000'000; } void window_sdl::setFramerate(int framerate) { /*todo*/ - if (!SDL_GL_SetSwapInterval(1)) { + if (!SDL_GL_SetSwapInterval(framerate)) { logger.error() << "Failed to set framerate: " << SDL_GetError(); } } diff --git a/src/window/input.cpp b/src/window/input.cpp index c774c6209..04cb6df42 100644 --- a/src/window/input.cpp +++ b/src/window/input.cpp @@ -8,7 +8,6 @@ debug::Logger logger("input"); -static std::unordered_map keynames {}; static std::unordered_map buttonsnames {}; static std::unordered_map mousecodes { @@ -19,22 +18,6 @@ static std::unordered_map mousecodes { {"side2", SDL_BUTTON_X2}, }; -std::string input_util::get_name(Mousecode code) { - const auto found = buttonsnames.find(static_cast(code)); - if (found == buttonsnames.end()) { - return "unknown"; - } - return found->second; -} - -std::string input_util::get_name(Keycode code) { - const auto found = keynames.find(static_cast(code)); - if (found == keynames.end()) { - return "unknown"; - } - return found->second; -} - void Binding::reset(InputType type, int code) { this->type = type; this->code = code; @@ -49,7 +32,11 @@ void Binding::reset(Mousecode code) { } Mousecode input_util::mousecode_from(const std::string& name) { - return {}; + const auto& found = mousecodes.find(name); + if (found == mousecodes.end()) { + return Mousecode::UNKNOWN; + } + return static_cast(found->second); } void input_util::initialize() { @@ -139,12 +126,12 @@ std::string Bindings::write() const { case InputType::KEYBOARD: value = "key:" + - input_util::get_name(static_cast(binding.code)); + input_util::to_string(static_cast(binding.code)); break; case InputType::MOUSE: value = "mouse:" + - input_util::get_name(static_cast(binding.code)); + input_util::to_string(static_cast(binding.code)); break; default: throw std::runtime_error("unsupported control type"); diff --git a/src/window/input.hpp b/src/window/input.hpp index c8a100f21..a6fdcb355 100644 --- a/src/window/input.hpp +++ b/src/window/input.hpp @@ -133,11 +133,6 @@ namespace input_util { std::string to_string(Keycode code); /// @return Mouse button label by keycode std::string to_string(Mousecode code); - - /// @return Key name by keycode - std::string get_name(Keycode code); - /// @return Mouse button name by keycode - std::string get_name(Mousecode code); } enum class InputType { diff --git a/src/window/window.hpp b/src/window/window.hpp index d19ab5087..976f74dc5 100644 --- a/src/window/window.hpp +++ b/src/window/window.hpp @@ -43,6 +43,9 @@ public: virtual const glm::ivec2& getSize() const { return size; } + virtual void setSize(const glm::ivec2& s) { + size = std::move(s); + } static std::tuple, std::unique_ptr> initialize(DisplaySettings* settings, std::string title); From bca742186f10784a963ef41a2c8434b9d15b9655 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 22:12:27 +0300 Subject: [PATCH 09/41] ci/cd update --- .github/workflows/appimage.yml | 2 +- .github/workflows/cmake.yml | 2 +- .github/workflows/macos.yml | 2 +- Dockerfile | 3 +-- README.md | 19 +++++-------------- dev/AppImageBuilder.yml | 2 +- flake.nix | 4 ++-- vcpkg.json | 2 +- 8 files changed, 13 insertions(+), 23 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 5a01a6186..21303003a 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -23,7 +23,7 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y build-essential libglfw3-dev libglfw3 libglew-dev libglew2.2 \ + sudo apt-get install -y build-essential libsdl3-dev libglew-dev libglew2.2 \ libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev \ libcurl4-openssl-dev libgtest-dev cmake squashfs-tools valgrind # fix luajit paths diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index ddaa95f8a..3bc0995bf 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -39,7 +39,7 @@ jobs: # make && make install INSTALL_INC=/usr/include/lua run: | sudo apt-get update - sudo apt-get install libglfw3-dev libglfw3 libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev libgtest-dev libcurl4-openssl-dev + sudo apt-get install libsdl3-dev libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev libgtest-dev libcurl4-openssl-dev # fix luajit paths sudo ln -s /usr/lib/x86_64-linux-gnu/libluajit-5.1.a /usr/lib/x86_64-linux-gnu/liblua-5.1.a sudo ln -s /usr/include/luajit-2.1 /usr/include/lua diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index f8fe3dfac..e4ec458bb 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -17,7 +17,7 @@ jobs: - name: Install dependencies from brew run: | - brew install glfw3 glew libpng openal-soft luajit libvorbis skypjack/entt/entt googletest glm + brew install sdl3 glew libpng openal-soft luajit libvorbis skypjack/entt/entt googletest glm - name: Configure run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_TESTS=ON -DVOXELENGINE_BUILD_APPDIR=1 diff --git a/Dockerfile b/Dockerfile index 9d0005f59..ad685f226 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,8 +15,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \ xauth \ gdb \ gdbserver \ - libglfw3-dev \ - libglfw3 \ + libsdl3-dev \ libglew-dev \ libglew2.2 \ libglm-dev \ diff --git a/README.md b/README.md index 30925fefd..292cdf44f 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,13 @@ sudo make install ```sh su - -apt-get install entt-devel libglfw3-devel libGLEW-devel libglm-devel libpng-devel libvorbis-devel libopenal-devel libluajit-devel libstdc++13-devel-static libcurl-devel +apt-get install entt-devel SDL3-devel libGLEW-devel libglm-devel libpng-devel libvorbis-devel libopenal-devel libluajit-devel libstdc++13-devel-static libcurl-devel ``` #### Debian based distros ```sh -sudo apt install libglfw3 libglfw3-dev libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev libcurl4-openssl-dev +sudo apt install libsdl3-dev libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev libcurl4-openssl-dev ``` > [!TIP] @@ -48,21 +48,12 @@ sudo apt install libglfw3 libglfw3-dev libglew-dev libglm-dev libpng-dev libopen #### RHEL based distros ```sh -sudo dnf install glfw-devel glew-devel glm-devel libpng-devel libvorbis-devel openal-soft-devel luajit-devel libcurl-devel +sudo dnf install SDL3-devel glew-devel glm-devel libpng-devel libvorbis-devel openal-soft-devel luajit-devel libcurl-devel ``` #### Arch based distros - -If you use X11: - ```sh -sudo pacman -S glfw-x11 glew glm libpng libvorbis openal luajit libcurl -``` - -If you use Wayland: - -```sh -sudo pacman -S glfw-wayland glew glm libpng libvorbis openal luajit libcurl +sudo pacman -S sdl3 glew glm libpng libvorbis openal luajit libcurl ``` And install EnTT: @@ -92,7 +83,7 @@ cmake --build . --parallel ### Install libraries ```sh -brew install glfw3 glew glm libpng libvorbis lua luajit libcurl openal-soft skypjack/entt/entt +brew install sdl3 glew glm libpng libvorbis lua luajit libcurl openal-soft skypjack/entt/entt ``` > [!TIP] diff --git a/dev/AppImageBuilder.yml b/dev/AppImageBuilder.yml index 16fcf57a7..c924db6d4 100644 --- a/dev/AppImageBuilder.yml +++ b/dev/AppImageBuilder.yml @@ -22,7 +22,7 @@ AppDir: - libexpat1 - libfam0 - libgcrypt20 - - libglfw3 + - libsdl3 - libglew2.2 - libpng16-16 - libopenal1 diff --git a/flake.nix b/flake.nix index bc9ead2b0..1c3daeb04 100644 --- a/flake.nix +++ b/flake.nix @@ -28,7 +28,7 @@ buildInputs = with pkgs; [ glm - glfw + sdl3 glew zlib libpng @@ -42,7 +42,7 @@ ]; # libglvnd packages = with pkgs; [ - glfw + sdl3 mesa freeglut entt diff --git a/vcpkg.json b/vcpkg.json index 17145c4a0..8ac88a6ef 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -4,7 +4,7 @@ "dependencies": [ "opengl", "openal-soft", - "glfw3", + "sdl3", "glew", "glm", "libpng", From dc84201db00baba0bf69a56037b327c12c9de450 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 22:28:32 +0300 Subject: [PATCH 10/41] Test manual build sdl for ubuntu --- .github/workflows/appimage.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 21303003a..f5caed0c7 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -23,7 +23,7 @@ jobs: - name: Install dependencies run: | sudo apt-get update - sudo apt-get install -y build-essential libsdl3-dev libglew-dev libglew2.2 \ + sudo apt-get install -y build-essential libglew-dev libglew2.2 \ libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev \ libcurl4-openssl-dev libgtest-dev cmake squashfs-tools valgrind # fix luajit paths @@ -35,6 +35,13 @@ jobs: cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=Release -DENTT_INSTALL=on .. sudo make install cd ../.. + # install SDL3 + git clone https://github.com/libsdl-org/SDL.git + cd SDL + cmake -G "Ninja Multi-Config" -B.build . + cmake --build .build --config Release -j + sudo cmake --install .build --config Release + cd .. - name: Configure run: cmake -S . -B build -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_APPDIR=1 -DVOXELENGINE_BUILD_TESTS=ON - name: Build From e4d8a34a487189084e481e1e1faf4836701ae843 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 22:32:45 +0300 Subject: [PATCH 11/41] refactor and speedup builds --- .github/workflows/appimage.yml | 2 +- .github/workflows/cmake.yml | 11 +++++++++-- .github/workflows/macos.yml | 2 +- .github/workflows/windows-clang.yml | 2 +- .github/workflows/windows.yml | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index f5caed0c7..1b0c0bdfe 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -45,7 +45,7 @@ jobs: - name: Configure run: cmake -S . -B build -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_APPDIR=1 -DVOXELENGINE_BUILD_TESTS=ON - name: Build - run: cmake --build build -t install + run: cmake --build build -t install -j - name: Run tests run: ctest --test-dir build - name: Run engine tests diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 3bc0995bf..ba88d2221 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -39,7 +39,7 @@ jobs: # make && make install INSTALL_INC=/usr/include/lua run: | sudo apt-get update - sudo apt-get install libsdl3-dev libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev libgtest-dev libcurl4-openssl-dev + sudo apt-get install libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev libgtest-dev libcurl4-openssl-dev # fix luajit paths sudo ln -s /usr/lib/x86_64-linux-gnu/libluajit-5.1.a /usr/lib/x86_64-linux-gnu/liblua-5.1.a sudo ln -s /usr/include/luajit-2.1 /usr/include/lua @@ -49,6 +49,13 @@ jobs: cmake -DCMAKE_BUILD_TYPE=Release -DENTT_INSTALL=on .. sudo make install cd ../.. + # install SDL3 + git clone https://github.com/libsdl-org/SDL.git + cd SDL + cmake -G "Ninja Multi-Config" -B.build . + cmake --build .build --config Release -j + sudo cmake --install .build --config Release + cd .. - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only @@ -61,7 +68,7 @@ jobs: - name: Build # Build your program with the given configuration run: | - cmake --build ${{github.workspace}}/build --config ${{inputs.build_type}} + cmake --build ${{github.workspace}}/build --config ${{inputs.build_type}} -j mv ${{github.workspace}}/build/VoxelEngine VoxelEngine - name: Run tests if: ${{ inputs.run_tests }} diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index e4ec458bb..06f0fa2e5 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -23,7 +23,7 @@ jobs: run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_TESTS=ON -DVOXELENGINE_BUILD_APPDIR=1 - name: Build - run: cmake --build build -t install + run: cmake --build build -t install -j - name: Make fix_dylibs.sh executable run: chmod +x dev/fix_dylibs.sh diff --git a/.github/workflows/windows-clang.yml b/.github/workflows/windows-clang.yml index cdf354dd6..f9bf72a2b 100644 --- a/.github/workflows/windows-clang.yml +++ b/.github/workflows/windows-clang.yml @@ -48,7 +48,7 @@ jobs: mkdir build cd build cmake -G "MinGW Makefiles" -DVCPKG_TARGET_TRIPLET=x64-mingw-static -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake .. - cmake --build . --config Release + cmake --build . --config Release -j - name: Package for Windows run: | mkdir packaged diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index e5ee5a69b..896aa7951 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -32,7 +32,7 @@ jobs: VCPKG_ROOT: ${{ github.workspace }}/vcpkg run: | cmake --preset default-vs-msvc-windows - cmake --build --preset default-vs-msvc-windows --config Release + cmake --build --preset default-vs-msvc-windows --config Release -j - name: Run tests run: ctest --preset default-vs-msvc-windows - name: Run engine tests From 5b3733de942795cc715d6c51e904844cd06288b9 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 22:39:07 +0300 Subject: [PATCH 12/41] use only 4 threads for build --- .github/workflows/cmake.yml | 4 ++-- .github/workflows/macos.yml | 2 +- .github/workflows/windows-clang.yml | 2 +- .github/workflows/windows.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index ba88d2221..973249e6f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -53,7 +53,7 @@ jobs: git clone https://github.com/libsdl-org/SDL.git cd SDL cmake -G "Ninja Multi-Config" -B.build . - cmake --build .build --config Release -j + cmake --build .build --config Release -j 4 sudo cmake --install .build --config Release cd .. @@ -68,7 +68,7 @@ jobs: - name: Build # Build your program with the given configuration run: | - cmake --build ${{github.workspace}}/build --config ${{inputs.build_type}} -j + cmake --build ${{github.workspace}}/build --config ${{inputs.build_type}} -j 4 mv ${{github.workspace}}/build/VoxelEngine VoxelEngine - name: Run tests if: ${{ inputs.run_tests }} diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 06f0fa2e5..8cfc20084 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -23,7 +23,7 @@ jobs: run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_TESTS=ON -DVOXELENGINE_BUILD_APPDIR=1 - name: Build - run: cmake --build build -t install -j + run: cmake --build build -t install -j 4 - name: Make fix_dylibs.sh executable run: chmod +x dev/fix_dylibs.sh diff --git a/.github/workflows/windows-clang.yml b/.github/workflows/windows-clang.yml index f9bf72a2b..3b860ed8c 100644 --- a/.github/workflows/windows-clang.yml +++ b/.github/workflows/windows-clang.yml @@ -48,7 +48,7 @@ jobs: mkdir build cd build cmake -G "MinGW Makefiles" -DVCPKG_TARGET_TRIPLET=x64-mingw-static -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=./vcpkg/scripts/buildsystems/vcpkg.cmake .. - cmake --build . --config Release -j + cmake --build . --config Release -j 4 - name: Package for Windows run: | mkdir packaged diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 896aa7951..03cdffcf4 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -32,7 +32,7 @@ jobs: VCPKG_ROOT: ${{ github.workspace }}/vcpkg run: | cmake --preset default-vs-msvc-windows - cmake --build --preset default-vs-msvc-windows --config Release -j + cmake --build --preset default-vs-msvc-windows --config Release -j 4 - name: Run tests run: ctest --preset default-vs-msvc-windows - name: Run engine tests From 43899d06eacc389bcdde42b29178c32e961e7878 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 22:40:59 +0300 Subject: [PATCH 13/41] Final ci/cd fix --- README.md | 6 +++++- dev/AppImageBuilder.yml | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 292cdf44f..c6e2a993e 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,13 @@ apt-get install entt-devel SDL3-devel libGLEW-devel libglm-devel libpng-devel li #### Debian based distros ```sh -sudo apt install libsdl3-dev libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev libcurl4-openssl-dev +sudo apt install libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev libcurl4-openssl-dev ``` +> [!WARNING] +> You need manualy prebuild and install SDL3 lib. + + > [!TIP] > CMake missing `LUA_INCLUDE_DIR` and `LUA_LIBRARIES` fix: > diff --git a/dev/AppImageBuilder.yml b/dev/AppImageBuilder.yml index c924db6d4..19b818f67 100644 --- a/dev/AppImageBuilder.yml +++ b/dev/AppImageBuilder.yml @@ -22,7 +22,6 @@ AppDir: - libexpat1 - libfam0 - libgcrypt20 - - libsdl3 - libglew2.2 - libpng16-16 - libopenal1 From 3843226497b2598efd0772fd32113087b99c2225 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sun, 5 Oct 2025 22:46:06 +0300 Subject: [PATCH 14/41] Final ci/cd fix --- .github/workflows/appimage.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 1b0c0bdfe..457040ae5 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -39,13 +39,13 @@ jobs: git clone https://github.com/libsdl-org/SDL.git cd SDL cmake -G "Ninja Multi-Config" -B.build . - cmake --build .build --config Release -j + cmake --build .build --config Release -j 4 sudo cmake --install .build --config Release cd .. - name: Configure run: cmake -S . -B build -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_APPDIR=1 -DVOXELENGINE_BUILD_TESTS=ON - name: Build - run: cmake --build build -t install -j + run: cmake --build build -t install -j 4 - name: Run tests run: ctest --test-dir build - name: Run engine tests From 706fe0c40ba5f7e12a3a77b5059a71fa5444cc44 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Mon, 6 Oct 2025 22:47:12 +0300 Subject: [PATCH 15/41] fix bug with keycodes --- src/window/detail/input_sdl.cpp | 89 +++++++++++++++++++++++++++++++++ src/window/input.cpp | 41 +-------------- src/window/input.hpp | 6 +++ 3 files changed, 97 insertions(+), 39 deletions(-) diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp index 673b1d690..bbc825286 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/input_sdl.cpp @@ -17,6 +17,79 @@ static debug::Logger logger("input"); +static std::unordered_map keycodes { + {"enter", SDL_SCANCODE_RETURN}, + {"space", SDL_SCANCODE_SPACE}, + {"backspace", SDL_SCANCODE_BACKSPACE}, + {"caps-lock", SDL_SCANCODE_CAPSLOCK}, + {"escape", SDL_SCANCODE_ESCAPE}, + {"delete", SDL_SCANCODE_DELETE}, + {"home", SDL_SCANCODE_HOME}, + {"end", SDL_SCANCODE_END}, + {"tab", SDL_SCANCODE_TAB}, + {"insert", SDL_SCANCODE_INSERT}, + {"page-down", SDL_SCANCODE_PAGEDOWN}, + {"page-up", SDL_SCANCODE_PAGEUP}, + {"left-shift", SDL_SCANCODE_LSHIFT}, + {"right-shift", SDL_SCANCODE_RSHIFT}, + {"left-ctrl", SDL_SCANCODE_LCTRL}, + {"right-ctrl", SDL_SCANCODE_RCTRL}, + {"left-alt", SDL_SCANCODE_LALT}, + {"right-alt", SDL_SCANCODE_RALT}, + {"left-super", SDL_SCANCODE_LGUI}, + {"right-super", SDL_SCANCODE_RGUI}, + {"grave-accent", SDL_SCANCODE_GRAVE}, + {"left", SDL_SCANCODE_LEFT}, + {"right", SDL_SCANCODE_RIGHT}, + {"down", SDL_SCANCODE_DOWN}, + {"up", SDL_SCANCODE_UP}, +}; +static std::unordered_map mousecodes { + {"left", SDL_BUTTON_LEFT}, + {"right", SDL_BUTTON_RIGHT}, + {"middle", SDL_BUTTON_MIDDLE}, + {"side1", SDL_BUTTON_X1}, + {"side2", SDL_BUTTON_X2}, +}; + +static std::unordered_map keynames {}; +static std::unordered_map buttonsnames {}; + +std::string input_util::get_name(Mousecode code) { + const auto found = buttonsnames.find(static_cast(code)); + if (found == buttonsnames.end()) { + return "unknown"; + } + return found->second; +} + +std::string input_util::get_name(Keycode code) { + const auto found = keynames.find(static_cast(code)); + if (found == keynames.end()) { + return "unknown"; + } + return found->second; +} + +void input_util::initialize() { + keycodes[std::to_string(0)] = SDL_SCANCODE_0; + for (int i = 1; i <= 9; i++) { + keycodes[std::to_string(i)] = SDL_SCANCODE_1 + i; + } + for (int i = 0; i < 25; i++) { + keycodes["f" + std::to_string(i + 1)] = SDL_SCANCODE_F1 + i; + } + for (char i = 'a'; i <= 'z'; i++) { + keycodes[std::string({i})] = SDL_SCANCODE_A - 'a' + i; + } + for (const auto& entry : keycodes) { + keynames[entry.second] = entry.first; + } + for (const auto& entry : mousecodes) { + buttonsnames[entry.second] = entry.first; + } +} + std::string input_util::to_string(Keycode code) { auto icode_repr = static_cast(code); const char* name = SDL_GetKeyName( @@ -26,9 +99,25 @@ std::string input_util::to_string(Keycode code) { } Keycode input_util::keycode_from(const std::string& name) { + auto found = std::find_if( + std::begin(keynames), std::end(keynames), [&name](auto&& p) { + return p.second == name; + } + ); + // Compatibility with old names + if (found != keynames.end()) return static_cast(found->first); + return static_cast(SDL_GetScancodeFromName(name.c_str())); } +Mousecode input_util::mousecode_from(const std::string& name) { + const auto& found = mousecodes.find(name); + if (found == mousecodes.end()) { + return Mousecode::UNKNOWN; + } + return static_cast(found->second); +} + input_sdl::input_sdl(window_sdl& window) : window(window) { input_util::initialize(); // We should always get char stream (maybe) diff --git a/src/window/input.cpp b/src/window/input.cpp index 04cb6df42..195f5ca82 100644 --- a/src/window/input.cpp +++ b/src/window/input.cpp @@ -4,20 +4,9 @@ #include "debug/Logger.hpp" #include "util/stringutil.hpp" -#include debug::Logger logger("input"); -static std::unordered_map buttonsnames {}; - -static std::unordered_map mousecodes { - {"left", SDL_BUTTON_LEFT}, - {"right", SDL_BUTTON_RIGHT}, - {"middle", SDL_BUTTON_MIDDLE}, - {"side1", SDL_BUTTON_X1}, - {"side2", SDL_BUTTON_X2}, -}; - void Binding::reset(InputType type, int code) { this->type = type; this->code = code; @@ -31,32 +20,6 @@ void Binding::reset(Mousecode code) { reset(InputType::MOUSE, static_cast(code)); } -Mousecode input_util::mousecode_from(const std::string& name) { - const auto& found = mousecodes.find(name); - if (found == mousecodes.end()) { - return Mousecode::UNKNOWN; - } - return static_cast(found->second); -} - -void input_util::initialize() { - // for (int i = 0; i <= 9; i++) { - // keycodes[std::to_string(i)] = GLFW_KEY_0 + i; - // } - // for (int i = 0; i < 25; i++) { - // keycodes["f" + std::to_string(i + 1)] = GLFW_KEY_F1 + i; - // } - // for (char i = 'a'; i <= 'z'; i++) { - // keycodes[std::string({i})] = GLFW_KEY_A - 'a' + i; - // } - // for (const auto& entry : keycodes) { - // keynames[entry.second] = entry.first; - // } - for (const auto& entry : mousecodes) { - buttonsnames[entry.second] = entry.first; - } -} - std::string input_util::to_string(Mousecode code) { switch (code) { case Mousecode::BUTTON_1: @@ -126,12 +89,12 @@ std::string Bindings::write() const { case InputType::KEYBOARD: value = "key:" + - input_util::to_string(static_cast(binding.code)); + input_util::get_name(static_cast(binding.code)); break; case InputType::MOUSE: value = "mouse:" + - input_util::to_string(static_cast(binding.code)); + input_util::get_name(static_cast(binding.code)); break; default: throw std::runtime_error("unsupported control type"); diff --git a/src/window/input.hpp b/src/window/input.hpp index a6fdcb355..7ae082dd3 100644 --- a/src/window/input.hpp +++ b/src/window/input.hpp @@ -124,6 +124,7 @@ inline Mousecode mousecodes_all[] { Mousecode::BUTTON_5, }; + namespace input_util { void initialize(); Keycode keycode_from(const std::string& name); @@ -133,6 +134,11 @@ namespace input_util { std::string to_string(Keycode code); /// @return Mouse button label by keycode std::string to_string(Mousecode code); + + /// @return Key name by keycode + std::string get_name(Keycode code); + /// @return Mouse button name by keycode + std::string get_name(Mousecode code); } enum class InputType { From fddf810daf4d600c1e5d330609ed3eaee9d77cf2 Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Tue, 7 Oct 2025 16:04:49 +0300 Subject: [PATCH 16/41] Small refactoring and restore Scissors logic. Render not work with enabled GL_SCISSOR_TEST --- src/window/detail/input_sdl.hpp | 2 +- src/window/detail/window_sdl.cpp | 66 ++++++++++++++++++++++++++++---- src/window/detail/window_sdl.hpp | 10 ++++- 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/window/detail/input_sdl.hpp b/src/window/detail/input_sdl.hpp index 6e1f055c0..5b8c5bd03 100644 --- a/src/window/detail/input_sdl.hpp +++ b/src/window/detail/input_sdl.hpp @@ -3,7 +3,7 @@ #include "window/input.hpp" #include "window/window.hpp" -struct window_sdl; +class window_sdl; class input_sdl final : public Input { public: diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index 93af4f514..753245a18 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -86,7 +86,7 @@ static void GLAPIENTRY gl_message_callback( if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) { return; } - if (!ENGINE_DEBUG_BUILD && severity != GL_DEBUG_SEVERITY_HIGH) { + if constexpr (!ENGINE_DEBUG_BUILD && severity != GL_DEBUG_SEVERITY_HIGH) { return; } logger.warning() << "GL:" << gl_error_name(type) << ":" @@ -216,7 +216,7 @@ window_sdl::~window_sdl() { } void window_sdl::swapBuffers() const noexcept { - if (!SDL_GL_SwapWindow(window)) [[unlikely]] { + if (!SDL_GL_SwapWindow(window)) [[unlikely]] { // C++20 needed logger.error() << "Cant swap buffer: " << SDL_GetError(); } } @@ -240,7 +240,7 @@ void window_sdl::setShouldClose(bool flag) { } void window_sdl::setCursor(CursorShape shape) { - SDL_Cursor* cursor; + SDL_Cursor *cursor = nullptr; switch (shape) { case CursorShape::ARROW: cursor = SDL_CreateSystemCursor( @@ -293,8 +293,10 @@ void window_sdl::setCursor(CursorShape shape) { SDL_SystemCursor::SDL_SYSTEM_CURSOR_NOT_ALLOWED ); break; - SDL_SetCursor(cursor); - SDL_DestroyCursor(cursor); + } + if (cursor) { + SDL_SetCursor(cursor); + SDL_DestroyCursor(cursor); } } void window_sdl::toggleFullscreen() { @@ -337,10 +339,60 @@ void window_sdl::setIcon(const ImageData *image) { } void window_sdl::pushScissor(glm::vec4 area) { + if (scissorStack.empty()) { + glEnable(GL_SCISSOR_TEST); + } + scissorStack.push(scissorArea); + + area.z += glm::ceil(area.x); + area.w += glm::ceil(area.y); + + area.x = glm::max(area.x, scissorArea.x); + area.y = glm::max(area.y, scissorArea.y); + + area.z = glm::min(area.z, scissorArea.z); + area.w = glm::min(area.w, scissorArea.w); + + if (area.z < 0.0f || area.w < 0.0f) { + glScissor(0, 0, 0, 0); + } else { + glScissor( + area.x, + size.y - area.w, + std::max(0, static_cast(glm::ceil(area.z - area.x))), + std::max(0, static_cast(glm::ceil(area.w - area.y))) + ); + } + scissorArea = area; } -void window_sdl::popScissor() { -} + void window_sdl::resetScissor() { + scissorArea = glm::vec4(0.0f, 0.0f, size.x, size.y); + scissorStack = std::stack(); + glDisable(GL_SCISSOR_TEST); +} + +void window_sdl::popScissor() { + if (scissorStack.empty()) { + logger.warning() << "extra Window::popScissor call"; + return; + } + glm::vec4 area = scissorStack.top(); + scissorStack.pop(); + if (area.z < 0.0f || area.w < 0.0f) { + glScissor(0, 0, 0, 0); + } else { + glScissor( + area.x, + size.y - area.w, + std::max(0, static_cast(area.z - area.x)), + std::max(0, static_cast(area.w - area.y)) + ); + } + if (scissorStack.empty()) { + glDisable(GL_SCISSOR_TEST); + } + scissorArea = area; } double window_sdl::time() { diff --git a/src/window/detail/window_sdl.hpp b/src/window/detail/window_sdl.hpp index 523b23929..26cd4fd62 100644 --- a/src/window/detail/window_sdl.hpp +++ b/src/window/detail/window_sdl.hpp @@ -1,7 +1,10 @@ #include + +#include + #include "window/window.hpp" -struct SDL_Window; +struct SDL_Window; class window_sdl final : public Window { public: @@ -39,7 +42,7 @@ public: std::unique_ptr takeScreenshot() override; [[nodiscard]] bool isValid() const override; - [[nodiscard]] SDL_Window* getSdlWindow() const; + [[nodiscard]] SDL_Window *getSdlWindow() const; private: bool isSuccessfull = true; bool maximized = false; @@ -50,4 +53,7 @@ private: SDL_Window *window; SDL_GLContext context; + + std::stack scissorStack; + glm::vec4 scissorArea; }; \ No newline at end of file From f631382dbd2963e8bf04ccd99dde0535314f2985 Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Tue, 7 Oct 2025 16:36:15 +0300 Subject: [PATCH 17/41] some refactoring, add props and fix scissors --- src/window/detail/window_sdl.cpp | 17 +++++++++++++++-- src/window/detail/window_sdl.hpp | 8 ++++---- src/window/window.hpp | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index 753245a18..b6eafd14c 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -146,7 +146,8 @@ window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { return; } - SDL_WindowFlags flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; + SDL_WindowFlags flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | + SDL_WINDOW_HIGH_PIXEL_DENSITY; if (settings->fullscreen.get()) { flags |= SDL_WINDOW_FULLSCREEN; @@ -185,6 +186,13 @@ window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { // SDL_GL_SetAttribute(SDL_WINDOW_ALLOW_HIGHDPI, false); #endif SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, settings->samples.get()); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); context = SDL_GL_CreateContext(window); if (!context) { @@ -203,6 +211,10 @@ window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { isSuccessfull = false; return; } + + float scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()); + + logger.info() << "monitor content scale: " << scale; } window_sdl::~window_sdl() { if (window) { @@ -215,10 +227,11 @@ window_sdl::~window_sdl() { } } -void window_sdl::swapBuffers() const noexcept { +void window_sdl::swapBuffers() noexcept { if (!SDL_GL_SwapWindow(window)) [[unlikely]] { // C++20 needed logger.error() << "Cant swap buffer: " << SDL_GetError(); } + resetScissor(); } bool window_sdl::isMaximized() const { return (SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) != 0; diff --git a/src/window/detail/window_sdl.hpp b/src/window/detail/window_sdl.hpp index 26cd4fd62..68baecf50 100644 --- a/src/window/detail/window_sdl.hpp +++ b/src/window/detail/window_sdl.hpp @@ -15,7 +15,7 @@ public: window_sdl &operator=(const window_sdl &) = delete; window_sdl &operator=(window_sdl &&) = default; - void swapBuffers() const noexcept override; + void swapBuffers() noexcept override; bool isMaximized() const override; bool isFocused() const override; @@ -51,9 +51,9 @@ private: bool toClose = false; bool fullscreen = false; - SDL_Window *window; - SDL_GLContext context; + SDL_Window *window = nullptr; + SDL_GLContext context = nullptr; std::stack scissorStack; - glm::vec4 scissorArea; + glm::vec4 scissorArea {}; }; \ No newline at end of file diff --git a/src/window/window.hpp b/src/window/window.hpp index 976f74dc5..e45261656 100644 --- a/src/window/window.hpp +++ b/src/window/window.hpp @@ -12,7 +12,7 @@ struct DisplaySettings; class Window { public: virtual ~Window() = default; - virtual void swapBuffers() const noexcept = 0; + virtual void swapBuffers() noexcept = 0; virtual bool isMaximized() const = 0; virtual bool isFocused() const = 0; From 13ae4ede723e3c67062b8cecee47ce7f54d57c45 Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Tue, 7 Oct 2025 16:42:24 +0300 Subject: [PATCH 18/41] fix scroll --- src/window/detail/input_sdl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp index bbc825286..bd6a8830f 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/input_sdl.cpp @@ -177,6 +177,9 @@ void input_sdl::pollEvents() { } cursor = {event.motion.x, event.motion.y}; break; + case SDL_EVENT_MOUSE_WHEEL: + scroll += event.wheel.integer_y; + break; case SDL_EVENT_WINDOW_RESIZED: window.setSize({event.window.data1, event.window.data2}); break; From f8302a42d0dd43bdcaa4d877a5180bd816d011aa Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Tue, 7 Oct 2025 16:43:32 +0300 Subject: [PATCH 19/41] fix typo --- src/window/detail/window_sdl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index b6eafd14c..51ce6d5cd 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -314,7 +314,7 @@ void window_sdl::setCursor(CursorShape shape) { } void window_sdl::toggleFullscreen() { fullscreen = !fullscreen; - if (SDL_SetWindowFullscreen(window, fullscreen)) { + if (!SDL_SetWindowFullscreen(window, fullscreen)) { logger.error() << "Cant toggle fullscreen window: " << SDL_GetError(); } } From d896d2debb3115bdaa9af5e18f9bebb8cb50aef3 Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Tue, 7 Oct 2025 17:20:06 +0300 Subject: [PATCH 20/41] fix some warns and errors --- src/window/detail/window_sdl.cpp | 2 +- src/window/detail/window_sdl.hpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index 51ce6d5cd..5b43cfcad 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -86,7 +86,7 @@ static void GLAPIENTRY gl_message_callback( if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) { return; } - if constexpr (!ENGINE_DEBUG_BUILD && severity != GL_DEBUG_SEVERITY_HIGH) { + if (!ENGINE_DEBUG_BUILD && severity != GL_DEBUG_SEVERITY_HIGH) { return; } logger.warning() << "GL:" << gl_error_name(type) << ":" diff --git a/src/window/detail/window_sdl.hpp b/src/window/detail/window_sdl.hpp index 68baecf50..845366f1c 100644 --- a/src/window/detail/window_sdl.hpp +++ b/src/window/detail/window_sdl.hpp @@ -45,9 +45,6 @@ public: [[nodiscard]] SDL_Window *getSdlWindow() const; private: bool isSuccessfull = true; - bool maximized = false; - bool focused = false; - bool iconified = false; bool toClose = false; bool fullscreen = false; From 5906421dcf3c49664f9f54b89be95cd8817b8845 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Tue, 7 Oct 2025 23:28:17 +0300 Subject: [PATCH 21/41] restore screenshot logic --- src/window/detail/window_sdl.cpp | 13 ++++++++++++- src/window/detail/window_sdl.hpp | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index 5b43cfcad..b8a4054d0 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -212,6 +214,8 @@ window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { return; } + renderer = SDL_CreateRenderer(window, "vc_main"); + float scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()); logger.info() << "monitor content scale: " << scale; @@ -420,8 +424,15 @@ void window_sdl::setFramerate(int framerate) { } // todo: move somewhere +// Possible do with SDL_RenderReadPixels std::unique_ptr window_sdl::takeScreenshot() { - return {}; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + auto data = std::make_unique(size.x * size.y * 3); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(0, 0, size.x, size.y, GL_RGB, GL_UNSIGNED_BYTE, data.get()); + return std::make_unique( + ImageFormat::rgb888, size.x, size.y, data.release() + ); } [[nodiscard]] bool window_sdl::isValid() const { diff --git a/src/window/detail/window_sdl.hpp b/src/window/detail/window_sdl.hpp index 845366f1c..e26fc6768 100644 --- a/src/window/detail/window_sdl.hpp +++ b/src/window/detail/window_sdl.hpp @@ -1,11 +1,10 @@ +#include #include #include #include "window/window.hpp" -struct SDL_Window; - class window_sdl final : public Window { public: window_sdl(DisplaySettings *settings, std::string title) noexcept; @@ -49,6 +48,7 @@ private: bool fullscreen = false; SDL_Window *window = nullptr; + SDL_Renderer *renderer = nullptr; SDL_GLContext context = nullptr; std::stack scissorStack; From ad5834b1e154f615e62c40631eee87852078a74d Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Fri, 10 Oct 2025 14:56:34 +0300 Subject: [PATCH 22/41] fix utf8 input --- src/window/detail/input_sdl.cpp | 20 +++++++++++--------- src/window/detail/input_sdl.hpp | 4 ++-- src/window/input.hpp | 6 ++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp index bd6a8830f..d45125fa6 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/input_sdl.cpp @@ -9,9 +9,10 @@ #include #include -#include +#include #include "debug/Logger.hpp" +#include "util/stringutil.hpp" #include "window/detail/window_sdl.hpp" #include "window/input.hpp" @@ -132,6 +133,9 @@ void input_sdl::pollEvents() { codepoints.clear(); pressedKeys.clear(); + std::string text {}; + uint size {}; + bool prevPressed = false; static SDL_Event event; @@ -184,15 +188,13 @@ void input_sdl::pollEvents() { window.setSize({event.window.data1, event.window.data2}); break; case SDL_EVENT_TEXT_INPUT: - std::vector vec( - event.text.text, - event.text.text + std::strlen(event.text.text) - ); - std::copy( - vec.begin(), vec.end(), std::back_inserter(codepoints) - ); + text += event.text.text; } } + if (!text.empty()) { + codepoints.push_back(util::decode_utf8(size, text.c_str())); + } + for (auto& [_, binding] : bindings.getAll()) { if (!binding.enabled) { binding.state = false; @@ -288,6 +290,6 @@ const std::vector& input_sdl::getPressedKeys() const { return pressedKeys; } -const std::vector& input_sdl::getCodepoints() const { +const std::vector& input_sdl::getCodepoints() const { return codepoints; } diff --git a/src/window/detail/input_sdl.hpp b/src/window/detail/input_sdl.hpp index 5b8c5bd03..a524f2023 100644 --- a/src/window/detail/input_sdl.hpp +++ b/src/window/detail/input_sdl.hpp @@ -38,7 +38,7 @@ public: ObserverHandler addKeyCallback(Keycode key, KeyCallback callback) override; const std::vector& getPressedKeys() const override; - const std::vector& getCodepoints() const override; + const std::vector& getCodepoints() const override; private: glm::vec2 delta; glm::vec2 cursor; @@ -49,7 +49,7 @@ private: bool cursorLocked = false; bool cursorDrag = false; Bindings bindings; - std::vector codepoints; + std::vector codepoints; std::vector pressedKeys; std::unordered_map> keyCallbacks; diff --git a/src/window/input.hpp b/src/window/input.hpp index 7ae082dd3..6e4c2a6c9 100644 --- a/src/window/input.hpp +++ b/src/window/input.hpp @@ -6,7 +6,6 @@ #include "util/HandlersList.hpp" - namespace dv { class value; } @@ -124,7 +123,6 @@ inline Mousecode mousecodes_all[] { Mousecode::BUTTON_5, }; - namespace input_util { void initialize(); Keycode keycode_from(const std::string& name); @@ -134,7 +132,7 @@ namespace input_util { std::string to_string(Keycode code); /// @return Mouse button label by keycode std::string to_string(Mousecode code); - + /// @return Key name by keycode std::string get_name(Keycode code); /// @return Mouse button name by keycode @@ -282,7 +280,7 @@ public: ) = 0; virtual const std::vector& getPressedKeys() const = 0; - virtual const std::vector& getCodepoints() const = 0; + virtual const std::vector& getCodepoints() const = 0; ObserverHandler addCallback(const std::string& name, KeyCallback callback) { return getBindings().require(name).onactived.add(callback); From 4e97923cee2a1581b83c6334afb99587286c6c1f Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Fri, 10 Oct 2025 17:27:40 +0300 Subject: [PATCH 23/41] fix cursors --- src/window/detail/window_sdl.cpp | 13 +++++++++++-- src/window/detail/window_sdl.hpp | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index b8a4054d0..c60870eb1 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -257,7 +257,13 @@ void window_sdl::setShouldClose(bool flag) { } void window_sdl::setCursor(CursorShape shape) { - SDL_Cursor *cursor = nullptr; + // so it method called each frame, we always recreate cursor. + // Refactor it + if (cursor) { + SDL_DestroyCursor(cursor); + cursor = nullptr; + } + switch (shape) { case CursorShape::ARROW: cursor = SDL_CreateSystemCursor( @@ -313,7 +319,6 @@ void window_sdl::setCursor(CursorShape shape) { } if (cursor) { SDL_SetCursor(cursor); - SDL_DestroyCursor(cursor); } } void window_sdl::toggleFullscreen() { @@ -321,6 +326,10 @@ void window_sdl::toggleFullscreen() { if (!SDL_SetWindowFullscreen(window, fullscreen)) { logger.error() << "Cant toggle fullscreen window: " << SDL_GetError(); } + if (!SDL_SyncWindow(window)) { + logger.error() << "Cant sync window after toggle fullscreen: " + << SDL_GetError(); + } } bool window_sdl::isFullscreen() const { return fullscreen; diff --git a/src/window/detail/window_sdl.hpp b/src/window/detail/window_sdl.hpp index e26fc6768..d6f507258 100644 --- a/src/window/detail/window_sdl.hpp +++ b/src/window/detail/window_sdl.hpp @@ -49,6 +49,7 @@ private: SDL_Window *window = nullptr; SDL_Renderer *renderer = nullptr; + SDL_Cursor *cursor = nullptr; SDL_GLContext context = nullptr; std::stack scissorStack; From 9f9978fb9898d668176e3848c116fe5798e914de Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Fri, 10 Oct 2025 17:42:22 +0300 Subject: [PATCH 24/41] fix focus problem --- src/window/detail/window_sdl.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index c60870eb1..4b5942dfe 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -149,7 +149,8 @@ window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { } SDL_WindowFlags flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | - SDL_WINDOW_HIGH_PIXEL_DENSITY; + // For process mouse clicks when not focused + SDL_WINDOW_NOT_FOCUSABLE; if (settings->fullscreen.get()) { flags |= SDL_WINDOW_FULLSCREEN; @@ -184,8 +185,6 @@ window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { SDL_GL_SetAttribute( SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG ); - // ?? - // SDL_GL_SetAttribute(SDL_WINDOW_ALLOW_HIGHDPI, false); #endif SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, settings->samples.get()); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); From 71ab542b6a18c9f57a3ade546f53ca2d0311224b Mon Sep 17 00:00:00 2001 From: Igor Stepanov Date: Fri, 10 Oct 2025 17:51:14 +0300 Subject: [PATCH 25/41] undo focus changes --- src/window/detail/window_sdl.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index 4b5942dfe..248d57974 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -148,9 +148,7 @@ window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { return; } - SDL_WindowFlags flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | - // For process mouse clicks when not focused - SDL_WINDOW_NOT_FOCUSABLE; + SDL_WindowFlags flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; if (settings->fullscreen.get()) { flags |= SDL_WINDOW_FULLSCREEN; From 3e48768e96149de985d6b711ef15b0255b017a03 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Fri, 10 Oct 2025 23:12:23 +0300 Subject: [PATCH 26/41] we not use sdl audio --- src/window/detail/window_sdl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index 248d57974..6024fe3c5 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -142,7 +142,7 @@ static bool initialize_gl(int width, int height) { } window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS)) { + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) { logger.error() << "failed to initialize SDL: " << SDL_GetError(); isSuccessfull = false; return; From 73f64c87ec955ff7ba76625235433006637a1d66 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Fri, 10 Oct 2025 23:19:51 +0300 Subject: [PATCH 27/41] Rename class --- src/window/detail/input_sdl.cpp | 2 +- src/window/detail/input_sdl.hpp | 6 ++--- src/window/detail/window_sdl.cpp | 42 ++++++++++++++++---------------- src/window/detail/window_sdl.hpp | 14 +++++------ 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/input_sdl.cpp index d45125fa6..1071357c9 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/input_sdl.cpp @@ -119,7 +119,7 @@ Mousecode input_util::mousecode_from(const std::string& name) { return static_cast(found->second); } -input_sdl::input_sdl(window_sdl& window) : window(window) { +input_sdl::input_sdl(SDLWindow& window) : window(window) { input_util::initialize(); // We should always get char stream (maybe) SDL_StartTextInput(window.getSdlWindow()); diff --git a/src/window/detail/input_sdl.hpp b/src/window/detail/input_sdl.hpp index a524f2023..8bdfe3159 100644 --- a/src/window/detail/input_sdl.hpp +++ b/src/window/detail/input_sdl.hpp @@ -3,7 +3,7 @@ #include "window/input.hpp" #include "window/window.hpp" -class window_sdl; +class SDLWindow; class input_sdl final : public Input { public: @@ -11,7 +11,7 @@ public: inline static constexpr short keys_buffer_size = mouse_keys_offset + sizeof(mousecodes_all) / sizeof(mousecodes_all[0]); - input_sdl(window_sdl& window); + input_sdl(SDLWindow& window); void pollEvents() override; @@ -53,5 +53,5 @@ private: std::vector pressedKeys; std::unordered_map> keyCallbacks; - window_sdl& window; + SDLWindow& window; }; \ No newline at end of file diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index 6024fe3c5..331f52b3f 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -141,7 +141,7 @@ static bool initialize_gl(int width, int height) { return true; } -window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { +SDLWindow::SDLWindow(DisplaySettings *settings, std::string title) noexcept { if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) { logger.error() << "failed to initialize SDL: " << SDL_GetError(); isSuccessfull = false; @@ -217,7 +217,7 @@ window_sdl::window_sdl(DisplaySettings *settings, std::string title) noexcept { logger.info() << "monitor content scale: " << scale; } -window_sdl::~window_sdl() { +SDLWindow::~SDLWindow() { if (window) { SDL_DestroyWindow(window); } @@ -228,32 +228,32 @@ window_sdl::~window_sdl() { } } -void window_sdl::swapBuffers() noexcept { +void SDLWindow::swapBuffers() noexcept { if (!SDL_GL_SwapWindow(window)) [[unlikely]] { // C++20 needed logger.error() << "Cant swap buffer: " << SDL_GetError(); } resetScissor(); } -bool window_sdl::isMaximized() const { +bool SDLWindow::isMaximized() const { return (SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) != 0; } -bool window_sdl::isFocused() const { +bool SDLWindow::isFocused() const { Uint32 flags = SDL_GetWindowFlags(window); return (flags & SDL_WINDOW_INPUT_FOCUS) != 0 || (flags & SDL_WINDOW_MOUSE_FOCUS) != 0; } -bool window_sdl::isIconified() const { +bool SDLWindow::isIconified() const { return (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) != 0; } -bool window_sdl::isShouldClose() const { +bool SDLWindow::isShouldClose() const { return toClose; } -void window_sdl::setShouldClose(bool flag) { +void SDLWindow::setShouldClose(bool flag) { toClose = flag; } -void window_sdl::setCursor(CursorShape shape) { +void SDLWindow::setCursor(CursorShape shape) { // so it method called each frame, we always recreate cursor. // Refactor it if (cursor) { @@ -318,7 +318,7 @@ void window_sdl::setCursor(CursorShape shape) { SDL_SetCursor(cursor); } } -void window_sdl::toggleFullscreen() { +void SDLWindow::toggleFullscreen() { fullscreen = !fullscreen; if (!SDL_SetWindowFullscreen(window, fullscreen)) { logger.error() << "Cant toggle fullscreen window: " << SDL_GetError(); @@ -328,11 +328,11 @@ void window_sdl::toggleFullscreen() { << SDL_GetError(); } } -bool window_sdl::isFullscreen() const { +bool SDLWindow::isFullscreen() const { return fullscreen; } -void window_sdl::setIcon(const ImageData *image) { +void SDLWindow::setIcon(const ImageData *image) { if (image == nullptr) { logger.error() << "Image is nullptr"; return; @@ -361,7 +361,7 @@ void window_sdl::setIcon(const ImageData *image) { SDL_DestroySurface(iconSurface); } -void window_sdl::pushScissor(glm::vec4 area) { +void SDLWindow::pushScissor(glm::vec4 area) { if (scissorStack.empty()) { glEnable(GL_SCISSOR_TEST); } @@ -389,13 +389,13 @@ void window_sdl::pushScissor(glm::vec4 area) { scissorArea = area; } -void window_sdl::resetScissor() { +void SDLWindow::resetScissor() { scissorArea = glm::vec4(0.0f, 0.0f, size.x, size.y); scissorStack = std::stack(); glDisable(GL_SCISSOR_TEST); } -void window_sdl::popScissor() { +void SDLWindow::popScissor() { if (scissorStack.empty()) { logger.warning() << "extra Window::popScissor call"; return; @@ -418,11 +418,11 @@ void window_sdl::popScissor() { scissorArea = area; } -double window_sdl::time() { +double SDLWindow::time() { return static_cast(SDL_GetTicksNS()) / 1'000'000'000; } -void window_sdl::setFramerate(int framerate) { +void SDLWindow::setFramerate(int framerate) { /*todo*/ if (!SDL_GL_SetSwapInterval(framerate)) { logger.error() << "Failed to set framerate: " << SDL_GetError(); @@ -431,7 +431,7 @@ void window_sdl::setFramerate(int framerate) { // todo: move somewhere // Possible do with SDL_RenderReadPixels -std::unique_ptr window_sdl::takeScreenshot() { +std::unique_ptr SDLWindow::takeScreenshot() { glBindFramebuffer(GL_FRAMEBUFFER, 0); auto data = std::make_unique(size.x * size.y * 3); glPixelStorei(GL_PACK_ALIGNMENT, 1); @@ -441,17 +441,17 @@ std::unique_ptr window_sdl::takeScreenshot() { ); } -[[nodiscard]] bool window_sdl::isValid() const { +[[nodiscard]] bool SDLWindow::isValid() const { return isSuccessfull; } -[[nodiscard]] SDL_Window *window_sdl::getSdlWindow() const { +[[nodiscard]] SDL_Window *SDLWindow::getSdlWindow() const { return window; } std::tuple, std::unique_ptr> Window::initialize( DisplaySettings *settings, std::string title ) { - auto window = std::make_unique(settings, title); + auto window = std::make_unique(settings, title); if (!window->isValid()) { return {nullptr, nullptr}; } diff --git a/src/window/detail/window_sdl.hpp b/src/window/detail/window_sdl.hpp index d6f507258..7c0fefa73 100644 --- a/src/window/detail/window_sdl.hpp +++ b/src/window/detail/window_sdl.hpp @@ -5,14 +5,14 @@ #include "window/window.hpp" -class window_sdl final : public Window { +class SDLWindow final : public Window { public: - window_sdl(DisplaySettings *settings, std::string title) noexcept; - ~window_sdl(); - window_sdl(const window_sdl &) = delete; - window_sdl(window_sdl &&) = default; - window_sdl &operator=(const window_sdl &) = delete; - window_sdl &operator=(window_sdl &&) = default; + SDLWindow(DisplaySettings *settings, std::string title) noexcept; + ~SDLWindow(); + SDLWindow(const SDLWindow &) = delete; + SDLWindow(SDLWindow &&) = default; + SDLWindow &operator=(const SDLWindow &) = delete; + SDLWindow &operator=(SDLWindow &&) = default; void swapBuffers() noexcept override; From a7a64f0bc2bbca0b26445eb67414f1aeb3eb7692 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Fri, 10 Oct 2025 23:23:39 +0300 Subject: [PATCH 28/41] Rename files --- src/window/detail/{input_sdl.cpp => SDLInput.cpp} | 4 ++-- src/window/detail/{input_sdl.hpp => SDLInput.hpp} | 0 src/window/detail/{window_sdl.cpp => SDLWindow.cpp} | 4 ++-- src/window/detail/{window_sdl.hpp => SDLWindow.hpp} | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename src/window/detail/{input_sdl.cpp => SDLInput.cpp} (99%) rename src/window/detail/{input_sdl.hpp => SDLInput.hpp} (100%) rename src/window/detail/{window_sdl.cpp => SDLWindow.cpp} (99%) rename src/window/detail/{window_sdl.hpp => SDLWindow.hpp} (100%) diff --git a/src/window/detail/input_sdl.cpp b/src/window/detail/SDLInput.cpp similarity index 99% rename from src/window/detail/input_sdl.cpp rename to src/window/detail/SDLInput.cpp index 1071357c9..c42ead4b1 100644 --- a/src/window/detail/input_sdl.cpp +++ b/src/window/detail/SDLInput.cpp @@ -1,4 +1,4 @@ -#include "window/detail/input_sdl.hpp" +#include "window/detail/SDLInput.hpp" #include #include @@ -13,7 +13,7 @@ #include "debug/Logger.hpp" #include "util/stringutil.hpp" -#include "window/detail/window_sdl.hpp" +#include "window/detail/SDLWindow.hpp" #include "window/input.hpp" static debug::Logger logger("input"); diff --git a/src/window/detail/input_sdl.hpp b/src/window/detail/SDLInput.hpp similarity index 100% rename from src/window/detail/input_sdl.hpp rename to src/window/detail/SDLInput.hpp diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/SDLWindow.cpp similarity index 99% rename from src/window/detail/window_sdl.cpp rename to src/window/detail/SDLWindow.cpp index 331f52b3f..ebc3f6a0a 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/SDLWindow.cpp @@ -1,4 +1,4 @@ -#include "window/detail/window_sdl.hpp" +#include "window/detail/SDLWindow.hpp" #include #include @@ -18,7 +18,7 @@ #include "graphics/core/ImageData.hpp" #include "graphics/core/Texture.hpp" #include "settings.hpp" -#include "window/detail/input_sdl.hpp" +#include "window/detail/SDLInput.hpp" static debug::Logger logger("window"); diff --git a/src/window/detail/window_sdl.hpp b/src/window/detail/SDLWindow.hpp similarity index 100% rename from src/window/detail/window_sdl.hpp rename to src/window/detail/SDLWindow.hpp From 685fbf66de47f76c7ec3aab85062846604944076 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Fri, 10 Oct 2025 23:23:52 +0300 Subject: [PATCH 29/41] Rename class --- src/window/detail/SDLInput.cpp | 34 ++++++++++++++++----------------- src/window/detail/SDLInput.hpp | 4 ++-- src/window/detail/SDLWindow.cpp | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/window/detail/SDLInput.cpp b/src/window/detail/SDLInput.cpp index c42ead4b1..bfda70b04 100644 --- a/src/window/detail/SDLInput.cpp +++ b/src/window/detail/SDLInput.cpp @@ -119,13 +119,13 @@ Mousecode input_util::mousecode_from(const std::string& name) { return static_cast(found->second); } -input_sdl::input_sdl(SDLWindow& window) : window(window) { +SDLInput::SDLInput(SDLWindow& window) : window(window) { input_util::initialize(); // We should always get char stream (maybe) SDL_StartTextInput(window.getSdlWindow()); } -void input_sdl::pollEvents() { +void SDLInput::pollEvents() { delta.x = 0.0f; delta.y = 0.0f; scroll = 0; @@ -226,70 +226,70 @@ void input_sdl::pollEvents() { } } -const char* input_sdl::getClipboardText() const { +const char* SDLInput::getClipboardText() const { return SDL_GetClipboardText(); } -void input_sdl::setClipboardText(const char* text) { +void SDLInput::setClipboardText(const char* text) { SDL_SetClipboardText(text); } -int input_sdl::getScroll() { +int SDLInput::getScroll() { return scroll; } -bool input_sdl::pressed(Keycode key) const { +bool SDLInput::pressed(Keycode key) const { int keycode = static_cast(key); if (keycode < 0 || keycode >= keys_buffer_size) { return false; } return keys[keycode]; } -bool input_sdl::jpressed(Keycode keycode) const { +bool SDLInput::jpressed(Keycode keycode) const { return pressed(keycode) && frames[static_cast(keycode)] == currentFrame; } -bool input_sdl::clicked(Mousecode code) const { +bool SDLInput::clicked(Mousecode code) const { return pressed( static_cast(mouse_keys_offset + static_cast(code)) ); } -bool input_sdl::jclicked(Mousecode code) const { +bool SDLInput::jclicked(Mousecode code) const { return clicked(code) && frames[static_cast(code) + mouse_keys_offset] == currentFrame; } -CursorState input_sdl::getCursor() const { +CursorState SDLInput::getCursor() const { return {isCursorLocked(), cursor, delta}; } -bool input_sdl::isCursorLocked() const { +bool SDLInput::isCursorLocked() const { return cursorLocked; } -void input_sdl::toggleCursor() { +void SDLInput::toggleCursor() { cursorDrag = false; cursorLocked = !cursorLocked; SDL_SetWindowRelativeMouseMode(window.getSdlWindow(), cursorLocked); } -Bindings& input_sdl::getBindings() { +Bindings& SDLInput::getBindings() { return bindings; } -const Bindings& input_sdl::getBindings() const { +const Bindings& SDLInput::getBindings() const { return bindings; } -ObserverHandler input_sdl::addKeyCallback(Keycode key, KeyCallback callback) { +ObserverHandler SDLInput::addKeyCallback(Keycode key, KeyCallback callback) { return keyCallbacks[key].add(std::move(callback)); } -const std::vector& input_sdl::getPressedKeys() const { +const std::vector& SDLInput::getPressedKeys() const { return pressedKeys; } -const std::vector& input_sdl::getCodepoints() const { +const std::vector& SDLInput::getCodepoints() const { return codepoints; } diff --git a/src/window/detail/SDLInput.hpp b/src/window/detail/SDLInput.hpp index 8bdfe3159..e94820318 100644 --- a/src/window/detail/SDLInput.hpp +++ b/src/window/detail/SDLInput.hpp @@ -5,13 +5,13 @@ class SDLWindow; -class input_sdl final : public Input { +class SDLInput final : public Input { public: inline static constexpr short mouse_keys_offset = 512; inline static constexpr short keys_buffer_size = mouse_keys_offset + sizeof(mousecodes_all) / sizeof(mousecodes_all[0]); - input_sdl(SDLWindow& window); + SDLInput(SDLWindow& window); void pollEvents() override; diff --git a/src/window/detail/SDLWindow.cpp b/src/window/detail/SDLWindow.cpp index ebc3f6a0a..86d66f56e 100644 --- a/src/window/detail/SDLWindow.cpp +++ b/src/window/detail/SDLWindow.cpp @@ -455,7 +455,7 @@ std::tuple, std::unique_ptr> Window::initialize( if (!window->isValid()) { return {nullptr, nullptr}; } - auto input = std::make_unique(*window); + auto input = std::make_unique(*window); return {std::move(window), std::move(input)}; } From 968d01274aee2771743b0e71d2e4c7d6cf146eb0 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Fri, 10 Oct 2025 23:28:22 +0300 Subject: [PATCH 30/41] Resave without format --- src/engine/Engine.cpp | 2 +- src/engine/Mainloop.cpp | 2 +- src/frontend/hud.cpp | 2 +- src/frontend/screens/LevelScreen.cpp | 2 +- src/frontend/screens/MenuScreen.cpp | 2 +- src/graphics/core/DrawContext.cpp | 2 +- src/graphics/render/BlocksPreview.cpp | 2 +- src/graphics/render/Skybox.cpp | 2 +- src/graphics/render/WorldRenderer.cpp | 2 +- src/graphics/ui/GUI.cpp | 2 +- src/graphics/ui/elements/ModelViewer.cpp | 2 +- src/graphics/ui/elements/TextBox.cpp | 2 +- src/logic/PlayerController.cpp | 2 +- src/window/{window.hpp => Window.hpp} | 0 src/window/detail/SDLInput.hpp | 2 +- src/window/detail/SDLWindow.hpp | 2 +- 16 files changed, 15 insertions(+), 15 deletions(-) rename src/window/{window.hpp => Window.hpp} (100%) diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index cc2863cad..212765f30 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -34,7 +34,7 @@ #include "util/platform.hpp" #include "window/Camera.hpp" #include "window/input.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "world/Level.hpp" #include "Mainloop.hpp" #include "ServerMainloop.hpp" diff --git a/src/engine/Mainloop.cpp b/src/engine/Mainloop.cpp index 838100379..a14c5464d 100644 --- a/src/engine/Mainloop.cpp +++ b/src/engine/Mainloop.cpp @@ -5,7 +5,7 @@ #include "devtools/Project.hpp" #include "frontend/screens/MenuScreen.hpp" #include "frontend/screens/LevelScreen.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "world/Level.hpp" #include "graphics/ui/GUI.hpp" #include "graphics/ui/elements/Container.hpp" diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 8484c4a9f..c8301d267 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -41,7 +41,7 @@ #include "voxels/GlobalChunks.hpp" #include "window/Camera.hpp" #include "window/input.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "world/Level.hpp" #include "world/World.hpp" #include "debug/Logger.hpp" diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index 6d65653e6..d398b3cc8 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -29,7 +29,7 @@ #include "util/stringutil.hpp" #include "voxels/Chunks.hpp" #include "window/Camera.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "world/Level.hpp" #include "world/World.hpp" diff --git a/src/frontend/screens/MenuScreen.cpp b/src/frontend/screens/MenuScreen.cpp index ffe1e2c73..c13394945 100644 --- a/src/frontend/screens/MenuScreen.cpp +++ b/src/frontend/screens/MenuScreen.cpp @@ -8,7 +8,7 @@ #include "graphics/core/Texture.hpp" #include "assets/Assets.hpp" #include "maths/UVRegion.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "window/Camera.hpp" #include "engine/Engine.hpp" diff --git a/src/graphics/core/DrawContext.cpp b/src/graphics/core/DrawContext.cpp index 67814de02..fc37fd46d 100644 --- a/src/graphics/core/DrawContext.cpp +++ b/src/graphics/core/DrawContext.cpp @@ -6,7 +6,7 @@ #include "Batch2D.hpp" #include "Framebuffer.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" static void set_blend_mode(BlendMode mode) { switch (mode) { diff --git a/src/graphics/render/BlocksPreview.cpp b/src/graphics/render/BlocksPreview.cpp index 971748436..9a1bf97dd 100644 --- a/src/graphics/render/BlocksPreview.cpp +++ b/src/graphics/render/BlocksPreview.cpp @@ -6,7 +6,7 @@ #include "frontend/ContentGfxCache.hpp" #include "voxels/Block.hpp" #include "window/Camera.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "graphics/core/Atlas.hpp" #include "graphics/core/Batch3D.hpp" #include "graphics/core/Framebuffer.hpp" diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index 64bbf71db..eb90feef8 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -7,7 +7,7 @@ #include "graphics/core/Cubemap.hpp" #include "graphics/core/Framebuffer.hpp" #include "graphics/core/DrawContext.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "window/Camera.hpp" #include "maths/UVRegion.hpp" diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index e459f8538..faa8fdc60 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -28,7 +28,7 @@ #include "voxels/Chunk.hpp" #include "voxels/Chunks.hpp" #include "voxels/Pathfinding.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "world/Level.hpp" #include "world/LevelEvents.hpp" #include "world/World.hpp" diff --git a/src/graphics/ui/GUI.cpp b/src/graphics/ui/GUI.cpp index 68642fe96..c58cded60 100644 --- a/src/graphics/ui/GUI.cpp +++ b/src/graphics/ui/GUI.cpp @@ -20,7 +20,7 @@ #include "graphics/core/Shader.hpp" #include "gui_util.hpp" #include "window/Camera.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "window/input.hpp" #include diff --git a/src/graphics/ui/elements/ModelViewer.cpp b/src/graphics/ui/elements/ModelViewer.cpp index 4dd514ab9..acc8170c1 100644 --- a/src/graphics/ui/elements/ModelViewer.cpp +++ b/src/graphics/ui/elements/ModelViewer.cpp @@ -10,7 +10,7 @@ #include "graphics/core/Shader.hpp" #include "graphics/core/Framebuffer.hpp" #include "graphics/core/DrawContext.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "../GUI.hpp" // TODO: remove diff --git a/src/graphics/ui/elements/TextBox.cpp b/src/graphics/ui/elements/TextBox.cpp index 4be01eafb..81732348f 100644 --- a/src/graphics/ui/elements/TextBox.cpp +++ b/src/graphics/ui/elements/TextBox.cpp @@ -16,7 +16,7 @@ #include "graphics/core/Font.hpp" #include "graphics/ui/markdown.hpp" #include "util/stringutil.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "devtools/actions.hpp" #include "../markdown.hpp" diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index 852f76f3c..8021db511 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -24,7 +24,7 @@ #include "voxels/Chunks.hpp" #include "voxels/voxel.hpp" #include "window/Camera.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" #include "window/input.hpp" #include "world/Level.hpp" diff --git a/src/window/window.hpp b/src/window/Window.hpp similarity index 100% rename from src/window/window.hpp rename to src/window/Window.hpp diff --git a/src/window/detail/SDLInput.hpp b/src/window/detail/SDLInput.hpp index e94820318..707eed78e 100644 --- a/src/window/detail/SDLInput.hpp +++ b/src/window/detail/SDLInput.hpp @@ -1,7 +1,7 @@ #include #include "window/input.hpp" -#include "window/window.hpp" +#include "window/Window.hpp" class SDLWindow; diff --git a/src/window/detail/SDLWindow.hpp b/src/window/detail/SDLWindow.hpp index 7c0fefa73..581d0fb34 100644 --- a/src/window/detail/SDLWindow.hpp +++ b/src/window/detail/SDLWindow.hpp @@ -3,7 +3,7 @@ #include -#include "window/window.hpp" +#include "window/Window.hpp" class SDLWindow final : public Window { public: From 726f004893904821bee18cac282b1caaf184a52a Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sat, 11 Oct 2025 09:31:41 +0300 Subject: [PATCH 31/41] add switching text edit state --- src/graphics/ui/elements/UINode.cpp | 3 +++ src/window/detail/SDLInput.cpp | 11 +++++++++-- src/window/detail/SDLInput.hpp | 5 ++++- src/window/input.hpp | 3 +++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/graphics/ui/elements/UINode.cpp b/src/graphics/ui/elements/UINode.cpp index 1e8f48d6e..3adcb1da9 100644 --- a/src/graphics/ui/elements/UINode.cpp +++ b/src/graphics/ui/elements/UINode.cpp @@ -4,6 +4,7 @@ #include "Container.hpp" #include "graphics/core/Batch2D.hpp" +#include "graphics/ui/GUI.hpp" using gui::UINode; using gui::Align; @@ -107,11 +108,13 @@ bool UINode::isPressed() const { } void UINode::onFocus() { + gui.getInput().startTextInput(); focused = true; focusCallbacks.notify(gui); } void UINode::defocus() { + gui.getInput().stopTextInput(); focused = false; defocusCallbacks.notify(gui); } diff --git a/src/window/detail/SDLInput.cpp b/src/window/detail/SDLInput.cpp index bfda70b04..5eec64c12 100644 --- a/src/window/detail/SDLInput.cpp +++ b/src/window/detail/SDLInput.cpp @@ -121,8 +121,6 @@ Mousecode input_util::mousecode_from(const std::string& name) { SDLInput::SDLInput(SDLWindow& window) : window(window) { input_util::initialize(); - // We should always get char stream (maybe) - SDL_StartTextInput(window.getSdlWindow()); } void SDLInput::pollEvents() { @@ -234,6 +232,15 @@ void SDLInput::setClipboardText(const char* text) { SDL_SetClipboardText(text); } +void SDLInput::startTextInput() { + logger.debug() << "Start text input"; + SDL_StartTextInput(window.getSdlWindow()); +} +void SDLInput::stopTextInput() { + logger.debug() << "Stop text input"; + SDL_StopTextInput(window.getSdlWindow()); +} + int SDLInput::getScroll() { return scroll; } diff --git a/src/window/detail/SDLInput.hpp b/src/window/detail/SDLInput.hpp index 707eed78e..dd1ec2447 100644 --- a/src/window/detail/SDLInput.hpp +++ b/src/window/detail/SDLInput.hpp @@ -1,7 +1,7 @@ #include -#include "window/input.hpp" #include "window/Window.hpp" +#include "window/input.hpp" class SDLWindow; @@ -18,6 +18,9 @@ public: const char* getClipboardText() const override; void setClipboardText(const char* str) override; + void startTextInput() override; + void stopTextInput() override; + int getScroll() override; bool pressed(Keycode keycode) const override; diff --git a/src/window/input.hpp b/src/window/input.hpp index 6e4c2a6c9..dfd5d9d5c 100644 --- a/src/window/input.hpp +++ b/src/window/input.hpp @@ -258,6 +258,9 @@ public: virtual const char* getClipboardText() const = 0; virtual void setClipboardText(const char* str) = 0; + virtual void startTextInput() = 0; + virtual void stopTextInput() = 0; + virtual int getScroll() = 0; virtual bool pressed(Keycode keycode) const = 0; From dfd0100d175a68839b1a30d6b30679396c959df0 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sat, 11 Oct 2025 10:02:32 +0300 Subject: [PATCH 32/41] Use textInput state only for TextBox --- src/graphics/ui/elements/TextBox.cpp | 7 +++++++ src/graphics/ui/elements/TextBox.hpp | 1 + src/graphics/ui/elements/UINode.cpp | 2 -- src/graphics/ui/elements/UINode.hpp | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/graphics/ui/elements/TextBox.cpp b/src/graphics/ui/elements/TextBox.cpp index 81732348f..ed5fb436e 100644 --- a/src/graphics/ui/elements/TextBox.cpp +++ b/src/graphics/ui/elements/TextBox.cpp @@ -616,8 +616,15 @@ bool TextBox::isAutoResize() const { return autoresize; } +void TextBox::defocus() { + Container::defocus(); + gui.getInput().stopTextInput(); +} + + void TextBox::onFocus() { Container::onFocus(); + gui.getInput().startTextInput(); if (onEditStart) { setCaret(input.size()); onEditStart(); diff --git a/src/graphics/ui/elements/TextBox.hpp b/src/graphics/ui/elements/TextBox.hpp index c4b88f909..5a8916694 100644 --- a/src/graphics/ui/elements/TextBox.hpp +++ b/src/graphics/ui/elements/TextBox.hpp @@ -230,6 +230,7 @@ namespace gui { virtual bool isShowLineNumbers() const; virtual void reposition() override; + virtual void defocus() override; virtual void onFocus() override; virtual void refresh() override; virtual void doubleClick(int x, int y) override; diff --git a/src/graphics/ui/elements/UINode.cpp b/src/graphics/ui/elements/UINode.cpp index 3adcb1da9..ee63a02b5 100644 --- a/src/graphics/ui/elements/UINode.cpp +++ b/src/graphics/ui/elements/UINode.cpp @@ -108,13 +108,11 @@ bool UINode::isPressed() const { } void UINode::onFocus() { - gui.getInput().startTextInput(); focused = true; focusCallbacks.notify(gui); } void UINode::defocus() { - gui.getInput().stopTextInput(); focused = false; defocusCallbacks.notify(gui); } diff --git a/src/graphics/ui/elements/UINode.hpp b/src/graphics/ui/elements/UINode.hpp index fc64527fd..f1536094e 100644 --- a/src/graphics/ui/elements/UINode.hpp +++ b/src/graphics/ui/elements/UINode.hpp @@ -192,6 +192,7 @@ namespace gui { virtual UINode* listenFocus(const onaction& action); virtual UINode* listenDefocus(const onaction& action); + virtual void defocus(); virtual void onFocus(); virtual void doubleClick(int x, int y); virtual void click(int x, int y); @@ -201,7 +202,6 @@ namespace gui { virtual void scrolled(int value); bool isPressed() const; - void defocus(); bool isFocused() const; /// @brief Check if element catches all user input when focused From 18d8c9cc981cf68070d42977a5bce3beb71deb9e Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sat, 11 Oct 2025 10:07:55 +0300 Subject: [PATCH 33/41] clean --- src/graphics/ui/elements/UINode.cpp | 1 - src/window/detail/SDLInput.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/graphics/ui/elements/UINode.cpp b/src/graphics/ui/elements/UINode.cpp index ee63a02b5..1e8f48d6e 100644 --- a/src/graphics/ui/elements/UINode.cpp +++ b/src/graphics/ui/elements/UINode.cpp @@ -4,7 +4,6 @@ #include "Container.hpp" #include "graphics/core/Batch2D.hpp" -#include "graphics/ui/GUI.hpp" using gui::UINode; using gui::Align; diff --git a/src/window/detail/SDLInput.cpp b/src/window/detail/SDLInput.cpp index 5eec64c12..38a25fae7 100644 --- a/src/window/detail/SDLInput.cpp +++ b/src/window/detail/SDLInput.cpp @@ -233,11 +233,9 @@ void SDLInput::setClipboardText(const char* text) { } void SDLInput::startTextInput() { - logger.debug() << "Start text input"; SDL_StartTextInput(window.getSdlWindow()); } void SDLInput::stopTextInput() { - logger.debug() << "Stop text input"; SDL_StopTextInput(window.getSdlWindow()); } From 378f5886583a0777cee91d80ce235aff32630b76 Mon Sep 17 00:00:00 2001 From: Ygrik2003 <59407669+Ygrik2003@users.noreply.github.com> Date: Tue, 14 Oct 2025 18:07:20 +0300 Subject: [PATCH 34/41] reset cmake min version changes --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1723ae29c..6966e81fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.11) +cmake_minimum_required(VERSION 3.5) project(VoxelEngine) set(CMAKE_CXX_STANDARD 17) From 7a9587bf8ff75ea95ab0ca4553d71e5b32f4de32 Mon Sep 17 00:00:00 2001 From: VOXEL <111713723+VOXEL0798@users.noreply.github.com> Date: Wed, 15 Oct 2025 01:25:25 +0300 Subject: [PATCH 35/41] Update flake.lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Обновил flake.lock поскольку в прежней версии были каналы в которых еще небыло sdl3, и собрать проект было не возможно. --- flake.lock | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 55f50fc42..ff2363b8d 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1722802969, - "narHash": "sha256-bPhyAXNnVerBZusxOuPMhMm0X7hSFLFKcH+7ynfgLjs=", + "lastModified": 1760349414, + "narHash": "sha256-W4Ri1ZwYuNcBzqQQa7NnWfrv0wHMo7rduTWjIeU9dZk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "785feb91183a50959823ff9ba9ef673105259cd5", + "rev": "c12c63cd6c5eb34c7b4c3076c6a99e00fcab86ec", "type": "github" }, "original": { @@ -59,3 +59,4 @@ "root": "root", "version": 7 } + From 52db37ae692752dec5640f332b40d9b643630c15 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Wed, 15 Oct 2025 22:30:05 +0300 Subject: [PATCH 36/41] Try fix ubuntu mouse grabbing --- src/window/detail/SDLInput.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/window/detail/SDLInput.cpp b/src/window/detail/SDLInput.cpp index 38a25fae7..1d977e814 100644 --- a/src/window/detail/SDLInput.cpp +++ b/src/window/detail/SDLInput.cpp @@ -277,6 +277,7 @@ void SDLInput::toggleCursor() { cursorDrag = false; cursorLocked = !cursorLocked; SDL_SetWindowRelativeMouseMode(window.getSdlWindow(), cursorLocked); + SDL_SetWindowMouseGrab(window.getSdlWindow(), cursorLocked); } Bindings& SDLInput::getBindings() { From 8481c5c2ba32b8fb06ce256a24574ddcf5bb7acb Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Fri, 17 Oct 2025 21:47:33 +0300 Subject: [PATCH 37/41] fix sdl build in cicd --- .github/workflows/appimage.yml | 9 +++++++++ .github/workflows/cmake.yml | 8 ++++++++ src/window/detail/SDLInput.cpp | 1 - 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 457040ae5..7b6e738da 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -26,6 +26,15 @@ jobs: sudo apt-get install -y build-essential libglew-dev libglew2.2 \ libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev \ libcurl4-openssl-dev libgtest-dev cmake squashfs-tools valgrind + # dependency for building sdl + # https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md + sudo apt-get install -y build-essential git make \ + pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev \ + libaudio-dev libfribidi-dev libjack-dev libsndio-dev libx11-dev libxext-dev \ + libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev \ + libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \ + libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev \ + libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev # fix luajit paths sudo ln -s /usr/lib/x86_64-linux-gnu/libluajit-5.1.a /usr/lib/x86_64-linux-gnu/liblua5.1.a sudo ln -s /usr/include/luajit-2.1 /usr/include/lua diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 973249e6f..27d128226 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -40,6 +40,14 @@ jobs: run: | sudo apt-get update sudo apt-get install libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev libvorbis-dev libgtest-dev libcurl4-openssl-dev + # dependency for building sdl + # https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md + sudo apt-get install -y build-essential git make \ + pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev \ + libaudio-dev libfribidi-dev libjack-dev libsndio-dev libx11-dev libxext-dev \ + libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev \ + libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \ + libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev # fix luajit paths sudo ln -s /usr/lib/x86_64-linux-gnu/libluajit-5.1.a /usr/lib/x86_64-linux-gnu/liblua-5.1.a sudo ln -s /usr/include/luajit-2.1 /usr/include/lua diff --git a/src/window/detail/SDLInput.cpp b/src/window/detail/SDLInput.cpp index 1d977e814..38a25fae7 100644 --- a/src/window/detail/SDLInput.cpp +++ b/src/window/detail/SDLInput.cpp @@ -277,7 +277,6 @@ void SDLInput::toggleCursor() { cursorDrag = false; cursorLocked = !cursorLocked; SDL_SetWindowRelativeMouseMode(window.getSdlWindow(), cursorLocked); - SDL_SetWindowMouseGrab(window.getSdlWindow(), cursorLocked); } Bindings& SDLInput::getBindings() { From 62ab514f132ecb1fa7cccba601390776798a6a70 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Fri, 17 Oct 2025 22:36:56 +0300 Subject: [PATCH 38/41] fix after merge --- src/window/Window.hpp | 6 +----- src/window/detail/SDLWindow.cpp | 17 +++++++++-------- src/window/detail/SDLWindow.hpp | 4 ++-- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/window/Window.hpp b/src/window/Window.hpp index 3cce5c863..f56b97f52 100644 --- a/src/window/Window.hpp +++ b/src/window/Window.hpp @@ -9,11 +9,7 @@ class ImageData; class Input; struct DisplaySettings; -enum class WindowMode { - WINDOWED, - FULLSCREEN, - BORDERLESS -}; +enum class WindowMode { WINDOWED, FULLSCREEN, BORDERLESS }; class Window { public: diff --git a/src/window/detail/SDLWindow.cpp b/src/window/detail/SDLWindow.cpp index 86d66f56e..86cfe6491 100644 --- a/src/window/detail/SDLWindow.cpp +++ b/src/window/detail/SDLWindow.cpp @@ -18,6 +18,7 @@ #include "graphics/core/ImageData.hpp" #include "graphics/core/Texture.hpp" #include "settings.hpp" +#include "window/Window.hpp" #include "window/detail/SDLInput.hpp" static debug::Logger logger("window"); @@ -318,18 +319,18 @@ void SDLWindow::setCursor(CursorShape shape) { SDL_SetCursor(cursor); } } -void SDLWindow::toggleFullscreen() { - fullscreen = !fullscreen; - if (!SDL_SetWindowFullscreen(window, fullscreen)) { +void SDLWindow::setMode(WindowMode mode) { + // WindowMode::WINDOWED by default have the next options as disbled + if (!SDL_SetWindowFullscreen(window, mode == WindowMode::FULLSCREEN)) { logger.error() << "Cant toggle fullscreen window: " << SDL_GetError(); } - if (!SDL_SyncWindow(window)) { - logger.error() << "Cant sync window after toggle fullscreen: " - << SDL_GetError(); + if (!SDL_SetWindowBordered(window, mode == WindowMode::BORDERLESS)) { + logger.error() << "Cant toggle bordered window: " << SDL_GetError(); } } -bool SDLWindow::isFullscreen() const { - return fullscreen; + +WindowMode SDLWindow::getMode() const { + return mode; } void SDLWindow::setIcon(const ImageData *image) { diff --git a/src/window/detail/SDLWindow.hpp b/src/window/detail/SDLWindow.hpp index 581d0fb34..8e9f23e8a 100644 --- a/src/window/detail/SDLWindow.hpp +++ b/src/window/detail/SDLWindow.hpp @@ -24,8 +24,8 @@ public: void setShouldClose(bool flag) override; void setCursor(CursorShape shape) override; - void toggleFullscreen() override; - bool isFullscreen() const override; + void setMode(WindowMode mode) override; + WindowMode getMode() const override; void setIcon(const ImageData *image) override; From 686a20cc810d74d79b66b4f516446c26c53e7ee5 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Fri, 17 Oct 2025 22:55:21 +0300 Subject: [PATCH 39/41] fix after merge --- src/window/detail/SDLWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/window/detail/SDLWindow.cpp b/src/window/detail/SDLWindow.cpp index 86cfe6491..01be25cd9 100644 --- a/src/window/detail/SDLWindow.cpp +++ b/src/window/detail/SDLWindow.cpp @@ -151,7 +151,8 @@ SDLWindow::SDLWindow(DisplaySettings *settings, std::string title) noexcept { SDL_WindowFlags flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; - if (settings->fullscreen.get()) { + if (settings->windowMode.get() == + static_cast(WindowMode::FULLSCREEN)) { flags |= SDL_WINDOW_FULLSCREEN; } From 14829f827ce63a9fad915e54cc18f5e4bb35a9e4 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sat, 18 Oct 2025 00:43:13 +0300 Subject: [PATCH 40/41] fix fps settings --- src/engine/Engine.cpp | 1 + src/window/detail/SDLWindow.cpp | 16 ++++++++++++++-- src/window/detail/SDLWindow.hpp | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index a977f354b..71bcd580f 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -308,6 +308,7 @@ void Engine::nextFrame() { : settings.display.framerate.get() ); window->swapBuffers(); + // todo: process it on another thread input->pollEvents(); } diff --git a/src/window/detail/SDLWindow.cpp b/src/window/detail/SDLWindow.cpp index 01be25cd9..7277c080e 100644 --- a/src/window/detail/SDLWindow.cpp +++ b/src/window/detail/SDLWindow.cpp @@ -18,6 +18,7 @@ #include "graphics/core/ImageData.hpp" #include "graphics/core/Texture.hpp" #include "settings.hpp" +#include "util/platform.hpp" #include "window/Window.hpp" #include "window/detail/SDLInput.hpp" @@ -231,6 +232,17 @@ SDLWindow::~SDLWindow() { } void SDLWindow::swapBuffers() noexcept { + if (framerate > 0) { + auto elapsedTime = time() - prevSwap; + auto frameTime = 1.0 / framerate; + if (elapsedTime < frameTime) { + platform::sleep( + static_cast((frameTime - elapsedTime) * 1000) + ); + } + prevSwap = time(); + } + if (!SDL_GL_SwapWindow(window)) [[unlikely]] { // C++20 needed logger.error() << "Cant swap buffer: " << SDL_GetError(); } @@ -425,10 +437,10 @@ double SDLWindow::time() { } void SDLWindow::setFramerate(int framerate) { - /*todo*/ - if (!SDL_GL_SetSwapInterval(framerate)) { + if (!SDL_GL_SetSwapInterval(framerate == -1)) { logger.error() << "Failed to set framerate: " << SDL_GetError(); } + this->framerate = framerate; } // todo: move somewhere diff --git a/src/window/detail/SDLWindow.hpp b/src/window/detail/SDLWindow.hpp index 8e9f23e8a..f1b32e837 100644 --- a/src/window/detail/SDLWindow.hpp +++ b/src/window/detail/SDLWindow.hpp @@ -47,6 +47,9 @@ private: bool toClose = false; bool fullscreen = false; + double framerate = -1; + double prevSwap = 0.0; + SDL_Window *window = nullptr; SDL_Renderer *renderer = nullptr; SDL_Cursor *cursor = nullptr; From 9e4b1c9d2c34537c7cc4b283654c81b8cacd7c84 Mon Sep 17 00:00:00 2001 From: Stepanov Igor Date: Sat, 18 Oct 2025 01:21:31 +0300 Subject: [PATCH 41/41] fix window mode --- src/window/detail/SDLWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/window/detail/SDLWindow.cpp b/src/window/detail/SDLWindow.cpp index 7277c080e..a0d6140a1 100644 --- a/src/window/detail/SDLWindow.cpp +++ b/src/window/detail/SDLWindow.cpp @@ -340,6 +340,7 @@ void SDLWindow::setMode(WindowMode mode) { if (!SDL_SetWindowBordered(window, mode == WindowMode::BORDERLESS)) { logger.error() << "Cant toggle bordered window: " << SDL_GetError(); } + this->mode = mode; } WindowMode SDLWindow::getMode() const {