2026-10-07 23:40:47 +00:00
// Voir LPVideoQualitySubsystem.h.
# include "LPVideoQualitySubsystem.h"
# include "Blueprint/UserWidget.h"
# include "Components/Button.h"
# include "Components/ButtonSlot.h"
# include "Components/HorizontalBox.h"
# include "Components/HorizontalBoxSlot.h"
# include "Components/PanelWidget.h"
# include "Components/ScrollBox.h"
# include "Components/ScrollBoxSlot.h"
# include "Components/SizeBox.h"
# include "Components/Slider.h"
# include "Components/TextBlock.h"
# include "Engine/GameInstance.h"
# include "Engine/World.h"
# include "HAL/IConsoleManager.h"
# include "LifePlay.h"
2026-10-21 07:36:04 +00:00
# include "LPSettingsSubsystem.h"
2026-10-07 23:40:47 +00:00
# include "Misc/ConfigCacheIni.h"
# include "Misc/Paths.h"
# include "DynamicRHI.h"
# include "RHI.h"
# include "RHIStats.h"
# include "Scalability.h"
# include "Styling/CoreStyle.h"
# include "Styling/SlateTypes.h"
namespace LPVideoQuality
{
constexpr int32 MaxLevel = 3 ;
// Niveau retenu quand la VRAM est inconnue (0 ou -1) : High.
constexpr int32 RecommendedUnknownLevel = 2 ;
// VRAM dediee en octets, 0 si inconnue (RHI absent, -nullrhi, valeur non renseignee).
int64 QueryDedicatedVideoMemoryBytes ( )
{
if ( ! GDynamicRHI )
{
return 0 ;
}
FTextureMemoryStats Stats ;
RHIGetTextureMemoryStats ( Stats ) ;
return FMath : : Max < int64 > ( Stats . DedicatedVideoMemory , 0 ) ;
}
// <4 Go Low, <6 Med, <10 High, sinon Epic ; 0 Go (inconnu) = High.
int32 LevelFromVramGB ( double VramGB )
{
if ( VramGB < = 0.0 )
{
return RecommendedUnknownLevel ;
}
if ( VramGB < 4.0 )
{
return 0 ;
}
if ( VramGB < 6.0 )
{
return 1 ;
}
if ( VramGB < 10.0 )
{
return 2 ;
}
return 3 ;
}
FString IniPath ( )
{
return FPaths : : Combine ( FPaths : : ProjectSavedDir ( ) , TEXT ( " Config/Windows/LPVideoQuality.ini " ) ) ;
}
FSlateFontInfo MenuFont ( )
{
FSlateFontInfo Font = FCoreStyle : : GetDefaultFontStyle ( " Regular " , 20 ) ;
Font . OutlineSettings . OutlineSize = 2 ;
Font . OutlineSettings . bApplyOutlineToDropShadows = true ;
Font . OutlineSettings . OutlineColor = FLinearColor ( 0.f , 0.f , 0.f , 0.8f ) ;
return Font ;
}
void FindLook ( UWidget * Widget , UTextBlock * & OutText , USlider * & OutSlider )
{
if ( ! Widget | | ( OutText & & OutSlider ) )
{
return ;
}
if ( ! OutText )
{
OutText = Cast < UTextBlock > ( Widget ) ;
}
if ( ! OutSlider )
{
OutSlider = Cast < USlider > ( Widget ) ;
}
if ( UUserWidget * User = Cast < UUserWidget > ( Widget ) )
{
FindLook ( User - > GetRootWidget ( ) , OutText , OutSlider ) ;
}
if ( UPanelWidget * Panel = Cast < UPanelWidget > ( Widget ) )
{
for ( int32 Index = 0 ; Index < Panel - > GetChildrenCount ( ) & & ! ( OutText & & OutSlider ) ; + + Index )
{
FindLook ( Panel - > GetChildAt ( Index ) , OutText , OutSlider ) ;
}
}
}
int32 ClampLevel ( int32 Level )
{
return FMath : : Clamp ( Level , 0 , MaxLevel ) ;
}
}
FLPVideoLevels FLPVideoLevels : : FromOverall ( int32 Level )
{
const int32 Clamped = LPVideoQuality : : ClampLevel ( Level ) ;
FLPVideoLevels Result ;
Result . Overall = Clamped ;
Result . Shadows = Clamped ;
Result . Textures = Clamped ;
Result . Effects = Clamped ;
Result . AA = Clamped ;
return Result ;
}
void FLPVideoLevels : : Normalize ( )
{
Shadows = LPVideoQuality : : ClampLevel ( Shadows ) ;
Textures = LPVideoQuality : : ClampLevel ( Textures ) ;
Effects = LPVideoQuality : : ClampLevel ( Effects ) ;
AA = LPVideoQuality : : ClampLevel ( AA ) ;
Overall = ( Shadows = = Textures & & Textures = = Effects & & Effects = = AA ) ? Shadows : - 1 ;
}
bool FLPVideoLevels : : operator = = ( const FLPVideoLevels & Other ) const
{
return Overall = = Other . Overall & & Shadows = = Other . Shadows & & Textures = = Other . Textures & & Effects = = Other . Effects & & AA = = Other . AA ;
}
FString ULPVideoQualitySubsystem : : LevelLabel ( int32 Level )
{
switch ( Level )
{
case 0 : return TEXT ( " Low " ) ;
case 1 : return TEXT ( " Med " ) ;
case 2 : return TEXT ( " High " ) ;
case 3 : return TEXT ( " Epic " ) ;
default : return TEXT ( " Custom " ) ;
}
}
void ULPVideoQualitySubsystem : : Initialize ( FSubsystemCollectionBase & Collection )
{
Super : : Initialize ( Collection ) ;
Load ( ) ;
ApplyToScalability ( ) ;
TickHandle = FTSTicker : : GetCoreTicker ( ) . AddTicker ( FTickerDelegate : : CreateUObject ( this , & ULPVideoQualitySubsystem : : Tick ) , 0.5f ) ;
}
void ULPVideoQualitySubsystem : : Deinitialize ( )
{
FTSTicker : : GetCoreTicker ( ) . RemoveTicker ( TickHandle ) ;
Super : : Deinitialize ( ) ;
}
bool ULPVideoQualitySubsystem : : Tick ( float DeltaTime )
{
( void ) DeltaTime ;
UWorld * World = GetWorld ( ) ;
if ( World & & World - > IsGameWorld ( ) & & LastAppliedWorld . Get ( ) ! = World )
{
// Le Blueprint peut reappliquer ses valeurs au chargement d'un niveau.
LastAppliedWorld = World ;
ApplyToScalability ( ) ;
}
EnsureControls ( ) ;
return true ;
}
void ULPVideoQualitySubsystem : : ReadFromScalability ( )
{
const Scalability : : FQualityLevels Current = Scalability : : GetQualityLevels ( ) ;
Levels . Shadows = Current . ShadowQuality ;
Levels . Textures = Current . TextureQuality ;
Levels . Effects = Current . EffectsQuality ;
Levels . AA = Current . AntiAliasingQuality ;
Levels . Normalize ( ) ;
}
void ULPVideoQualitySubsystem : : Load ( )
{
// Valeurs de repli : etat Scalability courant (premier lancement).
ReadFromScalability ( ) ;
const FString Ini = LPVideoQuality : : IniPath ( ) ;
FConfigFile File ;
File . Read ( Ini ) ;
bool bAnyKey = false ;
auto Read = [ & File , & bAnyKey ] ( const TCHAR * Key , int32 & Out )
{
FString Text ;
if ( File . GetString ( TEXT ( " LPVideoQuality " ) , Key , Text ) )
{
Out = FCString : : Atoi ( * Text ) ;
bAnyKey = true ;
}
} ;
// Overall est relu pour la trace mais ignore : Normalize() le recalcule.
int32 StoredOverall = Levels . Overall ;
Read ( TEXT ( " Overall " ) , StoredOverall ) ;
Read ( TEXT ( " Shadows " ) , Levels . Shadows ) ;
Read ( TEXT ( " Textures " ) , Levels . Textures ) ;
Read ( TEXT ( " Effects " ) , Levels . Effects ) ;
Read ( TEXT ( " AA " ) , Levels . AA ) ;
Levels . Normalize ( ) ;
if ( bAnyKey )
{
bConfigured = true ;
UE_LOG ( LogLifePlay , Display , TEXT ( " Video : relu Overall %d, Shadows %d, Textures %d, Effects %d, AA %d depuis %s " ) , Levels . Overall , Levels . Shadows , Levels . Textures , Levels . Effects , Levels . AA , * Ini ) ;
}
else
{
bConfigured = false ;
UE_LOG ( LogLifePlay , Display , TEXT ( " Video : pas de %s, niveaux lus depuis Scalability (Overall %d, Shadows %d, Textures %d, Effects %d, AA %d) " ) , * Ini , Levels . Overall , Levels . Shadows , Levels . Textures , Levels . Effects , Levels . AA ) ;
}
}
void ULPVideoQualitySubsystem : : Save ( ) const
{
const FString Ini = LPVideoQuality : : IniPath ( ) ;
FConfigFile File ;
File . Read ( Ini ) ;
auto Write = [ & File ] ( const TCHAR * Key , int32 Value )
{
File . SetString ( TEXT ( " LPVideoQuality " ) , Key , * FString : : FromInt ( Value ) ) ;
} ;
Write ( TEXT ( " Version " ) , 1 ) ;
Write ( TEXT ( " Overall " ) , Levels . Overall ) ;
Write ( TEXT ( " Shadows " ) , Levels . Shadows ) ;
Write ( TEXT ( " Textures " ) , Levels . Textures ) ;
Write ( TEXT ( " Effects " ) , Levels . Effects ) ;
Write ( TEXT ( " AA " ) , Levels . AA ) ;
File . Write ( Ini ) ;
UE_LOG ( LogLifePlay , Display , TEXT ( " Video : Overall %d, Shadows %d, Textures %d, Effects %d, AA %d enregistres dans %s " ) , Levels . Overall , Levels . Shadows , Levels . Textures , Levels . Effects , Levels . AA , * Ini ) ;
}
void ULPVideoQualitySubsystem : : ApplyToScalability ( )
{
if ( ! bConfigured )
{
return ;
}
// Ecrire uniquement les 4 sg.* en SetByConsole : SetQualityLevels appliquerait aussi
// r.ScreenPercentage / r.Streaming.PoolSize / r.SSS.Scale (souvent deja poses par le BP
// en SetByConsole) et spamait des warnings "SetByScalability ignored".
auto SetSg = [ ] ( const TCHAR * Name , int32 Value )
{
if ( IConsoleVariable * Variable = IConsoleManager : : Get ( ) . FindConsoleVariable ( Name ) )
{
Variable - > Set ( Value , ECVF_SetByConsole ) ;
}
} ;
SetSg ( TEXT ( " sg.ShadowQuality " ) , Levels . Shadows ) ;
SetSg ( TEXT ( " sg.TextureQuality " ) , Levels . Textures ) ;
SetSg ( TEXT ( " sg.EffectsQuality " ) , Levels . Effects ) ;
SetSg ( TEXT ( " sg.AntiAliasingQuality " ) , Levels . AA ) ;
UE_LOG ( LogLifePlay , Display , TEXT ( " Video : qualite appliquee (sg.ShadowQuality %d, sg.TextureQuality %d, sg.EffectsQuality %d, sg.AntiAliasingQuality %d) " ) , Levels . Shadows , Levels . Textures , Levels . Effects , Levels . AA ) ;
}
void ULPVideoQualitySubsystem : : SetLevels ( FLPVideoLevels NewLevels , bool bFromOverall )
{
if ( bFromOverall & & NewLevels . Overall > = 0 )
{
NewLevels = FLPVideoLevels : : FromOverall ( NewLevels . Overall ) ;
}
else
{
NewLevels . Normalize ( ) ;
}
Levels = NewLevels ;
bConfigured = true ;
ApplyToScalability ( ) ;
RefreshWidgets ( ) ;
Save ( ) ;
}
void ULPVideoQualitySubsystem : : RefreshWidgets ( )
{
if ( bRefreshing )
{
return ;
}
bRefreshing = true ;
const int32 Values [ NumRows ] = {
Levels . Overall > = 0 ? Levels . Overall : LPVideoQuality : : ClampLevel ( FMath : : RoundToInt ( ( Levels . Shadows + Levels . Textures + Levels . Effects + Levels . AA ) * 0.25f ) ) ,
Levels . Shadows , Levels . Textures , Levels . Effects , Levels . AA
} ;
for ( int32 Index = 0 ; Index < NumRows ; + + Index )
{
if ( USlider * Slider = Rows [ Index ] . Slider . Get ( ) )
{
Slider - > SetValue ( static_cast < float > ( Values [ Index ] ) ) ;
}
if ( UTextBlock * Readout = Rows [ Index ] . Readout . Get ( ) )
{
Readout - > SetText ( FText : : FromString ( LevelLabel ( Index = = RowOverall ? Levels . Overall : Values [ Index ] ) ) ) ;
}
}
bRefreshing = false ;
}
void ULPVideoQualitySubsystem : : OnOverallChanged ( float Value )
{
if ( bRefreshing )
{
return ;
}
SetLevels ( FLPVideoLevels : : FromOverall ( FMath : : RoundToInt ( Value ) ) , true ) ;
}
void ULPVideoQualitySubsystem : : OnShadowsChanged ( float Value )
{
if ( bRefreshing )
{
return ;
}
FLPVideoLevels L = Levels ;
L . Shadows = LPVideoQuality : : ClampLevel ( FMath : : RoundToInt ( Value ) ) ;
SetLevels ( L , false ) ;
}
void ULPVideoQualitySubsystem : : OnTexturesChanged ( float Value )
{
if ( bRefreshing )
{
return ;
}
FLPVideoLevels L = Levels ;
L . Textures = LPVideoQuality : : ClampLevel ( FMath : : RoundToInt ( Value ) ) ;
SetLevels ( L , false ) ;
}
void ULPVideoQualitySubsystem : : OnEffectsChanged ( float Value )
{
if ( bRefreshing )
{
return ;
}
FLPVideoLevels L = Levels ;
L . Effects = LPVideoQuality : : ClampLevel ( FMath : : RoundToInt ( Value ) ) ;
SetLevels ( L , false ) ;
}
void ULPVideoQualitySubsystem : : OnAAChanged ( float Value )
{
if ( bRefreshing )
{
return ;
}
FLPVideoLevels L = Levels ;
L . AA = LPVideoQuality : : ClampLevel ( FMath : : RoundToInt ( Value ) ) ;
SetLevels ( L , false ) ;
}
void ULPVideoQualitySubsystem : : OnRecommendedClicked ( )
{
const int64 VramBytes = LPVideoQuality : : QueryDedicatedVideoMemoryBytes ( ) ;
const double VramGB = static_cast < double > ( VramBytes ) / ( 1024.0 * 1024.0 * 1024.0 ) ;
const int32 Level = LPVideoQuality : : LevelFromVramGB ( VramGB ) ;
if ( VramBytes > 0 )
{
UE_LOG ( LogLifePlay , Display , TEXT ( " Video : Recommended = %s (niveau %d), VRAM dediee detectee %.1f Go " ) , * LevelLabel ( Level ) , Level , VramGB ) ;
}
else
{
UE_LOG ( LogLifePlay , Display , TEXT ( " Video : Recommended = %s (niveau %d), VRAM dediee inconnue (0 Go), defaut High " ) , * LevelLabel ( Level ) , Level ) ;
}
SetLevels ( FLPVideoLevels : : FromOverall ( Level ) , true ) ;
}
USlider * ULPVideoQualitySubsystem : : AddRow ( ERow Row , UScrollBox * Scroll , UWidget * & OutRow , const TCHAR * Name , const TCHAR * Label , FName Handler , const TCHAR * Tip , const FSlateFontInfo & Font , const FSlateColor & Color , const FSliderStyle * SliderStyle )
{
UHorizontalBox * Box = NewObject < UHorizontalBox > ( Scroll , Name ) ;
UTextBlock * Caption = NewObject < UTextBlock > ( Box ) ;
Caption - > SetText ( FText : : FromString ( Label ) ) ;
Caption - > SetFont ( Font ) ;
Caption - > SetColorAndOpacity ( Color ) ;
USizeBox * CaptionBox = NewObject < USizeBox > ( Box ) ;
CaptionBox - > SetWidthOverride ( 220.f ) ;
CaptionBox - > AddChild ( Caption ) ;
USlider * Slider = NewObject < USlider > ( Box ) ;
if ( SliderStyle )
{
Slider - > SetWidgetStyle ( * SliderStyle ) ;
}
Slider - > SetMinValue ( 0.f ) ;
Slider - > SetMaxValue ( static_cast < float > ( LPVideoQuality : : MaxLevel ) ) ;
Slider - > SetStepSize ( 1.f ) ;
Slider - > SetLocked ( false ) ;
Slider - > SetValue ( 0.f ) ;
UTextBlock * Readout = NewObject < UTextBlock > ( Box ) ;
Readout - > SetFont ( Font ) ;
Readout - > SetColorAndOpacity ( Color ) ;
if ( UHorizontalBoxSlot * Slot = Box - > AddChildToHorizontalBox ( CaptionBox ) )
{
Slot - > SetVerticalAlignment ( VAlign_Center ) ;
Slot - > SetPadding ( FMargin ( 10.f , 0.f , 20.f , 0.f ) ) ;
}
if ( UHorizontalBoxSlot * Slot = Box - > AddChildToHorizontalBox ( Slider ) )
{
Slot - > SetSize ( FSlateChildSize ( ESlateSizeRule : : Fill ) ) ;
Slot - > SetVerticalAlignment ( VAlign_Center ) ;
Slot - > SetPadding ( FMargin ( 0.f , 0.f , 20.f , 0.f ) ) ;
}
if ( UHorizontalBoxSlot * Slot = Box - > AddChildToHorizontalBox ( Readout ) )
{
Slot - > SetVerticalAlignment ( VAlign_Center ) ;
Slot - > SetPadding ( FMargin ( 0.f , 0.f , 10.f , 0.f ) ) ;
}
Box - > SetToolTipText ( FText : : FromString ( Tip ) ) ;
FScriptDelegate Delegate ;
Delegate . BindUFunction ( this , Handler ) ;
Slider - > OnValueChanged . Add ( Delegate ) ;
Rows [ Row ] . Slider = Slider ;
Rows [ Row ] . Readout = Readout ;
OutRow = Box ;
return Slider ;
}
UWidget * ULPVideoQualitySubsystem : : MakeRecommendedRow ( UScrollBox * Scroll , const FSlateFontInfo & Font , const FSlateColor & Color )
{
UHorizontalBox * Box = NewObject < UHorizontalBox > ( Scroll , TEXT ( " LPVideoRecommended " ) ) ;
UButton * Button = NewObject < UButton > ( Box ) ;
UTextBlock * Caption = NewObject < UTextBlock > ( Button ) ;
Caption - > SetText ( FText : : FromString ( TEXT ( " Recommended " ) ) ) ;
Caption - > SetFont ( Font ) ;
Caption - > SetColorAndOpacity ( Color ) ;
Button - > SetContent ( Caption ) ;
if ( UButtonSlot * ContentSlot = Cast < UButtonSlot > ( Caption - > Slot ) )
{
ContentSlot - > SetHorizontalAlignment ( HAlign_Left ) ;
ContentSlot - > SetVerticalAlignment ( VAlign_Center ) ;
ContentSlot - > SetPadding ( FMargin ( 10.f ) ) ;
}
FScriptDelegate Delegate ;
Delegate . BindUFunction ( this , GET_FUNCTION_NAME_CHECKED ( ULPVideoQualitySubsystem , OnRecommendedClicked ) ) ;
Button - > OnClicked . Add ( Delegate ) ;
if ( UHorizontalBoxSlot * Slot = Box - > AddChildToHorizontalBox ( Button ) )
{
Slot - > SetVerticalAlignment ( VAlign_Center ) ;
Slot - > SetHorizontalAlignment ( HAlign_Left ) ;
Slot - > SetPadding ( FMargin ( 10.f , 0.f , 0.f , 0.f ) ) ;
}
Box - > SetToolTipText ( FText : : FromString ( TEXT ( " Apply the recommended preset for this PC. " ) ) ) ;
RecommendedButton = Button ;
return Box ;
}
void ULPVideoQualitySubsystem : : EnsureControls ( )
{
2026-10-21 07:36:04 +00:00
// SET1-V1b : la liste de l'instance de MainMenu qui est a l'ecran, pas la premiere trouvee (une ancienne instance,
// retiree du viewport et pas encore collectee, vient souvent avant). Aucune a l'ecran : rien a faire. Pas d'etat par
// instance a remettre a zero : la presence de LPVideoOverall se lit sur les enfants de la liste choisie, et AddRow /
// MakeRecommendedRow rebranchent Rows et RecommendedButton sur les lignes de cette liste.
UScrollBox * Scroll = ULPSettingsSubsystem : : FindOnScreenSettingsList ( GetGameInstance ( ) ) ;
2026-10-07 23:40:47 +00:00
if ( ! Scroll )
{
return ;
}
int32 InsertAt = INDEX_NONE ;
for ( int32 Index = 0 ; Index < Scroll - > GetChildrenCount ( ) ; + + Index )
{
if ( UWidget * Child = Scroll - > GetChildAt ( Index ) )
{
if ( Child - > GetFName ( ) = = TEXT ( " LPVideoOverall " ) )
{
return ;
}
if ( InsertAt = = INDEX_NONE & & Child - > GetName ( ) . StartsWith ( TEXT ( " LPColor " ) ) )
{
InsertAt = Index ;
}
}
}
UTextBlock * SampleText = nullptr ;
USlider * SampleSlider = nullptr ;
for ( int32 Index = 0 ; Index < Scroll - > GetChildrenCount ( ) ; + + Index )
{
LPVideoQuality : : FindLook ( Scroll - > GetChildAt ( Index ) , SampleText , SampleSlider ) ;
}
const FSlateFontInfo Font = SampleText ? SampleText - > GetFont ( ) : LPVideoQuality : : MenuFont ( ) ;
const FSlateColor Color = SampleText ? SampleText - > GetColorAndOpacity ( ) : FSlateColor ( FLinearColor ( 1.f , 1.f , 1.f , 0.95f ) ) ;
const FSliderStyle * SliderStyle = SampleSlider ? & SampleSlider - > GetWidgetStyle ( ) : nullptr ;
// Nouvelle instance du menu : on repart de l'etat moteur tant que le joueur n'a rien choisi.
if ( ! bConfigured )
{
ReadFromScalability ( ) ;
}
UWidget * Built [ NumRows + 1 ] = { nullptr } ;
AddRow ( RowOverall , Scroll , Built [ 0 ] , TEXT ( " LPVideoOverall " ) , TEXT ( " Overall Quality " ) , GET_FUNCTION_NAME_CHECKED ( ULPVideoQualitySubsystem , OnOverallChanged ) , TEXT ( " Preset applied to shadows, textures, effects and anti-aliasing. Custom when they differ. " ) , Font , Color , SliderStyle ) ;
AddRow ( RowShadows , Scroll , Built [ 1 ] , TEXT ( " LPVideoShadows " ) , TEXT ( " Shadows " ) , GET_FUNCTION_NAME_CHECKED ( ULPVideoQualitySubsystem , OnShadowsChanged ) , TEXT ( " Shadow resolution and distance. " ) , Font , Color , SliderStyle ) ;
AddRow ( RowTextures , Scroll , Built [ 2 ] , TEXT ( " LPVideoTextures " ) , TEXT ( " Textures " ) , GET_FUNCTION_NAME_CHECKED ( ULPVideoQualitySubsystem , OnTexturesChanged ) , TEXT ( " Texture filtering and streaming budget. " ) , Font , Color , SliderStyle ) ;
AddRow ( RowEffects , Scroll , Built [ 3 ] , TEXT ( " LPVideoEffects " ) , TEXT ( " Effects " ) , GET_FUNCTION_NAME_CHECKED ( ULPVideoQualitySubsystem , OnEffectsChanged ) , TEXT ( " Translucency, refraction, subsurface scattering and particles. " ) , Font , Color , SliderStyle ) ;
AddRow ( RowAA , Scroll , Built [ 4 ] , TEXT ( " LPVideoAA " ) , TEXT ( " Anti-Aliasing " ) , GET_FUNCTION_NAME_CHECKED ( ULPVideoQualitySubsystem , OnAAChanged ) , TEXT ( " Anti-aliasing quality. The method itself is fixed. " ) , Font , Color , SliderStyle ) ;
Built [ 5 ] = MakeRecommendedRow ( Scroll , Font , Color ) ;
bool bInserted = false ;
if ( InsertAt ! = INDEX_NONE )
{
bInserted = true ;
for ( int32 Index = 0 ; Index < NumRows + 1 ; + + Index )
{
UPanelSlot * PanelSlot = Scroll - > InsertChildAt ( InsertAt + Index , Built [ Index ] ) ;
if ( ! PanelSlot )
{
bInserted = false ;
break ;
}
if ( UScrollBoxSlot * Slot = Cast < UScrollBoxSlot > ( PanelSlot ) )
{
Slot - > SetPadding ( FMargin ( 0.f , 0.f , 0.f , 10.f ) ) ;
}
}
}
if ( ! bInserted )
{
if ( InsertAt ! = INDEX_NONE )
{
// Repli : InsertChildAt a echoue. On retire ce qui a pu etre insere, on ajoute en fin
// puis on remet les LPColor* derriere en conservant leurs objets.
UE_LOG ( LogLifePlay , Warning , TEXT ( " Video : InsertChildAt a echoue, repli par AddChild et reordonnancement des reglages de couleur " ) ) ;
for ( UWidget * Row : Built )
{
if ( Row & & Row - > GetParent ( ) = = Scroll )
{
Scroll - > RemoveChild ( Row ) ;
}
}
}
for ( UWidget * Row : Built )
{
if ( UScrollBoxSlot * Slot = Cast < UScrollBoxSlot > ( Scroll - > AddChild ( Row ) ) )
{
Slot - > SetPadding ( FMargin ( 0.f , 0.f , 0.f , 10.f ) ) ;
}
}
if ( InsertAt ! = INDEX_NONE )
{
TArray < UWidget * > Colors ;
for ( int32 Index = 0 ; Index < Scroll - > GetChildrenCount ( ) ; + + Index )
{
UWidget * Child = Scroll - > GetChildAt ( Index ) ;
if ( Child & & Child - > GetName ( ) . StartsWith ( TEXT ( " LPColor " ) ) )
{
Colors . Add ( Child ) ;
}
}
for ( UWidget * Child : Colors )
{
Scroll - > RemoveChild ( Child ) ;
}
for ( UWidget * Child : Colors )
{
if ( UScrollBoxSlot * Slot = Cast < UScrollBoxSlot > ( Scroll - > AddChild ( Child ) ) )
{
Slot - > SetPadding ( FMargin ( 0.f , 0.f , 0.f , 10.f ) ) ;
}
}
}
}
// Les curseurs Blueprint remplaces par LPVideo* sont replies tout de suite ;
// LPSettingsSubsystem les garde replies au changement d'onglet.
for ( int32 Index = 0 ; Index < Scroll - > GetChildrenCount ( ) ; + + Index )
{
if ( UWidget * Child = Scroll - > GetChildAt ( Index ) )
{
const FName ChildName = Child - > GetFName ( ) ;
if ( ChildName = = TEXT ( " ShadowQuality " ) | | ChildName = = TEXT ( " PostProcessQuality " ) | | ChildName = = TEXT ( " PostProcessAAQuality " ) )
{
Child - > SetVisibility ( ESlateVisibility : : Collapsed ) ;
}
}
}
RefreshWidgets ( ) ;
// Nouvelle instance du menu : le Blueprint a pu reappliquer ses propres valeurs.
ApplyToScalability ( ) ;
2026-10-21 07:36:04 +00:00
const UUserWidget * Menu = Scroll - > GetTypedOuter < UUserWidget > ( ) ;
UE_LOG ( LogLifePlay , Display , TEXT ( " Video : controles ajoutes avant les reglages de couleur (sur %s) " ) , Menu ? * Menu - > GetName ( ) : TEXT ( " ? " ) ) ;
2026-10-07 23:40:47 +00:00
}