luciusDXL / TheForceEngine

Modern "Jedi Engine" replacement supporting Dark Forces, mods, and in the future Outlaws.
https://TheForceEngine.github.io
GNU General Public License v2.0
967 stars 71 forks source link

[🐛] Custom resolution resets to matching #433

Open JakeSmarter opened 1 month ago

JakeSmarter commented 1 month ago

Linux Flathub v1.10.000-28-ge19bcde1+

Whenever you return to the graphics settings menu, any custom resolution is reset to matching. However, the custom resolution is saved and loaded whenever you launch a “The Force Engine” instance, as long as you do not go into the graphics settings menu.

Furthermore, setting a custom resolution width basically does nothing for you, that is, it does not automatically change the height with the correct aspect ratio applied. However, setting the height does automatically change the width with the correct aspect ratio applied. But, the width UI field does not visibly change its value. :face_with_spiral_eyes:

JakeSmarter commented 1 month ago

Automatic custom resolution adjustment in both dimensions works as expected if “Widescreen” remains unchecked. If “Widescreen” is checked then automatic custom resolution adjustment only works when modifying “height” (without updating the “width” field).

Going back into the graphics menu always resets any custom resolution to “matching”.

mlauss2 commented 1 month ago

The culprit is frontendui.cpp::pickCurrentResolution(), I'll try to fix it if lucius doesn't beat me to it.

mlauss2 commented 1 month ago

You want to give this a try? It works(TM) for me:

index 64d708c5..61814cc3 100644
--- a/TheForceEngine/TFE_FrontEndUI/frontEndUi.cpp
+++ b/TheForceEngine/TFE_FrontEndUI/frontEndUi.cpp
@@ -260,10 +260,11 @@ namespace TFE_FrontEndUI
        void DrawLabelledIntSlider(float labelWidth, float valueWidth, const char* label, const char* tag, int* value, int min, int max);
        void DrawLabelledFloatSlider(float labelWidth, float valueWidth, const char* label, const char* tag, float* value, float min, float max);
        void configA11y(s32 tabWidth, u32 height);
-       void pickCurrentResolution();
        void manual();
        void credits();

+       static void initVirtualResolution(void);
+
        void configSaveLoadBegin(bool save);
        void renderBackground(bool forceTextureUpdate = false);
        void Tooltip(const char* text);
@@ -371,6 +372,8 @@ namespace TFE_FrontEndUI
                s_menuItemselected[5] = menuItem_Mods;
                s_menuItemselected[6] = menuItem_Editor;
                s_menuItemselected[7] = menuItem_Exit;
+
+               initVirtualResolution();
        }

        void shutdown()
@@ -408,7 +411,6 @@ namespace TFE_FrontEndUI
                s_subUI = FEUI_CONFIG;
                s_relativeMode = TFE_Input::relativeModeEnabled();
                TFE_Input::enableRelativeMode(false);
-               pickCurrentResolution();
        }

        bool isConfigMenuOpen()
@@ -578,13 +580,11 @@ namespace TFE_FrontEndUI
                        s_configTab = CONFIG_GAME;
                        s_appState = APP_STATE_MENU;
                        s_drawNoGameDataMsg = true;
-                       pickCurrentResolution();
                }
                else if (setDefaults)
                {
                        s_subUI = FEUI_NONE;
                        s_appState = APP_STATE_SET_DEFAULTS;
-                       pickCurrentResolution();
                }
                if (!drawFrontEnd)
                {
@@ -2434,7 +2434,7 @@ namespace TFE_FrontEndUI
                ImGui::LabelText("##ConfigLabel", "Standard Resolution:"); ImGui::SameLine(150 * s_uiScale);
                ImGui::SetNextItemWidth(196);
                ImGui::Combo("##Resolution", &s_resIndex, widescreen ? c_resolutionsWide : c_resolutions, IM_ARRAYSIZE(c_resolutions));
-               if (s_resIndex == TFE_ARRAYSIZE(c_resolutionDim))
+               if (s_resIndex == TFE_ARRAYSIZE(c_resolutionDim))       // "Match Window"
                {
                        DisplayInfo displayInfo;
                        TFE_RenderBackend::getDisplayInfo(&displayInfo);
@@ -2443,7 +2443,7 @@ namespace TFE_FrontEndUI
                        graphics->widescreen = true;
                        widescreen = true;
                }
-               else if (s_resIndex == TFE_ARRAYSIZE(c_resolutionDim) + 1)
+               else if (s_resIndex == TFE_ARRAYSIZE(c_resolutionDim) + 1)      // "Custom"
                {
                        ImGui::LabelText("##ConfigLabel", "Custom:"); ImGui::SameLine(100 * s_uiScale);
                        ImGui::SetNextItemWidth(196);
@@ -3097,20 +3097,36 @@ namespace TFE_FrontEndUI
                Tooltip("Disable illumination around the player caused by firing weapons.");
        }

-       void pickCurrentResolution()
+       // pick the right starting entry for the "Virtual Resolution" dropdown box
+       static void initVirtualResolution(void)
        {
                TFE_Settings_Graphics* graphics = TFE_Settings::getGraphicsSettings();
-
                const size_t count = TFE_ARRAYSIZE(c_resolutionDim);
+               DisplayInfo displayInfo;
+
+                TFE_RenderBackend::getDisplayInfo(&displayInfo);
+               s_resIndex = -1;
+
+               if ((graphics->gameResolution.x == displayInfo.width)
+                   && (graphics->gameResolution.z == displayInfo.height))
+               {
+                       s_resIndex = count;     // Match Window
+                       return;
+               }
+
+               // find match in list
                for (size_t i = 0; i < count; i++)
                {
-                       if (graphics->gameResolution.z == c_resolutionDim[i].z)
+                       if ((graphics->gameResolution.z == c_resolutionDim[i].z)
+                           && (graphics->gameResolution.x == c_resolutionDim[i].x))
                        {
                                s_resIndex = s32(i);
                                return;
                        }
                }
-               s_resIndex = count;
+
+               // it's a custom resolution then
+               s_resIndex = count + 1;
        }

        ////////////////////////////////////////////////////////////////
@@ -3126,8 +3142,6 @@ namespace TFE_FrontEndUI
        {
                s_subUI = FEUI_CONFIG;
                s_configTab = CONFIG_LOAD;
-
-               pickCurrentResolution();
        }

        void menuItem_Manual()
@@ -3144,8 +3158,6 @@ namespace TFE_FrontEndUI
        {
                s_subUI = FEUI_CONFIG;
                s_configTab = CONFIG_GAME;
-
-               pickCurrentResolution();
        }

        void menuItem_Mods()
JakeSmarter commented 1 month ago

:partying_face: Finally, I was able to test your branch but I did not review the code (this is something for @luciusDXL to do). The custom resolution does not reset to “Match window” any longer when you enter the graphics menu. However, automatic custom resolution adjustment is gone completely now. :slightly_frowning_face: So, this is something that may need to improve.

luciusDXL commented 1 month ago

Linux Flathub v1.10.000-28-ge19bcde1+

Whenever you return to the graphics settings menu, any custom resolution is reset to matching. However, the custom resolution is saved and loaded whenever you launch a “The Force Engine” instance, as long as you do not go into the graphics settings menu.

Furthermore, setting a custom resolution width basically does nothing for you, that is, it does not automatically change the height with the correct aspect ratio applied. However, setting the height does automatically change the width with the correct aspect ratio applied. But, the width UI field does not visibly change its value. 😵‍💫

The custom resolution does need more work, I agree. It isn't used very often and hasn't been well tested.

JakeSmarter commented 1 month ago

The custom resolution does need more work, I agree. It isn't used very often and hasn't been well tested.

It is a very good idea and very useful though. :+1: Ever since I discovered this feature’s potential and capabilities I use it permanently, hence me complaining that it resets although it is saved. It is especially useful for configuring exact multiples of native screen resolutions because this is something that is not always possible with EDID reported resolutions by monitors.

Properly used, it can produce a nice retro effect on high resolution monitors and at the same time improve fps rate. :wink:

mlauss2 commented 1 month ago

However, automatic custom resolution adjustment is gone completely now. 🙁 So, this is something that may need to improve.

Can you please elaborate? I'll try to fix this too.

JakeSmarter commented 1 month ago

However, automatic custom resolution adjustment is gone completely now. 🙁 So, this is something that may need to improve.

Can you please elaborate? I'll try to fix this too.

Given an aspect ratio, if you enter the number of pixels for any dimension the UI automatically computes the correct number of pixels for the other dimension and updates the field.

In v1.10.000 it works best if “Widescreen” is clear. Try to enter any numbers for either width or height and observe how the other field (for the other dimension) is updated automatically.

@luciusDXL Btw, as much as I appreciate the “Widescreen” checkbox (and effect) imho “Widescreen” as a term is a bit inconclusive: when is a screen wide enough to be considered as wide? Hence, it would be nice to have more control over the exact aspect ratio via a drop down menu or combo box with an enumeration of common aspect ratios, like 1:1, 5:4, 4:3 (default), 16:10, 16:9, 21:9, etc. Maybe even the option to specify the aspect ratio freely.