1043 lines
25 KiB
C++
1043 lines
25 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
#include "STextureHistogram.h"
|
|
#include "Widgets/Layout/SScaleBox.h"
|
|
#include "Materials/Material.h"
|
|
#include <Materials/MaterialInstanceDynamic.h>
|
|
#include <Styling/SlateBrush.h>
|
|
#include <Widgets/SOverlay.h>
|
|
#include <Widgets/Images/SImage.h>
|
|
#include <Widgets/Text/STextBlock.h>
|
|
#include <Widgets/Layout/SBox.h>
|
|
#include <Widgets/SBoxPanel.h>
|
|
#include <Brushes/SlateDynamicImageBrush.h>
|
|
#include "Framework/Application/SlateApplication.h"
|
|
|
|
void STextureHistogram::Construct(const FArguments& InArgs)
|
|
{
|
|
bDrawCombined = InArgs._DrawLayout == ETextureHistogramLayout::Combined;
|
|
bDrawBars = InArgs._DrawStyle == ETextureHistogramStyle::Bar;
|
|
|
|
if (bDrawCombined)
|
|
{
|
|
if (bDrawBars)
|
|
{
|
|
DrawCombineBarHistogram(InArgs);
|
|
}
|
|
else DrawCombineHistogramCurves(InArgs);
|
|
}
|
|
else
|
|
{
|
|
if (bDrawBars)
|
|
{
|
|
DrawSplitBarHistogram(InArgs);
|
|
}
|
|
else DrawSplitHistogramCurves(InArgs);
|
|
}
|
|
}
|
|
|
|
void STextureHistogram::DrawCombineHistogramCurves(const FArguments& InArgs)
|
|
{
|
|
ChildSlot
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SAssignNew(ReferenceLinesCombine, STextureHistogramReferenceLines)
|
|
.Color(InArgs._ScaleLineColor)
|
|
.Height(InArgs._Height)
|
|
.Label("RGB Channels, Luminance")
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SAssignNew(HistogramCurveR, STextureHistogramCurve)
|
|
.bShadeCurve(true)
|
|
.LineColor(InArgs._RCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SAssignNew(HistogramCurveG, STextureHistogramCurve)
|
|
.bShadeCurve(true)
|
|
.LineColor(InArgs._GCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SAssignNew(HistogramCurveA, STextureHistogramCurve)
|
|
.bShadeCurve(true)
|
|
.LineColor(InArgs._ACurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SAssignNew(HistogramCurveB, STextureHistogramCurve)
|
|
.bShadeCurve(true)
|
|
.LineColor(InArgs._BCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
];
|
|
}
|
|
|
|
void STextureHistogram::DrawSplitHistogramCurves(const FArguments& InArgs)
|
|
{
|
|
ChildSlot
|
|
[
|
|
SAssignNew(SplitBox,SVerticalBox)
|
|
|
|
+
|
|
|
|
SVerticalBox::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.FillHeight(0.25f)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SNew(SOverlay)
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(ReferenceLinesR, STextureHistogramReferenceLines)
|
|
.Color(InArgs._ScaleLineColor)
|
|
.Height(InArgs._Height)
|
|
.Label("R - Channel")
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(HistogramCurveR, STextureHistogramCurve)
|
|
.bShadeCurve(true)
|
|
.LineColor(InArgs._RCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
]
|
|
|
|
+
|
|
|
|
SVerticalBox::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.FillHeight(0.25f)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(ReferenceLinesG, STextureHistogramReferenceLines)
|
|
.Color(InArgs._ScaleLineColor)
|
|
.Height(InArgs._Height)
|
|
.Label("G - Channel")
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(HistogramCurveG, STextureHistogramCurve)
|
|
.bShadeCurve(true)
|
|
.LineColor(InArgs._GCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
]
|
|
|
|
+
|
|
|
|
SVerticalBox::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.FillHeight(0.25f)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(ReferenceLinesB, STextureHistogramReferenceLines)
|
|
.Color(InArgs._ScaleLineColor)
|
|
.Height(InArgs._Height)
|
|
.Label("B - Channel")
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(HistogramCurveB, STextureHistogramCurve)
|
|
.bShadeCurve(true)
|
|
.LineColor(InArgs._BCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
]
|
|
|
|
+
|
|
|
|
SVerticalBox::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.FillHeight(0.25f)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(ReferenceLinesA, STextureHistogramReferenceLines)
|
|
.Color(InArgs._ScaleLineColor)
|
|
.Height(InArgs._Height)
|
|
.Label("Luminance")
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(HistogramCurveA, STextureHistogramCurve)
|
|
.bShadeCurve(true)
|
|
.LineColor(InArgs._ACurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
void STextureHistogram::DrawCombineBarHistogram(const FArguments& InArgs)
|
|
{
|
|
ChildSlot
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SAssignNew(ReferenceLinesCombine, STextureHistogramReferenceLines)
|
|
.Color(InArgs._ScaleLineColor)
|
|
.Height(InArgs._Height)
|
|
.Label("RGB Channels, Luminance")
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SAssignNew(HistogramBarsR, STextureHistogramBars)
|
|
.ShadeColor(InArgs._RCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SAssignNew(HistogramBarsG, STextureHistogramBars)
|
|
.ShadeColor(InArgs._GCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SAssignNew(HistogramBarsB, STextureHistogramBars)
|
|
.ShadeColor(InArgs._BCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SAssignNew(HistogramBarsA, STextureHistogramBars)
|
|
.ShadeColor(InArgs._ACurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
];
|
|
}
|
|
|
|
void STextureHistogram::DrawSplitBarHistogram(const FArguments& InArgs)
|
|
{
|
|
ChildSlot
|
|
[
|
|
SNew(SVerticalBox)
|
|
|
|
+
|
|
|
|
SVerticalBox::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(ReferenceLinesR, STextureHistogramReferenceLines)
|
|
.Color(InArgs._ScaleLineColor)
|
|
.Height(InArgs._Height)
|
|
.Label("R - Channel")
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(HistogramBarsR, STextureHistogramBars)
|
|
.ShadeColor(InArgs._RCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
]
|
|
|
|
+
|
|
|
|
SVerticalBox::Slot()
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(ReferenceLinesG, STextureHistogramReferenceLines)
|
|
.Color(InArgs._ScaleLineColor)
|
|
.Height(InArgs._Height)
|
|
.Label("G - Channel")
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(HistogramBarsG, STextureHistogramBars)
|
|
.ShadeColor(InArgs._GCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
]
|
|
|
|
+
|
|
|
|
SVerticalBox::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(ReferenceLinesB, STextureHistogramReferenceLines)
|
|
.Color(InArgs._ScaleLineColor)
|
|
.Height(InArgs._Height)
|
|
.Label("B - Channel")
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(HistogramBarsB, STextureHistogramBars)
|
|
.ShadeColor(InArgs._BCurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
]
|
|
|
|
+
|
|
|
|
SVerticalBox::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
.VAlign(VAlign_Fill)
|
|
.Padding(TextureHistogramUtils::Margin)
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(ReferenceLinesA, STextureHistogramReferenceLines)
|
|
.Color(InArgs._ScaleLineColor)
|
|
.Height(InArgs._Height)
|
|
.Label("Luminance")
|
|
]
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SAssignNew(HistogramBarsA, STextureHistogramBars)
|
|
.ShadeColor(InArgs._ACurveColor)
|
|
.Height(InArgs._Height)
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
void STextureHistogram::SetHistogramData(TArray<FVector4> InHistogramData)
|
|
{
|
|
HistogramData = InHistogramData;
|
|
|
|
if (bDrawBars)
|
|
{
|
|
HistogramBarsR->SetHistogramData(GetRValues());
|
|
HistogramBarsG->SetHistogramData(GetGValues());
|
|
HistogramBarsB->SetHistogramData(GetBValues());
|
|
HistogramBarsA->SetHistogramData(GetLuminanceValues());
|
|
|
|
if (bDrawCombined)
|
|
{
|
|
int MaxBin = GetMaxBin();
|
|
HistogramBarsR->SetMax(MaxBin);
|
|
HistogramBarsG->SetMax(MaxBin);
|
|
HistogramBarsB->SetMax(MaxBin);
|
|
HistogramBarsA->SetMax(MaxBin);
|
|
|
|
ReferenceLinesCombine->SetMax(MaxBin);
|
|
}
|
|
else
|
|
{
|
|
int MaxR = HistogramBarsR->GetMaxBin();
|
|
int MaxG = HistogramBarsG->GetMaxBin();
|
|
int MaxB = HistogramBarsB->GetMaxBin();
|
|
int MaxA = HistogramBarsA->GetMaxBin();
|
|
|
|
HistogramBarsR->SetMax(MaxR);
|
|
HistogramBarsG->SetMax(MaxG);
|
|
HistogramBarsB->SetMax(MaxB);
|
|
HistogramBarsA->SetMax(MaxA);
|
|
|
|
ReferenceLinesR->SetMax(MaxR);
|
|
ReferenceLinesG->SetMax(MaxG);
|
|
ReferenceLinesB->SetMax(MaxB);
|
|
ReferenceLinesA->SetMax(MaxA);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HistogramCurveR->SetHistogramData(GetRValues());
|
|
HistogramCurveG->SetHistogramData(GetGValues());
|
|
HistogramCurveB->SetHistogramData(GetBValues());
|
|
HistogramCurveA->SetHistogramData(GetLuminanceValues());
|
|
|
|
if (bDrawCombined)
|
|
{
|
|
int MaxBin = GetMaxBin();
|
|
HistogramCurveR->SetMax(MaxBin);
|
|
HistogramCurveG->SetMax(MaxBin);
|
|
HistogramCurveB->SetMax(MaxBin);
|
|
HistogramCurveA->SetMax(MaxBin);
|
|
|
|
ReferenceLinesCombine->SetMax(MaxBin);
|
|
}
|
|
else
|
|
{
|
|
int MaxR = HistogramCurveR->GetMaxBin();
|
|
int MaxG = HistogramCurveG->GetMaxBin();
|
|
int MaxB = HistogramCurveB->GetMaxBin();
|
|
int MaxA = HistogramCurveA->GetMaxBin();
|
|
|
|
HistogramCurveR->SetMax(MaxR);
|
|
HistogramCurveG->SetMax(MaxG);
|
|
HistogramCurveB->SetMax(MaxB);
|
|
HistogramCurveA->SetMax(MaxA);
|
|
|
|
ReferenceLinesR->SetMax(MaxR);
|
|
ReferenceLinesG->SetMax(MaxG);
|
|
ReferenceLinesB->SetMax(MaxB);
|
|
ReferenceLinesA->SetMax(MaxA);
|
|
}
|
|
}
|
|
}
|
|
|
|
int STextureHistogram::GetMaxBin()
|
|
{
|
|
int Max = 0;
|
|
for (auto Data : HistogramData)
|
|
{
|
|
Max = FMath::Max3(FMath::Max3(Data.X, Data.Y, Data.Z), Data.W,(double)Max);
|
|
}
|
|
|
|
return Max;
|
|
}
|
|
|
|
TArray<int32> STextureHistogram::GetRValues() const
|
|
{
|
|
TArray<int32> RValues;
|
|
for (auto Data : HistogramData)
|
|
{
|
|
RValues.Add(Data.X);
|
|
}
|
|
|
|
return RValues;
|
|
}
|
|
|
|
TArray<int32> STextureHistogram::GetGValues() const
|
|
{
|
|
TArray<int32> GValues;
|
|
for (auto Data : HistogramData)
|
|
{
|
|
GValues.Add(Data.Y);
|
|
}
|
|
|
|
return GValues;
|
|
}
|
|
|
|
TArray<int32> STextureHistogram::GetBValues() const
|
|
{
|
|
TArray<int32> BValues;
|
|
for (auto Data : HistogramData)
|
|
{
|
|
BValues.Add(Data.Z);
|
|
}
|
|
|
|
return BValues;
|
|
}
|
|
|
|
TArray<int32> STextureHistogram::GetLuminanceValues() const
|
|
{
|
|
TArray<int32> AValues;
|
|
for (auto Data : HistogramData)
|
|
{
|
|
AValues.Add(Data.W);
|
|
}
|
|
|
|
return AValues;
|
|
}
|
|
|
|
void STextureHistogramCurve::Construct(const FArguments& InArgs)
|
|
{
|
|
bShadeCurve = InArgs._bShadeCurve;
|
|
LineColor = InArgs._LineColor;
|
|
ShadeColor = FColor(LineColor.R * 255, LineColor.G * 255, LineColor.B * 255, LineColor.A * 255);
|
|
|
|
ChildSlot
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SNew(SScaleBox)
|
|
.Stretch(EStretch::ScaleToFit)
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(5.0f, InArgs._Height)
|
|
.BorderImage(FCoreStyle::Get().GetBrush("GenericWhiteBox"))
|
|
[
|
|
SAssignNew(Canvas, SCanvas)
|
|
]
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
void STextureHistogramCurve::SetHistogramData(const TArray<int32>& InHistogramData)
|
|
{
|
|
HistogramData = InHistogramData;
|
|
}
|
|
|
|
int STextureHistogramCurve::GetMaxBin()
|
|
{
|
|
int MaxValue = 0;
|
|
for (auto Data : HistogramData)
|
|
{
|
|
MaxValue = FMath::Max(Data,(double)MaxValue);
|
|
}
|
|
|
|
return MaxValue;
|
|
}
|
|
|
|
void STextureHistogramCurve::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
|
|
{
|
|
Canvas->Invalidate(EInvalidateWidget::Layout);
|
|
}
|
|
|
|
int32 STextureHistogramCurve::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
|
|
{
|
|
FSlateWindowElementList& ElementList = OutDrawElements;
|
|
|
|
TArray<int32> Values = HistogramData;
|
|
|
|
DrawHistogramCurve(AllottedGeometry, ElementList, LayerId, Values);
|
|
|
|
return LayerId;
|
|
}
|
|
|
|
void STextureHistogramCurve::DrawHistogramCurve(const FGeometry& AllottedGeometry, FSlateWindowElementList& ElementList, int32 LayerId, TArray<int32> Values) const
|
|
{
|
|
if (Values.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Histogram parameters
|
|
int32 NumBins = Values.Num();
|
|
float MaxBarHeight = AllottedGeometry.GetLocalSize().Y; // Maximum height of the histogram bars
|
|
float BarWidth = AllottedGeometry.GetLocalSize().X / NumBins; // Width of each histogram bar
|
|
|
|
// Normalize histogram counts
|
|
int32 MaxCount = FMath::Max(100,Max);
|
|
TArray<float> NormalizedCounts;
|
|
for (int32 Count : Values)
|
|
{
|
|
float NormalizedCount = Count / static_cast<float>(MaxCount) * MaxBarHeight;
|
|
NormalizedCounts.Add(NormalizedCount);
|
|
}
|
|
|
|
// Calculate data points for the line
|
|
TArray<FVector2D> LinePoints;
|
|
for (int32 BinIndex = 0; BinIndex < NumBins; ++BinIndex)
|
|
{
|
|
float X = BinIndex * BarWidth + BarWidth * 0.5f; // X-coordinate in the middle of each bar
|
|
float Y = MaxBarHeight - NormalizedCounts[BinIndex]; // Y-coordinate based on the normalized count
|
|
LinePoints.Add(FVector2D(X, Y));
|
|
}
|
|
// Calculate data points for shading the area under the curve
|
|
TArray<FVector2D> ShadePoints = LinePoints;
|
|
ShadePoints.Insert(FVector2D(LinePoints[0].X, MaxBarHeight), 0);
|
|
ShadePoints.Add(FVector2D(LinePoints[NumBins-1].X, MaxBarHeight));
|
|
|
|
// Draw histogram line
|
|
FSlateDrawElement::MakeLines(
|
|
ElementList,
|
|
LayerId,
|
|
AllottedGeometry.ToPaintGeometry(),
|
|
ShadePoints,
|
|
ESlateDrawEffect::None,
|
|
LineColor, // Line color
|
|
true,
|
|
2.0
|
|
);
|
|
|
|
if (bShadeCurve)
|
|
{
|
|
DrawShadeForCurve(AllottedGeometry, ElementList, LayerId, ShadePoints);
|
|
}
|
|
}
|
|
|
|
void STextureHistogramCurve::DrawShadeForCurve(const FGeometry& AllottedGeometry, FSlateWindowElementList& ElementList, int32 LayerId,TArray<FVector2D> ShadePoints) const
|
|
{
|
|
// Create a vertex buffer for the filled polygon
|
|
TArray<FSlateVertex> Vertices;
|
|
TArray<SlateIndex> Indices;
|
|
Vertices.Reserve(ShadePoints.Num() * 2);
|
|
Indices.Reserve((ShadePoints.Num()) * 6);
|
|
|
|
int32 StartVertexIndex = 0;
|
|
int32 BottomVertexIndex = ShadePoints.Num() - 1;
|
|
|
|
FVector2D Offset = AllottedGeometry.GetAccumulatedRenderTransform().GetTranslation();
|
|
|
|
for (const FVector2D& Point : ShadePoints)
|
|
{
|
|
auto AbsolutePosition = AllottedGeometry.LocalToAbsolute(Point);
|
|
FSlateVertex Vertex;// = FSlateVertex::Make<ESlateVertexRounding::Disabled>(AllottedGeometry.GetAccumulatedRenderTransform(), +FVector2D(0.5f + SelectionX1 + ArrowSize, 0.5f + ArrowY + ArrowSize) * Scale, AtlasOffset + FVector2D(0.0f, 1.0f) * AtlasUVSize, ArrowFillColor));
|
|
Vertex.Position = AbsolutePosition;//Offset.X + Point.X;
|
|
//Vertex.Position[1] = Offset.Y + Point.Y;
|
|
Vertex.TexCoords[0] = 0;
|
|
Vertex.TexCoords[1] = 0;
|
|
Vertex.TexCoords[2] = Vertex.TexCoords[3] = 1.0f;
|
|
Vertex.Color = ShadeColor;
|
|
Vertices.Emplace(Vertex);
|
|
|
|
FSlateVertex Vertex2;
|
|
FVector2D BasePosition = FVector2D(Point.X, AllottedGeometry.GetLocalSize().Y);
|
|
Vertex2.Position = AllottedGeometry.LocalToAbsolute(BasePosition);
|
|
Vertex2.TexCoords[0] = 0;
|
|
Vertex2.TexCoords[1] = 0;
|
|
Vertex2.TexCoords[2] = Vertex.TexCoords[3] = 1.0f;
|
|
Vertex2.Color = ShadeColor;
|
|
Vertices.Emplace(Vertex2);
|
|
}
|
|
|
|
// Add indices for the filled polygon
|
|
for (int32 Index = 0; Index < Vertices.Num() - 1 ; Index ++)
|
|
{
|
|
Indices.Add(Index);
|
|
Indices.Add(Index + 1);
|
|
Indices.Add(Index + 2);
|
|
}
|
|
|
|
const FSlateBrush* MyBrush = FCoreStyle::Get().GetBrush("GenericWhiteBox");
|
|
FSlateResourceHandle Handle = MyBrush->GetRenderingResource();
|
|
|
|
// Draw filled area under the curve
|
|
FSlateDrawElement::MakeCustomVerts(
|
|
ElementList,
|
|
LayerId,
|
|
Handle,
|
|
Vertices,
|
|
Indices,
|
|
nullptr,
|
|
0,
|
|
0
|
|
);
|
|
}
|
|
|
|
//////////////////////////// STextureHistogramBars ///////////////////////////////////////
|
|
|
|
void STextureHistogramBars::Construct(const FArguments& InArgs)
|
|
{
|
|
ShadeColor = InArgs._ShadeColor;
|
|
|
|
ChildSlot
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SNew(SScaleBox)
|
|
.Stretch(EStretch::ScaleToFit)
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(5.0f, InArgs._Height)
|
|
.BorderImage(FCoreStyle::Get().GetBrush("GenericWhiteBox"))
|
|
[
|
|
SAssignNew(Canvas, SCanvas)
|
|
]
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
void STextureHistogramBars::SetHistogramData(const TArray<int32>& InHistogramData)
|
|
{
|
|
HistogramData = InHistogramData;
|
|
Max = GetMaxBin();
|
|
}
|
|
|
|
int STextureHistogramBars::GetMaxBin()
|
|
{
|
|
int MaxValue = 0;
|
|
for (auto Data : HistogramData)
|
|
{
|
|
MaxValue = FMath::Max(Data, (double)MaxValue);
|
|
}
|
|
|
|
return MaxValue;
|
|
}
|
|
|
|
void STextureHistogramBars::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
|
|
{
|
|
Canvas->Invalidate(EInvalidateWidget::Layout);
|
|
}
|
|
|
|
int32 STextureHistogramBars::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
|
|
{
|
|
FSlateWindowElementList& ElementList = OutDrawElements;
|
|
|
|
TArray<int32> Values = HistogramData;
|
|
|
|
DrawHistogramBars(AllottedGeometry, ElementList, LayerId, Values, ShadeColor);
|
|
return LayerId;
|
|
}
|
|
|
|
void STextureHistogramBars::DrawHistogramBars(const FGeometry& AllottedGeometry, FSlateWindowElementList& ElementList, int32 LayerId, TArray<int32> Values, FLinearColor BarColor) const
|
|
{
|
|
/// Histogram parameters
|
|
int32 NumBins = Values.Num();
|
|
float MaxBarHeight = AllottedGeometry.GetLocalSize().Y; // Maximum height of the histogram bars
|
|
float BarWidth = AllottedGeometry.GetLocalSize().X / NumBins; // Width of each histogram bar
|
|
|
|
// Normalize histogram counts
|
|
int32 MaxCount = FMath::Max(100, Max);//*TArray<TOptional<int32>>::Max(HistogramData);
|
|
TArray<float> NormalizedCounts;
|
|
for (int32 Count : Values)
|
|
{
|
|
float NormalizedCount = Count / static_cast<float>(MaxCount) * MaxBarHeight;
|
|
NormalizedCounts.Add(NormalizedCount);
|
|
}
|
|
|
|
const FSlateBrush* MyBrush = FCoreStyle::Get().GetBrush("GenericWhiteBox");//new FSlateColorBrush(FColor(1,1,1, BarColor.A));
|
|
FLinearColor BarTint = FLinearColor(BarColor.R, BarColor.G, BarColor.B, BarColor.A);
|
|
|
|
// Draw histogram bars
|
|
FVector2D BarPosition(0.0f, MaxBarHeight);
|
|
for (int32 BinIndex = 0; BinIndex < NumBins; ++BinIndex)
|
|
{
|
|
FSlateDrawElement::MakeBox(
|
|
ElementList,
|
|
LayerId,
|
|
AllottedGeometry.ToPaintGeometry( FVector2D(BarWidth, NormalizedCounts[BinIndex]), FSlateLayoutTransform(FVector2D(BarPosition.X, MaxBarHeight - NormalizedCounts[BinIndex]))),
|
|
MyBrush,
|
|
ESlateDrawEffect::None,
|
|
BarTint // Bar color
|
|
);
|
|
|
|
BarPosition.X += BarWidth;
|
|
}
|
|
}
|
|
|
|
////////////////// STextureHistogramReferenceLines ///////////////////////////////////////////////
|
|
|
|
void STextureHistogramReferenceLines::Construct(const FArguments& InArgs)
|
|
{
|
|
Color = InArgs._Color;
|
|
NumBins = InArgs._NumBins;
|
|
NumHorizontalScaleLines = InArgs._NumHorizontalScaleLines;
|
|
NumVerticalScaleLines = InArgs._NumVerticalScaleLines;
|
|
bDraw = InArgs._bDraw;
|
|
bDrawBackground = InArgs._bDrawBackground;
|
|
Label = InArgs._Label;
|
|
|
|
ChildSlot
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
+
|
|
|
|
SOverlay::Slot()
|
|
[
|
|
SNew(SScaleBox)
|
|
.Stretch(EStretch::ScaleToFit)
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(5.0f, InArgs._Height)
|
|
.BorderImage(FCoreStyle::Get().GetBrush("GenericWhiteBox"))
|
|
[
|
|
SAssignNew(Canvas, SCanvas)
|
|
]
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
void STextureHistogramReferenceLines::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
|
|
{
|
|
Canvas->Invalidate(EInvalidateWidget::Layout);
|
|
}
|
|
|
|
int32 STextureHistogramReferenceLines::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
|
|
{
|
|
FSlateWindowElementList& ElementList = OutDrawElements;
|
|
|
|
if (bDraw)
|
|
{
|
|
DrawReferenceLines(AllottedGeometry, ElementList, LayerId);
|
|
}
|
|
|
|
return LayerId;
|
|
}
|
|
|
|
void STextureHistogramReferenceLines::DrawReferenceLines(const FGeometry& AllottedGeometry, FSlateWindowElementList& ElementList, int32 LayerId) const
|
|
{
|
|
// Histogram parameters
|
|
int32 TotalBins = NumBins;
|
|
float MaxBarHeight = AllottedGeometry.GetLocalSize().Y; // Maximum height of the histogram bars
|
|
float BarWidth = AllottedGeometry.GetLocalSize().X / TotalBins; // Width of each histogram bar
|
|
|
|
// Normalize histogram counts
|
|
int32 MaxCount = FMath::Max(100, Max);
|
|
|
|
//Draw ReferenceLine
|
|
float ReferenceValue1 = MaxBarHeight;
|
|
float ReferenceValue2 = MaxBarHeight;
|
|
TArray<FVector2D> ReferenceLinePoints;
|
|
ReferenceLinePoints.Add(FVector2D(0.0f, 0.0f));
|
|
ReferenceLinePoints.Add(FVector2D(0.0f, ReferenceValue1));
|
|
ReferenceLinePoints.Add(FVector2D(AllottedGeometry.GetLocalSize().X, ReferenceValue1));
|
|
|
|
FSlateDrawElement::MakeLines(
|
|
ElementList,
|
|
LayerId,
|
|
AllottedGeometry.ToPaintGeometry(),
|
|
ReferenceLinePoints,
|
|
ESlateDrawEffect::None,
|
|
FLinearColor::White // Reference line color
|
|
);
|
|
|
|
// Draw vertical small reference lines
|
|
int32 NumReferenceLines = NumVerticalScaleLines; // Number of reference lines to draw
|
|
for (int32 LineIndex = 0; LineIndex < NumReferenceLines; ++LineIndex)
|
|
{
|
|
int Count = (MaxCount * (LineIndex + 1) / NumReferenceLines);
|
|
float Y = MaxBarHeight - (MaxBarHeight * (float)Count / MaxCount);
|
|
|
|
TArray<FVector2D> Points =
|
|
{
|
|
FVector2D(0.0f, Y),
|
|
FVector2D(-5, Y)
|
|
};
|
|
FSlateDrawElement::MakeLines(
|
|
ElementList,
|
|
LayerId,
|
|
AllottedGeometry.ToPaintGeometry(),
|
|
Points,
|
|
ESlateDrawEffect::None,
|
|
FLinearColor::White // Reference line color
|
|
);
|
|
|
|
//Full fadded Background Line
|
|
if (bDrawBackground)
|
|
{
|
|
auto FadeWhite = FLinearColor::White;
|
|
FadeWhite.A = 0.1f;
|
|
TArray<FVector2D> Points2 =
|
|
{
|
|
FVector2D(0.0f, Y),
|
|
FVector2D(AllottedGeometry.GetLocalSize().X, Y)
|
|
};
|
|
FSlateDrawElement::MakeLines(
|
|
ElementList,
|
|
LayerId,
|
|
AllottedGeometry.ToPaintGeometry(),
|
|
Points2,
|
|
ESlateDrawEffect::PreMultipliedAlpha,
|
|
FadeWhite // Reference line color
|
|
);
|
|
}
|
|
|
|
|
|
FString UnitText = FString::Printf(TEXT("%d"), Count);
|
|
|
|
//Format Count to use small values for large numbers
|
|
if (Count / 1000 > 0)
|
|
{
|
|
UnitText = FString::Printf(TEXT("%d K"), Count / 1000);
|
|
}
|
|
|
|
FSlateFontInfo FontInfo = FCoreStyle::GetDefaultFontStyle("Regular", 6);
|
|
FVector2D TextSize = FSlateApplication::Get().GetRenderer()->GetFontMeasureService()->Measure(UnitText, FontInfo);
|
|
FVector2D TextPosition = FVector2D( -TextSize.X - 5.0f, Y - TextSize.Y * 0.5f);
|
|
FSlateDrawElement::MakeText(
|
|
ElementList,
|
|
LayerId,
|
|
AllottedGeometry.ToPaintGeometry(TextSize,FSlateLayoutTransform(TextPosition)),
|
|
UnitText,
|
|
FontInfo,
|
|
ESlateDrawEffect::None,
|
|
FLinearColor::White // Text color
|
|
);
|
|
}
|
|
|
|
// Draw Horizontal small reference lines
|
|
NumReferenceLines = NumHorizontalScaleLines;//NumBins / 32; // Number of reference lines to draw
|
|
for (int32 LineIndex = 0; LineIndex < NumReferenceLines; ++LineIndex)
|
|
{
|
|
float X = (AllottedGeometry.GetLocalSize().X * (LineIndex + 1) / NumReferenceLines);
|
|
float Y = -5;
|
|
TArray<FVector2D> Points =
|
|
{
|
|
FVector2D(X, MaxBarHeight),
|
|
FVector2D(X, MaxBarHeight - Y)
|
|
};
|
|
FSlateDrawElement::MakeLines(
|
|
ElementList,
|
|
LayerId,
|
|
AllottedGeometry.ToPaintGeometry(),
|
|
Points,
|
|
ESlateDrawEffect::None,
|
|
FLinearColor::White // Reference line color
|
|
);
|
|
|
|
//Full fadded Background Line
|
|
|
|
if (bDrawBackground)
|
|
{
|
|
auto FadeWhite = FLinearColor::White;
|
|
FadeWhite.A = 0.1f;
|
|
TArray<FVector2D> Points2 =
|
|
{
|
|
FVector2D(X, MaxBarHeight),
|
|
FVector2D(X, 0)
|
|
};
|
|
FSlateDrawElement::MakeLines(
|
|
ElementList,
|
|
LayerId,
|
|
AllottedGeometry.ToPaintGeometry(),
|
|
Points2,
|
|
ESlateDrawEffect::PreMultipliedAlpha,
|
|
FadeWhite // Reference line color
|
|
);
|
|
}
|
|
|
|
FString UnitText = FString::Printf(TEXT("%d"), (TotalBins * (LineIndex + 1) / NumReferenceLines));
|
|
FSlateFontInfo FontInfo = FCoreStyle::GetDefaultFontStyle("Regular", 6);
|
|
FVector2D TextSize = FSlateApplication::Get().GetRenderer()->GetFontMeasureService()->Measure(UnitText, FontInfo);
|
|
FVector2D TextPosition = FVector2D( X - (TextSize.X * 0.5f), MaxBarHeight - (Y * 2) - TextSize.Y * 0.5f);
|
|
FSlateDrawElement::MakeText(
|
|
ElementList,
|
|
LayerId,
|
|
AllottedGeometry.ToPaintGeometry(TextSize, FSlateLayoutTransform(TextPosition)),
|
|
UnitText,
|
|
FontInfo,
|
|
ESlateDrawEffect::None,
|
|
FLinearColor::White // Text color
|
|
);
|
|
}
|
|
|
|
//Label below the reference line
|
|
FString UnitText = Label;
|
|
FSlateFontInfo FontInfo = FCoreStyle::GetDefaultFontStyle("Bold", 8);
|
|
FVector2D TextSize = FSlateApplication::Get().GetRenderer()->GetFontMeasureService()->Measure(UnitText, FontInfo);
|
|
FVector2D TextPosition = FVector2D((AllottedGeometry.GetLocalSize().X / 2) - (TextSize.X * 0.5f), MaxBarHeight + 25 - (TextSize.Y * 0.5f));
|
|
FSlateDrawElement::MakeText(
|
|
ElementList,
|
|
LayerId,
|
|
AllottedGeometry.ToPaintGeometry(TextSize, FSlateLayoutTransform(TextPosition)),
|
|
UnitText,
|
|
FontInfo,
|
|
ESlateDrawEffect::None,
|
|
FLinearColor::White // Text color
|
|
);
|
|
} |