diff --git a/SofaGLFW/src/SofaGLFW/BaseGUIEngine.h b/SofaGLFW/src/SofaGLFW/BaseGUIEngine.h index 8a99fd0411..697381b761 100644 --- a/SofaGLFW/src/SofaGLFW/BaseGUIEngine.h +++ b/SofaGLFW/src/SofaGLFW/BaseGUIEngine.h @@ -50,6 +50,7 @@ class BaseGUIEngine virtual sofa::type::Vec2i getFrameBufferPixels(std::vector& pixels) = 0; virtual void openFile(SofaGLFWBaseGUI* baseGUI, sofa::core::sptr& groot) {}; virtual void loadFile(SofaGLFWBaseGUI* baseGUI, sofa::core::sptr& groot, std::string filePathName, bool reload = false) {}; + virtual void contentScaleChanged(float xscale, float yscale) {} }; } // namespace sofaglfw diff --git a/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.cpp b/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.cpp index 68ee16069e..bbba19867b 100644 --- a/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.cpp +++ b/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.cpp @@ -305,6 +305,7 @@ bool SofaGLFWBaseGUI::createWindow(int width, int height, const char* title, boo glfwSetCursorEnterCallback(glfwWindow, cursor_enter_callback); glfwSetMonitorCallback(monitor_callback); glfwSetCharCallback(glfwWindow, character_callback); + glfwSetWindowContentScaleCallback(glfwWindow, content_scale_callback); glfwSetWindowUserPointer(glfwWindow, this); @@ -995,6 +996,15 @@ void SofaGLFWBaseGUI::translateToViewportCoordinates (SofaGLFWBaseGUI* gui,doubl gui->m_translatedCursorPos = Vec2d{xpos, ypos} - (gui->m_viewPortPosition - gui->m_windowPosition); } +void SofaGLFWBaseGUI::content_scale_callback(GLFWwindow *window, float xscale, float yscale) +{ + auto currentGUI = s_mapGUIs[window]; + if (currentGUI && currentGUI->m_guiEngine) + { + currentGUI->m_guiEngine->contentScaleChanged(xscale, yscale); + } +} + void SofaGLFWBaseGUI::cursor_position_callback(GLFWwindow* window, double xpos, double ypos) { auto currentGUI = s_mapGUIs.find(window); diff --git a/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.h b/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.h index 83328d29b1..3bb8d86800 100644 --- a/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.h +++ b/SofaGLFW/src/SofaGLFW/SofaGLFWBaseGUI.h @@ -156,6 +156,7 @@ class SOFAGLFW_API SofaGLFWBaseGUI : public BaseViewer static void window_pos_callback(GLFWwindow* window, int xpos, int ypos); static int handleArrowKeys(int key); static void translateToViewportCoordinates (SofaGLFWBaseGUI* gui,double xpos, double ypos); + static void content_scale_callback(GLFWwindow* window, float xscale, float yscale); void makeCurrentContext(GLFWwindow* sofaWindow); void runStep(); diff --git a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp index c283e7a4e6..ca0380966f 100644 --- a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp +++ b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.cpp @@ -166,85 +166,14 @@ void ImGuiGUIEngine::initBackend(GLFWwindow* glfwWindow) ImGui_ImplOpenGL3_Init(nullptr); #endif // SOFAIMGUI_FORCE_OPENGL2 == 1 - GLFWmonitor* windowMonitor = glfwGetWindowMonitor(glfwWindow); - if (!windowMonitor) + float yscale { 1.f }; + if (GLFWmonitor* windowMonitor = findMyMonitor(glfwWindow)) { - windowMonitor = glfwGetPrimaryMonitor(); - } - if (windowMonitor) - { - float xscale{}, yscale{}; + float xscale{}; glfwGetMonitorContentScale(windowMonitor, &xscale, &yscale); - - ImGuiIO& io = ImGui::GetIO(); - - io.Fonts->AddFontFromMemoryCompressedTTF(ROBOTO_MEDIUM_compressed_data, ROBOTO_MEDIUM_compressed_size, 16 * yscale); - - ImFontConfig config; - config.MergeMode = true; - config.GlyphMinAdvanceX = 16.0f; // Use if you want to make the icon monospaced - static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; - io.Fonts->AddFontFromMemoryCompressedTTF(FA_REGULAR_400_compressed_data, FA_REGULAR_400_compressed_size, 16 * yscale, &config, icon_ranges); - io.Fonts->AddFontFromMemoryCompressedTTF(FA_SOLID_900_compressed_data, FA_SOLID_900_compressed_size, 16 * yscale, &config, icon_ranges); - - // restore the global scale stored in the Settings ini file - const float globalScale = static_cast(ini.GetDoubleValue("Visualization", "globalScale", 1.0)); - this->setScale(globalScale, windowMonitor); } - - // restore window settings if set - const bool rememberWindowPosition = ini.GetBoolValue("Window", "rememberWindowPosition", true); - if(rememberWindowPosition) - { - if(ini.KeyExists("Window", "windowPosX") && ini.KeyExists("Window", "windowPosY")) - { - const long windowPosX = ini.GetLongValue("Window", "windowPosX"); - const long windowPosY = ini.GetLongValue("Window", "windowPosY"); - - int monitorCount; - GLFWmonitor** monitors = glfwGetMonitors(&monitorCount); - - bool foundValidMonitor = false; - for (int i = 0; i < monitorCount; ++i) - { - if (GLFWmonitor* monitor = monitors[i]) - { - //retrieve the work area of the monitor in the whole desktop space, in screen coordinates - int monitorXPos{0}, monitorYPos{0}, monitorWidth{0}, monitorHeight{0}; - glfwGetMonitorWorkarea(monitor, &monitorXPos, &monitorYPos, &monitorWidth, &monitorHeight); - if(!monitorWidth || !monitorHeight) - { - msg_error("ImGuiGUIEngine") << "Unknown error while trying to fetch the monitor information."; - } - else - { - constexpr long margin = 5; // avoid the case where the window is positioned on the border of the monitor (almost invisible/non-selectable) - - if(windowPosX >= (monitorXPos) && - windowPosX <= (monitorXPos + monitorWidth-margin) && - windowPosY >= (monitorYPos) && - windowPosY <= (monitorYPos + monitorHeight-margin)) - { - glfwSetWindowPos(glfwWindow, static_cast(windowPosX), static_cast(windowPosY)); - foundValidMonitor = true; - break; - } - - } - } - } - - if (!foundValidMonitor) - { - msg_error("ImGuiGUIEngine") << "The window position from settings is invalid for any monitor."; - } - } - else - { - msg_error("ImGuiGUIEngine") << "Cannot set window position from settings."; - } - } + loadFont(yscale); const bool rememberWindowSize = ini.GetBoolValue("Window", "rememberWindowSize", true); if(rememberWindowSize) @@ -805,6 +734,103 @@ void ImGuiGUIEngine::resetView(ImGuiID dockspace_id, const char* windowNameScene firstRunState.setState(true);// Mark first run as complete } +GLFWmonitor* ImGuiGUIEngine::findMyMonitor(GLFWwindow* glfwWindow) +{ + GLFWmonitor* foundMonitor { nullptr }; + + const bool rememberWindowPosition = ini.GetBoolValue("Window", "rememberWindowPosition", true); + if(rememberWindowPosition) + { + if(ini.KeyExists("Window", "windowPosX") && ini.KeyExists("Window", "windowPosY")) + { + const long windowPosX = ini.GetLongValue("Window", "windowPosX"); + const long windowPosY = ini.GetLongValue("Window", "windowPosY"); + + int monitorCount; + GLFWmonitor** monitors = glfwGetMonitors(&monitorCount); + + bool foundValidMonitor = false; + for (int i = 0; i < monitorCount; ++i) + { + if (GLFWmonitor* monitor = monitors[i]) + { + //retrieve the work area of the monitor in the whole desktop space, in screen coordinates + int monitorXPos{0}, monitorYPos{0}, monitorWidth{0}, monitorHeight{0}; + glfwGetMonitorWorkarea(monitor, &monitorXPos, &monitorYPos, &monitorWidth, &monitorHeight); + if(!monitorWidth || !monitorHeight) + { + msg_error("ImGuiGUIEngine") << "Unknown error while trying to fetch the monitor information."; + } + else + { + constexpr long margin = 5; // avoid the case where the window is positioned on the border of the monitor (almost invisible/non-selectable) + + if(windowPosX >= (monitorXPos) && + windowPosX <= (monitorXPos + monitorWidth-margin) && + windowPosY >= (monitorYPos) && + windowPosY <= (monitorYPos + monitorHeight-margin)) + { + glfwSetWindowPos(glfwWindow, static_cast(windowPosX), static_cast(windowPosY)); + foundValidMonitor = true; + foundMonitor = monitor; + break; + } + + } + } + } + + if (!foundValidMonitor) + { + msg_error("ImGuiGUIEngine") << "The window position from settings is invalid for any monitor."; + } + } + else + { + msg_error("ImGuiGUIEngine") << "Cannot set window position from settings."; + } + } + + if (!foundMonitor) + { + foundMonitor = glfwGetPrimaryMonitor(); + } + + return foundMonitor; +} + +void ImGuiGUIEngine::loadFont(float yscale) +{ + constexpr float fontSize = 16.f; + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->Clear(); + + io.Fonts->AddFontFromMemoryCompressedTTF(ROBOTO_MEDIUM_compressed_data, ROBOTO_MEDIUM_compressed_size, fontSize * yscale); + + ImFontConfig config; + config.MergeMode = true; + config.GlyphMinAdvanceX = fontSize * yscale; + + static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; + io.Fonts->AddFontFromMemoryCompressedTTF(FA_REGULAR_400_compressed_data, FA_REGULAR_400_compressed_size, fontSize * yscale, &config, icon_ranges); + io.Fonts->AddFontFromMemoryCompressedTTF(FA_SOLID_900_compressed_data, FA_SOLID_900_compressed_size, fontSize * yscale, &config, icon_ranges); + + // restore the global scale stored in the Settings ini file + const float globalScale = static_cast(ini.GetDoubleValue("Visualization", "globalScale", 1.0)); + this->setScale(globalScale); + + io.Fonts->Build(); + +#if SOFAIMGUI_FORCE_OPENGL2 == 1 + ImGui_ImplOpenGL2_DestroyFontsTexture(); + ImGui_ImplOpenGL2_CreateFontsTexture(); +#else + ImGui_ImplOpenGL3_DestroyFontsTexture(); + ImGui_ImplOpenGL3_CreateFontsTexture(); +#endif +} + void ImGuiGUIEngine::beforeDraw(GLFWwindow*) { @@ -884,20 +910,15 @@ bool ImGuiGUIEngine::dispatchMouseEvents() return !ImGui::GetIO().WantCaptureMouse || isMouseOnViewport; } +void ImGuiGUIEngine::contentScaleChanged(float xscale, float yscale) +{ + loadFont(yscale); +} -void ImGuiGUIEngine::setScale(double globalScale, GLFWmonitor* monitor) +void ImGuiGUIEngine::setScale(float globalScale) { - if(!monitor) - { - monitor = glfwGetPrimaryMonitor(); - } - ImGuiIO& io = ImGui::GetIO(); - - float xscale{}, yscale{}; - glfwGetMonitorContentScale(monitor, &xscale, &yscale); - - io.FontGlobalScale = globalScale / yscale; + io.FontGlobalScale = globalScale; } type::Vec2i ImGuiGUIEngine::getFrameBufferPixels(std::vector& pixels) diff --git a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h index ada302fd89..a2c2cb0ae4 100644 --- a/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h +++ b/SofaImGui/src/SofaImGui/ImGuiGUIEngine.h @@ -60,9 +60,10 @@ class ImGuiGUIEngine : public sofaglfw::BaseGUIEngine void terminate() override; bool isTerminated() const override { return m_isTerminated; }; bool dispatchMouseEvents() override; + void contentScaleChanged(float xscale, float yscale) override; // apply global scale on the given monitor (if null, it will fetch the main monitor) - void setScale(double globalScale, GLFWmonitor* monitor); + void setScale(float globalScale); // reset counters void resetCounter() override; @@ -85,6 +86,8 @@ class ImGuiGUIEngine : public sofaglfw::BaseGUIEngine bool isMouseOnViewport { false }; CSimpleIniA ini; void resetView(ImGuiID dockspace_id, const char *windowNameSceneGraph, const char *winNameSelectionDescription, const char *windowNameLog, const char *windowNameViewport) ; + GLFWmonitor* findMyMonitor(GLFWwindow* glfwWindow); + void loadFont(float yscale); // WindowState members windows::WindowState winManagerProfiler; diff --git a/SofaImGui/src/SofaImGui/windows/Settings.cpp b/SofaImGui/src/SofaImGui/windows/Settings.cpp index 899084972e..ea7e541575 100644 --- a/SofaImGui/src/SofaImGui/windows/Settings.cpp +++ b/SofaImGui/src/SofaImGui/windows/Settings.cpp @@ -74,7 +74,7 @@ namespace windows constexpr float MAX_SCALE = 2.0f; ImGui::DragFloat("global scale", &globalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp); // Scale everything - engine->setScale(globalScale, nullptr); + engine->setScale(globalScale); ini.SetDoubleValue("Visualization", "globalScale", static_cast(globalScale)); if (std::abs(iniGlobalScale - globalScale) > 0.005f)