You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#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]
533 lines
15 KiB
C++
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
|