@ -11,12 +11,16 @@
# include <iomanip>
# include <numeric>
# include <array>
# include <components/debug/debuglog.hpp>
# include <components/misc/stringops.hpp>
# include <components/misc/constants.hpp>
# include <components/widgets/sharedstatebutton.hpp>
# include <components/settings/settings.hpp>
# include <components/resource/resourcesystem.hpp>
# include <components/resource/scenemanager.hpp>
# include <components/sceneutil/lightmanager.hpp>
# include "../mwbase/environment.hpp"
# include "../mwbase/world.hpp"
@ -69,6 +73,9 @@ namespace
std : : string getAspect ( int x , int y )
{
int gcd = std : : gcd ( x , y ) ;
if ( gcd = = 0 )
return std : : string ( ) ;
int xaspect = x / gcd ;
int yaspect = y / gcd ;
// special case: 8 : 5 is usually referred to as 16:10
@ -111,11 +118,24 @@ namespace
if ( ! widget - > getUserString ( settingMax ) . empty ( ) )
max = MyGUI : : utility : : parseFloat ( widget - > getUserString ( settingMax ) ) ;
}
void updateMaxLightsComboBox ( MyGUI : : ComboBox * box )
{
constexpr int min = 8 ;
constexpr int max = 32 ;
constexpr int increment = 8 ;
int maxLights = Settings : : Manager : : getInt ( " max lights " , " Shaders " ) ;
// show increments of 8 in dropdown
if ( maxLights > = min & & maxLights < = max & & ! ( maxLights % increment ) )
box - > setIndexSelected ( ( maxLights / increment ) - 1 ) ;
else
box - > setIndexSelected ( MyGUI : : ITEM_NONE ) ;
}
}
namespace MWGui
{
void SettingsWindow : : configureWidgets ( MyGUI : : Widget * widget )
void SettingsWindow : : configureWidgets ( MyGUI : : Widget * widget , bool init )
{
MyGUI : : EnumeratorWidgetPtr widgets = widget - > getEnumerator ( ) ;
while ( widgets . next ( ) )
@ -129,7 +149,8 @@ namespace MWGui
getSettingCategory ( current ) )
? " #{sOn} " : " #{sOff} " ;
current - > castType < MyGUI : : Button > ( ) - > setCaptionWithReplacing ( initialValue ) ;
current - > eventMouseButtonClick + = MyGUI : : newDelegate ( this , & SettingsWindow : : onButtonToggled ) ;
if ( init )
current - > eventMouseButtonClick + = MyGUI : : newDelegate ( this , & SettingsWindow : : onButtonToggled ) ;
}
if ( type = = sliderType )
{
@ -149,6 +170,12 @@ namespace MWGui
ss < < std : : fixed < < std : : setprecision ( 2 ) < < value / Constants : : CellSizeInUnits ;
valueStr = ss . str ( ) ;
}
else if ( valueType = = " Float " )
{
std : : stringstream ss ;
ss < < std : : fixed < < std : : setprecision ( 2 ) < < value ;
valueStr = ss . str ( ) ;
}
else
valueStr = MyGUI : : utility : : toString ( int ( value ) ) ;
@ -163,12 +190,13 @@ namespace MWGui
valueStr = MyGUI : : utility : : toString ( value ) ;
scroll - > setScrollPosition ( value ) ;
}
scroll - > eventScrollChangePosition + = MyGUI : : newDelegate ( this , & SettingsWindow : : onSliderChangePosition ) ;
if ( init )
scroll - > eventScrollChangePosition + = MyGUI : : newDelegate ( this , & SettingsWindow : : onSliderChangePosition ) ;
if ( scroll - > getVisible ( ) )
updateSliderLabel ( scroll , valueStr ) ;
}
configureWidgets ( current );
configureWidgets ( current , init );
}
}
@ -199,7 +227,7 @@ namespace MWGui
getWidget ( unusedSlider , widgetName ) ;
unusedSlider - > setVisible ( false ) ;
configureWidgets ( mMainWidget );
configureWidgets ( mMainWidget , true );
setTitle ( " #{sOptions} " ) ;
@ -216,6 +244,9 @@ namespace MWGui
getWidget ( mControllerSwitch , " ControllerButton " ) ;
getWidget ( mWaterTextureSize , " WaterTextureSize " ) ;
getWidget ( mWaterReflectionDetail , " WaterReflectionDetail " ) ;
getWidget ( mLightingMethodButton , " LightingMethodButton " ) ;
getWidget ( mLightsResetButton , " LightsResetButton " ) ;
getWidget ( mMaxLights , " MaxLights " ) ;
if ( MWBase : : Environment : : get ( ) . getVrMode ( ) )
{
@ -247,6 +278,10 @@ namespace MWGui
mWaterTextureSize - > eventComboChangePosition + = MyGUI : : newDelegate ( this , & SettingsWindow : : onWaterTextureSizeChanged ) ;
mWaterReflectionDetail - > eventComboChangePosition + = MyGUI : : newDelegate ( this , & SettingsWindow : : onWaterReflectionDetailChanged ) ;
mLightingMethodButton - > eventComboChangePosition + = MyGUI : : newDelegate ( this , & SettingsWindow : : onLightingMethodButtonChanged ) ;
mLightsResetButton - > eventMouseButtonClick + = MyGUI : : newDelegate ( this , & SettingsWindow : : onLightsResetButtonClicked ) ;
mMaxLights - > eventComboChangePosition + = MyGUI : : newDelegate ( this , & SettingsWindow : : onMaxLightsChanged ) ;
mKeyboardSwitch - > eventMouseButtonClick + = MyGUI : : newDelegate ( this , & SettingsWindow : : onKeyboardSwitchClicked ) ;
mControllerSwitch - > eventMouseButtonClick + = MyGUI : : newDelegate ( this , & SettingsWindow : : onControllerSwitchClicked ) ;
@ -273,8 +308,10 @@ namespace MWGui
std : : sort ( resolutions . begin ( ) , resolutions . end ( ) , sortResolutions ) ;
for ( std : : pair < int , int > & resolution : resolutions )
{
std : : string str = MyGUI : : utility : : toString ( resolution . first ) + " x " + MyGUI : : utility : : toString ( resolution . second )
+ " ( " + getAspect ( resolution . first , resolution . second ) + " ) " ;
std : : string str = MyGUI : : utility : : toString ( resolution . first ) + " x " + MyGUI : : utility : : toString ( resolution . second ) ;
std : : string aspect = getAspect ( resolution . first , resolution . second ) ;
if ( ! aspect . empty ( ) )
str = str + " ( " + aspect + " ) " ;
if ( mResolutionList - > findItemIndexWith ( str ) = = MyGUI : : ITEM_NONE )
mResolutionList - > addItem ( str ) ;
@ -309,6 +346,8 @@ namespace MWGui
waterReflectionDetail = std : : min ( 5 , std : : max ( 0 , waterReflectionDetail ) ) ;
mWaterReflectionDetail - > setIndexSelected ( waterReflectionDetail ) ;
updateMaxLightsComboBox ( mMaxLights ) ;
mWindowBorderButton - > setEnabled ( ! Settings : : Manager : : getBool ( " fullscreen " , " Video " ) ) ;
mKeyboardSwitch - > setStateSelected ( true ) ;
@ -409,6 +448,54 @@ namespace MWGui
apply ( ) ;
}
void SettingsWindow : : onLightingMethodButtonChanged ( MyGUI : : ComboBox * _sender , size_t pos )
{
if ( pos = = MyGUI : : ITEM_NONE )
return ;
std : : string message = " This change requires a restart to take effect. " ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > interactiveMessageBox ( message , { " #{sOK} " } , true ) ;
Settings : : Manager : : setString ( " lighting method " , " Shaders " , _sender - > getItemNameAt ( pos ) ) ;
apply ( ) ;
}
void SettingsWindow : : onMaxLightsChanged ( MyGUI : : ComboBox * _sender , size_t pos )
{
int count = 8 * ( pos + 1 ) ;
Settings : : Manager : : setInt ( " max lights " , " Shaders " , count ) ;
apply ( ) ;
configureWidgets ( mMainWidget , false ) ;
}
void SettingsWindow : : onLightsResetButtonClicked ( MyGUI : : Widget * _sender )
{
std : : vector < std : : string > buttons = { " #{sYes} " , " #{sNo} " } ;
std : : string message = " Resets to default values, would you like to continue? Changes to lighting method will require a restart. " ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > interactiveMessageBox ( message , buttons , true ) ;
int selectedButton = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > readPressedButton ( ) ;
if ( selectedButton = = 1 | | selectedButton = = - 1 )
return ;
constexpr std : : array < const char * , 6 > settings = {
" light bounds multiplier " ,
" maximum light distance " ,
" light fade start " ,
" minimum interior brightness " ,
" max lights " ,
" lighting method " ,
} ;
for ( const auto & setting : settings )
Settings : : Manager : : setString ( setting , " Shaders " , Settings : : Manager : : mDefaultSettings [ { " Shaders " , setting } ] ) ;
mLightingMethodButton - > setIndexSelected ( mLightingMethodButton - > findItemIndexWith ( Settings : : Manager : : mDefaultSettings [ { " Shaders " , " lighting method " } ] ) ) ;
updateMaxLightsComboBox ( mMaxLights ) ;
apply ( ) ;
configureWidgets ( mMainWidget , false ) ;
}
void SettingsWindow : : onButtonToggled ( MyGUI : : Widget * _sender )
{
std : : string on = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getGameSettingString ( " sOn " , " On " ) ;
@ -511,6 +598,12 @@ namespace MWGui
ss < < std : : fixed < < std : : setprecision ( 2 ) < < value / Constants : : CellSizeInUnits ;
valueStr = ss . str ( ) ;
}
else if ( valueType = = " Float " )
{
std : : stringstream ss ;
ss < < std : : fixed < < std : : setprecision ( 2 ) < < value ;
valueStr = ss . str ( ) ;
}
else
valueStr = MyGUI : : utility : : toString ( int ( value ) ) ;
}
@ -609,6 +702,30 @@ namespace MWGui
layoutControlsBox ( ) ;
}
void SettingsWindow : : updateLightSettings ( )
{
auto lightingMethod = MWBase : : Environment : : get ( ) . getResourceSystem ( ) - > getSceneManager ( ) - > getLightingMethod ( ) ;
std : : string lightingMethodStr = SceneUtil : : LightManager : : getLightingMethodString ( lightingMethod ) ;
mLightingMethodButton - > removeAllItems ( ) ;
std : : array < SceneUtil : : LightingMethod , 3 > methods = {
SceneUtil : : LightingMethod : : FFP ,
SceneUtil : : LightingMethod : : PerObjectUniform ,
SceneUtil : : LightingMethod : : SingleUBO ,
} ;
for ( const auto & method : methods )
{
if ( ! MWBase : : Environment : : get ( ) . getResourceSystem ( ) - > getSceneManager ( ) - > isSupportedLightingMethod ( method ) )
continue ;
mLightingMethodButton - > addItem ( SceneUtil : : LightManager : : getLightingMethodString ( method ) ) ;
}
mLightingMethodButton - > setIndexSelected ( mLightingMethodButton - > findItemIndexWith ( lightingMethodStr ) ) ;
}
void SettingsWindow : : layoutControlsBox ( )
{
const int h = 18 ;
@ -671,6 +788,7 @@ namespace MWGui
{
highlightCurrentResolution ( ) ;
updateControlsBox ( ) ;
updateLightSettings ( ) ;
resetScrollbars ( ) ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > setKeyFocusWidget ( mOkButton ) ;
}