87 lines
5.2 KiB
C++
87 lines
5.2 KiB
C++
#include "IronsPerformanceOverlay.h"
|
|
#include "IronsHost.h"
|
|
#include "IronsPerformanceSubsystem.h"
|
|
#include "Blueprint/WidgetTree.h"
|
|
#include "Components/CanvasPanel.h"
|
|
#include "Rendering/DrawElements.h"
|
|
#include "Styling/CoreStyle.h"
|
|
#include "Fonts/CompositeFont.h"
|
|
#include "Fonts/FontMeasure.h"
|
|
#include "Framework/Application/SlateApplication.h"
|
|
#include "Misc/Paths.h"
|
|
|
|
namespace {
|
|
const TSharedPtr<const FCompositeFont>& PerformanceFont(){
|
|
static TSharedPtr<const FCompositeFont> Font=MakeShared<FCompositeFont>(TEXT("Regular"),FPaths::ProjectContentDir()/TEXT("IRONSPORE/Raw/Fonts/IronsSansSC-Regular.ttf"),EFontHinting::Default,EFontLoadingPolicy::LazyLoad);return Font;
|
|
}
|
|
}
|
|
|
|
FIronsPerformanceLayout FIronsPerformanceLayout::Make(FVector2D Size,bool Enabled,int32 Corner)
|
|
{
|
|
FIronsPerformanceLayout L;
|
|
Size.X=FMath::Max(1.0,Size.X);Size.Y=FMath::Max(1.0,Size.Y);
|
|
L.PanelScale=FMath::Min(Size.X/1920.f,Size.Y/1080.f);
|
|
Corner=FMath::Clamp(Corner,0,3);
|
|
const bool Left=Corner==1||Corner==3,Bottom=Corner>=2;
|
|
const float S=L.PanelScale,Width=660*S,Height=72*S,Margin=16*S;
|
|
const float X=Left?Margin:Size.X-Margin-Width,Y=Bottom?Size.Y-Margin-Height:Margin;
|
|
L.Panel=FSlateRect(X,Y,X+Width,Y+Height);
|
|
const float Band=Enabled?104*S:0;
|
|
L.ContentScale=FMath::Min(Size.X/1920.f,(Size.Y-Band)/1080.f);
|
|
L.ContentOrigin=(Size-FVector2D(1920,1080)*L.ContentScale-FVector2D(0,Band))*.5f;
|
|
if(!Bottom)L.ContentOrigin.Y+=Band;
|
|
return L;
|
|
}
|
|
void UIronsPerformanceOverlay::NativeConstruct()
|
|
{
|
|
Super::NativeConstruct();SetIsFocusable(false);SetVisibility(ESlateVisibility::HitTestInvisible);
|
|
if(WidgetTree&&!WidgetTree->RootWidget)WidgetTree->RootWidget=WidgetTree->ConstructWidget<UCanvasPanel>();
|
|
}
|
|
void UIronsPerformanceOverlay::NativeTick(const FGeometry& Geometry,float DeltaTime)
|
|
{
|
|
Super::NativeTick(Geometry,DeltaTime);
|
|
auto H=GetGameInstance<UIronsGameInstance>();auto Metrics=GetGameInstance()?GetGameInstance()->GetSubsystem<UIronsPerformanceSubsystem>():nullptr;
|
|
if(!H||!Metrics)return;const auto& S=Metrics->GetSnapshot();
|
|
const float Scale=FIronsPerformanceLayout::Make(Geometry.GetLocalSize(),true,H->PerformanceCorner).PanelScale;
|
|
if(CachedRevision==S.Revision&&bCachedEnglish==H->bEnglish&&FMath::IsNearlyEqual(CachedScale,Scale))return;
|
|
CachedRevision=S.Revision;bCachedEnglish=H->bEnglish;CachedScale=Scale;
|
|
auto Fit=[&](const FString& Text,float Width,int32 Size){
|
|
FSlateFontInfo Info(PerformanceFont(),FMath::Max(1,FMath::RoundToInt(Size*Scale)));
|
|
const auto Measure=FSlateApplication::Get().GetRenderer()->GetFontMeasureService();
|
|
const float Measured=Measure->Measure(Text,Info).X;
|
|
if(Measured>Width*Scale)Info.Size=FMath::Max(7,FMath::FloorToInt(Info.Size*Width*Scale/Measured));
|
|
Measure->Measure(Text,Info); // Prepare the actual glyph size before either widget paints.
|
|
return Info.Size;
|
|
};
|
|
const TCHAR* Keys[]={TEXT("ue.perfFps"),TEXT("ue.perfFrame"),TEXT("ue.perfGpu"),TEXT("ue.perfGame"),TEXT("ue.perfRender"),TEXT("ue.perfRhi")};
|
|
const double Numbers[]={S.Fps,S.FrameMs,S.GpuMs,S.GameMs,S.RenderMs,S.RhiMs};
|
|
for(int32 I=0;I<6;++I){
|
|
Labels[I]=H->Label(Keys[I]);const double N=Numbers[I];
|
|
Values[I]=N<0||!FMath::IsFinite(N)?TEXT("—"):I==0?FString::Printf(TEXT("%.1f"),N):FString::Printf(TEXT("%.2f ms"),N);
|
|
LabelSizes[I]=Fit(Labels[I],96,14);ValueSizes[I]=Fit(Values[I],106,16);
|
|
Colors[I]=FLinearColor(.4f,.55f,.6f);
|
|
if(N>=0&&FMath::IsFinite(N)){double Ms=I==0?1000/FMath::Max(N,.001):N;
|
|
Colors[I]=Ms>33.3334?FLinearColor(1,.34f,.28f):Ms>16.6667?FLinearColor(.98f,.73f,.3f):FLinearColor(.35f,.88f,.83f);}
|
|
}
|
|
}
|
|
int32 UIronsPerformanceOverlay::NativePaint(const FPaintArgs& Args,const FGeometry& G,const FSlateRect& Cull,FSlateWindowElementList& Out,int32 Layer,const FWidgetStyle& Style,bool Enabled)const
|
|
{
|
|
int32 Z=Super::NativePaint(Args,G,Cull,Out,Layer,Style,Enabled);
|
|
auto H=GetGameInstance<UIronsGameInstance>();if(!H||!H->bShowPerformance)return Z;
|
|
const auto L=FIronsPerformanceLayout::Make(G.GetLocalSize(),true,H->PerformanceCorner);const float S=L.PanelScale;
|
|
auto Geo=[&](float X,float Y,float W,float Height){return G.ToPaintGeometry(FVector2D(W,Height)*S,FSlateLayoutTransform(FVector2D(L.Panel.Left,L.Panel.Top)+FVector2D(X,Y)*S));};
|
|
FSlateDrawElement::MakeBox(Out,++Z,Geo(0,0,660,72),FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),ESlateDrawEffect::None,FLinearColor(.012f,.025f,.033f,.94f));
|
|
FSlateDrawElement::MakeBox(Out,++Z,Geo(0,0,3,72),FCoreStyle::Get().GetBrush(TEXT("WhiteBrush")),ESlateDrawEffect::None,FLinearColor(.25f,.7f,.7f));
|
|
auto DrawText=[&](float X,float Y,float Width,const FString& Text,int32 Size,FLinearColor Color){
|
|
FSlateFontInfo Info(PerformanceFont(),FMath::Max(1,Size));
|
|
Out.PushClip(FSlateClippingZone(Geo(X,Y,Width,25)));
|
|
FSlateDrawElement::MakeText(Out,++Z,Geo(X,Y,Width,25),Text,Info,ESlateDrawEffect::None,Color);
|
|
Out.PopClip();
|
|
};
|
|
for(int32 I=0;I<6;++I){float X=14+(I%3)*216,Y=9+(I/3)*32;
|
|
DrawText(X,Y,96,Labels[I],LabelSizes[I],FLinearColor(.7f,.8f,.83f));
|
|
DrawText(X+102,Y-1,106,Values[I],ValueSizes[I],Colors[I]);
|
|
}
|
|
return Z;
|
|
}
|