// Fill out your copyright notice in the Description page of Project Settings.
#include "SmoothLineWidget.h"
#include "Components/CanvasPanelSlot.h"
int32 USmoothLineWidget::NativePaint(const FPaintArgs& Args,
const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect,
FSlateWindowElementList& OutDrawElements,
int32 LayerId,
const FWidgetStyle& InWidgetStyle,
bool bParentEnabled) const
{
PaintSmoothLine(OutDrawElements, AllottedGeometry, LayerId, MultiPoint, LineThickness, LineColor);
PaintCustomVertex(OutDrawElements, AllottedGeometry, LayerId, MultiPoint, UnderLineColor);
//PaintDKERLine(OutDrawElements, AllottedGeometry, LayerId, LineThickness, LineColor);
DrawSpline(OutDrawElements, AllottedGeometry, LayerId, aPositionA, aPositionB, LineColor);
return LayerId++;
}
void USmoothLineWidget::DrawSpline(FSlateWindowElementList& WindowElements,
const FGeometry& Geometry,
int32 LayerId,
FVector2D PositionA,
FVector2D PositionB,
FColor Color) const {
TArray<FVector2D> SplinePosition;
for (int32 Lerping = 0; Lerping < 100; Lerping++) {
FVector2D HelpPosition = FVector2D(PositionA.X, PositionB.Y);
float AHelpPositionY = (PositionB.Y - PositionA.Y) * Lerping / 100;
float HelpBPositionX = (PositionB.X - PositionA.X) * Lerping / 100;
FVector2D AHelpPosition = FVector2D(PositionA.X, PositionA.Y + AHelpPositionY);
FVector2D HelpBPosition = FVector2D(HelpBPositionX, PositionB.Y);
float ResX = PositionA.X + (HelpBPositionX - PositionA.X) * Lerping / 100;
float ResY = PositionB.Y + (PositionB.Y - AHelpPositionY) * Lerping / 100;
FVector2D ResPosition = FVector2D(ResX, ResY);
SplinePosition.Add(ResPosition);
}
PaintSmoothLine(WindowElements, Geometry, LayerId, SplinePosition, LineThickness, Color);
}
void USmoothLineWidget::PaintPoint(FSlateWindowElementList& WindowElements,
const FGeometry& Geometry,
int32 LayerId,
FVector2D Position,
FColor Color) const {
TArray<FSlateVertex> VertexArray;
TArray<SlateIndex> Indexes;
FVector2D LeftTopPos = FVector2D(Position.X - 2, Position.Y - 2);
FVector2D RightTopPos = FVector2D(Position.X + 2, Position.Y - 2);
FVector2D LeftDownPos = FVector2D(Position.X - 2, Position.Y + 2);
FVector2D RightDownPos = FVector2D(Position.X + 2, Position.Y + 2);
const FSlateBrush* Brush = FCoreStyle::Get().GetBrush("ColorSpectrum.Speturm");
const FSlateRenderTransform& SlateRenderTransform = Geometry.ToPaintGeometry().GetAccumulatedRenderTransform();
LeftTopPos = SlateRenderTransform.TransformPoint(LeftTopPos);
RightTopPos = SlateRenderTransform.TransformPoint(RightTopPos);
LeftDownPos = SlateRenderTransform.TransformPoint(LeftDownPos);
RightDownPos = SlateRenderTransform.TransformPoint(RightDownPos);
FSlateVertex LeftTopVertex;
FSlateVertex RightTopVertex;
FSlateVertex LeftDownVertex;
FSlateVertex RightDownVertex;
LeftTopVertex.Position = LeftTopPos;
RightTopVertex.Position = RightTopPos;
LeftDownVertex.Position = LeftDownPos;
RightDownVertex.Position = RightDownPos;
LeftTopVertex.Color = Color;
RightTopVertex.Color = Color;
LeftDownVertex.Color = Color;
RightDownVertex.Color = Color;
int32 LeftTopIndex = VertexArray.Add(LeftTopVertex);
int32 RightTopIndex = VertexArray.Add(RightTopVertex);
int32 LeftDownIndex = VertexArray.Add(LeftDownVertex);
int32 RightDownIndex = VertexArray.Add(RightDownVertex);
Indexes.Add(LeftTopIndex);
Indexes.Add(RightTopIndex);
Indexes.Add(LeftDownIndex);
Indexes.Add(RightTopIndex);
Indexes.Add(LeftDownIndex);
Indexes.Add(RightDownIndex);
for (FSlateVertex& SlateVertex : VertexArray)
{
SlateVertex.TexCoords[0] = 0.f;
SlateVertex.TexCoords[1] = 0.f;
}
FSlateResourceHandle ResourceHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(*Brush);
FSlateDrawElement::MakeCustomVerts(WindowElements, LayerId, ResourceHandle, VertexArray, Indexes, nullptr, 0, 0);
}
void USmoothLineWidget::PaintDKERLine(FSlateWindowElementList& WindowElements,
const FGeometry& Geometry,
int32 LayerId,
float Thickness,
FColor Color) const {
float WidgetWidth;
float WidgetHeight;
UCanvasPanelSlot* CanvasSlot = Cast<UCanvasPanelSlot>(this->Slot);
if (CanvasSlot->IsValidLowLevel()) {
WidgetWidth = CanvasSlot->GetSize().X;
WidgetHeight = CanvasSlot->GetSize().Y;
}
TArray<FVector2D> Points;
Points.Add(FVector2D(0, 0));
Points.Add(FVector2D(0, WidgetHeight));
Points.Add(FVector2D(WidgetWidth, 0));
PaintSmoothLine(WindowElements, Geometry, LayerId, Points, LineThickness, Color);
}
void USmoothLineWidget::PaintSmoothLine(FSlateWindowElementList& WindowElements,
const FGeometry& Geometry,
int32 LayerId,
TArray<FVector2D> MultiPoints,
float Thickness,
FColor Color) const
{
if (MultiPoints.Num() < 2 || Thickness <= 0) return;//如果
FRichCurve* RichCurve = new FRichCurve();
for (FVector2D InPoint : MultiPoints)
{
PaintPoint(WindowElements, Geometry, LayerId, InPoint, Color);
FKeyHandle KeyHandle = RichCurve->AddKey(InPoint.X, InPoint.Y);
if (isCull) RichCurve->SetKeyInterpMode(KeyHandle, RCIM_Cubic);
else RichCurve->SetKeyInterpMode(KeyHandle, RCIM_Linear);
}
float WidgetWidth;
UCanvasPanelSlot* CanvasPanelSlot = Cast<UCanvasPanelSlot>(this->Slot);
if (CanvasPanelSlot->IsValidLowLevel())
{
WidgetWidth = CanvasPanelSlot->GetSize().X;
}
else
{
return;
}
TArray<FVector2D> ResultPoints;
int32 Begin = 0;
int32 End = WidgetWidth;
for (float X = 0; X < WidgetWidth; X++)
{
float Y = RichCurve->Eval(X);
FVector2D ResultPoint(X, Y);
ResultPoints.Add(ResultPoint);
}
delete RichCurve;
FSlateDrawElement::MakeLines(WindowElements, LayerId, Geometry.ToPaintGeometry(), ResultPoints, ESlateDrawEffect::None, Color, true, Thickness);
}
void USmoothLineWidget::PaintCustomVertex(FSlateWindowElementList& WindowElements,
const FGeometry& Geometry,
int32 LayerId,
TArray<FVector2D> MultiPoints,
FColor Color) const {
TArray<FSlateVertex> CustomVertArray;
TArray<SlateIndex> SlateIndexes;
const FSlateBrush* Brush = FCoreStyle::Get().GetBrush("ColorSpectrum.Speturm");
const FSlateRenderTransform& SlateRenderTransform = Geometry.ToPaintGeometry().GetAccumulatedRenderTransform();
UCanvasPanelSlot* CanvasPanelSlot = Cast<UCanvasPanelSlot>(this->Slot);
float WidgetWidth;
float WidgetHeight;
if (CanvasPanelSlot->IsValidLowLevel())
{
WidgetWidth = CanvasPanelSlot->GetSize().X;
WidgetHeight = CanvasPanelSlot->GetSize().Y;
}
FSlateVertex FirstVertex;
FirstVertex.Position = SlateRenderTransform.TransformPoint(FVector2D(0, 0));
FirstVertex.Color = Color;
int32 Index = CustomVertArray.Add(FirstVertex);
SlateIndexes.Add(Index);
FSlateVertex SecondVertex;
SecondVertex.Color = Color;
if (MultiPoints.Num() > 0) {
SecondVertex.Position = SlateRenderTransform.TransformPoint(FVector2D(MultiPoints[1].X, 0));
Index = CustomVertArray.Add(SecondVertex);
SlateIndexes.Add(Index);
}
FSlateVertex ThirdVertex;
ThirdVertex.Color = Color;
if (MultiPoints.Num() > 0) {
ThirdVertex.Position = SlateRenderTransform.TransformPoint(FVector2D(MultiPoints[1].X, MultiPoints[1].Y));
Index = CustomVertArray.Add(ThirdVertex);
SlateIndexes.Add(Index);
}
for (int32 i = 1; i < MultiPoints.Num() - 1; i++) {
FVector2D tempOne = SlateRenderTransform.TransformPoint(MultiPoints[i]);
FSlateVertex OneVertex;
OneVertex.Position = tempOne;
OneVertex.Color = Color;
int32 Index1 = CustomVertArray.Add(OneVertex);
FVector2D tempTwo = SlateRenderTransform.TransformPoint(MultiPoints[i + 1]);
FSlateVertex TwoVertex;
TwoVertex.Position = tempTwo;
TwoVertex.Color = Color;
int32 Index2 = CustomVertArray.Add(TwoVertex);
FSlateVertex ThreeVertex;
ThreeVertex.Position = SlateRenderTransform.TransformPoint(FVector2D(MultiPoints[i].X, 0));
ThreeVertex.Color = Color;
int32 Index3 = CustomVertArray.Add(ThreeVertex);
FSlateVertex FourVertex;
FourVertex.Position = SlateRenderTransform.TransformPoint(FVector2D(MultiPoints[i + 1].X, 0));
FourVertex.Color = Color;
int32 Index4 = CustomVertArray.Add(FourVertex);
SlateIndexes.Add(Index1);
SlateIndexes.Add(Index2);
SlateIndexes.Add(Index3);
SlateIndexes.Add(Index4);
SlateIndexes.Add(Index3);
SlateIndexes.Add(Index2);
}
FSlateVertex FinalVertex;
FVector2D tempOne = SlateRenderTransform.TransformPoint(MultiPoints[MultiPoints.Num() - 1]);
FinalVertex.Position = tempOne;
FinalVertex.Color = Color;
int32 Index1 = CustomVertArray.Add(FinalVertex);
int32 Index2 = 0;
FSlateVertex FinalVertex1;
if (MultiPoints.Num() > 0) {
FVector2D tempTwo = SlateRenderTransform.TransformPoint(FVector2D(WidgetWidth, MultiPoints[MultiPoints.Num() - 1].Y));
FinalVertex1.Position = tempTwo;
FinalVertex1.Color = Color;
Index2 = CustomVertArray.Add(FinalVertex1);
}
FSlateVertex FinalVertex2;
FVector2D tempThree = SlateRenderTransform.TransformPoint(FVector2D(MultiPoints[MultiPoints.Num() - 1].X, 0));
FinalVertex2.Position = tempThree;
FinalVertex2.Color = Color;
int32 Index3 = CustomVertArray.Add(FinalVertex2);
int32 Index4 = 0;
FSlateVertex FinalVertex3;
if (MultiPoints.Num() > 0) {
FVector2D tempFour = SlateRenderTransform.TransformPoint(FVector2D(WidgetWidth, 0));
FinalVertex3.Position = tempFour;
FinalVertex3.Color = Color;
Index4 = CustomVertArray.Add(FinalVertex3);
}
SlateIndexes.Add(Index1);
SlateIndexes.Add(Index2);
SlateIndexes.Add(Index3);
SlateIndexes.Add(Index3);
SlateIndexes.Add(Index4);
SlateIndexes.Add(Index2);
for (FSlateVertex& SlateVertex : CustomVertArray)
{
SlateVertex.TexCoords[0] = 0.f;
SlateVertex.TexCoords[1] = 0.f;
}
FSlateResourceHandle ResourceHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(*Brush);
FSlateDrawElement::MakeCustomVerts(WindowElements, LayerId, ResourceHandle, CustomVertArray, SlateIndexes, nullptr, 0, 0);
}
void USmoothLineWidget::SetValues(TArray<float> Values)
{
if (Values.Num() < 2) return;
MultiPoint.Empty();
UCanvasPanelSlot* CanvasPanelSlot = Cast<UCanvasPanelSlot>(this->Slot);
float WidgetWidth;
float WidgetHeight;
if (CanvasPanelSlot->IsValidLowLevel())
{
WidgetHeight = CanvasPanelSlot->GetSize().Y;
WidgetWidth = CanvasPanelSlot->GetSize().X;
}
else
{
return;
}
float Space = WidgetWidth / (Values.Num() - 1);
for (int32 Index = 0; Index < Values.Num(); Index++)
{
FVector2D KeyPosition(Space * Index, WidgetHeight - Values[Index]);
MultiPoint.Add(KeyPosition);
}
}
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "SmoothLineWidget.generated.h"
/**
*
*/
UCLASS()
class TEST_API USmoothLineWidget : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void SetValues(TArray<float> Values);
protected:
virtual int32 NativePaint(const FPaintArgs& Args,
const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect,
FSlateWindowElementList& OutDrawElements,
int32 LayerId,
const FWidgetStyle& InWidgetStyle,
bool bParentEnabled) const override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 10))
float LineThickness;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 360))
FColor LineColor;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 360))
FColor UnderLineColor;
/*UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<float> PointValues;*/
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool isCull;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<FVector2D> MultiPoint;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FVector2D aPositionA;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FVector2D aPositionB;
private:
void PaintCustomVertex(FSlateWindowElementList& WindowElements,
const FGeometry& Geometry,
int32 LayerId,
TArray<FVector2D> MultiPoints,
FColor Color) const;
void PaintSmoothLine(FSlateWindowElementList& WindowElements,
const FGeometry& Geometry,
int32 LayerId,
TArray<FVector2D> MultiPoints,
float Thickness,
FColor Color) const;
void PaintDKERLine(FSlateWindowElementList& WindowElements,
const FGeometry& Geometry,
int32 LayerId,
float Thickness,
FColor Color) const;
void PaintPoint(FSlateWindowElementList& WindowElements,
const FGeometry& Geometry,
int32 LayerId,
FVector2D Position,
FColor Color) const;
void DrawSpline(FSlateWindowElementList& WindowElements,
const FGeometry& Geometry,
int32 LayerId,
FVector2D PositionA,
FVector2D PositionB,
FColor Color) const;
};