2021-11-18 14:37:34 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "SVirtualAssetsStatistics.h"
2022-01-24 09:12:04 -05:00
2022-08-30 23:03:03 -04:00
# include "Containers/Array.h"
# include "Containers/UnrealString.h"
# include "Delegates/Delegate.h"
# include "Fonts/SlateFontInfo.h"
2022-09-05 06:19:34 -04:00
# include "FrameNumberTimeEvaluator.h"
2022-08-30 23:03:03 -04:00
# include "Framework/Commands/UIAction.h"
2022-01-24 09:12:04 -05:00
# include "Framework/Notifications/NotificationManager.h"
2022-08-30 23:03:03 -04:00
# include "Framework/Text/TextLayout.h"
# include "HAL/PlatformCrt.h"
# include "HAL/PlatformTime.h"
# include "Internationalization/Internationalization.h"
2022-09-05 06:19:34 -04:00
# include "Internationalization/FastDecimalFormat.h"
2022-08-30 23:03:03 -04:00
# include "Layout/BasicLayoutWidgetSlot.h"
# include "Layout/Children.h"
# include "Layout/Margin.h"
2022-07-15 06:38:07 -04:00
# include "Logging/MessageLog.h"
2022-08-30 23:03:03 -04:00
# include "Logging/TokenizedMessage.h"
# include "Misc/Attribute.h"
# include "Misc/Paths.h"
# include "Misc/ScopeLock.h"
# include "SlotBase.h"
# include "Styling/CoreStyle.h"
# include "Styling/SlateColor.h"
2021-11-18 14:37:34 -05:00
# include "Styling/StyleColors.h"
2022-08-30 23:03:03 -04:00
# include "Textures/SlateIcon.h"
# include "ToolMenu.h"
# include "ToolMenuDelegates.h"
# include "ToolMenuSection.h"
# include "Types/WidgetActiveTimerDelegate.h"
# include "UObject/UObjectGlobals.h"
# include "Virtualization/VirtualizationTypes.h"
2021-11-18 14:37:34 -05:00
# include "Widgets/Layout/SGridPanel.h"
2022-01-24 09:12:04 -05:00
# include "Widgets/Layout/SScrollBox.h"
2022-08-30 23:03:03 -04:00
# include "Widgets/Notifications/SNotificationList.h"
2021-11-18 14:37:34 -05:00
# include "Widgets/SBoxPanel.h"
2022-01-24 09:12:04 -05:00
# include "Widgets/Text/STextBlock.h"
2021-11-18 14:37:34 -05:00
2022-08-30 23:03:03 -04:00
class SWidget ;
2022-09-06 10:13:34 -04:00
# define LOCTEXT_NAMESPACE "VirtualizationEditor"
2021-11-18 14:37:34 -05:00
2022-09-05 06:19:34 -04:00
namespace
{
FString SingleDecimalFormat ( double Value )
{
const FNumberFormattingOptions NumberFormattingOptions = FNumberFormattingOptions ( )
. SetUseGrouping ( true )
. SetMinimumFractionalDigits ( 1 )
. SetMaximumFractionalDigits ( 1 ) ;
return FastDecimalFormat : : NumberToString ( Value , ExpressionParser : : GetLocalizedNumberFormattingRules ( ) , NumberFormattingOptions ) ;
}
} //namespace
2021-11-18 14:37:34 -05:00
2021-11-23 15:05:13 -05:00
SVirtualAssetsStatisticsDialog : : SVirtualAssetsStatisticsDialog ( )
{
2022-07-20 06:59:09 -04:00
using namespace UE : : Virtualization ;
2022-08-19 19:15:42 -04:00
// TODO - need a way to make this work once the system is initialized
2021-11-23 15:05:13 -05:00
// Register our VA notification delegate with the event
2022-08-19 19:15:42 -04:00
if ( IVirtualizationSystem : : IsInitialized ( ) )
{
IVirtualizationSystem & System = IVirtualizationSystem : : Get ( ) ;
System . GetNotificationEvent ( ) . AddRaw ( this , & SVirtualAssetsStatisticsDialog : : OnNotificationEvent ) ;
}
2021-11-23 15:05:13 -05:00
}
SVirtualAssetsStatisticsDialog : : ~ SVirtualAssetsStatisticsDialog ( )
{
2022-07-20 06:59:09 -04:00
using namespace UE : : Virtualization ;
2021-11-23 15:05:13 -05:00
// Unregister our VA notification delegate with the event
IVirtualizationSystem & System = IVirtualizationSystem : : Get ( ) ;
System . GetNotificationEvent ( ) . RemoveAll ( this ) ;
}
2022-07-20 06:59:09 -04:00
void SVirtualAssetsStatisticsDialog : : OnNotificationEvent ( UE : : Virtualization : : IVirtualizationSystem : : ENotification Notification , const FIoHash & PayloadId )
2021-11-23 15:05:13 -05:00
{
2022-07-20 06:59:09 -04:00
using namespace UE : : Virtualization ;
2021-11-23 15:05:13 -05:00
FScopeLock SocpeLock ( & NotificationCS ) ;
switch ( Notification )
{
case IVirtualizationSystem : : ENotification : : PullBegunNotification :
{
2021-12-01 11:49:50 -05:00
IsPulling = true ;
2021-11-23 15:05:13 -05:00
NumPullRequests + + ;
2021-12-01 11:49:50 -05:00
2021-11-23 15:05:13 -05:00
break ;
}
case IVirtualizationSystem : : ENotification : : PullEndedNotification :
{
2021-12-01 11:49:50 -05:00
if ( IsPulling = = true )
{
NumPullRequests - - ;
IsPulling = NumPullRequests ! = 0 ;
}
2021-11-23 15:05:13 -05:00
break ;
}
case IVirtualizationSystem : : ENotification : : PullFailedNotification :
{
2022-04-22 08:55:44 -04:00
NumPullRequestFailures + + ;
2021-11-23 15:05:13 -05:00
break ;
}
default :
break ;
}
}
2021-11-18 14:37:34 -05:00
void SVirtualAssetsStatisticsDialog : : Construct ( const FArguments & InArgs )
{
this - > ChildSlot
[
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
2021-11-23 05:39:59 -05:00
. Padding ( 0 , 20 , 0 , 0 )
2021-11-18 14:37:34 -05:00
. Expose ( GridSlot )
[
2022-01-24 09:12:04 -05:00
SAssignNew ( ScrollBox , SScrollBox )
. Orientation ( EOrientation : : Orient_Horizontal )
. ScrollBarAlwaysVisible ( false )
+ SScrollBox : : Slot ( )
[
GetGridPanel ( )
]
2021-11-18 14:37:34 -05:00
]
] ;
2022-01-21 10:57:43 -05:00
RegisterActiveTimer ( 0.25f , FWidgetActiveTimerDelegate : : CreateSP ( this , & SVirtualAssetsStatisticsDialog : : UpdateGridPanels ) ) ;
2021-11-18 14:37:34 -05:00
}
EActiveTimerReturnType SVirtualAssetsStatisticsDialog : : UpdateGridPanels ( double InCurrentTime , float InDeltaTime )
{
2022-01-24 09:12:04 -05:00
ScrollBox - > ClearChildren ( ) ;
ScrollBox - > AddSlot ( )
2022-01-21 10:57:43 -05:00
[
GetGridPanel ( )
] ;
2022-01-24 09:12:04 -05:00
2021-11-18 14:37:34 -05:00
SlatePrepass ( GetPrepassLayoutScaleMultiplier ( ) ) ;
2022-01-21 10:57:43 -05:00
const float PullNotifactionTimeLimit = 1.0f ;
// Only show the pull notification if we have been pulling for more than a second..
if ( NumPullRequests ! = 0 )
{
PullNotificationTimer + = InDeltaTime ;
}
else
{
PullNotificationTimer = 0.0f ;
}
if ( PullNotificationTimer > PullNotifactionTimeLimit & & PullRequestNotificationItem . IsValid ( ) = = false )
2021-11-23 15:05:13 -05:00
{
// No existing notification or the existing one has finished
2022-04-22 08:55:44 -04:00
FNotificationInfo Info ( LOCTEXT ( " PayloadSyncNotifcation " , " Syncing Asset Payloads " ) ) ;
2021-11-23 15:05:13 -05:00
Info . bFireAndForget = false ;
2022-04-22 08:55:44 -04:00
Info . bUseLargeFont = false ;
Info . bUseThrobber = false ;
2021-11-23 15:05:13 -05:00
Info . FadeOutDuration = 0.5f ;
Info . ExpireDuration = 0.0f ;
PullRequestNotificationItem = FSlateNotificationManager : : Get ( ) . AddNotification ( Info ) ;
if ( PullRequestNotificationItem . IsValid ( ) )
{
PullRequestNotificationItem - > SetCompletionState ( SNotificationItem : : CS_Pending ) ;
}
}
2022-04-22 08:55:44 -04:00
if ( NumPullRequestFailures > 0 & & PullRequestFailedNotificationItem . IsValid ( ) = = false )
{
// No existing notification or the existing one has finished
FNotificationInfo Info ( LOCTEXT ( " PayloadFailedNotifcation " , " Failed to sync some Virtual Asset payloads from available backends. \n Some assets may no longer be usable.. " ) ) ;
Info . bFireAndForget = false ;
Info . bUseLargeFont = false ;
Info . bUseThrobber = false ;
Info . FadeOutDuration = 0.5f ;
Info . ExpireDuration = 0.0f ;
2022-05-09 13:31:58 -04:00
Info . Image = FAppStyle : : GetBrush ( TEXT ( " MessageLog.Warning " ) ) ;
2022-04-22 08:55:44 -04:00
Info . ButtonDetails . Add ( FNotificationButtonInfo ( LOCTEXT ( " PullFailedIgnore " , " Ignore " ) , LOCTEXT ( " PullFailedIgnoreToolTip " , " Ignore future warnings " ) , FSimpleDelegate : : CreateSP ( this , & SVirtualAssetsStatisticsDialog : : OnWarningReasonIgnore ) , SNotificationItem : : CS_None ) ) ;
Info . ButtonDetails . Add ( FNotificationButtonInfo ( LOCTEXT ( " PullFailedOK " , " Ok " ) , LOCTEXT ( " PullFailedOkToolTip " , " Notify future warnings " ) , FSimpleDelegate : : CreateSP ( this , & SVirtualAssetsStatisticsDialog : : OnWarningReasonOk ) , SNotificationItem : : CS_None ) ) ;
Info . HyperlinkText = LOCTEXT ( " PullFailed_ShowLog " , " Show Message Log " ) ;
Info . Hyperlink = FSimpleDelegate : : CreateStatic ( [ ] ( ) { FMessageLog ( " LogVirtualization " ) . Open ( EMessageSeverity : : Warning , true ) ; } ) ;
PullRequestFailedNotificationItem = FSlateNotificationManager : : Get ( ) . AddNotification ( Info ) ;
}
2021-11-23 15:05:13 -05:00
if ( NumPullRequests = = 0 & & PullRequestNotificationItem . IsValid ( ) = = true )
{
PullRequestNotificationItem - > SetCompletionState ( SNotificationItem : : CS_Success ) ;
PullRequestNotificationItem - > ExpireAndFadeout ( ) ;
PullRequestNotificationItem . Reset ( ) ;
}
2021-11-18 14:37:34 -05:00
return EActiveTimerReturnType : : Continue ;
}
2022-04-22 08:55:44 -04:00
void SVirtualAssetsStatisticsDialog : : OnWarningReasonOk ( )
{
if ( PullRequestFailedNotificationItem . IsValid ( ) = = true )
{
PullRequestFailedNotificationItem - > ExpireAndFadeout ( ) ;
PullRequestFailedNotificationItem . Reset ( ) ;
NumPullRequestFailures = 0 ;
}
}
void SVirtualAssetsStatisticsDialog : : OnWarningReasonIgnore ( )
{
if ( PullRequestFailedNotificationItem . IsValid ( ) = = true )
{
PullRequestFailedNotificationItem - > ExpireAndFadeout ( ) ;
}
}
2021-11-18 14:37:34 -05:00
TSharedRef < SWidget > SVirtualAssetsStatisticsDialog : : GetGridPanel ( )
{
2022-07-20 06:59:09 -04:00
using namespace UE : : Virtualization ;
2021-11-18 14:37:34 -05:00
const float RowMargin = 0.0f ;
const float TitleMargin = 10.0f ;
const float ColumnMargin = 10.0f ;
2024-05-13 07:26:28 -04:00
const float BorderPadding = ColumnMargin / 2.0f ;
const FMargin StdMargin ( ColumnMargin , RowMargin ) ;
2021-11-18 14:37:34 -05:00
const FSlateColor TitleColor = FStyleColors : : AccentWhite ;
const FSlateFontInfo TitleFont = FCoreStyle : : GetDefaultFontStyle ( " Bold " , 10 ) ;
2024-05-13 07:26:28 -04:00
FSlateColor Color = FStyleColors : : Foreground ;
FSlateFontInfo Font = FCoreStyle : : GetDefaultFontStyle ( " Regular " , 10 ) ;
2021-11-18 14:37:34 -05:00
2024-05-13 07:26:28 -04:00
struct FPanels
2022-08-19 19:15:42 -04:00
{
2024-05-13 07:26:28 -04:00
TSharedPtr < SGridPanel > Names ;
TSharedPtr < SGridPanel > Pull ;
TSharedPtr < SGridPanel > Cache ;
TSharedPtr < SGridPanel > Push ;
2022-08-19 19:15:42 -04:00
2024-05-13 07:26:28 -04:00
} Panels ;
2022-08-19 19:15:42 -04:00
2024-06-04 07:15:51 -04:00
// Early out if the system is disabled
if ( IVirtualizationSystem : : Get ( ) . IsEnabled ( ) = = false )
{
return SNew ( STextBlock )
. Margin ( FMargin ( ColumnMargin , RowMargin ) )
. ColorAndOpacity ( TitleColor )
. Font ( TitleFont )
. Justification ( ETextJustify : : Center )
. Text ( LOCTEXT ( " Disabled " , " Virtual Assets Are Disabled For This Project " ) ) ;
}
2024-05-13 07:26:28 -04:00
TSharedRef < SHorizontalBox > Panel = SNew ( SHorizontalBox ) ;
Panel - > AddSlot ( )
. Padding ( BorderPadding )
. AutoWidth ( )
[
SAssignNew ( Panels . Names , SGridPanel )
+ SGridPanel : : Slot ( 0 , 0 )
[
SNew ( STextBlock )
. Margin ( FMargin ( ColumnMargin + ( BorderPadding / 2.0f ) , RowMargin + ( BorderPadding / 2.0f ) ) )
. ColorAndOpacity ( TitleColor )
. Font ( TitleFont )
. Justification ( ETextJustify : : Left )
]
+ SGridPanel : : Slot ( 0 , 1 )
[
SNew ( STextBlock )
. Margin ( FMargin ( ColumnMargin , RowMargin , 0.0f , TitleMargin ) )
. ColorAndOpacity ( TitleColor )
. Font ( TitleFont )
. Justification ( ETextJustify : : Left )
. Text ( LOCTEXT ( " Backend " , " Backend " ) )
]
] ;
2022-08-19 19:15:42 -04:00
2024-05-13 07:26:28 -04:00
auto CreateGridPanels = [ & ] ( FText & & Label )
2021-11-23 06:54:34 -05:00
{
2024-05-13 07:26:28 -04:00
TSharedPtr < SGridPanel > GridPanel ;
2021-11-23 06:54:34 -05:00
2024-05-13 07:26:28 -04:00
Panel - > AddSlot ( )
. Padding ( BorderPadding )
. AutoWidth ( )
[
SNew ( SBorder )
. Padding ( BorderPadding )
2021-11-23 06:54:34 -05:00
[
2024-05-13 07:26:28 -04:00
SAssignNew ( GridPanel , SGridPanel )
+ SGridPanel : : Slot ( 1 , 0 )
[
SNew ( STextBlock )
. Margin ( FMargin ( ColumnMargin , RowMargin ) )
. ColorAndOpacity ( TitleColor )
. Font ( TitleFont )
. Justification ( ETextJustify : : Center )
. Text ( MoveTemp ( Label ) )
]
+ SGridPanel : : Slot ( 0 , 1 )
[
SNew ( STextBlock )
. Margin ( FMargin ( ColumnMargin , RowMargin , 0.0f , TitleMargin ) )
. ColorAndOpacity ( TitleColor )
. Font ( TitleFont )
. Justification ( ETextJustify : : Center )
. Text ( LOCTEXT ( " Count " , " Count " ) )
]
+ SGridPanel : : Slot ( 1 , 1 )
[
SNew ( STextBlock )
. Margin ( FMargin ( ColumnMargin , RowMargin , 0.0f , TitleMargin ) )
. ColorAndOpacity ( TitleColor )
. Font ( TitleFont )
. Justification ( ETextJustify : : Center )
. Text ( LOCTEXT ( " Size " , " Size (MiB) " ) )
]
+ SGridPanel : : Slot ( 2 , 1 )
[
SNew ( STextBlock )
. Margin ( FMargin ( ColumnMargin , RowMargin , 0.0f , TitleMargin ) )
. ColorAndOpacity ( TitleColor )
. Font ( TitleFont )
. Justification ( ETextJustify : : Center )
. Text ( LOCTEXT ( " Time " , " Avg (ms) " ) )
]
]
] ;
return GridPanel ;
2021-11-23 06:54:34 -05:00
} ;
2024-05-13 07:26:28 -04:00
Panels . Pull = CreateGridPanels ( LOCTEXT ( " Download " , " Download " ) ) ;
Panels . Cache = CreateGridPanels ( LOCTEXT ( " Cache " , " Cache " ) ) ;
Panels . Push = CreateGridPanels ( LOCTEXT ( " Upload " , " Upload " ) ) ;
2021-11-23 06:54:34 -05:00
2024-05-13 07:26:28 -04:00
int32 RowIndex = 2 ;
2024-05-14 07:59:24 -04:00
auto DisplayPayloadActivityInfo = [ & StdMargin , & Color , & Font , & RowIndex , & Panels ] ( const FString & Name , const FPayloadActivityInfo & PayloadActivityInfo )
2024-05-13 07:26:28 -04:00
{
Panels . Names - > AddSlot ( 0 , RowIndex )
[
SNew ( STextBlock )
. Margin ( StdMargin )
. ColorAndOpacity ( Color )
. Font ( Font )
. Justification ( ETextJustify : : Left )
2024-05-14 07:59:24 -04:00
. Text ( FText : : FromString ( Name ) )
2024-05-13 07:26:28 -04:00
] ;
2021-11-23 06:54:34 -05:00
2024-05-13 07:26:28 -04:00
auto FillPanelDetails = [ & StdMargin , & Color , & Font , & RowIndex ] ( TSharedPtr < SGridPanel > & Panel , const FPayloadActivityInfo : : FActivity & Activity )
{
Panel - > AddSlot ( 0 , RowIndex )
[
SNew ( STextBlock )
. Margin ( StdMargin )
. ColorAndOpacity ( Color )
. Font ( Font )
. Justification ( ETextJustify : : Center )
. Text ( FText : : FromString ( FString : : Printf ( TEXT ( " %u " ) , Activity . PayloadCount ) ) )
] ;
2024-05-13 09:20:26 -04:00
const double TotalBytesMiB = static_cast < double > ( Activity . TotalBytes ) / ( 1024.0 * 1024.0 ) ;
2024-05-13 07:26:28 -04:00
Panel - > AddSlot ( 1 , RowIndex )
[
SNew ( STextBlock )
. Margin ( StdMargin )
. ColorAndOpacity ( Color )
. Font ( Font )
. Justification ( ETextJustify : : Center )
. Text ( FText : : FromString ( SingleDecimalFormat ( TotalBytesMiB ) ) )
] ;
const double TotalTime = static_cast < double > ( FPlatformTime : : ToMilliseconds64 ( Activity . CyclesSpent ) ) ;
2024-05-13 09:20:26 -04:00
const double Avg = Activity . PayloadCount > 0 ? TotalTime / static_cast < double > ( Activity . PayloadCount ) : 0.0 ;
2024-05-13 07:26:28 -04:00
Panel - > AddSlot ( 2 , RowIndex )
[
SNew ( STextBlock )
. Margin ( StdMargin )
. ColorAndOpacity ( Color )
. Font ( Font )
. Justification ( ETextJustify : : Center )
. Text ( FText : : FromString ( SingleDecimalFormat ( Avg ) ) )
] ;
} ;
FillPanelDetails ( Panels . Pull , PayloadActivityInfo . Pull ) ;
FillPanelDetails ( Panels . Cache , PayloadActivityInfo . Cache ) ;
FillPanelDetails ( Panels . Push , PayloadActivityInfo . Push ) ;
RowIndex + + ;
} ;
2024-05-14 07:59:24 -04:00
TArray < FBackendStats > BackendStats = IVirtualizationSystem : : Get ( ) . GetBackendStatistics ( ) ;
for ( const FBackendStats & Stats : BackendStats )
{
DisplayPayloadActivityInfo ( Stats . ConfigName , Stats . PayloadActivity ) ;
}
2024-05-13 07:26:28 -04:00
2024-05-14 07:59:24 -04:00
FPayloadActivityInfo AccumulatedPayloadAcitvityInfo = IVirtualizationSystem : : Get ( ) . GetSystemStatistics ( ) ;
2024-05-13 07:26:28 -04:00
Color = TitleColor ;
Font = TitleFont ;
2024-05-14 07:59:24 -04:00
DisplayPayloadActivityInfo ( FString ( " Total " ) , AccumulatedPayloadAcitvityInfo ) ;
2021-11-18 14:37:34 -05:00
return Panel ;
}
# undef LOCTEXT_NAMESPACE