Files
UnrealEngineUWP/Engine/Source/Editor/DerivedDataEditor/Private/SVirtualAssetsStatistics.cpp

599 lines
17 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SVirtualAssetsStatistics.h"
Add an opt in entry to the asset context menu that allows the user to re-hydrate a virtualized package. #rb Sebastian.Nordgren #jira UE-159595 #rnx #preflight 62d13965a66919b6700c8069 ### SVirtualAssetsStatistics - We do not currently have a virtualization specific editor module and have been piggybacking onto the DDC editor module, so although this new code has nothing to do with the VA statistics panel it seems easier to keep the code in a single file and then split it later when we move it to a virtualization editor module. - At the moment if the files being hydrated are not checked out then the process will fail. Support for auto checkout will be added in a future submit. ### EditorExperimentalSettings - By default no change will be made to the context menu. The user must edit the experimental editor settings and opt in to be able to see it. - This is because the feature should not really be used in day to day workflows and is provided to either fix problems or to make it easier for people developing the virtualization system. ### PackageRehydrationProcess - Fixed some typos in error messages - Being unable to write to the package is considered an error rather than a warning. It was demoted to a warning when virtualizing to try and reduce the number of blocked submits but we do not have this problem with rehydration. - Added code to reset the loader of a package if it happens to be already loaded in the editor now that we can invoke it from the editor. [CL 21107763 by paul chipchase in ue5-main branch]
2022-07-15 06:38:07 -04:00
#include "ContentBrowserDataMenuContexts.h"
#include "ContentBrowserDataSource.h"
#include "Framework/Notifications/NotificationManager.h"
#include "Internationalization/FastDecimalFormat.h"
Add an opt in entry to the asset context menu that allows the user to re-hydrate a virtualized package. #rb Sebastian.Nordgren #jira UE-159595 #rnx #preflight 62d13965a66919b6700c8069 ### SVirtualAssetsStatistics - We do not currently have a virtualization specific editor module and have been piggybacking onto the DDC editor module, so although this new code has nothing to do with the VA statistics panel it seems easier to keep the code in a single file and then split it later when we move it to a virtualization editor module. - At the moment if the files being hydrated are not checked out then the process will fail. Support for auto checkout will be added in a future submit. ### EditorExperimentalSettings - By default no change will be made to the context menu. The user must edit the experimental editor settings and opt in to be able to see it. - This is because the feature should not really be used in day to day workflows and is provided to either fix problems or to make it easier for people developing the virtualization system. ### PackageRehydrationProcess - Fixed some typos in error messages - Being unable to write to the package is considered an error rather than a warning. It was demoted to a warning when virtualizing to try and reduce the number of blocked submits but we do not have this problem with rehydration. - Added code to reset the loader of a package if it happens to be already loaded in the editor now that we can invoke it from the editor. [CL 21107763 by paul chipchase in ue5-main branch]
2022-07-15 06:38:07 -04:00
#include "Logging/MessageLog.h"
#include "Math/BasicMathExpressionEvaluator.h"
#include "Math/UnitConversion.h"
#include "Misc/ExpressionParser.h"
Add an opt in entry to the asset context menu that allows the user to re-hydrate a virtualized package. #rb Sebastian.Nordgren #jira UE-159595 #rnx #preflight 62d13965a66919b6700c8069 ### SVirtualAssetsStatistics - We do not currently have a virtualization specific editor module and have been piggybacking onto the DDC editor module, so although this new code has nothing to do with the VA statistics panel it seems easier to keep the code in a single file and then split it later when we move it to a virtualization editor module. - At the moment if the files being hydrated are not checked out then the process will fail. Support for auto checkout will be added in a future submit. ### EditorExperimentalSettings - By default no change will be made to the context menu. The user must edit the experimental editor settings and opt in to be able to see it. - This is because the feature should not really be used in day to day workflows and is provided to either fix problems or to make it easier for people developing the virtualization system. ### PackageRehydrationProcess - Fixed some typos in error messages - Being unable to write to the package is considered an error rather than a warning. It was demoted to a warning when virtualizing to try and reduce the number of blocked submits but we do not have this problem with rehydration. - Added code to reset the loader of a package if it happens to be already loaded in the editor now that we can invoke it from the editor. [CL 21107763 by paul chipchase in ue5-main branch]
2022-07-15 06:38:07 -04:00
#include "Settings/EditorExperimentalSettings.h"
#include "Styling/AppStyle.h"
#include "Styling/StyleColors.h"
Add an opt in entry to the asset context menu that allows the user to re-hydrate a virtualized package. #rb Sebastian.Nordgren #jira UE-159595 #rnx #preflight 62d13965a66919b6700c8069 ### SVirtualAssetsStatistics - We do not currently have a virtualization specific editor module and have been piggybacking onto the DDC editor module, so although this new code has nothing to do with the VA statistics panel it seems easier to keep the code in a single file and then split it later when we move it to a virtualization editor module. - At the moment if the files being hydrated are not checked out then the process will fail. Support for auto checkout will be added in a future submit. ### EditorExperimentalSettings - By default no change will be made to the context menu. The user must edit the experimental editor settings and opt in to be able to see it. - This is because the feature should not really be used in day to day workflows and is provided to either fix problems or to make it easier for people developing the virtualization system. ### PackageRehydrationProcess - Fixed some typos in error messages - Being unable to write to the package is considered an error rather than a warning. It was demoted to a warning when virtualizing to try and reduce the number of blocked submits but we do not have this problem with rehydration. - Added code to reset the loader of a package if it happens to be already loaded in the editor now that we can invoke it from the editor. [CL 21107763 by paul chipchase in ue5-main branch]
2022-07-15 06:38:07 -04:00
#include "ToolMenus.h"
#include "VirtualizationManager.h"
#include "Widgets/Layout/SGridPanel.h"
#include "Widgets/Layout/SScrollBox.h"
#include "Widgets/SBoxPanel.h"
#include "Widgets/Text/STextBlock.h"
#define LOCTEXT_NAMESPACE "VirtualAssets"
extern FString SingleDecimalFormat(double Value);
Add an opt in entry to the asset context menu that allows the user to re-hydrate a virtualized package. #rb Sebastian.Nordgren #jira UE-159595 #rnx #preflight 62d13965a66919b6700c8069 ### SVirtualAssetsStatistics - We do not currently have a virtualization specific editor module and have been piggybacking onto the DDC editor module, so although this new code has nothing to do with the VA statistics panel it seems easier to keep the code in a single file and then split it later when we move it to a virtualization editor module. - At the moment if the files being hydrated are not checked out then the process will fail. Support for auto checkout will be added in a future submit. ### EditorExperimentalSettings - By default no change will be made to the context menu. The user must edit the experimental editor settings and opt in to be able to see it. - This is because the feature should not really be used in day to day workflows and is provided to either fix problems or to make it easier for people developing the virtualization system. ### PackageRehydrationProcess - Fixed some typos in error messages - Being unable to write to the package is considered an error rather than a warning. It was demoted to a warning when virtualizing to try and reduce the number of blocked submits but we do not have this problem with rehydration. - Added code to reset the loader of a package if it happens to be already loaded in the editor now that we can invoke it from the editor. [CL 21107763 by paul chipchase in ue5-main branch]
2022-07-15 06:38:07 -04:00
// This namespace contains code for adding the re-hydration options to the editor context menu.
// For now it is easier to just put all virtualization editor code in this .cpp until we make
// a virtualization specific editor module like 'DerivedDataEditor'
namespace UE::Virtualization::Rehydration
{
/**
* Attempt to rehydrate the provided files although this currently assumes that the user has
* checked the files out of source control before hand.
*/
void RehydratePackages(TArray<FString> SelectedFiles)
{
TArray<FText> Errors;
Add an ini file option which when set to true allows package submissions to source control to go ahead even if the virtualization process failed. #rb none #jira UE-159596 #rnx #preflight 62d94160110da0f944afdd32 ### Problem - When rolling our virtualization to projects we have run into a number of set up problems which has caused users to fail to submit packages from the editor as when the virtualization failed we prevented the overall submit from going through. - Although we will eventually work through all of these problems and add better fault tolerance for now it is annoying for the content team so we need an easy way for a project to allow package submits to be completed even if the virtualization process part of the submit failed. - Worth noting that the virtualization process failing should never affect the state of the package files, the only downside is that the packages may not be virtualized. ### Fix - The virtualization/rehydration of packages now return an enum instead of a bool although at the moment we are only returning Success and Failed, but it will allow us to expand in the future - Combined the code calling the virtualization process from both the source control window and the source control changelist window into a single utility function. -- Now the two windows only diverge on how they report failure to the user. - This new utility function now checks to see if the virtualization manager suggests if failing the virtualization process should block any package submission to source control or not. - I am not happy with this solution, but I haven't come up with anything that feels right, this solution will at least work. [CL 21199597 by paul chipchase in ue5-main branch]
2022-07-21 08:31:47 -04:00
if (IVirtualizationSystem::Get().TryRehydratePackages(SelectedFiles, Errors) == ERehydrationResult::Success)
Add an opt in entry to the asset context menu that allows the user to re-hydrate a virtualized package. #rb Sebastian.Nordgren #jira UE-159595 #rnx #preflight 62d13965a66919b6700c8069 ### SVirtualAssetsStatistics - We do not currently have a virtualization specific editor module and have been piggybacking onto the DDC editor module, so although this new code has nothing to do with the VA statistics panel it seems easier to keep the code in a single file and then split it later when we move it to a virtualization editor module. - At the moment if the files being hydrated are not checked out then the process will fail. Support for auto checkout will be added in a future submit. ### EditorExperimentalSettings - By default no change will be made to the context menu. The user must edit the experimental editor settings and opt in to be able to see it. - This is because the feature should not really be used in day to day workflows and is provided to either fix problems or to make it easier for people developing the virtualization system. ### PackageRehydrationProcess - Fixed some typos in error messages - Being unable to write to the package is considered an error rather than a warning. It was demoted to a warning when virtualizing to try and reduce the number of blocked submits but we do not have this problem with rehydration. - Added code to reset the loader of a package if it happens to be already loaded in the editor now that we can invoke it from the editor. [CL 21107763 by paul chipchase in ue5-main branch]
2022-07-15 06:38:07 -04:00
{
// TODO: At some point ::TryRehydratePackages will return more detail info about the process
// when it does we should make a better job at logging it.
const FText Message = LOCTEXT("RehydrationSucccess", "Files were successfully re-hydrated");
FNotificationInfo Info(Message);
Info.bFireAndForget = true;
Info.ExpireDuration = 2.0f;
FSlateNotificationManager::Get().AddNotification(Info);
}
else
{
const bool bForceNotification = true;
FMessageLog Log("LogVirtualization");
for (const FText& Error : Errors)
{
Log.Error(Error);
}
Log.Notify(LOCTEXT("RehydrationFailed", "Failed to rehydrate packages, see the message log for more info"), EMessageSeverity::Info, bForceNotification);
}
}
void BrowserItemsToFilePaths(const TArray<FContentBrowserItem>& Source, TArray<FString>& OutResult)
{
for (const FContentBrowserItem& SelectedItem : Source)
{
const FContentBrowserItemData* SelectedItemData = SelectedItem.GetPrimaryInternalItem();
if (SelectedItemData == nullptr)
{
continue;
}
if (!SelectedItemData->IsFile())
{
continue;
}
UContentBrowserDataSource* DataSource = SelectedItemData->GetOwnerDataSource();
if (DataSource == nullptr)
{
continue;
}
FString Path;
if (DataSource->GetItemPhysicalPath(*SelectedItemData, Path))
{
OutResult.Add(FPaths::ConvertRelativePathToFull(Path));
}
}
}
void AddContextMenuEntry()
{
if (UToolMenu* Menu = UToolMenus::Get()->ExtendMenu("ContentBrowser.AssetContextMenu.AssetActionsSubMenu"))
{
Menu->AddDynamicSection("VirtualizedAssetsDynamic", FNewToolMenuDelegate::CreateLambda([](UToolMenu* Menu)
{
const UContentBrowserDataMenuContext_FileMenu* Context = Menu->FindContext<UContentBrowserDataMenuContext_FileMenu>();
if (Context == nullptr)
{
return;
}
if (Context->bCanBeModified == false)
{
return;
}
if (GetDefault<UEditorExperimentalSettings>()->bVirtualizedAssetRehydration == false)
{
return;
}
TArray<FString> SelectedFiles;
BrowserItemsToFilePaths(Context->SelectedItems, SelectedFiles);
if (SelectedFiles.IsEmpty())
{
return;
}
FToolMenuSection& Section = Menu->AddSection("VirtualizedAssets", LOCTEXT("VirtualizedAssetsHeading", "Virtualized Assets"));
{
Section.AddMenuEntry(
"RehydrateAsset",
LOCTEXT("RehydrateAsset", "Rehydrate Asset"),
LOCTEXT("RehydrateAssetTooltip", "Pulls the assets virtualized payloads and stores them in the package file once more"),
FSlateIcon(),
FUIAction(FExecuteAction::CreateStatic(&RehydratePackages, SelectedFiles))
);
}
}));
}
}
} // UE::Virtualization::Rehydration
SVirtualAssetsStatisticsDialog::SVirtualAssetsStatisticsDialog()
{
using namespace UE::Virtualization;
// Register our VA notification delegate with the event
IVirtualizationSystem& System = IVirtualizationSystem::Get();
System.GetNotificationEvent().AddRaw(this, &SVirtualAssetsStatisticsDialog::OnNotificationEvent);
Add an opt in entry to the asset context menu that allows the user to re-hydrate a virtualized package. #rb Sebastian.Nordgren #jira UE-159595 #rnx #preflight 62d13965a66919b6700c8069 ### SVirtualAssetsStatistics - We do not currently have a virtualization specific editor module and have been piggybacking onto the DDC editor module, so although this new code has nothing to do with the VA statistics panel it seems easier to keep the code in a single file and then split it later when we move it to a virtualization editor module. - At the moment if the files being hydrated are not checked out then the process will fail. Support for auto checkout will be added in a future submit. ### EditorExperimentalSettings - By default no change will be made to the context menu. The user must edit the experimental editor settings and opt in to be able to see it. - This is because the feature should not really be used in day to day workflows and is provided to either fix problems or to make it easier for people developing the virtualization system. ### PackageRehydrationProcess - Fixed some typos in error messages - Being unable to write to the package is considered an error rather than a warning. It was demoted to a warning when virtualizing to try and reduce the number of blocked submits but we do not have this problem with rehydration. - Added code to reset the loader of a package if it happens to be already loaded in the editor now that we can invoke it from the editor. [CL 21107763 by paul chipchase in ue5-main branch]
2022-07-15 06:38:07 -04:00
UE::Virtualization::Rehydration::AddContextMenuEntry();
}
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;
IVirtualizationSystem& System = IVirtualizationSystem::Get();
TSharedRef<SGridPanel> Panel = SNew(SGridPanel);
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);
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