From 979d5f29c0f66f63bf2ccdd6cc92ea84f0facbf9 Mon Sep 17 00:00:00 2001 From: BruegelN Date: Sun, 29 Dec 2024 14:29:30 +0100 Subject: [PATCH 01/11] Add option for dpiScale to globalContext and scale font with dpiScale factor --- include/polyscope/context.h | 1 + src/imgui_config.cpp | 5 +++-- src/render/opengl/gl_engine_glfw.cpp | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/polyscope/context.h b/include/polyscope/context.h index 0c591c000..34cc79802 100644 --- a/include/polyscope/context.h +++ b/include/polyscope/context.h @@ -56,6 +56,7 @@ struct Context { std::map>> structures; std::map> groups; float lengthScale = 1.; + float dpiScale = 1.; std::tuple boundingBox = std::tuple{glm::vec3{-1., -1., -1.}, glm::vec3{1., 1., 1.}}; std::vector> slicePlanes; diff --git a/src/imgui_config.cpp b/src/imgui_config.cpp index bc6df1431..d4ae6ec4e 100644 --- a/src/imgui_config.cpp +++ b/src/imgui_config.cpp @@ -1,6 +1,7 @@ // Copyright 2017-2023, Nicholas Sharp and the Polyscope contributors. https://polyscope.run #include "polyscope/imgui_config.h" +#include namespace polyscope { @@ -84,13 +85,13 @@ std::tuple prepareImGuiFonts() { { // add regular font ImFontConfig config; regularFont = io.Fonts->AddFontFromMemoryCompressedTTF(render::getLatoRegularCompressedData(), - render::getLatoRegularCompressedSize(), 18.0f, &config); + render::getLatoRegularCompressedSize(), state::globalContext.dpiScale*18.0f, &config); } { // add mono font ImFontConfig config; monoFont = io.Fonts->AddFontFromMemoryCompressedTTF(render::getCousineRegularCompressedData(), - render::getCousineRegularCompressedSize(), 16.0f, &config); + render::getCousineRegularCompressedSize(), state::globalContext.dpiScale*16.0f, &config); } // io.Fonts->AddFontFromFileTTF("test-font-name.ttf", 16); diff --git a/src/render/opengl/gl_engine_glfw.cpp b/src/render/opengl/gl_engine_glfw.cpp index d483c2388..826cb7fae 100644 --- a/src/render/opengl/gl_engine_glfw.cpp +++ b/src/render/opengl/gl_engine_glfw.cpp @@ -112,6 +112,10 @@ void GLEngineGLFW::initializeImGui() { const char* glsl_version = "#version 150"; ImGui_ImplOpenGL3_Init(glsl_version); + float xScale, yScale; + glfwGetWindowContentScale(mainWindow, &xScale, &yScale); + state::globalContext.dpiScale = std::min(xScale, yScale); + configureImGui(); } @@ -132,6 +136,10 @@ void GLEngineGLFW::shutdownImGui() { } void GLEngineGLFW::ImGuiNewFrame() { + float xScale, yScale; + glfwGetWindowContentScale(mainWindow, &xScale, &yScale); + state::globalContext.dpiScale = std::min(xScale, yScale); + ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); From 40f4f2712808dfb2738d6aba6269058d6ac526d9 Mon Sep 17 00:00:00 2001 From: BruegelN Date: Sat, 1 Feb 2025 15:59:05 +0100 Subject: [PATCH 02/11] Scale everthing with the dpiScale factor --- examples/demo-app/demo_app.cpp | 2 +- include/polyscope/parameterization_quantity.ipp | 6 +++--- include/polyscope/scalar_quantity.ipp | 2 +- src/camera_view.cpp | 2 +- src/curve_network.cpp | 2 +- src/file_helpers.cpp | 2 +- src/image_quantity_base.cpp | 2 +- src/messages.cpp | 2 +- src/point_cloud.cpp | 2 +- src/polyscope.cpp | 16 +++++++++------- src/render/color_maps.cpp | 3 ++- src/render/engine.cpp | 2 +- src/render/ground_plane.cpp | 6 +++--- src/surface_mesh.cpp | 12 ++++++------ src/view.cpp | 10 +++++----- src/volume_grid.cpp | 6 +++--- src/volume_grid_scalar_quantity.cpp | 2 +- src/volume_mesh.cpp | 6 +++--- 18 files changed, 44 insertions(+), 41 deletions(-) diff --git a/examples/demo-app/demo_app.cpp b/examples/demo-app/demo_app.cpp index afa339b85..d19959806 100644 --- a/examples/demo-app/demo_app.cpp +++ b/examples/demo-app/demo_app.cpp @@ -780,7 +780,7 @@ void callback() { static int loadedMat = 1; static bool depthClick = false; - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * polyscope::state::globalContext.dpiScale); ImGui::InputInt("num points", &numPoints); ImGui::InputFloat("param value", ¶m); diff --git a/include/polyscope/parameterization_quantity.ipp b/include/polyscope/parameterization_quantity.ipp index f7254e127..f8b0fdb84 100644 --- a/include/polyscope/parameterization_quantity.ipp +++ b/include/polyscope/parameterization_quantity.ipp @@ -61,7 +61,7 @@ ParameterizationQuantity::ParameterizationQuantity(QuantityT& quantit template void ParameterizationQuantity::buildParameterizationUI() { - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); // Modulo stripey width if (ImGui::DragFloat("period", &checkerSize.get(), .001, 0.0001, 1.0, "%.4f", @@ -82,7 +82,7 @@ void ParameterizationQuantity::buildParameterizationUI() { setCheckerColors(getCheckerColors()); break; case ParamVizStyle::CHECKER_ISLANDS: - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); if (ImGui::DragFloat("alt darkness", &altDarkness.get(), 0.01, 0., 1.)) { altDarkness.manuallyChanged(); requestRedraw(); @@ -103,7 +103,7 @@ void ParameterizationQuantity::buildParameterizationUI() { case ParamVizStyle::LOCAL_CHECK: case ParamVizStyle::LOCAL_RAD: { // Angle slider - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); ImGui::SliderAngle("angle shift", &localRot, -180, 180); // displays in degrees, works in radians TODO refresh/update/persist if (ImGui::DragFloat("alt darkness", &altDarkness.get(), 0.01, 0., 1.)) { diff --git a/include/polyscope/scalar_quantity.ipp b/include/polyscope/scalar_quantity.ipp index 00089beaa..06d12138c 100644 --- a/include/polyscope/scalar_quantity.ipp +++ b/include/polyscope/scalar_quantity.ipp @@ -147,7 +147,7 @@ void ScalarQuantity::buildScalarUI() { // Isolines if (isolinesEnabled.get()) { - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); auto styleName = [](const IsolineStyle& m) -> std::string { diff --git a/src/camera_view.cpp b/src/camera_view.cpp index 5f3c708b6..34276b749 100644 --- a/src/camera_view.cpp +++ b/src/camera_view.cpp @@ -366,7 +366,7 @@ void CameraView::buildCustomUI() { void CameraView::buildCustomOptionsUI() { - ImGui::PushItemWidth(150); + ImGui::PushItemWidth(150 * state::globalContext.dpiScale); if (widgetFocalLengthUpper == -777) widgetFocalLengthUpper = 2. * (*widgetFocalLength.get().getValuePtr()); if (ImGui::SliderFloat("widget focal length", widgetFocalLength.get().getValuePtr(), 0, widgetFocalLengthUpper, diff --git a/src/curve_network.cpp b/src/curve_network.cpp index f9b917b5a..7ed9ac8d1 100644 --- a/src/curve_network.cpp +++ b/src/curve_network.cpp @@ -402,7 +402,7 @@ void CurveNetwork::buildCustomUI() { setColor(getColor()); } ImGui::SameLine(); - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); if (ImGui::SliderFloat("Radius", radius.get().getValuePtr(), 0.0, .1, "%.5f", ImGuiSliderFlags_Logarithmic | ImGuiSliderFlags_NoRoundToFormat)) { radius.manuallyChanged(); diff --git a/src/file_helpers.cpp b/src/file_helpers.cpp index 52371c38c..cdceb12bc 100644 --- a/src/file_helpers.cpp +++ b/src/file_helpers.cpp @@ -14,7 +14,7 @@ void filenamePromptCallback(char* buff, size_t len) { static bool windowOpen = true; ImGui::Begin("Enter filename", &windowOpen, ImGuiWindowFlags_AlwaysAutoResize); - ImGui::PushItemWidth(500); + ImGui::PushItemWidth(500 * state::globalContext.dpiScale); ImGui::InputText("##filename", buff, len); if (ImGui::Button("Ok")) { diff --git a/src/image_quantity_base.cpp b/src/image_quantity_base.cpp index e3f8e4fee..222d22e01 100644 --- a/src/image_quantity_base.cpp +++ b/src/image_quantity_base.cpp @@ -114,7 +114,7 @@ void ImageQuantity::buildImageUI() { if (getShowFullscreen()) { - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); if (ImGui::SliderFloat("transparency", &transparency.get(), 0.f, 1.f)) { transparency.manuallyChanged(); requestRedraw(); diff --git a/src/messages.cpp b/src/messages.cpp index 3f4fc021f..286551644 100644 --- a/src/messages.cpp +++ b/src/messages.cpp @@ -174,7 +174,7 @@ void buildWarningUI(std::string warningBaseString, std::string warningDetailStri } // Nice button sizing - float buttonWidth = 120; + float buttonWidth = 120 * state::globalContext.dpiScale; float buttonOffset = (warningModalSize.x - buttonWidth) / 2.0; buttonOffset = std::max(buttonOffset, 0.0f); doIndent = buttonOffset > 0; diff --git a/src/point_cloud.cpp b/src/point_cloud.cpp index a947a1150..e1443c94f 100644 --- a/src/point_cloud.cpp +++ b/src/point_cloud.cpp @@ -266,7 +266,7 @@ void PointCloud::buildCustomUI() { setPointColor(getPointColor()); } ImGui::SameLine(); - ImGui::PushItemWidth(70); + ImGui::PushItemWidth(70 * state::globalContext.dpiScale); if (ImGui::SliderFloat("Radius", pointRadius.get().getValuePtr(), 0.0, .1, "%.5f", ImGuiSliderFlags_Logarithmic | ImGuiSliderFlags_NoRoundToFormat)) { pointRadius.manuallyChanged(); diff --git a/src/polyscope.cpp b/src/polyscope.cpp index 037eeebd8..979fba010 100644 --- a/src/polyscope.cpp +++ b/src/polyscope.cpp @@ -47,8 +47,10 @@ bool unshowRequested = false; float imguiStackMargin = 10; float lastWindowHeightPolyscope = 200; float lastWindowHeightUser = 200; -float leftWindowsWidth = 305; -float rightWindowsWidth = 500; +constexpr float LEFT_WINDOWS_WIDTH = 305; +constexpr float RIGHT_WINDOWS_WIDTH = 500; +float leftWindowsWidth = LEFT_WINDOWS_WIDTH; +float rightWindowsWidth = RIGHT_WINDOWS_WIDTH; auto lastMainLoopIterTime = std::chrono::steady_clock::now(); @@ -554,7 +556,7 @@ void userGuiBegin() { void userGuiEnd() { if (options::userGuiIsOnRightSide) { - rightWindowsWidth = ImGui::GetWindowWidth(); + rightWindowsWidth = RIGHT_WINDOWS_WIDTH * state::globalContext.dpiScale; lastWindowHeightUser = imguiStackMargin + ImGui::GetWindowHeight(); } else { lastWindowHeightUser = 0; @@ -645,7 +647,7 @@ void buildPolyscopeGui() { ImGui::Text("Rolling: %.1f ms/frame (%.1f fps)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Last: %.1f ms/frame (%.1f fps)", ImGui::GetIO().DeltaTime * 1000.f, 1.f / ImGui::GetIO().DeltaTime); - ImGui::PushItemWidth(40); + ImGui::PushItemWidth(40 * state::globalContext.dpiScale); if (ImGui::InputInt("max fps", &options::maxFPS, 0)) { if (options::maxFPS < 1 && options::maxFPS != -1) { options::maxFPS = -1; @@ -679,7 +681,7 @@ void buildPolyscopeGui() { lastWindowHeightPolyscope = imguiStackMargin + ImGui::GetWindowHeight(); - leftWindowsWidth = ImGui::GetWindowWidth(); + leftWindowsWidth = LEFT_WINDOWS_WIDTH * state::globalContext.dpiScale; ImGui::End(); } @@ -748,7 +750,7 @@ void buildStructureGui() { ImGui::PopID(); } - leftWindowsWidth = ImGui::GetWindowWidth(); + leftWindowsWidth = LEFT_WINDOWS_WIDTH * state::globalContext.dpiScale; ImGui::End(); } @@ -767,7 +769,7 @@ void buildPickGui() { ImGui::Separator(); selection.first->buildPickUI(selection.second); - rightWindowsWidth = ImGui::GetWindowWidth(); + rightWindowsWidth = RIGHT_WINDOWS_WIDTH * state::globalContext.dpiScale; ImGui::End(); } } diff --git a/src/render/color_maps.cpp b/src/render/color_maps.cpp index bfe0fb7c2..ce8d1545b 100644 --- a/src/render/color_maps.cpp +++ b/src/render/color_maps.cpp @@ -6,6 +6,7 @@ #include "polyscope/render/engine.h" #include "imgui.h" +#include "polyscope/polyscope.h" namespace polyscope { @@ -17,7 +18,7 @@ namespace render { bool buildColormapSelector(std::string& cm, std::string fieldName) { bool changed = false; - ImGui::PushItemWidth(125); + ImGui::PushItemWidth(125 * state::globalContext.dpiScale); if (ImGui::BeginCombo(fieldName.c_str(), cm.c_str())) { for (auto& c : render::engine->colorMaps) { diff --git a/src/render/engine.cpp b/src/render/engine.cpp index 819eb9596..15cf34846 100644 --- a/src/render/engine.cpp +++ b/src/render/engine.cpp @@ -280,7 +280,7 @@ void Engine::buildEngineGui() { if (ImGui::TreeNode("Appearance")) { // == Display - ImGui::PushItemWidth(120); + ImGui::PushItemWidth(120 * state::globalContext.dpiScale); // ImGui::Text("Background"); // ImGui::SameLine(); static std::string displayBackgroundName = "None"; diff --git a/src/render/ground_plane.cpp b/src/render/ground_plane.cpp index dec2e2054..e99c1c713 100644 --- a/src/render/ground_plane.cpp +++ b/src/render/ground_plane.cpp @@ -411,7 +411,7 @@ void GroundPlane::buildGui() { ImGui::SetNextItemOpen(false, ImGuiCond_FirstUseEver); if (ImGui::TreeNode("Ground Plane")) { - ImGui::PushItemWidth(160); + ImGui::PushItemWidth(160*state::globalContext.dpiScale); if (ImGui::BeginCombo("Mode", modeName(options::groundPlaneMode).c_str())) { for (GroundPlaneMode m : {GroundPlaneMode::None, GroundPlaneMode::Tile, GroundPlaneMode::TileReflection, GroundPlaneMode::ShadowOnly}) { @@ -426,7 +426,7 @@ void GroundPlane::buildGui() { ImGui::PopItemWidth(); // Height - ImGui::PushItemWidth(80); + ImGui::PushItemWidth(80 * state::globalContext.dpiScale); switch (options::groundPlaneHeightMode) { case GroundPlaneHeightMode::Automatic: if (ImGui::SliderFloat("##HeightValue", options::groundPlaneHeightFactor.getValuePtr(), -1.0, 1.0)) @@ -446,7 +446,7 @@ void GroundPlane::buildGui() { } ImGui::PopItemWidth(); ImGui::SameLine(); - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100*state::globalContext.dpiScale); if (ImGui::BeginCombo("Height##Mode", heightModeName(options::groundPlaneHeightMode).c_str())) { for (GroundPlaneHeightMode m : {GroundPlaneHeightMode::Automatic, GroundPlaneHeightMode::Manual}) { std::string mName = heightModeName(m); diff --git a/src/surface_mesh.cpp b/src/surface_mesh.cpp index b16082f9a..baac46fd2 100644 --- a/src/surface_mesh.cpp +++ b/src/surface_mesh.cpp @@ -1249,7 +1249,7 @@ void SurfaceMesh::buildCustomUI() { { // Flat shading or smooth shading? ImGui::SameLine(); - ImGui::PushItemWidth(85); + ImGui::PushItemWidth(85 * state::globalContext.dpiScale); auto styleName = [](const MeshShadeStyle& m) -> std::string { switch (m) { @@ -1278,7 +1278,7 @@ void SurfaceMesh::buildCustomUI() { { // Edge options ImGui::SameLine(); - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); if (edgeWidth.get() == 0.) { bool showEdges = false; if (ImGui::Checkbox("Edges", &showEdges)) { @@ -1291,14 +1291,14 @@ void SurfaceMesh::buildCustomUI() { } // Edge color - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); if (ImGui::ColorEdit3("Edge Color", &edgeColor.get()[0], ImGuiColorEditFlags_NoInputs)) setEdgeColor(edgeColor.get()); ImGui::PopItemWidth(); // Edge width ImGui::SameLine(); - ImGui::PushItemWidth(75); + ImGui::PushItemWidth(75 * state::globalContext.dpiScale); if (ImGui::SliderFloat("Width", &edgeWidth.get(), 0.001, 2.)) { // NOTE: this intentionally circumvents the setEdgeWidth() setter to avoid repopulating the buffer as the // slider is dragged---otherwise we repopulate the buffer on every change, which mostly works fine. This is a @@ -1419,12 +1419,12 @@ long long int SurfaceMesh::selectVertex() { ImGui::SetNextWindowSize(ImVec2(300, 0), ImGuiCond_Once); ImGui::Begin("Select vertex", &showWindow); - ImGui::PushItemWidth(300); + ImGui::PushItemWidth(300 * state::globalContext.dpiScale); ImGui::TextUnformatted("Hold ctrl and left-click to select a vertex"); ImGui::Separator(); // Choose by number - ImGui::PushItemWidth(300); + ImGui::PushItemWidth(300 * state::globalContext.dpiScale); static int iV = -1; ImGui::InputInt("index", &iV); if (ImGui::Button("Select by index")) { diff --git a/src/view.cpp b/src/view.cpp index 4511205e5..72c0fd42e 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -728,7 +728,7 @@ void buildViewGui() { std::string viewStyleName = to_string(view::style); - ImGui::PushItemWidth(120); + ImGui::PushItemWidth(120 * state::globalContext.dpiScale); std::array styles{NavigateStyle::Turntable, NavigateStyle::Free, NavigateStyle::Planar, NavigateStyle::None, NavigateStyle::FirstPerson}; if (ImGui::BeginCombo("##View Style", viewStyleName.c_str())) { @@ -747,7 +747,7 @@ void buildViewGui() { ImGui::Text("Camera Style"); { // == Up direction - ImGui::PushItemWidth(120); + ImGui::PushItemWidth(120 * state::globalContext.dpiScale); std::string upStyleName; switch (upDir) { case UpDir::XUp: @@ -802,7 +802,7 @@ void buildViewGui() { } { // == Front direction - ImGui::PushItemWidth(120); + ImGui::PushItemWidth(120 * state::globalContext.dpiScale); std::string frontStyleName; switch (frontDir) { case FrontDir::XFront: @@ -894,7 +894,7 @@ void buildViewGui() { ImGui::TextUnformatted("Bounding Box:"); - ImGui::PushItemWidth(200); + ImGui::PushItemWidth(200 * state::globalContext.dpiScale); glm::vec3& bboxMin = std::get<0>(state::boundingBox); glm::vec3& bboxMax = std::get<1>(state::boundingBox); if (ImGui::InputFloat3("min", &bboxMin[0])) updateStructureExtents(); @@ -958,7 +958,7 @@ void buildViewGui() { { ImGui::TextUnformatted("Dim:"); ImGui::SameLine(); - ImGui::PushItemWidth(50); + ImGui::PushItemWidth(50 * state::globalContext.dpiScale); bool changed = false; int currWidth = view::windowWidth; int currHeight = view::windowHeight; diff --git a/src/volume_grid.cpp b/src/volume_grid.cpp index 1ad3b6688..526e28b98 100644 --- a/src/volume_grid.cpp +++ b/src/volume_grid.cpp @@ -52,7 +52,7 @@ void VolumeGrid::buildCustomUI() { { // Edge options ImGui::SameLine(); - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); if (edgeWidth.get() == 0.) { bool showEdges = false; if (ImGui::Checkbox("Edges", &showEdges)) { @@ -65,14 +65,14 @@ void VolumeGrid::buildCustomUI() { } // Edge color - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); if (ImGui::ColorEdit3("Edge Color", &edgeColor.get()[0], ImGuiColorEditFlags_NoInputs)) setEdgeColor(edgeColor.get()); ImGui::PopItemWidth(); // Edge width ImGui::SameLine(); - ImGui::PushItemWidth(75); + ImGui::PushItemWidth(75 * state::globalContext.dpiScale); if (ImGui::SliderFloat("Width", &edgeWidth.get(), 0.001, 2.)) { // NOTE: this intentionally circumvents the setEdgeWidth() setter to avoid repopulating the buffer as the // slider is dragged---otherwise we repopulate the buffer on every change, which mostly works fine. This is a diff --git a/src/volume_grid_scalar_quantity.cpp b/src/volume_grid_scalar_quantity.cpp index cde441a9b..530736a2c 100644 --- a/src/volume_grid_scalar_quantity.cpp +++ b/src/volume_grid_scalar_quantity.cpp @@ -70,7 +70,7 @@ void VolumeGridNodeScalarQuantity::buildCustomUI() { ImGui::SameLine(); // Set isovalue - ImGui::PushItemWidth(120); + ImGui::PushItemWidth(120 * state::globalContext.dpiScale); if (ImGui::SliderFloat("##Radius", &isosurfaceLevel.get(), vizRangeMin.get(), vizRangeMax.get(), "%.4e")) { // Note: we intentionally do this rather than calling setIsosurfaceLevel(), because that function immediately // recomputes the levelset mesh, which is too expensive during user interaction diff --git a/src/volume_mesh.cpp b/src/volume_mesh.cpp index 97f0e8689..9e69abb9b 100644 --- a/src/volume_mesh.cpp +++ b/src/volume_mesh.cpp @@ -871,7 +871,7 @@ void VolumeMesh::buildCustomUI() { ImGui::SameLine(); { // Edge options - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); if (edgeWidth.get() == 0.) { bool showEdges = false; if (ImGui::Checkbox("Edges", &showEdges)) { @@ -884,14 +884,14 @@ void VolumeMesh::buildCustomUI() { } // Edge color - ImGui::PushItemWidth(100); + ImGui::PushItemWidth(100 * state::globalContext.dpiScale); if (ImGui::ColorEdit3("Edge Color", &edgeColor.get()[0], ImGuiColorEditFlags_NoInputs)) setEdgeColor(edgeColor.get()); ImGui::PopItemWidth(); // Edge width ImGui::SameLine(); - ImGui::PushItemWidth(60); + ImGui::PushItemWidth(60 * state::globalContext.dpiScale); if (ImGui::SliderFloat("Width", &edgeWidth.get(), 0.001, 2.)) { // NOTE: this intentionally circumvents the setEdgeWidth() setter to avoid repopulating the buffer as the // slider is dragged---otherwise we repopulate the buffer on every change, which mostly works fine. This is a From 821fbf97a8d6d3e995516850474d0232986e6386 Mon Sep 17 00:00:00 2001 From: BruegelN Date: Thu, 6 Mar 2025 19:09:09 +0100 Subject: [PATCH 03/11] set GLFW_SCALE_TO_MONITOR for proper windows size on start up --- src/render/opengl/gl_engine_glfw.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/render/opengl/gl_engine_glfw.cpp b/src/render/opengl/gl_engine_glfw.cpp index 826cb7fae..948cb889d 100644 --- a/src/render/opengl/gl_engine_glfw.cpp +++ b/src/render/opengl/gl_engine_glfw.cpp @@ -50,6 +50,10 @@ void GLEngineGLFW::initialize() { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + // this is required to make sure the initial windows size is appropriate + glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); + #if __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif From 6e934ac105789b88bf02bbdb6d8a17b8f65f19eb Mon Sep 17 00:00:00 2001 From: BruegelN Date: Thu, 6 Mar 2025 19:20:57 +0100 Subject: [PATCH 04/11] Make sure the dpiScale factor is in a reasonable range (1x-10x) --- src/render/opengl/gl_engine_glfw.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/render/opengl/gl_engine_glfw.cpp b/src/render/opengl/gl_engine_glfw.cpp index 948cb889d..4a2d0ed81 100644 --- a/src/render/opengl/gl_engine_glfw.cpp +++ b/src/render/opengl/gl_engine_glfw.cpp @@ -116,9 +116,12 @@ void GLEngineGLFW::initializeImGui() { const char* glsl_version = "#version 150"; ImGui_ImplOpenGL3_Init(glsl_version); - float xScale, yScale; - glfwGetWindowContentScale(mainWindow, &xScale, &yScale); - state::globalContext.dpiScale = std::min(xScale, yScale); + float xScale, dont_use_yScale; + glfwGetWindowContentScale(mainWindow, &xScale, &dont_use_yScale); + if (xScale == NULL) { + xScale = 1.0f; + } + state::globalContext.dpiScale = std::min(std::max(xScale, 1.0f), 10.0f); configureImGui(); } @@ -140,9 +143,12 @@ void GLEngineGLFW::shutdownImGui() { } void GLEngineGLFW::ImGuiNewFrame() { - float xScale, yScale; - glfwGetWindowContentScale(mainWindow, &xScale, &yScale); - state::globalContext.dpiScale = std::min(xScale, yScale); + float xScale, dont_use_yScale; + glfwGetWindowContentScale(mainWindow, &xScale, &dont_use_yScale); + if (xScale == NULL) { + xScale = 1.0f; + } + state::globalContext.dpiScale = std::min(std::max(xScale, 1.0f), 10.0f); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); From ad28cdc84459555ea285e9ce4c558c5874130458 Mon Sep 17 00:00:00 2001 From: Nicholas Sharp Date: Mon, 12 May 2025 18:47:22 -0700 Subject: [PATCH 05/11] some refactor/renaming, plus bugfixes for nested context push --- examples/demo-app/demo_app.cpp | 2 +- include/polyscope/context.h | 1 - include/polyscope/options.h | 3 ++ .../polyscope/parameterization_quantity.ipp | 6 +-- include/polyscope/render/engine.h | 2 +- .../polyscope/render/opengl/gl_engine_glfw.h | 1 + include/polyscope/scalar_quantity.ipp | 2 +- src/camera_view.cpp | 2 +- src/curve_network.cpp | 2 +- src/file_helpers.cpp | 2 +- src/image_quantity_base.cpp | 2 +- src/imgui_config.cpp | 14 +++---- src/messages.cpp | 2 +- src/options.cpp | 1 + src/point_cloud.cpp | 2 +- src/polyscope.cpp | 27 ++++++------- src/render/color_maps.cpp | 2 +- src/render/engine.cpp | 25 +++++------- src/render/ground_plane.cpp | 8 ++-- src/render/opengl/gl_engine_glfw.cpp | 38 +++++++++++++++---- src/surface_mesh.cpp | 12 +++--- src/view.cpp | 10 ++--- src/volume_grid.cpp | 6 +-- src/volume_grid_scalar_quantity.cpp | 2 +- src/volume_mesh.cpp | 6 +-- 25 files changed, 102 insertions(+), 78 deletions(-) diff --git a/examples/demo-app/demo_app.cpp b/examples/demo-app/demo_app.cpp index d19959806..54aeb071a 100644 --- a/examples/demo-app/demo_app.cpp +++ b/examples/demo-app/demo_app.cpp @@ -780,7 +780,7 @@ void callback() { static int loadedMat = 1; static bool depthClick = false; - ImGui::PushItemWidth(100 * polyscope::state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * polyscope::options::uiScale); ImGui::InputInt("num points", &numPoints); ImGui::InputFloat("param value", ¶m); diff --git a/include/polyscope/context.h b/include/polyscope/context.h index 34cc79802..0c591c000 100644 --- a/include/polyscope/context.h +++ b/include/polyscope/context.h @@ -56,7 +56,6 @@ struct Context { std::map>> structures; std::map> groups; float lengthScale = 1.; - float dpiScale = 1.; std::tuple boundingBox = std::tuple{glm::vec3{-1., -1., -1.}, glm::vec3{1., 1., 1.}}; std::vector> slicePlanes; diff --git a/include/polyscope/options.h b/include/polyscope/options.h index 627512a88..e2919ef2d 100644 --- a/include/polyscope/options.h +++ b/include/polyscope/options.h @@ -93,6 +93,9 @@ extern std::string screenshotExtension; // sets the extension used for automatic // SSAA scaling in pixel multiples extern int ssaaFactor; +// DPI scaling to scale the UI on high-resolutoin screens +extern float uiScale; + // Transparency settings for the renderer extern TransparencyMode transparencyMode; extern int transparencyRenderPasses; diff --git a/include/polyscope/parameterization_quantity.ipp b/include/polyscope/parameterization_quantity.ipp index f8b0fdb84..80f5028be 100644 --- a/include/polyscope/parameterization_quantity.ipp +++ b/include/polyscope/parameterization_quantity.ipp @@ -61,7 +61,7 @@ ParameterizationQuantity::ParameterizationQuantity(QuantityT& quantit template void ParameterizationQuantity::buildParameterizationUI() { - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); // Modulo stripey width if (ImGui::DragFloat("period", &checkerSize.get(), .001, 0.0001, 1.0, "%.4f", @@ -82,7 +82,7 @@ void ParameterizationQuantity::buildParameterizationUI() { setCheckerColors(getCheckerColors()); break; case ParamVizStyle::CHECKER_ISLANDS: - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); if (ImGui::DragFloat("alt darkness", &altDarkness.get(), 0.01, 0., 1.)) { altDarkness.manuallyChanged(); requestRedraw(); @@ -103,7 +103,7 @@ void ParameterizationQuantity::buildParameterizationUI() { case ParamVizStyle::LOCAL_CHECK: case ParamVizStyle::LOCAL_RAD: { // Angle slider - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); ImGui::SliderAngle("angle shift", &localRot, -180, 180); // displays in degrees, works in radians TODO refresh/update/persist if (ImGui::DragFloat("alt darkness", &altDarkness.get(), 0.01, 0., 1.)) { diff --git a/include/polyscope/render/engine.h b/include/polyscope/render/engine.h index c37d3f861..c78e68514 100644 --- a/include/polyscope/render/engine.h +++ b/include/polyscope/render/engine.h @@ -629,6 +629,7 @@ class Engine { bool useAltDisplayBuffer = false; // if true, push final render results offscreen to the alt buffer instead // Internal windowing and engine details + virtual void configureImGui() {}; // generates font things ImFontAtlas* globalFontAtlas = nullptr; ImFont* regularFont = nullptr; ImFont* monoFont = nullptr; @@ -658,7 +659,6 @@ class Engine { TransparencyMode currLightingTransparencyMode = TransparencyMode::None; // Helpers - void configureImGui(); void loadDefaultMaterials(); void loadDefaultMaterial(std::string name); std::shared_ptr loadMaterialTexture(float* data, int width, int height); diff --git a/include/polyscope/render/opengl/gl_engine_glfw.h b/include/polyscope/render/opengl/gl_engine_glfw.h index 574f2b277..8b951c0be 100644 --- a/include/polyscope/render/opengl/gl_engine_glfw.h +++ b/include/polyscope/render/opengl/gl_engine_glfw.h @@ -77,6 +77,7 @@ class GLEngineGLFW : public GLEngine { void shutdownImGui() override; void ImGuiNewFrame() override; void ImGuiRender() override; + void configureImGui() override; protected: // Internal windowing and engine details diff --git a/include/polyscope/scalar_quantity.ipp b/include/polyscope/scalar_quantity.ipp index 06d12138c..bff31d155 100644 --- a/include/polyscope/scalar_quantity.ipp +++ b/include/polyscope/scalar_quantity.ipp @@ -147,7 +147,7 @@ void ScalarQuantity::buildScalarUI() { // Isolines if (isolinesEnabled.get()) { - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); auto styleName = [](const IsolineStyle& m) -> std::string { diff --git a/src/camera_view.cpp b/src/camera_view.cpp index 34276b749..872059d3b 100644 --- a/src/camera_view.cpp +++ b/src/camera_view.cpp @@ -366,7 +366,7 @@ void CameraView::buildCustomUI() { void CameraView::buildCustomOptionsUI() { - ImGui::PushItemWidth(150 * state::globalContext.dpiScale); + ImGui::PushItemWidth(150 * options::uiScale); if (widgetFocalLengthUpper == -777) widgetFocalLengthUpper = 2. * (*widgetFocalLength.get().getValuePtr()); if (ImGui::SliderFloat("widget focal length", widgetFocalLength.get().getValuePtr(), 0, widgetFocalLengthUpper, diff --git a/src/curve_network.cpp b/src/curve_network.cpp index 7ed9ac8d1..de1e5198e 100644 --- a/src/curve_network.cpp +++ b/src/curve_network.cpp @@ -402,7 +402,7 @@ void CurveNetwork::buildCustomUI() { setColor(getColor()); } ImGui::SameLine(); - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); if (ImGui::SliderFloat("Radius", radius.get().getValuePtr(), 0.0, .1, "%.5f", ImGuiSliderFlags_Logarithmic | ImGuiSliderFlags_NoRoundToFormat)) { radius.manuallyChanged(); diff --git a/src/file_helpers.cpp b/src/file_helpers.cpp index cdceb12bc..7b45b16af 100644 --- a/src/file_helpers.cpp +++ b/src/file_helpers.cpp @@ -14,7 +14,7 @@ void filenamePromptCallback(char* buff, size_t len) { static bool windowOpen = true; ImGui::Begin("Enter filename", &windowOpen, ImGuiWindowFlags_AlwaysAutoResize); - ImGui::PushItemWidth(500 * state::globalContext.dpiScale); + ImGui::PushItemWidth(500 * options::uiScale); ImGui::InputText("##filename", buff, len); if (ImGui::Button("Ok")) { diff --git a/src/image_quantity_base.cpp b/src/image_quantity_base.cpp index 222d22e01..2d5c761ff 100644 --- a/src/image_quantity_base.cpp +++ b/src/image_quantity_base.cpp @@ -114,7 +114,7 @@ void ImageQuantity::buildImageUI() { if (getShowFullscreen()) { - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); if (ImGui::SliderFloat("transparency", &transparency.get(), 0.f, 1.f)) { transparency.manuallyChanged(); requestRedraw(); diff --git a/src/imgui_config.cpp b/src/imgui_config.cpp index d4ae6ec4e..5fd8dd930 100644 --- a/src/imgui_config.cpp +++ b/src/imgui_config.cpp @@ -18,11 +18,11 @@ void configureImGuiStyle() { // Style ImGuiStyle* style = &ImGui::GetStyle(); - style->WindowRounding = 1; - style->FrameRounding = 1; - style->FramePadding.y = 4; - style->ScrollbarRounding = 1; - style->ScrollbarSize = 20; + style->WindowRounding = 1 * options::uiScale; + style->FrameRounding = 1 * options::uiScale; + style->FramePadding.y = 4 * options::uiScale; + style->ScrollbarRounding = 1 * options::uiScale; + style->ScrollbarSize = 20 * options::uiScale; // Colors @@ -85,13 +85,13 @@ std::tuple prepareImGuiFonts() { { // add regular font ImFontConfig config; regularFont = io.Fonts->AddFontFromMemoryCompressedTTF(render::getLatoRegularCompressedData(), - render::getLatoRegularCompressedSize(), state::globalContext.dpiScale*18.0f, &config); + render::getLatoRegularCompressedSize(), options::uiScale*18.0f, &config); } { // add mono font ImFontConfig config; monoFont = io.Fonts->AddFontFromMemoryCompressedTTF(render::getCousineRegularCompressedData(), - render::getCousineRegularCompressedSize(), state::globalContext.dpiScale*16.0f, &config); + render::getCousineRegularCompressedSize(), options::uiScale*16.0f, &config); } // io.Fonts->AddFontFromFileTTF("test-font-name.ttf", 16); diff --git a/src/messages.cpp b/src/messages.cpp index 286551644..69770cbb3 100644 --- a/src/messages.cpp +++ b/src/messages.cpp @@ -174,7 +174,7 @@ void buildWarningUI(std::string warningBaseString, std::string warningDetailStri } // Nice button sizing - float buttonWidth = 120 * state::globalContext.dpiScale; + float buttonWidth = 120 * options::uiScale; float buttonOffset = (warningModalSize.x - buttonWidth) / 2.0; buttonOffset = std::max(buttonOffset, 0.0f); doIndent = buttonOffset > 0; diff --git a/src/options.cpp b/src/options.cpp index a97ec2ba2..4a0bf655a 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -42,6 +42,7 @@ float shadowDarkness = 0.25; // Rendering options +float uiScale = 1.0; int ssaaFactor = 1; // Transparency diff --git a/src/point_cloud.cpp b/src/point_cloud.cpp index e1443c94f..93f7600a9 100644 --- a/src/point_cloud.cpp +++ b/src/point_cloud.cpp @@ -266,7 +266,7 @@ void PointCloud::buildCustomUI() { setPointColor(getPointColor()); } ImGui::SameLine(); - ImGui::PushItemWidth(70 * state::globalContext.dpiScale); + ImGui::PushItemWidth(70 * options::uiScale); if (ImGui::SliderFloat("Radius", pointRadius.get().getValuePtr(), 0.0, .1, "%.5f", ImGuiSliderFlags_Logarithmic | ImGuiSliderFlags_NoRoundToFormat)) { pointRadius.manuallyChanged(); diff --git a/src/polyscope.cpp b/src/polyscope.cpp index 979fba010..ae0e88596 100644 --- a/src/polyscope.cpp +++ b/src/polyscope.cpp @@ -183,7 +183,7 @@ bool isInitialized() { return state::initialized; } void pushContext(std::function callbackFunction, bool drawDefaultUI) { // Create a new context and push it on to the stack - ImGuiContext* newContext = ImGui::CreateContext(render::engine->getImGuiGlobalFontAtlas()); + ImGuiContext* newContext = ImGui::CreateContext(); ImGuiIO& oldIO = ImGui::GetIO(); // used to GLFW + OpenGL data to the new IO object #ifdef IMGUI_HAS_DOCK ImGuiPlatformIO& oldPlatformIO = ImGui::GetPlatformIO(); @@ -196,9 +196,7 @@ void pushContext(std::function callbackFunction, bool drawDefaultUI) { ImGui::GetIO().BackendPlatformUserData = oldIO.BackendPlatformUserData; ImGui::GetIO().BackendRendererUserData = oldIO.BackendRendererUserData; - if (options::configureImGuiStyleCallback) { - options::configureImGuiStyleCallback(); - } + render::engine->configureImGui(); contextStack.push_back(ContextEntry{newContext, callbackFunction, drawDefaultUI}); @@ -437,7 +435,6 @@ void renderSlicePlanes() { } void renderScene() { - processLazyProperties(); render::engine->applyTransparencySettings(); @@ -556,7 +553,7 @@ void userGuiBegin() { void userGuiEnd() { if (options::userGuiIsOnRightSide) { - rightWindowsWidth = RIGHT_WINDOWS_WIDTH * state::globalContext.dpiScale; + rightWindowsWidth = RIGHT_WINDOWS_WIDTH * options::uiScale; lastWindowHeightUser = imguiStackMargin + ImGui::GetWindowHeight(); } else { lastWindowHeightUser = 0; @@ -647,7 +644,7 @@ void buildPolyscopeGui() { ImGui::Text("Rolling: %.1f ms/frame (%.1f fps)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Last: %.1f ms/frame (%.1f fps)", ImGui::GetIO().DeltaTime * 1000.f, 1.f / ImGui::GetIO().DeltaTime); - ImGui::PushItemWidth(40 * state::globalContext.dpiScale); + ImGui::PushItemWidth(40 * options::uiScale); if (ImGui::InputInt("max fps", &options::maxFPS, 0)) { if (options::maxFPS < 1 && options::maxFPS != -1) { options::maxFPS = -1; @@ -681,7 +678,7 @@ void buildPolyscopeGui() { lastWindowHeightPolyscope = imguiStackMargin + ImGui::GetWindowHeight(); - leftWindowsWidth = LEFT_WINDOWS_WIDTH * state::globalContext.dpiScale; + leftWindowsWidth = LEFT_WINDOWS_WIDTH * options::uiScale; ImGui::End(); } @@ -750,7 +747,7 @@ void buildStructureGui() { ImGui::PopID(); } - leftWindowsWidth = LEFT_WINDOWS_WIDTH * state::globalContext.dpiScale; + leftWindowsWidth = LEFT_WINDOWS_WIDTH * options::uiScale; ImGui::End(); } @@ -769,7 +766,7 @@ void buildPickGui() { ImGui::Separator(); selection.first->buildPickUI(selection.second); - rightWindowsWidth = RIGHT_WINDOWS_WIDTH * state::globalContext.dpiScale; + rightWindowsWidth = RIGHT_WINDOWS_WIDTH * options::uiScale; ImGui::End(); } } @@ -802,7 +799,6 @@ void buildUserGuiAndInvokeCallback() { } void draw(bool withUI, bool withContextCallback) { - processLazyProperties(); // Update buffer and context render::engine->makeContextCurrent(); @@ -852,8 +848,6 @@ void draw(bool withUI, bool withContextCallback) { (contextStack.back().callback)(); } - processLazyProperties(); - // Draw structures in the scene if (redrawNextFrame || options::alwaysRedraw) { renderScene(); @@ -1226,6 +1220,7 @@ namespace lazy { TransparencyMode transparencyMode = TransparencyMode::None; int transparencyRenderPasses = 8; int ssaaFactor = 1; +float uiScale = 1; bool groundPlaneEnabled = true; GroundPlaneMode groundPlaneMode = GroundPlaneMode::TileReflection; ScaledValue groundPlaneHeightFactor = 0; @@ -1262,6 +1257,12 @@ void processLazyProperties() { lazy::ssaaFactor = options::ssaaFactor; render::engine->setSSAAFactor(options::ssaaFactor); } + + // uiScale + if (lazy::uiScale != options::uiScale) { + lazy::uiScale = options::uiScale; + render::engine->configureImGui(); + } // ground plane if (lazy::groundPlaneEnabled != options::groundPlaneEnabled || lazy::groundPlaneMode != options::groundPlaneMode) { diff --git a/src/render/color_maps.cpp b/src/render/color_maps.cpp index ce8d1545b..79a0dc66d 100644 --- a/src/render/color_maps.cpp +++ b/src/render/color_maps.cpp @@ -18,7 +18,7 @@ namespace render { bool buildColormapSelector(std::string& cm, std::string fieldName) { bool changed = false; - ImGui::PushItemWidth(125 * state::globalContext.dpiScale); + ImGui::PushItemWidth(125 * options::uiScale); if (ImGui::BeginCombo(fieldName.c_str(), cm.c_str())) { for (auto& c : render::engine->colorMaps) { diff --git a/src/render/engine.cpp b/src/render/engine.cpp index 15cf34846..9075756e0 100644 --- a/src/render/engine.cpp +++ b/src/render/engine.cpp @@ -280,7 +280,7 @@ void Engine::buildEngineGui() { if (ImGui::TreeNode("Appearance")) { // == Display - ImGui::PushItemWidth(120 * state::globalContext.dpiScale); + ImGui::PushItemWidth(120 * options::uiScale); // ImGui::Text("Background"); // ImGui::SameLine(); static std::string displayBackgroundName = "None"; @@ -349,13 +349,19 @@ void Engine::buildEngineGui() { // == Anti-aliasing ImGui::SetNextItemOpen(false, ImGuiCond_FirstUseEver); - if (ImGui::TreeNode("Anti-Aliasing")) { + if (ImGui::TreeNode("Anti-Aliasing & DPI")) { if (ImGui::InputInt("SSAA (pretty)", &ssaaFactor, 1)) { ssaaFactor = std::min(ssaaFactor, 4); ssaaFactor = std::max(ssaaFactor, 1); options::ssaaFactor = ssaaFactor; requestRedraw(); } + + if (ImGui::InputFloat("DPI scale", &options::uiScale, 0.25f)) { + options::uiScale = std::min(options::uiScale, 4.f); + options::uiScale = std::max(options::uiScale, 0.25f); + requestRedraw(); + } ImGui::TreePop(); } @@ -477,7 +483,7 @@ void Engine::setScreenBufferViewports() { } bool Engine::bindSceneBuffer() { - setCurrentPixelScaling(ssaaFactor); + setCurrentPixelScaling(ssaaFactor * options::uiScale); return sceneBuffer->bindForRendering(); } @@ -1093,18 +1099,6 @@ const ValueColorMap& Engine::getColorMap(const std::string& name) { } -void Engine::configureImGui() { - - if (options::prepareImGuiFontsCallback) { - std::tie(globalFontAtlas, regularFont, monoFont) = options::prepareImGuiFontsCallback(); - } - - - if (options::configureImGuiStyleCallback) { - options::configureImGuiStyleCallback(); - } -} - void Engine::loadDefaultColorMap(std::string name) { const std::vector* buff = nullptr; @@ -1181,6 +1175,7 @@ void Engine::showTextureInImGuiWindow(std::string windowName, TextureBuffer* buf ImGui::End(); } +// TODO remove this, it's not global anymore, each context gets its own ImFontAtlas* Engine::getImGuiGlobalFontAtlas() { return globalFontAtlas; } void Engine::preserveResourceUntilImguiFrameCompletes(std::shared_ptr texture) { diff --git a/src/render/ground_plane.cpp b/src/render/ground_plane.cpp index e99c1c713..d07935b2c 100644 --- a/src/render/ground_plane.cpp +++ b/src/render/ground_plane.cpp @@ -277,7 +277,7 @@ void GroundPlane::draw(bool isRedraw) { render::engine->setDepthMode(DepthMode::Less); sceneAltFrameBuffer->resize(factor * view::bufferWidth / 2, factor * view::bufferHeight / 2); sceneAltFrameBuffer->setViewport(0, 0, factor * view::bufferWidth / 2, factor * view::bufferHeight / 2); - render::engine->setCurrentPixelScaling(factor / 2.); + render::engine->setCurrentPixelScaling(factor / 2. * options::uiScale); sceneAltFrameBuffer->bindForRendering(); sceneAltFrameBuffer->clearColor = {view::bgColor[0], view::bgColor[1], view::bgColor[2]}; @@ -411,7 +411,7 @@ void GroundPlane::buildGui() { ImGui::SetNextItemOpen(false, ImGuiCond_FirstUseEver); if (ImGui::TreeNode("Ground Plane")) { - ImGui::PushItemWidth(160*state::globalContext.dpiScale); + ImGui::PushItemWidth(160*options::uiScale); if (ImGui::BeginCombo("Mode", modeName(options::groundPlaneMode).c_str())) { for (GroundPlaneMode m : {GroundPlaneMode::None, GroundPlaneMode::Tile, GroundPlaneMode::TileReflection, GroundPlaneMode::ShadowOnly}) { @@ -426,7 +426,7 @@ void GroundPlane::buildGui() { ImGui::PopItemWidth(); // Height - ImGui::PushItemWidth(80 * state::globalContext.dpiScale); + ImGui::PushItemWidth(80 * options::uiScale); switch (options::groundPlaneHeightMode) { case GroundPlaneHeightMode::Automatic: if (ImGui::SliderFloat("##HeightValue", options::groundPlaneHeightFactor.getValuePtr(), -1.0, 1.0)) @@ -446,7 +446,7 @@ void GroundPlane::buildGui() { } ImGui::PopItemWidth(); ImGui::SameLine(); - ImGui::PushItemWidth(100*state::globalContext.dpiScale); + ImGui::PushItemWidth(100*options::uiScale); if (ImGui::BeginCombo("Height##Mode", heightModeName(options::groundPlaneHeightMode).c_str())) { for (GroundPlaneHeightMode m : {GroundPlaneHeightMode::Automatic, GroundPlaneHeightMode::Manual}) { std::string mName = heightModeName(m); diff --git a/src/render/opengl/gl_engine_glfw.cpp b/src/render/opengl/gl_engine_glfw.cpp index 4a2d0ed81..43d4d76be 100644 --- a/src/render/opengl/gl_engine_glfw.cpp +++ b/src/render/opengl/gl_engine_glfw.cpp @@ -121,11 +121,34 @@ void GLEngineGLFW::initializeImGui() { if (xScale == NULL) { xScale = 1.0f; } - state::globalContext.dpiScale = std::min(std::max(xScale, 1.0f), 10.0f); + options::uiScale = std::min(std::max(xScale, 1.0f), 10.0f); configureImGui(); } +void GLEngineGLFW::configureImGui() { + + if (options::prepareImGuiFontsCallback) { + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->Clear(); + + // these are necessary if different fonts are loaded in the callback + // (don't totally understand why, allegedly it may change in the future) + ImGui_ImplOpenGL3_DestroyFontsTexture(); + + std::tie(globalFontAtlas, regularFont, monoFont) = options::prepareImGuiFontsCallback(); + + ImGui_ImplOpenGL3_CreateFontsTexture(); + } + + + if (options::configureImGuiStyleCallback) { + options::configureImGuiStyleCallback(); + } +} + + void GLEngineGLFW::shutdown() { checkError(); @@ -143,12 +166,13 @@ void GLEngineGLFW::shutdownImGui() { } void GLEngineGLFW::ImGuiNewFrame() { - float xScale, dont_use_yScale; - glfwGetWindowContentScale(mainWindow, &xScale, &dont_use_yScale); - if (xScale == NULL) { - xScale = 1.0f; - } - state::globalContext.dpiScale = std::min(std::max(xScale, 1.0f), 10.0f); + // TODO + // float xScale, dont_use_yScale; + // glfwGetWindowContentScale(mainWindow, &xScale, &dont_use_yScale); + // if (xScale == NULL) { + // xScale = 1.0f; + // } + // options::uiScale = std::min(std::max(xScale, 1.0f), 10.0f); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); diff --git a/src/surface_mesh.cpp b/src/surface_mesh.cpp index baac46fd2..b6c1b3140 100644 --- a/src/surface_mesh.cpp +++ b/src/surface_mesh.cpp @@ -1249,7 +1249,7 @@ void SurfaceMesh::buildCustomUI() { { // Flat shading or smooth shading? ImGui::SameLine(); - ImGui::PushItemWidth(85 * state::globalContext.dpiScale); + ImGui::PushItemWidth(85 * options::uiScale); auto styleName = [](const MeshShadeStyle& m) -> std::string { switch (m) { @@ -1278,7 +1278,7 @@ void SurfaceMesh::buildCustomUI() { { // Edge options ImGui::SameLine(); - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); if (edgeWidth.get() == 0.) { bool showEdges = false; if (ImGui::Checkbox("Edges", &showEdges)) { @@ -1291,14 +1291,14 @@ void SurfaceMesh::buildCustomUI() { } // Edge color - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); if (ImGui::ColorEdit3("Edge Color", &edgeColor.get()[0], ImGuiColorEditFlags_NoInputs)) setEdgeColor(edgeColor.get()); ImGui::PopItemWidth(); // Edge width ImGui::SameLine(); - ImGui::PushItemWidth(75 * state::globalContext.dpiScale); + ImGui::PushItemWidth(75 * options::uiScale); if (ImGui::SliderFloat("Width", &edgeWidth.get(), 0.001, 2.)) { // NOTE: this intentionally circumvents the setEdgeWidth() setter to avoid repopulating the buffer as the // slider is dragged---otherwise we repopulate the buffer on every change, which mostly works fine. This is a @@ -1419,12 +1419,12 @@ long long int SurfaceMesh::selectVertex() { ImGui::SetNextWindowSize(ImVec2(300, 0), ImGuiCond_Once); ImGui::Begin("Select vertex", &showWindow); - ImGui::PushItemWidth(300 * state::globalContext.dpiScale); + ImGui::PushItemWidth(300 * options::uiScale); ImGui::TextUnformatted("Hold ctrl and left-click to select a vertex"); ImGui::Separator(); // Choose by number - ImGui::PushItemWidth(300 * state::globalContext.dpiScale); + ImGui::PushItemWidth(300 * options::uiScale); static int iV = -1; ImGui::InputInt("index", &iV); if (ImGui::Button("Select by index")) { diff --git a/src/view.cpp b/src/view.cpp index 72c0fd42e..f3f2940c7 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -728,7 +728,7 @@ void buildViewGui() { std::string viewStyleName = to_string(view::style); - ImGui::PushItemWidth(120 * state::globalContext.dpiScale); + ImGui::PushItemWidth(120 * options::uiScale); std::array styles{NavigateStyle::Turntable, NavigateStyle::Free, NavigateStyle::Planar, NavigateStyle::None, NavigateStyle::FirstPerson}; if (ImGui::BeginCombo("##View Style", viewStyleName.c_str())) { @@ -747,7 +747,7 @@ void buildViewGui() { ImGui::Text("Camera Style"); { // == Up direction - ImGui::PushItemWidth(120 * state::globalContext.dpiScale); + ImGui::PushItemWidth(120 * options::uiScale); std::string upStyleName; switch (upDir) { case UpDir::XUp: @@ -802,7 +802,7 @@ void buildViewGui() { } { // == Front direction - ImGui::PushItemWidth(120 * state::globalContext.dpiScale); + ImGui::PushItemWidth(120 * options::uiScale); std::string frontStyleName; switch (frontDir) { case FrontDir::XFront: @@ -894,7 +894,7 @@ void buildViewGui() { ImGui::TextUnformatted("Bounding Box:"); - ImGui::PushItemWidth(200 * state::globalContext.dpiScale); + ImGui::PushItemWidth(200 * options::uiScale); glm::vec3& bboxMin = std::get<0>(state::boundingBox); glm::vec3& bboxMax = std::get<1>(state::boundingBox); if (ImGui::InputFloat3("min", &bboxMin[0])) updateStructureExtents(); @@ -958,7 +958,7 @@ void buildViewGui() { { ImGui::TextUnformatted("Dim:"); ImGui::SameLine(); - ImGui::PushItemWidth(50 * state::globalContext.dpiScale); + ImGui::PushItemWidth(50 * options::uiScale); bool changed = false; int currWidth = view::windowWidth; int currHeight = view::windowHeight; diff --git a/src/volume_grid.cpp b/src/volume_grid.cpp index 526e28b98..299b5815f 100644 --- a/src/volume_grid.cpp +++ b/src/volume_grid.cpp @@ -52,7 +52,7 @@ void VolumeGrid::buildCustomUI() { { // Edge options ImGui::SameLine(); - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); if (edgeWidth.get() == 0.) { bool showEdges = false; if (ImGui::Checkbox("Edges", &showEdges)) { @@ -65,14 +65,14 @@ void VolumeGrid::buildCustomUI() { } // Edge color - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); if (ImGui::ColorEdit3("Edge Color", &edgeColor.get()[0], ImGuiColorEditFlags_NoInputs)) setEdgeColor(edgeColor.get()); ImGui::PopItemWidth(); // Edge width ImGui::SameLine(); - ImGui::PushItemWidth(75 * state::globalContext.dpiScale); + ImGui::PushItemWidth(75 * options::uiScale); if (ImGui::SliderFloat("Width", &edgeWidth.get(), 0.001, 2.)) { // NOTE: this intentionally circumvents the setEdgeWidth() setter to avoid repopulating the buffer as the // slider is dragged---otherwise we repopulate the buffer on every change, which mostly works fine. This is a diff --git a/src/volume_grid_scalar_quantity.cpp b/src/volume_grid_scalar_quantity.cpp index 530736a2c..430155696 100644 --- a/src/volume_grid_scalar_quantity.cpp +++ b/src/volume_grid_scalar_quantity.cpp @@ -70,7 +70,7 @@ void VolumeGridNodeScalarQuantity::buildCustomUI() { ImGui::SameLine(); // Set isovalue - ImGui::PushItemWidth(120 * state::globalContext.dpiScale); + ImGui::PushItemWidth(120 * options::uiScale); if (ImGui::SliderFloat("##Radius", &isosurfaceLevel.get(), vizRangeMin.get(), vizRangeMax.get(), "%.4e")) { // Note: we intentionally do this rather than calling setIsosurfaceLevel(), because that function immediately // recomputes the levelset mesh, which is too expensive during user interaction diff --git a/src/volume_mesh.cpp b/src/volume_mesh.cpp index 9e69abb9b..820540fde 100644 --- a/src/volume_mesh.cpp +++ b/src/volume_mesh.cpp @@ -871,7 +871,7 @@ void VolumeMesh::buildCustomUI() { ImGui::SameLine(); { // Edge options - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); if (edgeWidth.get() == 0.) { bool showEdges = false; if (ImGui::Checkbox("Edges", &showEdges)) { @@ -884,14 +884,14 @@ void VolumeMesh::buildCustomUI() { } // Edge color - ImGui::PushItemWidth(100 * state::globalContext.dpiScale); + ImGui::PushItemWidth(100 * options::uiScale); if (ImGui::ColorEdit3("Edge Color", &edgeColor.get()[0], ImGuiColorEditFlags_NoInputs)) setEdgeColor(edgeColor.get()); ImGui::PopItemWidth(); // Edge width ImGui::SameLine(); - ImGui::PushItemWidth(60 * state::globalContext.dpiScale); + ImGui::PushItemWidth(60 * options::uiScale); if (ImGui::SliderFloat("Width", &edgeWidth.get(), 0.001, 2.)) { // NOTE: this intentionally circumvents the setEdgeWidth() setter to avoid repopulating the buffer as the // slider is dragged---otherwise we repopulate the buffer on every change, which mostly works fine. This is a From 2b96120ffad4be04758f9f2b630571df8b6d7744 Mon Sep 17 00:00:00 2001 From: Nicholas Sharp Date: Mon, 12 May 2025 18:53:53 -0700 Subject: [PATCH 06/11] remove global font atlas engine pointer --- include/polyscope/render/engine.h | 2 -- src/imgui_config.cpp | 5 ++--- src/render/engine.cpp | 3 --- src/render/opengl/gl_engine_glfw.cpp | 3 ++- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/include/polyscope/render/engine.h b/include/polyscope/render/engine.h index c78e68514..f33f7748c 100644 --- a/include/polyscope/render/engine.h +++ b/include/polyscope/render/engine.h @@ -518,7 +518,6 @@ class Engine { virtual void ImGuiRender() = 0; void setImGuiStyle(); - ImFontAtlas* getImGuiGlobalFontAtlas(); // Display an ImGui window showing a texture // WARNING: you must ensure that the texture buffer pointer stays valid until after the ImGui frame is rendered, which @@ -630,7 +629,6 @@ class Engine { // Internal windowing and engine details virtual void configureImGui() {}; // generates font things - ImFontAtlas* globalFontAtlas = nullptr; ImFont* regularFont = nullptr; ImFont* monoFont = nullptr; FrameBuffer* currRenderFramebuffer = nullptr; diff --git a/src/imgui_config.cpp b/src/imgui_config.cpp index 5fd8dd930..928e5f8c3 100644 --- a/src/imgui_config.cpp +++ b/src/imgui_config.cpp @@ -78,7 +78,7 @@ std::tuple prepareImGuiFonts() { ImGuiIO& io = ImGui::GetIO(); // outputs - ImFontAtlas* globalFontAtlas; + ImFontAtlas* fontAtlas; ImFont* regularFont; ImFont* monoFont; @@ -97,9 +97,8 @@ std::tuple prepareImGuiFonts() { // io.Fonts->AddFontFromFileTTF("test-font-name.ttf", 16); io.Fonts->Build(); - globalFontAtlas = io.Fonts; - return std::tuple{globalFontAtlas, regularFont, monoFont}; + return std::tuple{fontAtlas, regularFont, monoFont}; } } // namespace polyscope diff --git a/src/render/engine.cpp b/src/render/engine.cpp index 9075756e0..37ce2ba0a 100644 --- a/src/render/engine.cpp +++ b/src/render/engine.cpp @@ -1175,9 +1175,6 @@ void Engine::showTextureInImGuiWindow(std::string windowName, TextureBuffer* buf ImGui::End(); } -// TODO remove this, it's not global anymore, each context gets its own -ImFontAtlas* Engine::getImGuiGlobalFontAtlas() { return globalFontAtlas; } - void Engine::preserveResourceUntilImguiFrameCompletes(std::shared_ptr texture) { resourcesPreservedForImGuiFrame.push_back(texture); } diff --git a/src/render/opengl/gl_engine_glfw.cpp b/src/render/opengl/gl_engine_glfw.cpp index 43d4d76be..f3802cf0c 100644 --- a/src/render/opengl/gl_engine_glfw.cpp +++ b/src/render/opengl/gl_engine_glfw.cpp @@ -137,7 +137,8 @@ void GLEngineGLFW::configureImGui() { // (don't totally understand why, allegedly it may change in the future) ImGui_ImplOpenGL3_DestroyFontsTexture(); - std::tie(globalFontAtlas, regularFont, monoFont) = options::prepareImGuiFontsCallback(); + ImFontAtlas* _unused; + std::tie(_unused, regularFont, monoFont) = options::prepareImGuiFontsCallback(); ImGui_ImplOpenGL3_CreateFontsTexture(); } From 799cc6713f079e8852a731bc1611dc6608a38a4d Mon Sep 17 00:00:00 2001 From: Nicholas Sharp Date: Wed, 14 May 2025 14:24:25 -0700 Subject: [PATCH 07/11] autoset uiscale and restore from prefs file --- .../polyscope/render/opengl/gl_engine_glfw.h | 2 ++ src/options.cpp | 2 +- src/polyscope.cpp | 9 +++++- src/render/engine.cpp | 2 +- src/render/opengl/gl_engine_glfw.cpp | 29 ++++++++++++++----- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/include/polyscope/render/opengl/gl_engine_glfw.h b/include/polyscope/render/opengl/gl_engine_glfw.h index 8b951c0be..a86eba99d 100644 --- a/include/polyscope/render/opengl/gl_engine_glfw.h +++ b/include/polyscope/render/opengl/gl_engine_glfw.h @@ -82,6 +82,8 @@ class GLEngineGLFW : public GLEngine { protected: // Internal windowing and engine details GLFWwindow* mainWindow = nullptr; + + void setUIScaleFromSystemDPI(); }; } // namespace backend_openGL3 diff --git a/src/options.cpp b/src/options.cpp index 4a0bf655a..b3ce25582 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -42,7 +42,7 @@ float shadowDarkness = 0.25; // Rendering options -float uiScale = 1.0; +float uiScale = -1.0; // unset, must be set manually or during initialization int ssaaFactor = 1; // Transparency diff --git a/src/polyscope.cpp b/src/polyscope.cpp index ae0e88596..15933e898 100644 --- a/src/polyscope.cpp +++ b/src/polyscope.cpp @@ -84,6 +84,10 @@ void readPrefsFile() { int val = prefsJSON["windowPosY"]; if (val >= 0 && val < 10000) view::initWindowPosY = val; } + if (prefsJSON.count("uiScale") > 0) { + float val = prefsJSON["uiScale"]; + if (val >= 0.25 && val <= 4.0) options::uiScale = val; + } } } @@ -100,6 +104,7 @@ void writePrefsFile() { std::tie(posX, posY) = render::engine->getWindowPos(); int windowWidth = view::windowWidth; int windowHeight = view::windowHeight; + float uiScale = options::uiScale; // Validate values. Don't write the prefs file if any of these values are obviously bogus (this seems to happen at // least on Windows when the application is minimzed) @@ -108,6 +113,7 @@ void writePrefsFile() { valuesValid &= posY >= 0 && posY < 10000; valuesValid &= windowWidth >= 64 && windowWidth < 10000; valuesValid &= windowHeight >= 64 && windowHeight < 10000; + valuesValid &= uiScale >= 0.25 && uiScale <= 4.; if (!valuesValid) return; // Build json object @@ -116,6 +122,7 @@ void writePrefsFile() { {"windowHeight", windowHeight}, {"windowPosX", posX}, {"windowPosY", posY}, + {"uiScale", uiScale}, }; // Write out json object @@ -1220,7 +1227,7 @@ namespace lazy { TransparencyMode transparencyMode = TransparencyMode::None; int transparencyRenderPasses = 8; int ssaaFactor = 1; -float uiScale = 1; +float uiScale = -1.; bool groundPlaneEnabled = true; GroundPlaneMode groundPlaneMode = GroundPlaneMode::TileReflection; ScaledValue groundPlaneHeightFactor = 0; diff --git a/src/render/engine.cpp b/src/render/engine.cpp index 37ce2ba0a..34afd921b 100644 --- a/src/render/engine.cpp +++ b/src/render/engine.cpp @@ -357,7 +357,7 @@ void Engine::buildEngineGui() { requestRedraw(); } - if (ImGui::InputFloat("DPI scale", &options::uiScale, 0.25f)) { + if (ImGui::InputFloat("UI Scale", &options::uiScale, 0.25f)) { options::uiScale = std::min(options::uiScale, 4.f); options::uiScale = std::max(options::uiScale, 0.25f); requestRedraw(); diff --git a/src/render/opengl/gl_engine_glfw.cpp b/src/render/opengl/gl_engine_glfw.cpp index f3802cf0c..e7c00e257 100644 --- a/src/render/opengl/gl_engine_glfw.cpp +++ b/src/render/opengl/gl_engine_glfw.cpp @@ -76,6 +76,14 @@ void GLEngineGLFW::initialize() { setWindowResizable(view::windowResizable); + // Set the UI scale to account for system-requested DPI scaling + // Currently we do *not* watch for changes of this value e.g. if a window moves between + // monitors with different DPI behaviors. We could, but it would require some logic to + // avoid overwriting values that a user might have set. + if(options::uiScale < 0) { // only set from system if the value is -1, meaning not set yet + setUIScaleFromSystemDPI(); + } + // === Initialize openGL // Load openGL functions (using GLAD) #ifndef __APPLE__ @@ -105,6 +113,16 @@ void GLEngineGLFW::initialize() { populateDefaultShadersAndRules(); } +void GLEngineGLFW::setUIScaleFromSystemDPI() { + + float xScale, dont_use_yScale; + glfwGetWindowContentScale(mainWindow, &xScale, &dont_use_yScale); + + // clamp to values within [1x,4x] scaling + xScale = std::fmin(std::fmax(xScale, 1.0f), 4.0f); + + options::uiScale = xScale; +} void GLEngineGLFW::initializeImGui() { bindDisplay(); @@ -116,18 +134,15 @@ void GLEngineGLFW::initializeImGui() { const char* glsl_version = "#version 150"; ImGui_ImplOpenGL3_Init(glsl_version); - float xScale, dont_use_yScale; - glfwGetWindowContentScale(mainWindow, &xScale, &dont_use_yScale); - if (xScale == NULL) { - xScale = 1.0f; - } - options::uiScale = std::min(std::max(xScale, 1.0f), 10.0f); - configureImGui(); } void GLEngineGLFW::configureImGui() { + if(options::uiScale < 0){ + exception("uiScale is < 0. Perhaps it wasn't initialized?"); + } + if (options::prepareImGuiFontsCallback) { ImGuiIO& io = ImGui::GetIO(); From 07fd391c31bdda95ea2b98c080c5bd36d12a7621 Mon Sep 17 00:00:00 2001 From: Nicholas Sharp Date: Wed, 14 May 2025 14:34:59 -0700 Subject: [PATCH 08/11] disable GLFW_SCALE_TO_MONITOR --- src/render/opengl/gl_engine_glfw.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/render/opengl/gl_engine_glfw.cpp b/src/render/opengl/gl_engine_glfw.cpp index e7c00e257..5dfd390fa 100644 --- a/src/render/opengl/gl_engine_glfw.cpp +++ b/src/render/opengl/gl_engine_glfw.cpp @@ -51,8 +51,13 @@ void GLEngineGLFW::initialize() { glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - // this is required to make sure the initial windows size is appropriate - glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); + // This tells GLFW to scale window size/positioning/content based on the system-reported DPI scaling factor + // However, it can lead to some confusing behaviors, for instance, on linux with scaling=200%, if the user + // sets view::windowWidth = 1280, they might get back a window with windowWidth == bufferWidth == 2560, + // which is quite confusing. + // For this reason we _do not_ set this hint. If desired, the user can specify a windowWidth = 1280*uiScale, + // or let the window size by loaded from .polyscope.ini after setting manually once. + // glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); #if __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); @@ -74,6 +79,10 @@ void GLEngineGLFW::initialize() { view::windowWidth = newWindowWidth; view::windowHeight = newWindowHeight; + std::cout << "created window with: \n"; + std::cout << " bufferWidth: " << view::bufferWidth << " bufferHeight: " << view::bufferHeight << "\n"; + std::cout << " windowWidth: " << view::windowWidth << " windowHeight: " << view::windowHeight << "\n"; + setWindowResizable(view::windowResizable); // Set the UI scale to account for system-requested DPI scaling From b80d77968a42801f9dfb151bb7fc40a6d3d48978 Mon Sep 17 00:00:00 2001 From: Nicholas Sharp Date: Wed, 14 May 2025 14:50:57 -0700 Subject: [PATCH 09/11] remove debug code --- src/render/opengl/gl_engine_glfw.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/render/opengl/gl_engine_glfw.cpp b/src/render/opengl/gl_engine_glfw.cpp index 5dfd390fa..fb36312ab 100644 --- a/src/render/opengl/gl_engine_glfw.cpp +++ b/src/render/opengl/gl_engine_glfw.cpp @@ -79,10 +79,6 @@ void GLEngineGLFW::initialize() { view::windowWidth = newWindowWidth; view::windowHeight = newWindowHeight; - std::cout << "created window with: \n"; - std::cout << " bufferWidth: " << view::bufferWidth << " bufferHeight: " << view::bufferHeight << "\n"; - std::cout << " windowWidth: " << view::windowWidth << " windowHeight: " << view::windowHeight << "\n"; - setWindowResizable(view::windowResizable); // Set the UI scale to account for system-requested DPI scaling From d47a774fc3ea77a14d263fe732f71308db375629 Mon Sep 17 00:00:00 2001 From: Nicholas Sharp Date: Wed, 14 May 2025 14:52:58 -0700 Subject: [PATCH 10/11] set uiScale on non-glfw backends --- src/render/mock_opengl/mock_gl_engine.cpp | 3 +++ src/render/opengl/gl_engine_egl.cpp | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/render/mock_opengl/mock_gl_engine.cpp b/src/render/mock_opengl/mock_gl_engine.cpp index 5a52407bb..7c5cc30cc 100644 --- a/src/render/mock_opengl/mock_gl_engine.cpp +++ b/src/render/mock_opengl/mock_gl_engine.cpp @@ -1562,6 +1562,9 @@ void MockGLEngine::initialize() { GLFrameBuffer* glScreenBuffer = new GLFrameBuffer(view::bufferWidth, view::bufferHeight, true); displayBuffer.reset(glScreenBuffer); + if(options::uiScale < 0) { // only set from system if the value is -1, meaning not set yet + options::uiScale = 1.; + } // normally we get initial values for the buffer size from the window framework, // with the mock backend we we need to manually set them to some sane value diff --git a/src/render/opengl/gl_engine_egl.cpp b/src/render/opengl/gl_engine_egl.cpp index 0d9d4db01..34ae3fb03 100644 --- a/src/render/opengl/gl_engine_egl.cpp +++ b/src/render/opengl/gl_engine_egl.cpp @@ -254,6 +254,10 @@ void GLEngineEGL::initialize() { << "EGL version: " << majorVer << "." << minorVer << std::endl; } + if(options::uiScale < 0) { // only set from system if the value is -1, meaning not set yet + options::uiScale = 1.; + } + { // Manually create the screen frame buffer // NOTE: important difference here, we manually create both the framebuffer and and its render buffer, since // headless EGL means we are not getting them from a window From fd0f8799fe2595f451b040c330c44753ff29318c Mon Sep 17 00:00:00 2001 From: Nicholas Sharp Date: Wed, 14 May 2025 15:09:42 -0700 Subject: [PATCH 11/11] fix imgui init calls for non-GLFW backends --- .../polyscope/render/mock_opengl/mock_gl_engine.h | 1 + include/polyscope/render/opengl/gl_engine_egl.h | 1 + src/render/mock_opengl/mock_gl_engine.cpp | 15 ++++++++++++++- src/render/opengl/gl_engine_egl.cpp | 13 +++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/polyscope/render/mock_opengl/mock_gl_engine.h b/include/polyscope/render/mock_opengl/mock_gl_engine.h index f9d512f56..bcdb7e3e4 100644 --- a/include/polyscope/render/mock_opengl/mock_gl_engine.h +++ b/include/polyscope/render/mock_opengl/mock_gl_engine.h @@ -358,6 +358,7 @@ class MockGLEngine : public Engine { // ImGui void initializeImGui() override; + void configureImGui() override; void shutdownImGui() override; void ImGuiNewFrame() override; void ImGuiRender() override; diff --git a/include/polyscope/render/opengl/gl_engine_egl.h b/include/polyscope/render/opengl/gl_engine_egl.h index 7948436a5..21897c5ff 100644 --- a/include/polyscope/render/opengl/gl_engine_egl.h +++ b/include/polyscope/render/opengl/gl_engine_egl.h @@ -69,6 +69,7 @@ class GLEngineEGL : public GLEngine { // === ImGui void initializeImGui() override; + void configureImGui() override; void shutdownImGui() override; void ImGuiNewFrame() override; void ImGuiRender() override; diff --git a/src/render/mock_opengl/mock_gl_engine.cpp b/src/render/mock_opengl/mock_gl_engine.cpp index 7c5cc30cc..e744a2876 100644 --- a/src/render/mock_opengl/mock_gl_engine.cpp +++ b/src/render/mock_opengl/mock_gl_engine.cpp @@ -1562,7 +1562,7 @@ void MockGLEngine::initialize() { GLFrameBuffer* glScreenBuffer = new GLFrameBuffer(view::bufferWidth, view::bufferHeight, true); displayBuffer.reset(glScreenBuffer); - if(options::uiScale < 0) { // only set from system if the value is -1, meaning not set yet + if (options::uiScale < 0) { // only set from system if the value is -1, meaning not set yet options::uiScale = 1.; } @@ -1581,6 +1581,19 @@ void MockGLEngine::initializeImGui() { configureImGui(); } +void MockGLEngine::configureImGui() { + + // don't both calling the style callbacks, there is no UI + + if (options::uiScale < 0) { + exception("uiScale is < 0. Perhaps it wasn't initialized?"); + } + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->Clear(); + io.Fonts->Build(); +} + void MockGLEngine::shutdown() { checkError(); shutdownImGui(); diff --git a/src/render/opengl/gl_engine_egl.cpp b/src/render/opengl/gl_engine_egl.cpp index 34ae3fb03..5d354798f 100644 --- a/src/render/opengl/gl_engine_egl.cpp +++ b/src/render/opengl/gl_engine_egl.cpp @@ -436,6 +436,19 @@ void GLEngineEGL::initializeImGui() { configureImGui(); } +void GLEngineEGL::configureImGui() { + + // don't both calling the style callbacks, there is no UI + + if (options::uiScale < 0) { + exception("uiScale is < 0. Perhaps it wasn't initialized?"); + } + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->Clear(); + io.Fonts->Build(); +} + void GLEngineEGL::shutdown() { checkError(); shutdownImGui();