From 9969ce018b23df7759651e16ac0a25a03961414d Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Sat, 29 Jan 2022 20:35:08 +0100 Subject: [PATCH] Backend abstraction --- CMakeLists.txt | 3 + core/CMakeLists.txt | 26 +- core/backends/glfw/backend.cpp | 301 ++++++++++++++++++ .../glfw}/imgui/imgui_impl_glfw.cpp | 0 .../glfw}/imgui/imgui_impl_glfw.h | 0 core/backends/glfw/keybinds.h | 24 ++ core/src/backend.h | 12 + core/src/core.cpp | 266 +--------------- core/src/glfw_window.h | 6 - core/src/gui/dialogs/loading_screen.cpp | 21 +- core/src/gui/dialogs/loading_screen.h | 2 - core/src/gui/main_window.cpp | 14 +- core/src/gui/menus/display.cpp | 3 +- core/src/gui/widgets/frequency_select.cpp | 20 +- core/src/gui/widgets/waterfall.cpp | 12 +- misc_modules/frequency_manager/src/main.cpp | 5 +- misc_modules/scheduler/src/main.cpp | 5 +- misc_modules/scheduler/src/sched_task.h | 5 +- 18 files changed, 410 insertions(+), 315 deletions(-) create mode 100644 core/backends/glfw/backend.cpp rename core/{src => backends/glfw}/imgui/imgui_impl_glfw.cpp (100%) rename core/{src => backends/glfw}/imgui/imgui_impl_glfw.h (100%) create mode 100644 core/backends/glfw/keybinds.h create mode 100644 core/src/backend.h delete mode 100644 core/src/glfw_window.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 788ce053..b337abb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,9 @@ else() set(CMAKE_INSTALL_PREFIX "/usr") endif() +# Backends +option(OPT_BACKEND_GLFW "Use the GLFW backend" ON) + # Compatibility Options option(OPT_OVERRIDE_STD_FILESYSTEM "Use a local version of std::filesystem on systems that don't have it yet" OFF) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 5a37ca1f..13764c47 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -17,8 +17,13 @@ if (MSVC) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) endif () +# Configure backend sources +if (OPT_BACKEND_GLFW) + file(GLOB_RECURSE BACKEND_SRC "backends/glfw/*.cpp" "backends/glfw/*.c") +endif (OPT_BACKEND_GLFW) + # Add code to dyn lib -add_library(sdrpp_core SHARED ${SRC}) +add_library(sdrpp_core SHARED ${SRC} ${BACKEND_SRC}) # Set compiler options if (MSVC) @@ -36,6 +41,25 @@ target_compile_definitions(sdrpp_core PUBLIC INSTALL_PREFIX="${CMAKE_INSTALL_PRE target_include_directories(sdrpp_core PUBLIC "src/") target_include_directories(sdrpp_core PUBLIC "src/imgui") +# Configure backend includes and libraries +if (OPT_BACKEND_GLFW) + target_include_directories(sdrpp_core PUBLIC "backends/glfw") + target_include_directories(sdrpp_core PUBLIC "backends/glfw/imgui") + + if (MSVC) + # GLFW3 + find_package(glfw3 CONFIG REQUIRED) + target_link_libraries(sdrpp_core PUBLIC glfw) + else() + find_package(PkgConfig) + pkg_check_modules(GLFW3 REQUIRED glfw3) + + target_include_directories(sdrpp_core PUBLIC ${GLFW3_INCLUDE_DIRS}) + target_link_directories(sdrpp_core PUBLIC ${GLFW3_LIBRARY_DIRS}) + target_link_libraries(sdrpp_core PUBLIC ${GLFW3_LIBRARIES}) + endif() +endif (OPT_BACKEND_GLFW) + # Link to libcorrect if (USE_INTERNAL_LIBCORRECT) target_include_directories(sdrpp_core PUBLIC "libcorrect/include") diff --git a/core/backends/glfw/backend.cpp b/core/backends/glfw/backend.cpp new file mode 100644 index 00000000..232b9e06 --- /dev/null +++ b/core/backends/glfw/backend.cpp @@ -0,0 +1,301 @@ +#include +#include "imgui.h" +#include "imgui_impl_glfw.h" +#include "imgui_impl_opengl3.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace backend { + const char* OPENGL_VERSIONS_GLSL[] = { + "#version 120", + "#version 300 es", + "#version 120" + }; + + const int OPENGL_VERSIONS_MAJOR[] = { + 3, + 3, + 2 + }; + + const int OPENGL_VERSIONS_MINOR[] = { + 0, + 1, + 1 + }; + + const bool OPENGL_VERSIONS_IS_ES[] = { + false, + true, + false + }; + + #define OPENGL_VERSION_COUNT (sizeof(OPENGL_VERSIONS_GLSL) / sizeof(char*)) + + bool maximized = false; + bool fullScreen = false; + int winHeight; + int winWidth; + bool _maximized = maximized; + int fsWidth, fsHeight, fsPosX, fsPosY; + int _winWidth, _winHeight; + GLFWwindow* window; + GLFWmonitor* monitor; + + static void glfw_error_callback(int error, const char* description) { + spdlog::error("Glfw Error {0}: {1}", error, description); + } + + static void maximized_callback(GLFWwindow* window, int n) { + if (n == GLFW_TRUE) { + maximized = true; + } + else { + maximized = false; + } + } + + int init(std::string resDir) { + // Load config + core::configManager.acquire(); + winWidth = core::configManager.conf["windowSize"]["w"]; + winHeight = core::configManager.conf["windowSize"]["h"]; + maximized = core::configManager.conf["maximized"]; + fullScreen = core::configManager.conf["fullscreen"]; + core::configManager.release(); + + // Setup window + glfwSetErrorCallback(glfw_error_callback); + if (!glfwInit()) { + return 1; + } + + #ifdef __APPLE__ + // GL 3.2 + GLSL 150 + const char* glsl_version = "#version 150"; + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac + + // Create window with graphics context + monitor = glfwGetPrimaryMonitor(); + window = glfwCreateWindow(winWidth, winHeight, "SDR++ v" VERSION_STR " (Built at " __TIME__ ", " __DATE__ ")", NULL, NULL); + if (window == NULL) + return 1; + glfwMakeContextCurrent(window); + #else + const char* glsl_version = "#version 120"; + monitor = NULL; + for (int i = 0; i < OPENGL_VERSION_COUNT; i++) { + glsl_version = OPENGL_VERSIONS_GLSL[i]; + glfwWindowHint(GLFW_CLIENT_API, OPENGL_VERSIONS_IS_ES[i] ? GLFW_OPENGL_ES_API : GLFW_OPENGL_API); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, OPENGL_VERSIONS_MAJOR[i]); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, OPENGL_VERSIONS_MINOR[i]); + + // Create window with graphics context + monitor = glfwGetPrimaryMonitor(); + window = glfwCreateWindow(winWidth, winHeight, "SDR++ v" VERSION_STR " (Built at " __TIME__ ", " __DATE__ ")", NULL, NULL); + if (window == NULL) { + spdlog::info("OpenGL {0}.{1} {2}was not supported", OPENGL_VERSIONS_MAJOR[i], OPENGL_VERSIONS_MINOR[i], OPENGL_VERSIONS_IS_ES[i] ? "ES " : ""); + continue; + } + spdlog::info("Using OpenGL {0}.{1}{2}", OPENGL_VERSIONS_MAJOR[i], OPENGL_VERSIONS_MINOR[i], OPENGL_VERSIONS_IS_ES[i] ? " ES" : ""); + glfwMakeContextCurrent(window); + break; + } + + #endif + + // Add callback for max/min if GLFW supports it + #if (GLFW_VERSION_MAJOR == 3) && (GLFW_VERSION_MINOR >= 3) + if (maximized) { + glfwMaximizeWindow(window); + } + + glfwSetWindowMaximizeCallback(window, maximized_callback); + #endif + + // Load app icon + if (!std::filesystem::is_regular_file(resDir + "/icons/sdrpp.png")) { + spdlog::error("Icon file '{0}' doesn't exist!", resDir + "/icons/sdrpp.png"); + return 1; + } + + GLFWimage icons[10]; + icons[0].pixels = stbi_load(((std::string)(resDir + "/icons/sdrpp.png")).c_str(), &icons[0].width, &icons[0].height, 0, 4); + icons[1].pixels = (unsigned char*)malloc(16 * 16 * 4); + icons[1].width = icons[1].height = 16; + icons[2].pixels = (unsigned char*)malloc(24 * 24 * 4); + icons[2].width = icons[2].height = 24; + icons[3].pixels = (unsigned char*)malloc(32 * 32 * 4); + icons[3].width = icons[3].height = 32; + icons[4].pixels = (unsigned char*)malloc(48 * 48 * 4); + icons[4].width = icons[4].height = 48; + icons[5].pixels = (unsigned char*)malloc(64 * 64 * 4); + icons[5].width = icons[5].height = 64; + icons[6].pixels = (unsigned char*)malloc(96 * 96 * 4); + icons[6].width = icons[6].height = 96; + icons[7].pixels = (unsigned char*)malloc(128 * 128 * 4); + icons[7].width = icons[7].height = 128; + icons[8].pixels = (unsigned char*)malloc(196 * 196 * 4); + icons[8].width = icons[8].height = 196; + icons[9].pixels = (unsigned char*)malloc(256 * 256 * 4); + icons[9].width = icons[9].height = 256; + stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[1].pixels, 16, 16, 16 * 4, 4); + stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[2].pixels, 24, 24, 24 * 4, 4); + stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[3].pixels, 32, 32, 32 * 4, 4); + stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[4].pixels, 48, 48, 48 * 4, 4); + stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[5].pixels, 64, 64, 64 * 4, 4); + stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[6].pixels, 96, 96, 96 * 4, 4); + stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[7].pixels, 128, 128, 128 * 4, 4); + stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[8].pixels, 196, 196, 196 * 4, 4); + stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[9].pixels, 256, 256, 256 * 4, 4); + glfwSetWindowIcon(window, 10, icons); + stbi_image_free(icons[0].pixels); + for (int i = 1; i < 10; i++) { + free(icons[i].pixels); + } + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + (void)io; + io.IniFilename = NULL; + + // Setup Platform/Renderer bindings + ImGui_ImplGlfw_InitForOpenGL(window, true); + + if (!ImGui_ImplOpenGL3_Init(glsl_version)) { + // If init fail, try to fall back on GLSL 1.2 + spdlog::warn("Could not init using OpenGL with normal GLSL version, falling back to GLSL 1.2"); + if (!ImGui_ImplOpenGL3_Init("#version 120")) { + spdlog::error("Failed to initialize OpenGL with GLSL 1.2"); + return -1; + } + } + + // Set window size and fullscreen state + glfwGetWindowSize(window, &_winWidth, &_winHeight); + if (fullScreen) { + spdlog::info("Fullscreen: ON"); + fsWidth = _winWidth; + fsHeight = _winHeight; + glfwGetWindowPos(window, &fsPosX, &fsPosY); + const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); + glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, 0); + } + + // Everything went according to plan + return 0; + } + + void beginFrame() { + // Start the Dear ImGui frame + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + } + + void render(bool vsync) { + // Rendering + ImGui::Render(); + int display_w, display_h; + glfwGetFramebufferSize(window, &display_w, &display_h); + glViewport(0, 0, display_w, display_h); + glClearColor(gui::themeManager.clearColor.x, gui::themeManager.clearColor.y, gui::themeManager.clearColor.z, gui::themeManager.clearColor.w); + glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + + glfwSwapInterval(vsync); + glfwSwapBuffers(window); + } + + void getMouseScreenPos(double& x, double& y) { + glfwGetCursorPos(window, &x, &y); + } + + void setMouseScreenPos(double x, double y) { + glfwSetCursorPos(window, x, y); + } + + int renderLoop() { + // Main loop + while (!glfwWindowShouldClose(window)) { + glfwPollEvents(); + + beginFrame(); + + if (_maximized != maximized) { + _maximized = maximized; + core::configManager.acquire(); + core::configManager.conf["maximized"] = _maximized; + if (!maximized) { + glfwSetWindowSize(window, core::configManager.conf["windowSize"]["w"], core::configManager.conf["windowSize"]["h"]); + } + core::configManager.release(true); + } + + glfwGetWindowSize(window, &_winWidth, &_winHeight); + + if (ImGui::IsKeyPressed(GLFW_KEY_F11)) { + fullScreen = !fullScreen; + if (fullScreen) { + spdlog::info("Fullscreen: ON"); + fsWidth = _winWidth; + fsHeight = _winHeight; + glfwGetWindowPos(window, &fsPosX, &fsPosY); + const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); + glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, 0); + core::configManager.acquire(); + core::configManager.conf["fullscreen"] = true; + core::configManager.release(); + } + else { + spdlog::info("Fullscreen: OFF"); + glfwSetWindowMonitor(window, nullptr, fsPosX, fsPosY, fsWidth, fsHeight, 0); + core::configManager.acquire(); + core::configManager.conf["fullscreen"] = false; + core::configManager.release(); + } + } + + if ((_winWidth != winWidth || _winHeight != winHeight) && !maximized && _winWidth > 0 && _winHeight > 0) { + winWidth = _winWidth; + winHeight = _winHeight; + core::configManager.acquire(); + core::configManager.conf["windowSize"]["w"] = winWidth; + core::configManager.conf["windowSize"]["h"] = winHeight; + core::configManager.release(true); + } + + if (winWidth > 0 && winHeight > 0) { + ImGui::SetNextWindowPos(ImVec2(0, 0)); + ImGui::SetNextWindowSize(ImVec2(_winWidth, _winHeight)); + gui::mainWindow.draw(); + } + + render(); + } + } + + int end() { + // Cleanup + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + glfwDestroyWindow(window); + glfwTerminate(); + + return 0; // TODO: Int really needed? + } +} \ No newline at end of file diff --git a/core/src/imgui/imgui_impl_glfw.cpp b/core/backends/glfw/imgui/imgui_impl_glfw.cpp similarity index 100% rename from core/src/imgui/imgui_impl_glfw.cpp rename to core/backends/glfw/imgui/imgui_impl_glfw.cpp diff --git a/core/src/imgui/imgui_impl_glfw.h b/core/backends/glfw/imgui/imgui_impl_glfw.h similarity index 100% rename from core/src/imgui/imgui_impl_glfw.h rename to core/backends/glfw/imgui/imgui_impl_glfw.h diff --git a/core/backends/glfw/keybinds.h b/core/backends/glfw/keybinds.h new file mode 100644 index 00000000..30dbc6fe --- /dev/null +++ b/core/backends/glfw/keybinds.h @@ -0,0 +1,24 @@ +#pragma once +#include + +#define KB_KEY_HOME GLFW_KEY_HOME +#define KB_KEY_MENU GLFW_KEY_MENU +#define KB_KEY_END GLFW_KEY_END +#define KB_KEY_ESC GLFW_KEY_ESCAPE +#define KB_KEY_PG_UP GLFW_KEY_PAGE_UP +#define KB_KEY_PG_DOWN GLFW_KEY_PAGE_DOWN + +#define KB_KEY_ENTER GLFW_KEY_ENTER +#define KB_KEY_KP_ENTER GLFW_KEY_KP_ENTER +#define KB_KEY_DEL GLFW_KEY_DELETE +#define KB_KEY_BACKSPACE GLFW_KEY_BACKSPACE + +#define KB_KEY_LEFT GLFW_KEY_LEFT +#define KB_KEY_RIGHT GLFW_KEY_RIGHT +#define KB_KEY_UP GLFW_KEY_UP +#define KB_KEY_DOWN GLFW_KEY_DOWN + +#define KB_KEY_LCTRL GLFW_KEY_LEFT_CONTROL +#define KB_KEY_RCTRL GLFW_KEY_RIGHT_CONTROL +#define KB_KEY_LSHIFT GLFW_KEY_LEFT_SHIFT +#define KB_KEY_RSHIFT GLFW_KEY_RIGHT_SHIFT \ No newline at end of file diff --git a/core/src/backend.h b/core/src/backend.h new file mode 100644 index 00000000..bae9a36c --- /dev/null +++ b/core/src/backend.h @@ -0,0 +1,12 @@ +#pragma once +#include + +namespace backend { + int init(std::string resDir); + void beginFrame(); + void render(bool vsync = true); + void getMouseScreenPos(double& x, double& y); + void setMouseScreenPos(double x, double y); + int renderLoop(); + int end(); +} \ No newline at end of file diff --git a/core/src/core.cpp b/core/src/core.cpp index a8d0c8f4..4d6d8039 100644 --- a/core/src/core.cpp +++ b/core/src/core.cpp @@ -3,7 +3,6 @@ #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include -#include #include #include #include @@ -14,10 +13,10 @@ #include #include #include -#include #include #include #include +#include #define STB_IMAGE_RESIZE_IMPLEMENTATION #include @@ -36,37 +35,10 @@ #endif #endif -const char* OPENGL_VERSIONS_GLSL[] = { - "#version 120", - "#version 300 es", - "#version 120" -}; - -const int OPENGL_VERSIONS_MAJOR[] = { - 3, - 3, - 2 -}; - -const int OPENGL_VERSIONS_MINOR[] = { - 0, - 1, - 1 -}; - -const bool OPENGL_VERSIONS_IS_ES[] = { - false, - true, - false -}; - -#define OPENGL_VERSION_COUNT (sizeof(OPENGL_VERSIONS_GLSL) / sizeof(char*)) - namespace core { ConfigManager configManager; ModuleManager moduleManager; ModuleComManager modComManager; - GLFWwindow* window; void setInputSampleRate(double samplerate) { // Forward this to the server @@ -84,22 +56,6 @@ namespace core { } }; -bool maximized = false; -bool fullScreen = false; - -static void glfw_error_callback(int error, const char* description) { - spdlog::error("Glfw Error {0}: {1}", error, description); -} - -static void maximized_callback(GLFWwindow* window, int n) { - if (n == GLFW_TRUE) { - maximized = true; - } - else { - maximized = false; - } -} - // main int sdrpp_main(int argc, char* argv[]) { spdlog::info("SDR++ v" VERSION_STR); @@ -268,7 +224,6 @@ int sdrpp_main(int argc, char* argv[]) { core::configManager.load(defConfig); core::configManager.enableAutoSave(); - core::configManager.acquire(); // Fix missing elements in config for (auto const& item : defConfig.items()) { @@ -297,16 +252,11 @@ int sdrpp_main(int argc, char* argv[]) { core::configManager.conf["moduleInstances"][_name] = newMod; } - fullScreen = core::configManager.conf["fullscreen"]; - core::configManager.release(true); if (options::opts.serverMode) { return server::main(); } core::configManager.acquire(); - int winWidth = core::configManager.conf["windowSize"]["w"]; - int winHeight = core::configManager.conf["windowSize"]["h"]; - maximized = core::configManager.conf["maximized"]; std::string resDir = core::configManager.conf["resourcesDirectory"]; json bandColors = core::configManager.conf["bandColors"]; core::configManager.release(); @@ -318,123 +268,13 @@ int sdrpp_main(int argc, char* argv[]) { return 1; } - // Setup window - glfwSetErrorCallback(glfw_error_callback); - if (!glfwInit()) { - return 1; - } - -#ifdef __APPLE__ - // GL 3.2 + GLSL 150 - const char* glsl_version = "#version 150"; - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac - - // Create window with graphics context - GLFWmonitor* monitor = glfwGetPrimaryMonitor(); - core::window = glfwCreateWindow(winWidth, winHeight, "SDR++ v" VERSION_STR " (Built at " __TIME__ ", " __DATE__ ")", NULL, NULL); - if (core::window == NULL) - return 1; - glfwMakeContextCurrent(core::window); -#else - const char* glsl_version = "#version 120"; - GLFWmonitor* monitor = NULL; - for (int i = 0; i < OPENGL_VERSION_COUNT; i++) { - glsl_version = OPENGL_VERSIONS_GLSL[i]; - glfwWindowHint(GLFW_CLIENT_API, OPENGL_VERSIONS_IS_ES[i] ? GLFW_OPENGL_ES_API : GLFW_OPENGL_API); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, OPENGL_VERSIONS_MAJOR[i]); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, OPENGL_VERSIONS_MINOR[i]); - - // Create window with graphics context - monitor = glfwGetPrimaryMonitor(); - core::window = glfwCreateWindow(winWidth, winHeight, "SDR++ v" VERSION_STR " (Built at " __TIME__ ", " __DATE__ ")", NULL, NULL); - if (core::window == NULL) { - spdlog::info("OpenGL {0}.{1} {2}was not supported", OPENGL_VERSIONS_MAJOR[i], OPENGL_VERSIONS_MINOR[i], OPENGL_VERSIONS_IS_ES[i] ? "ES " : ""); - continue; - } - spdlog::info("Using OpenGL {0}.{1}{2}", OPENGL_VERSIONS_MAJOR[i], OPENGL_VERSIONS_MINOR[i], OPENGL_VERSIONS_IS_ES[i] ? " ES" : ""); - glfwMakeContextCurrent(core::window); - break; - } - -#endif - - // Add callback for max/min if GLFW supports it -#if (GLFW_VERSION_MAJOR == 3) && (GLFW_VERSION_MINOR >= 3) - if (maximized) { - glfwMaximizeWindow(core::window); - } - - glfwSetWindowMaximizeCallback(core::window, maximized_callback); -#endif - - // Load app icon - if (!std::filesystem::is_regular_file(resDir + "/icons/sdrpp.png")) { - spdlog::error("Icon file '{0}' doesn't exist!", resDir + "/icons/sdrpp.png"); - return 1; - } - - GLFWimage icons[10]; - icons[0].pixels = stbi_load(((std::string)(resDir + "/icons/sdrpp.png")).c_str(), &icons[0].width, &icons[0].height, 0, 4); - icons[1].pixels = (unsigned char*)malloc(16 * 16 * 4); - icons[1].width = icons[1].height = 16; - icons[2].pixels = (unsigned char*)malloc(24 * 24 * 4); - icons[2].width = icons[2].height = 24; - icons[3].pixels = (unsigned char*)malloc(32 * 32 * 4); - icons[3].width = icons[3].height = 32; - icons[4].pixels = (unsigned char*)malloc(48 * 48 * 4); - icons[4].width = icons[4].height = 48; - icons[5].pixels = (unsigned char*)malloc(64 * 64 * 4); - icons[5].width = icons[5].height = 64; - icons[6].pixels = (unsigned char*)malloc(96 * 96 * 4); - icons[6].width = icons[6].height = 96; - icons[7].pixels = (unsigned char*)malloc(128 * 128 * 4); - icons[7].width = icons[7].height = 128; - icons[8].pixels = (unsigned char*)malloc(196 * 196 * 4); - icons[8].width = icons[8].height = 196; - icons[9].pixels = (unsigned char*)malloc(256 * 256 * 4); - icons[9].width = icons[9].height = 256; - stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[1].pixels, 16, 16, 16 * 4, 4); - stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[2].pixels, 24, 24, 24 * 4, 4); - stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[3].pixels, 32, 32, 32 * 4, 4); - stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[4].pixels, 48, 48, 48 * 4, 4); - stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[5].pixels, 64, 64, 64 * 4, 4); - stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[6].pixels, 96, 96, 96 * 4, 4); - stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[7].pixels, 128, 128, 128 * 4, 4); - stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[8].pixels, 196, 196, 196 * 4, 4); - stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[9].pixels, 256, 256, 256 * 4, 4); - glfwSetWindowIcon(core::window, 10, icons); - stbi_image_free(icons[0].pixels); - for (int i = 1; i < 10; i++) { - free(icons[i].pixels); - } - - // Setup Dear ImGui context - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - (void)io; - io.IniFilename = NULL; - - // Setup Platform/Renderer bindings - ImGui_ImplGlfw_InitForOpenGL(core::window, true); - - if (!ImGui_ImplOpenGL3_Init(glsl_version)) { - // If init fail, try to fall back on GLSL 1.2 - spdlog::warn("Could not init using OpenGL with normal GLSL version, falling back to GLSL 1.2"); - if (!ImGui_ImplOpenGL3_Init("#version 120")) { - spdlog::error("Failed to initialize OpenGL with GLSL 1.2"); - return -1; - } - } + // Initialize backend + int biRes = backend::init(resDir); + if (biRes < 0) { return biRes; } if (!style::loadFonts(resDir)) { return -1; } thememenu::init(resDir); - LoadingScreen::setWindow(core::window); - LoadingScreen::show("Loading icons"); spdlog::info("Loading icons"); if (!icons::load(resDir)) { return -1; } @@ -447,110 +287,20 @@ int sdrpp_main(int argc, char* argv[]) { spdlog::info("Loading band plans color table"); bandplan::loadColorTable(bandColors); - bool _maximized = maximized; - int fsWidth, fsHeight, fsPosX, fsPosY; - int _winWidth, _winHeight; - glfwGetWindowSize(core::window, &_winWidth, &_winHeight); - - if (fullScreen) { - spdlog::info("Fullscreen: ON"); - fsWidth = _winWidth; - fsHeight = _winHeight; - glfwGetWindowPos(core::window, &fsPosX, &fsPosY); - const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); - glfwSetWindowMonitor(core::window, monitor, 0, 0, mode->width, mode->height, 0); - } - gui::mainWindow.init(); spdlog::info("Ready."); - // Main loop - while (!glfwWindowShouldClose(core::window)) { - glfwPollEvents(); - - // Start the Dear ImGui frame - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - //ImGui::ShowDemoWindow(); - - if (_maximized != maximized) { - _maximized = maximized; - core::configManager.acquire(); - core::configManager.conf["maximized"] = _maximized; - if (!maximized) { - glfwSetWindowSize(core::window, core::configManager.conf["windowSize"]["w"], core::configManager.conf["windowSize"]["h"]); - } - core::configManager.release(true); - } - - glfwGetWindowSize(core::window, &_winWidth, &_winHeight); - - if (ImGui::IsKeyPressed(GLFW_KEY_F11)) { - fullScreen = !fullScreen; - if (fullScreen) { - spdlog::info("Fullscreen: ON"); - fsWidth = _winWidth; - fsHeight = _winHeight; - glfwGetWindowPos(core::window, &fsPosX, &fsPosY); - const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); - glfwSetWindowMonitor(core::window, monitor, 0, 0, mode->width, mode->height, 0); - core::configManager.acquire(); - core::configManager.conf["fullscreen"] = true; - core::configManager.release(); - } - else { - spdlog::info("Fullscreen: OFF"); - glfwSetWindowMonitor(core::window, nullptr, fsPosX, fsPosY, fsWidth, fsHeight, 0); - core::configManager.acquire(); - core::configManager.conf["fullscreen"] = false; - core::configManager.release(); - } - } - - if ((_winWidth != winWidth || _winHeight != winHeight) && !maximized && _winWidth > 0 && _winHeight > 0) { - winWidth = _winWidth; - winHeight = _winHeight; - core::configManager.acquire(); - core::configManager.conf["windowSize"]["w"] = winWidth; - core::configManager.conf["windowSize"]["h"] = winHeight; - core::configManager.release(true); - } - - if (winWidth > 0 && winHeight > 0) { - ImGui::SetNextWindowPos(ImVec2(0, 0)); - ImGui::SetNextWindowSize(ImVec2(_winWidth, _winHeight)); - gui::mainWindow.draw(); - } - - // Rendering - ImGui::Render(); - int display_w, display_h; - glfwGetFramebufferSize(core::window, &display_w, &display_h); - glViewport(0, 0, display_w, display_h); - //glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f); - glClearColor(gui::themeManager.clearColor.x, gui::themeManager.clearColor.y, gui::themeManager.clearColor.z, gui::themeManager.clearColor.w); - glClear(GL_COLOR_BUFFER_BIT); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - - glfwSwapInterval(1); // Enable vsync - glfwSwapBuffers(core::window); - } + // Run render loop (TODO: CHECK RETURN VALUE) + backend::renderLoop(); // Shut down all modules for (auto& [name, mod] : core::moduleManager.modules) { mod.end(); } - // Cleanup - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - - glfwDestroyWindow(core::window); - glfwTerminate(); + // Terminate backend (TODO: CHECK RETURN VALUE) + backend::end(); sigpath::signalPath.stop(); diff --git a/core/src/glfw_window.h b/core/src/glfw_window.h deleted file mode 100644 index 5c40d087..00000000 --- a/core/src/glfw_window.h +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include - -namespace core { - SDRPP_EXPORT GLFWwindow* window; -}; \ No newline at end of file diff --git a/core/src/gui/dialogs/loading_screen.cpp b/core/src/gui/dialogs/loading_screen.cpp index 909cf173..65efa3c4 100644 --- a/core/src/gui/dialogs/loading_screen.cpp +++ b/core/src/gui/dialogs/loading_screen.cpp @@ -7,20 +7,13 @@ #include #include #include +#include namespace LoadingScreen { - GLFWwindow* _win; - - void setWindow(GLFWwindow* win) { - _win = win; - } void show(std::string msg) { - glfwPollEvents(); - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); + backend::beginFrame(); - ImGui::NewFrame(); ImGui::Begin("Main", NULL, WINDOW_FLAGS); @@ -46,14 +39,6 @@ namespace LoadingScreen { ImGui::End(); - ImGui::Render(); - int display_w, display_h; - glfwGetFramebufferSize(_win, &display_w, &display_h); - glViewport(0, 0, display_w, display_h); - glClearColor(gui::themeManager.clearColor.x, gui::themeManager.clearColor.y, gui::themeManager.clearColor.z, gui::themeManager.clearColor.w); - glClear(GL_COLOR_BUFFER_BIT); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - - glfwSwapBuffers(_win); + backend::render(false); } } \ No newline at end of file diff --git a/core/src/gui/dialogs/loading_screen.h b/core/src/gui/dialogs/loading_screen.h index fd5ef5fe..7ed85ccf 100644 --- a/core/src/gui/dialogs/loading_screen.h +++ b/core/src/gui/dialogs/loading_screen.h @@ -2,9 +2,7 @@ #include #include #include -#include namespace LoadingScreen { - void setWindow(GLFWwindow* win); void show(std::string msg); }; \ No newline at end of file diff --git a/core/src/gui/main_window.cpp b/core/src/gui/main_window.cpp index fde2f738..994fa6a2 100644 --- a/core/src/gui/main_window.cpp +++ b/core/src/gui/main_window.cpp @@ -4,7 +4,6 @@ #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" #include -#include #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include void MainWindow::init() { LoadingScreen::show("Initializing UI"); @@ -355,7 +355,7 @@ void MainWindow::draw() { // To Bar ImGui::PushID(ImGui::GetID("sdrpp_menu_btn")); - if (ImGui::ImageButton(icons::MENU, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(GLFW_KEY_MENU, false)) { + if (ImGui::ImageButton(icons::MENU, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(KB_KEY_MENU, false)) { showMenu = !showMenu; core::configManager.acquire(); core::configManager.conf["showMenu"] = showMenu; @@ -369,14 +369,14 @@ void MainWindow::draw() { if (playButtonLocked && !tmpPlaySate) { style::beginDisabled(); } if (playing) { ImGui::PushID(ImGui::GetID("sdrpp_stop_btn")); - if (ImGui::ImageButton(icons::STOP, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(GLFW_KEY_END, false)) { + if (ImGui::ImageButton(icons::STOP, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(KB_KEY_END, false)) { setPlayState(false); } ImGui::PopID(); } else { // TODO: Might need to check if there even is a device ImGui::PushID(ImGui::GetID("sdrpp_play_btn")); - if (ImGui::ImageButton(icons::PLAY, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(GLFW_KEY_END, false)) { + if (ImGui::ImageButton(icons::PLAY, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(KB_KEY_END, false)) { setPlayState(true); } ImGui::PopID(); @@ -439,7 +439,7 @@ void MainWindow::draw() { if (ImGui::IsMouseDown(ImGuiMouseButton_Left)) { showCredits = false; } - if (ImGui::IsKeyPressed(GLFW_KEY_ESCAPE)) { + if (ImGui::IsKeyPressed(KB_KEY_ESC)) { showCredits = false; } @@ -557,12 +557,12 @@ void MainWindow::draw() { if (!lockWaterfallControls) { // Handle arrow keys if (vfo != NULL && (gui::waterfall.mouseInFFT || gui::waterfall.mouseInWaterfall)) { - if (ImGui::IsKeyPressed(GLFW_KEY_LEFT) && !gui::freqSelect.digitHovered) { + if (ImGui::IsKeyPressed(KB_KEY_LEFT) && !gui::freqSelect.digitHovered) { double nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset - vfo->snapInterval; nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval; tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq); } - if (ImGui::IsKeyPressed(GLFW_KEY_RIGHT) && !gui::freqSelect.digitHovered) { + if (ImGui::IsKeyPressed(KB_KEY_RIGHT) && !gui::freqSelect.digitHovered) { double nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset + vfo->snapInterval; nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval; tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq); diff --git a/core/src/gui/menus/display.cpp b/core/src/gui/menus/display.cpp index e04ea3bc..387dd03a 100644 --- a/core/src/gui/menus/display.cpp +++ b/core/src/gui/menus/display.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace displaymenu { bool showWaterfall; @@ -89,7 +90,7 @@ namespace displaymenu { void draw(void* ctx) { float menuWidth = ImGui::GetContentRegionAvailWidth(); - bool homePressed = ImGui::IsKeyPressed(GLFW_KEY_HOME, false); + bool homePressed = ImGui::IsKeyPressed(KB_KEY_HOME, false); if (ImGui::Checkbox("Show Waterfall##_sdrpp", &showWaterfall) || homePressed) { if (homePressed) { showWaterfall = !showWaterfall; } showWaterfall ? gui::waterfall.showWaterfall() : gui::waterfall.hideWaterfall(); diff --git a/core/src/gui/widgets/frequency_select.cpp b/core/src/gui/widgets/frequency_select.cpp index ff3f2992..90d7968e 100644 --- a/core/src/gui/widgets/frequency_select.cpp +++ b/core/src/gui/widgets/frequency_select.cpp @@ -2,8 +2,8 @@ #include #include #include -#include -#include +#include +#include #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS @@ -87,9 +87,9 @@ void FrequencySelect::decrementDigit(int i) { void FrequencySelect::moveCursorToDigit(int i) { double xpos, ypos; - glfwGetCursorPos(core::window, &xpos, &ypos); - float nxpos = (digitTopMaxs[i].x + digitTopMins[i].x) / 2.0f; - glfwSetCursorPos(core::window, nxpos, ypos); + backend::getMouseScreenPos(xpos, ypos); + double nxpos = (digitTopMaxs[i].x + digitTopMins[i].x) / 2.0; + backend::setMouseScreenPos(nxpos, ypos); } void FrequencySelect::draw() { @@ -165,23 +165,23 @@ void FrequencySelect::draw() { } if (onDigit) { hovered = true; - if (rightClick || (ImGui::IsKeyPressed(GLFW_KEY_DELETE) || ImGui::IsKeyPressed(GLFW_KEY_ENTER) || ImGui::IsKeyPressed(GLFW_KEY_KP_ENTER))) { + if (rightClick || (ImGui::IsKeyPressed(KB_KEY_DEL) || ImGui::IsKeyPressed(KB_KEY_ENTER) || ImGui::IsKeyPressed(KB_KEY_KP_ENTER))) { for (int j = i; j < 12; j++) { digits[j] = 0; } frequencyChanged = true; } - if (ImGui::IsKeyPressed(GLFW_KEY_UP)) { + if (ImGui::IsKeyPressed(KB_KEY_UP)) { incrementDigit(i); } - if (ImGui::IsKeyPressed(GLFW_KEY_DOWN)) { + if (ImGui::IsKeyPressed(KB_KEY_DOWN)) { decrementDigit(i); } - if ((ImGui::IsKeyPressed(GLFW_KEY_LEFT) || ImGui::IsKeyPressed(GLFW_KEY_BACKSPACE)) && i > 0) { + if ((ImGui::IsKeyPressed(KB_KEY_LEFT) || ImGui::IsKeyPressed(KB_KEY_BACKSPACE)) && i > 0) { moveCursorToDigit(i - 1); } - if (ImGui::IsKeyPressed(GLFW_KEY_RIGHT) && i < 11) { + if (ImGui::IsKeyPressed(KB_KEY_RIGHT) && i < 11) { moveCursorToDigit(i + 1); } diff --git a/core/src/gui/widgets/waterfall.cpp b/core/src/gui/widgets/waterfall.cpp index c80cded1..d2f598ef 100644 --- a/core/src/gui/widgets/waterfall.cpp +++ b/core/src/gui/widgets/waterfall.cpp @@ -4,9 +4,9 @@ #include #include #include -#include #include #include +#include float DEFAULT_COLOR_MAP[][3] = { { 0x00, 0x00, 0x20 }, @@ -387,8 +387,8 @@ namespace ImGui { } // If the left and right keys are pressed while hovering the freq scale, move it too - bool leftKeyPressed = ImGui::IsKeyPressed(GLFW_KEY_LEFT); - if ((leftKeyPressed || ImGui::IsKeyPressed(GLFW_KEY_RIGHT)) && mouseInFreq) { + bool leftKeyPressed = ImGui::IsKeyPressed(KB_KEY_LEFT); + if ((leftKeyPressed || ImGui::IsKeyPressed(KB_KEY_RIGHT)) && mouseInFreq) { viewOffset += leftKeyPressed ? (viewBandwidth / 20.0) : (-viewBandwidth / 20.0); if (viewOffset + (viewBandwidth / 2.0) > wholeBandwidth / 2.0) { @@ -435,7 +435,7 @@ namespace ImGui { ImGui::TextUnformatted(name.c_str()); - if (ImGui::IsKeyDown(GLFW_KEY_LEFT_CONTROL) || ImGui::IsKeyDown(GLFW_KEY_RIGHT_CONTROL)) { + if (ImGui::IsKeyDown(KB_KEY_LCTRL) || ImGui::IsKeyDown(KB_KEY_RCTRL)) { ImGui::Separator(); printAndScale(_vfo->generalOffset + centerFreq, buf); ImGui::Text("Frequency: %sHz", buf); @@ -461,7 +461,7 @@ namespace ImGui { } // Handle Page Up to cycle through VFOs - if (ImGui::IsKeyPressed(GLFW_KEY_PAGE_UP) && selVfo != NULL) { + if (ImGui::IsKeyPressed(KB_KEY_PG_UP) && selVfo != NULL) { std::string next = (--vfos.end())->first; std::string lowest = ""; double lowestOffset = INFINITY; @@ -484,7 +484,7 @@ namespace ImGui { } // Handle Page Down to cycle through VFOs - if (ImGui::IsKeyPressed(GLFW_KEY_PAGE_DOWN) && selVfo != NULL) { + if (ImGui::IsKeyPressed(KB_KEY_PG_DOWN) && selVfo != NULL) { std::string next = (--vfos.end())->first; std::string highest = ""; double highestOffset = -INFINITY; diff --git a/misc_modules/frequency_manager/src/main.cpp b/misc_modules/frequency_manager/src/main.cpp index 37f8d314..43274c02 100644 --- a/misc_modules/frequency_manager/src/main.cpp +++ b/misc_modules/frequency_manager/src/main.cpp @@ -13,6 +13,7 @@ #include #include #include +#include SDRPP_MOD_INFO{ /* Name: */ "frequency_manager", @@ -497,8 +498,8 @@ private: if (ImGui::Selectable((name + "##_freq_mgr_bkm_name_" + _this->name).c_str(), &bm.selected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_SelectOnClick)) { // if shift or control isn't pressed, deselect all others - if (!ImGui::IsKeyDown(GLFW_KEY_LEFT_SHIFT) && !ImGui::IsKeyDown(GLFW_KEY_RIGHT_SHIFT) && - !ImGui::IsKeyDown(GLFW_KEY_LEFT_CONTROL) && !ImGui::IsKeyDown(GLFW_KEY_RIGHT_CONTROL)) { + if (!ImGui::IsKeyDown(KB_KEY_LSHIFT) && !ImGui::IsKeyDown(KB_KEY_RSHIFT) && + !ImGui::IsKeyDown(KB_KEY_LCTRL) && !ImGui::IsKeyDown(KB_KEY_RCTRL)) { for (auto& [_name, _bm] : _this->bookmarks) { if (name == _name) { continue; } _bm.selected = false; diff --git a/misc_modules/scheduler/src/main.cpp b/misc_modules/scheduler/src/main.cpp index e5227467..4dea23b6 100644 --- a/misc_modules/scheduler/src/main.cpp +++ b/misc_modules/scheduler/src/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include SDRPP_MOD_INFO{ /* Name: */ "scheduler", @@ -100,8 +101,8 @@ private: if (ImGui::Selectable((name + "##_freq_mgr_bkm_name_" + _this->name).c_str(), &bm.selected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_SelectOnClick)) { // if shift or control isn't pressed, deselect all others - if (!ImGui::IsKeyDown(GLFW_KEY_LEFT_SHIFT) && !ImGui::IsKeyDown(GLFW_KEY_RIGHT_SHIFT) && - !ImGui::IsKeyDown(GLFW_KEY_LEFT_CONTROL) && !ImGui::IsKeyDown(GLFW_KEY_RIGHT_CONTROL)) { + if (!ImGui::IsKeyDown(KB_KEY_LSHIFT) && !ImGui::IsKeyDown(KB_KEY_RSHIFT) && + !ImGui::IsKeyDown(KB_KEY_LCTRL) && !ImGui::IsKeyDown(KB_KEY_RCTRL)) { for (auto& [_name, _bm] : _this->tasks) { if (name == _name) { continue; } _bm.selected = false; diff --git a/misc_modules/scheduler/src/sched_task.h b/misc_modules/scheduler/src/sched_task.h index 41a11de9..25bffc9f 100644 --- a/misc_modules/scheduler/src/sched_task.h +++ b/misc_modules/scheduler/src/sched_task.h @@ -3,6 +3,7 @@ #include #include #include +#include class Task { public: @@ -77,8 +78,8 @@ public: if (ImGui::Selectable((act->getName() + "##scheduler_task_actions_entry").c_str(), &act->selected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_SelectOnClick)) { // if shift or control isn't pressed, deselect all others - if (!ImGui::IsKeyDown(GLFW_KEY_LEFT_SHIFT) && !ImGui::IsKeyDown(GLFW_KEY_RIGHT_SHIFT) && - !ImGui::IsKeyDown(GLFW_KEY_LEFT_CONTROL) && !ImGui::IsKeyDown(GLFW_KEY_RIGHT_CONTROL)) { + if (!ImGui::IsKeyDown(KB_KEY_LSHIFT) && !ImGui::IsKeyDown(KB_KEY_RSHIFT) && + !ImGui::IsKeyDown(KB_KEY_LCTRL) && !ImGui::IsKeyDown(KB_KEY_RCTRL)) { int _id = 0; for (auto& _act : actions) { if (_id == id) { continue; }