Files
UnrealEngineUWP/Engine/Source/Editor/VirtualizationEditor/Private/SVirtualAssetsStatistics.cpp
paul chipchase 57db613f63 Move the rehydration context menu functionality from the statistics panel to its own code file
#rb Per.Larsson
#jira UE-162600
#rnx
#preflight 6317334c7b21ad1e0a1448be

- When the statistics panel lived in the DDC editor module it was easier to keep all virtualization functionality in one place. Now that we have our own module we can move it to its own code file for better readability.
- Added a utility function ::SetupMenuEntries called when the module is started, we should add all future menu entries here.

[CL 21816542 by paul chipchase in ue5-main branch]
2022-09-06 10:13:34 -04:00

533 lines
15 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SVirtualAssetsStatistics.h"
#include "Containers/Array.h"
#include "Containers/UnrealString.h"
#include "Delegates/Delegate.h"
#include "Fonts/SlateFontInfo.h"
#include "FrameNumberTimeEvaluator.h"
#include "Framework/Commands/UIAction.h"
#include "Framework/Notifications/NotificationManager.h"
#include "Framework/Text/TextLayout.h"
#include "HAL/PlatformCrt.h"
#include "HAL/PlatformTime.h"
#include "Internationalization/Internationalization.h"
#include "Internationalization/FastDecimalFormat.h"
#include "Layout/BasicLayoutWidgetSlot.h"
#include "Layout/Children.h"
#include "Layout/Margin.h"
#include "Logging/MessageLog.h"
#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"
#include "Styling/StyleColors.h"
#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"
#include "Widgets/Layout/SGridPanel.h"
#include "Widgets/Layout/SScrollBox.h"
#include "Widgets/Notifications/SNotificationList.h"
#include "Widgets/SBoxPanel.h"
#include "Widgets/Text/STextBlock.h"
class SWidget;
#define LOCTEXT_NAMESPACE "VirtualizationEditor"
namespace
{
FString SingleDecimalFormat(double Value)
{
const FNumberFormattingOptions NumberFormattingOptions = FNumberFormattingOptions()
.SetUseGrouping(true)
.SetMinimumFractionalDigits(1)
.SetMaximumFractionalDigits(1);
return FastDecimalFormat::NumberToString(Value, ExpressionParser::GetLocalizedNumberFormattingRules(), NumberFormattingOptions);
}
} //namespace
SVirtualAssetsStatisticsDialog::SVirtualAssetsStatisticsDialog()
{
using namespace UE::Virtualization;
// TODO - need a way to make this work once the system is initialized
// Register our VA notification delegate with the event
if (IVirtualizationSystem::IsInitialized())
{
IVirtualizationSystem& System = IVirtualizationSystem::Get();
System.GetNotificationEvent().AddRaw(this, &SVirtualAssetsStatisticsDialog::OnNotificationEvent);
}
}
SVirtualAssetsStatisticsDialog::~SVirtualAssetsStatisticsDialog()
{
using namespace UE::Virtualization;
// Unregister our VA notification delegate with the event
IVirtualizationSystem& System = IVirtualizationSystem::Get();
System.GetNotificationEvent().RemoveAll(this);
}
void SVirtualAssetsStatisticsDialog::OnNotificationEvent(UE::Virtualization::IVirtualizationSystem::ENotification Notification, const FIoHash& PayloadId)
{
using namespace UE::Virtualization;
FScopeLock SocpeLock(&NotificationCS);
switch (Notification)
{
case IVirtualizationSystem::ENotification::PullBegunNotification:
{
IsPulling = true;
NumPullRequests++;
break;
}
case IVirtualizationSystem::ENotification::PullEndedNotification:
{
if (IsPulling == true)
{
NumPullRequests--;
IsPulling = NumPullRequests!=0;
}
break;
}
case IVirtualizationSystem::ENotification::PullFailedNotification:
{
NumPullRequestFailures++;
break;
}
default:
break;
}
}
void SVirtualAssetsStatisticsDialog::Construct(const FArguments& InArgs)
{
this->ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(0, 20, 0, 0)
.Expose(GridSlot)
[
SAssignNew(ScrollBox, SScrollBox)
.Orientation(EOrientation::Orient_Horizontal)
.ScrollBarAlwaysVisible(false)
+ SScrollBox::Slot()
[
GetGridPanel()
]
]
];
RegisterActiveTimer(0.25f, FWidgetActiveTimerDelegate::CreateSP(this, &SVirtualAssetsStatisticsDialog::UpdateGridPanels));
}
EActiveTimerReturnType SVirtualAssetsStatisticsDialog::UpdateGridPanels(double InCurrentTime, float InDeltaTime)
{
ScrollBox->ClearChildren();
ScrollBox->AddSlot()
[
GetGridPanel()
];
SlatePrepass(GetPrepassLayoutScaleMultiplier());
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 )
{
// No existing notification or the existing one has finished
FNotificationInfo Info(LOCTEXT("PayloadSyncNotifcation", "Syncing Asset Payloads"));
Info.bFireAndForget = false;
Info.bUseLargeFont = false;
Info.bUseThrobber = false;
Info.FadeOutDuration = 0.5f;
Info.ExpireDuration = 0.0f;
PullRequestNotificationItem = FSlateNotificationManager::Get().AddNotification(Info);
if (PullRequestNotificationItem.IsValid())
{
PullRequestNotificationItem->SetCompletionState(SNotificationItem::CS_Pending);
}
}
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.\nSome assets may no longer be usable.."));
Info.bFireAndForget = false;
Info.bUseLargeFont = false;
Info.bUseThrobber = false;
Info.FadeOutDuration = 0.5f;
Info.ExpireDuration = 0.0f;
Info.Image = FAppStyle::GetBrush(TEXT("MessageLog.Warning"));
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);
}
if ( NumPullRequests==0 && PullRequestNotificationItem.IsValid()==true )
{
PullRequestNotificationItem->SetCompletionState(SNotificationItem::CS_Success);
PullRequestNotificationItem->ExpireAndFadeout();
PullRequestNotificationItem.Reset();
}
return EActiveTimerReturnType::Continue;
}
void SVirtualAssetsStatisticsDialog::OnWarningReasonOk()
{
if (PullRequestFailedNotificationItem.IsValid() == true)
{
PullRequestFailedNotificationItem->ExpireAndFadeout();
PullRequestFailedNotificationItem.Reset();
NumPullRequestFailures = 0;
}
}
void SVirtualAssetsStatisticsDialog::OnWarningReasonIgnore()
{
if (PullRequestFailedNotificationItem.IsValid() == true)
{
PullRequestFailedNotificationItem->ExpireAndFadeout();
}
}
TSharedRef<SWidget> SVirtualAssetsStatisticsDialog::GetGridPanel()
{
using namespace UE::Virtualization;
const float RowMargin = 0.0f;
const float TitleMargin = 10.0f;
const float ColumnMargin = 10.0f;
const FSlateColor TitleColor = FStyleColors::AccentWhite;
const FSlateFontInfo TitleFont = FCoreStyle::GetDefaultFontStyle("Bold", 10);
const double BytesToMegaBytes = 1.0 / (1024.0 * 1024.0);
TSharedRef<SGridPanel> Panel = SNew(SGridPanel);
// TODO - need a way to make this work once the system is initialized
if (!IVirtualizationSystem::IsInitialized())
{
Panel->AddSlot(0, 0)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("LazyInit", "System is uninitialized until first use"))
];
return Panel;
}
IVirtualizationSystem& System = IVirtualizationSystem::Get();
if (System.IsEnabled() == false)
{
Panel->AddSlot(0,0)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Disabled", "Virtual Assets Are Disabled For This Project"))
];
}
else
{
int32 Row = 0;
Panel->AddSlot(2, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Read", "Read"))
];
Panel->AddSlot(5, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Write", "Write"))
];
Panel->AddSlot(8, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Cache", "Cache"))
];
Row++;
Panel->AddSlot(0, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin, 0.0f, TitleMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Left)
.Text(LOCTEXT("Backend", "Backend"))
];
Panel->AddSlot(1, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin, 0.0f, TitleMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Count", "Count"))
];
Panel->AddSlot(2, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin, 0.0f, TitleMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Time", "Time (Sec)"))
];
Panel->AddSlot(3, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin, 0.0f, TitleMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Size", "Size (MB)"))
];
Panel->AddSlot(4, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin, 0.0f, TitleMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Count", "Count"))
];
Panel->AddSlot(5, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin, 0.0f, TitleMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Time", "Time (Sec)"))
];
Panel->AddSlot(6, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin, 0.0f, TitleMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Size", "Size (MB)"))
];
Panel->AddSlot(7, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin, 0.0f, TitleMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Count", "Count"))
];
Panel->AddSlot(8, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin, 0.0f, TitleMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Time", "Time (Sec)"))
];
Panel->AddSlot(9, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin, 0.0f, TitleMargin))
.ColorAndOpacity(TitleColor)
.Font(TitleFont)
.Justification(ETextJustify::Center)
.Text(LOCTEXT("Size", "Size (MB)"))
];
Row++;
FPayloadActivityInfo AccumulatedPayloadAcitvityInfo = System.GetAccumualtedPayloadActivityInfo();
FSlateColor Color = FStyleColors::Foreground;
FSlateFontInfo Font = FCoreStyle::GetDefaultFontStyle("Regular", 10);
auto DisplayPayloadActivityInfo = [&](const FString& DebugName, const FString& ConfigName, const FPayloadActivityInfo& PayloadActivityInfo)
{
Panel->AddSlot(0, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(Color)
.Font(Font)
.Justification(ETextJustify::Left)
.Text(FText::FromString(DebugName))
];
Panel->AddSlot(1, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(Color)
.Font(Font)
.Justification(ETextJustify::Center)
.Text_Lambda([PayloadActivityInfo] { return FText::FromString(FString::Printf(TEXT("%u"), PayloadActivityInfo.Pull.PayloadCount)); })
];
Panel->AddSlot(2, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(Color)
.Font(Font)
.Justification(ETextJustify::Center)
.Text_Lambda([PayloadActivityInfo] { return FText::FromString(SingleDecimalFormat((double)PayloadActivityInfo.Pull.CyclesSpent * FPlatformTime::GetSecondsPerCycle())); })
];
Panel->AddSlot(3, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(Color)
.Font(Font)
.Justification(ETextJustify::Center)
.Text_Lambda([PayloadActivityInfo, BytesToMegaBytes] { return FText::FromString(SingleDecimalFormat((double)PayloadActivityInfo.Pull.TotalBytes * BytesToMegaBytes)); })
];
Panel->AddSlot(4, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(Color)
.Font(Font)
.Justification(ETextJustify::Center)
.Text_Lambda([PayloadActivityInfo] { return FText::FromString(FString::Printf(TEXT("%u"), PayloadActivityInfo.Push.PayloadCount)); })
];
Panel->AddSlot(5, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(Color)
.Font(Font)
.Justification(ETextJustify::Center)
.Text_Lambda([PayloadActivityInfo] { return FText::FromString(SingleDecimalFormat((double)PayloadActivityInfo.Push.CyclesSpent * FPlatformTime::GetSecondsPerCycle())); })
];
Panel->AddSlot(6, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(Color)
.Font(Font)
.Justification(ETextJustify::Center)
.Text_Lambda([PayloadActivityInfo, BytesToMegaBytes] { return FText::FromString(SingleDecimalFormat((double)PayloadActivityInfo.Push.TotalBytes * BytesToMegaBytes)); })
];
Panel->AddSlot(7, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(Color)
.Font(Font)
.Justification(ETextJustify::Center)
.Text_Lambda([PayloadActivityInfo] { return FText::FromString(FString::Printf(TEXT("%u"), PayloadActivityInfo.Cache.PayloadCount)); })
];
Panel->AddSlot(8, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(Color)
.Font(Font)
.Justification(ETextJustify::Center)
.Text_Lambda([PayloadActivityInfo] { return FText::FromString(SingleDecimalFormat((double)PayloadActivityInfo.Cache.CyclesSpent * FPlatformTime::GetSecondsPerCycle())); })
];
Panel->AddSlot(9, Row)
[
SNew(STextBlock)
.Margin(FMargin(ColumnMargin, RowMargin))
.ColorAndOpacity(Color)
.Font(Font)
.Justification(ETextJustify::Center)
.Text_Lambda([PayloadActivityInfo, BytesToMegaBytes] { return FText::FromString(SingleDecimalFormat((double)PayloadActivityInfo.Cache.TotalBytes * BytesToMegaBytes)); })
];
Row++;
};
System.GetPayloadActivityInfo(DisplayPayloadActivityInfo);
Color = TitleColor;
Font = TitleFont;
DisplayPayloadActivityInfo(FString("Total"), FString("Total"), AccumulatedPayloadAcitvityInfo);
}
return Panel;
}
#undef LOCTEXT_NAMESPACE