UE4 UI画曲线

// 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;
};

猜你喜欢

转载自blog.csdn.net/qqQQqsadfj/article/details/129670707