Dhewm3SettingsMenu: Rework resolution/windowed/MSAA part of Video Options

Now the CVars are set immediately and "Apply" only does
`vid_restart partial`, while "Reset" resets the CVars to the values
that were set when opening the menu.
This also works the other way around: Changing a CVar (in the console
or other menu or r_fullscreen with Alt-Enter) is immediately reflected
in the menu.

Furthermore, "fullscreen desktop" now is its own setting (=> can be set
even if windowed mode is selected), to accommodate switchting between
windowed and fullscreen with Alt-Enter
This commit is contained in:
Daniel Gibson 2024-06-12 22:47:43 +02:00
parent 94738f1f16
commit 9eff1d9be2

View file

@ -1676,30 +1676,32 @@ static CVarOption videoOptionsImmediately[] = {
};
idList<VidMode> vidModes;
static int selModeIdx = 0;
static int customVidRes[2];
static int fullscreenChoice = 0;
static int msaaModeIndex = 0;
static bool initialFullscreen = false;
static bool initialFullscreenDesktop = false;
static int initialMode = 0;
static int initialCustomVidRes[2];
static int initialMSAAmode = 0;
static int qualityPreset = 0;
static void SetVideoStuffFromCVars()
{
const int curMode = r_mode.GetInteger();
for ( int i=0, n=vidModes.Num(); i < n; ++i ) {
if ( vidModes[i].mode == curMode ) {
selModeIdx = i;
break;
}
initialMode = curMode;
int w, h;
if ( !R_GetModeInfo( &w, &h, curMode ) ) {
// invalid mode
initialMode = (curMode < 0) ? -1 : 4; // safe default (800x600)
r_mode.SetInteger( initialMode );
}
customVidRes[0] = r_customWidth.GetInteger();
customVidRes[1] = r_customHeight.GetInteger();
initialCustomVidRes[0] = r_customWidth.GetInteger();
initialCustomVidRes[1] = r_customHeight.GetInteger();
fullscreenChoice = r_fullscreen.GetBool() ? ( r_fullscreenDesktop.GetBool() ? 1 : 2 ) : 0;
initialFullscreen = r_fullscreen.GetBool();
initialFullscreenDesktop = r_fullscreenDesktop.GetBool();
const int msaa = r_multiSamples.GetInteger();
msaaModeIndex = Min( 4, ( msaa > 1 ) ? idMath::ILog2( msaa ) : 0 );
initialMSAAmode = r_multiSamples.GetInteger();
qualityPreset = com_machineSpec.GetInteger();
if ( qualityPreset == -1 ) {
@ -1711,55 +1713,66 @@ static void SetVideoStuffFromCVars()
}
}
static bool VideoHasApplyableChanges()
static bool VideoHasResettableChanges()
{
const int curMode = r_mode.GetInteger();
if ( curMode != vidModes[selModeIdx].mode
|| ( curMode == -1 && ( customVidRes[0] != r_customWidth.GetInteger()
|| customVidRes[1] != r_customHeight.GetInteger() ) ) )
if ( curMode != initialMode )
return true;
if ( curMode == -1 && ( initialCustomVidRes[0] != r_customWidth.GetInteger()
|| initialCustomVidRes[1] != r_customHeight.GetInteger() ) )
{
return true;
}
int oldFullscreenChoice = r_fullscreen.GetBool() ? ( r_fullscreenDesktop.GetBool() ? 1 : 2 ) : 0;
if ( oldFullscreenChoice != fullscreenChoice )
if ( r_fullscreen.GetBool() != initialFullscreen
|| r_fullscreenDesktop.GetBool() != initialFullscreenDesktop )
{
return true;
int msaa = ( msaaModeIndex > 0 ) ? ( 1 << msaaModeIndex ) : 0;
if ( msaa != r_multiSamples.GetInteger() )
}
if ( initialMSAAmode != r_multiSamples.GetInteger() ) {
return true;
}
return false;
}
static bool VideoHasApplyableChanges()
{
glimpParms_t curState = GLimp_GetCurState();
int wantedWidth = 0, wantedHeight = 0;
R_GetModeInfo( &wantedWidth, &wantedHeight, r_mode.GetInteger() );
if ( wantedWidth != curState.width || wantedHeight != curState.height ) {
return true;
}
if ( r_fullscreen.GetBool() != curState.fullScreen
|| (curState.fullScreen && r_fullscreenDesktop.GetBool() != curState.fullScreenDesktop) )
{
return true;
}
if ( r_multiSamples.GetInteger() != curState.multiSamples ) {
return true;
}
return false;
}
static void ApplyVideoSettings()
{
if ( selModeIdx == 0 ) {
r_customWidth.SetInteger( customVidRes[0] );
r_customHeight.SetInteger( customVidRes[1] );
r_mode.SetInteger( -1 );
} else {
r_mode.SetInteger( vidModes[selModeIdx].mode );
}
switch ( fullscreenChoice ) {
case 0:
r_fullscreen.SetBool( false );
break;
case 1:
r_fullscreen.SetBool( true );
r_fullscreenDesktop.SetBool( true );
break;
case 2:
r_fullscreen.SetBool( true );
r_fullscreenDesktop.SetBool( false );
}
int msaa = ( msaaModeIndex > 0 ) ? ( 1 << msaaModeIndex ) : 0;
r_multiSamples.SetInteger( msaa );
cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "vid_restart partial\n" );
}
static void VideoResetChanges()
{
r_mode.SetInteger( initialMode );
r_customWidth.SetInteger( initialCustomVidRes[0] );
r_customHeight.SetInteger( initialCustomVidRes[1] );
r_fullscreen.SetBool( initialFullscreen );
r_fullscreenDesktop.SetBool( initialFullscreenDesktop );
r_multiSamples.SetInteger( initialMSAAmode );
}
static void InitVideoOptionsMenu()
{
InitOptions( videoOptionsImmediately, IM_ARRAYSIZE(videoOptionsImmediately) );
@ -1799,11 +1812,9 @@ static void DrawVideoOptionsMenu()
const int oldMSAA = r_multiSamples.GetInteger();
cmdSystem->BufferCommandText( CMD_EXEC_NOW, "execMachineSpec nores\n" );
const int newMSAA = r_multiSamples.GetInteger();
if ( newMSAA != oldMSAA ) {
// select the modified MSAA mode in the slider, but restore the CVars old value
// so the Apply button is active and can be pressed for vid_restart
msaaModeIndex = Min( 4, ( newMSAA > 1 ) ? idMath::ILog2( newMSAA ) : 0 );
if ( oldMSAA > 0 && qualityPreset >= 2 ) {
// the user already changed the MSAA at some point, and chose High or Ultra Quality,
// which both set MSAA to 0 - restore users setting
r_multiSamples.SetInteger( oldMSAA );
}
}
@ -1811,27 +1822,64 @@ static void DrawVideoOptionsMenu()
ImGui::SeparatorText( "Options that must be applied" );
ImGui::Combo( "Window Mode", &fullscreenChoice,
"Normal window\0Fullscreen window at screen resolution\0Real Fullscreen Mode\0" );
// fullscreen
int fullscreenChoice = r_fullscreen.GetBool();
if ( ImGui::Combo( "Window Mode", &fullscreenChoice, "Windowed\0Fullscreen\0" ) ) {
r_fullscreen.SetBool( fullscreenChoice != 0 );
}
AddTooltip( "r_fullscreen" );
bool fullscreenDesktop = r_fullscreenDesktop.GetBool();
if ( ImGui::Checkbox( "Fullscreen Desktop Mode: Use borderless window at desktop resolution for fullscreen", &fullscreenDesktop ) ) {
r_fullscreenDesktop.SetBool( fullscreenDesktop );
}
AddTooltip( "r_fullscreenDesktop" );
AddDescrTooltip( "ignores the resolution configured in dhewm3, doesn't switch the display resolution, can prevent issues like desktop icons being rearranged after running the game" );
AddTooltip( "r_fullscreen / r_fullscreenDesktop" );
if ( fullscreenChoice == 1 ) {
ImGui::TextDisabled( " (Resolution not configurable because for this mode\n the current desktop/screen resolution is used)" );
} else {
ImGui::Combo( "Resolution", &selModeIdx, [](void* data, int idx) -> const char* {
const idList<VidMode>& vms = *static_cast< const idList<VidMode>* >(data);
return vms[idx].label.c_str();
}, &vidModes, vidModes.Num() );
AddTooltip( "r_mode" );
if ( selModeIdx == 0 ) {
if ( ImGui::InputInt2( "Custom Resolution (width x height)", customVidRes ) ) {
customVidRes[0] = idMath::ClampInt( 1, 128000, customVidRes[0] );
customVidRes[1] = idMath::ClampInt( 1, 128000, customVidRes[1] );
// Video Mode / Resolution
static int selModeIdx = -1; // index within our vidModes array
static int selMode = -3; // global mode number (as used in r_mode)
int curMode = r_mode.GetInteger();
if ( selMode != curMode ) {
selMode = curMode;
int w, h;
if ( !R_GetModeInfo( &w, &h, curMode ) ) {
// invalid mode
selMode = (curMode < 0) ? -1 : 4; // safe default (800x600)
r_mode.SetInteger( selMode );
}
selModeIdx = 0; // set *something* in case it's not found below
for ( int i=0, n=vidModes.Num(); i < n; ++i ) {
if ( vidModes[i].mode == selMode ) {
selModeIdx = i;
break;
}
AddTooltip( "r_customWidth / r_customHeight" );
}
}
const char* resLabel = ( fullscreenChoice && fullscreenDesktop ) ? "Window Resolution (ignored for Fullscreen Desktop Mode!)###resMode" : "Resolution###resMode";
if ( ImGui::Combo( resLabel, &selModeIdx, [](void* data, int idx) -> const char* {
const idList<VidMode>& vms = *static_cast< const idList<VidMode>* >(data);
return vms[idx].label.c_str();
}, &vidModes, vidModes.Num() ) )
{
selMode = vidModes[selModeIdx].mode;
r_mode.SetInteger( selMode );
}
AddTooltip( "r_mode" );
if ( selMode == -1 ) {
int vidRes[2] = { r_customWidth.GetInteger(), r_customHeight.GetInteger() };
if ( ImGui::InputInt2( "Custom Resolution (width x height)", vidRes ) ) {
vidRes[0] = idMath::ClampInt( 1, 128000, vidRes[0] );
vidRes[1] = idMath::ClampInt( 1, 128000, vidRes[1] );
r_customWidth.SetInteger( vidRes[0] );
r_customHeight.SetInteger( vidRes[1] );
}
AddTooltip( "r_customWidth / r_customHeight" );
}
// resolution info text
int sdlDisplayIdx = SDL_GetWindowDisplayIndex( SDL_GL_GetCurrentWindow() );
SDL_Rect displayRect = {};
SDL_GetDisplayBounds( sdlDisplayIdx, &displayRect );
@ -1849,27 +1897,42 @@ static void DrawVideoOptionsMenu()
ImGui::TextDisabled( "Display Size: %d x %d", displayRect.w, displayRect.h );
}
// MSAA
static const char* msaaLevels[] = { "No Antialiasing", "2x", "4x", "8x", "16x" };
int msaa = r_multiSamples.GetInteger();
int msaaModeIndex = Min( 4, ( msaa > 1 ) ? idMath::ILog2( msaa ) : 0 );
const char* curLvl = msaaLevels[msaaModeIndex];
ImGui::SliderInt( "Antialiasing (MSAA)", &msaaModeIndex, 0, 4, curLvl, ImGuiSliderFlags_NoInput );
if ( ImGui::SliderInt( "Antialiasing (MSAA)", &msaaModeIndex, 0, 4, curLvl, ImGuiSliderFlags_NoInput ) ) {
msaa = ( msaaModeIndex > 0 ) ? ( 1 << msaaModeIndex ) : 0;
r_multiSamples.SetInteger( msaa );
}
AddCVarOptionTooltips( r_multiSamples, "Note: Not all GPUs/drivers support all modes, esp. not 16x!" );
// Apply Button
if ( !VideoHasApplyableChanges() ) {
ImGui::BeginDisabled();
ImGui::Button( "Apply" );
AddTooltip( "No changes were made, so there's nothing to apply" );
ImGui::SameLine();
ImGui::Button( "Reset" );
AddTooltip( "No changes were made, so there's nothing to reset" );
ImGui::EndDisabled();
} else {
if ( ImGui::Button( "Apply" ) ) {
ApplyVideoSettings();
}
AddTooltip( "Click to apply the settings above, will restart the renderer (but not the game)" );
AddTooltip( "Click to apply the settings above, might restart the renderer (but not the game)" );
}
ImGui::SameLine();
// Reset button
if ( !VideoHasResettableChanges() ) {
ImGui::BeginDisabled();
ImGui::Button( "Reset" );
AddTooltip( "The window's current state is like it was when opening the menu, so there's nothing to reset" );
ImGui::EndDisabled();
} else {
ImGui::SameLine();
if ( ImGui::Button("Reset") ) {
SetVideoStuffFromCVars();
VideoResetChanges();
}
AddTooltip( "Click to restore the settings as the were when opening this menu" );
}