UE4C++UI平滑曲线图绘制
- 前言
UE4的曲线在UMG上面绘制的时候总是和麻烦的,这里我们借用UE4曲线FRichCurve,向其中传入对应的Key值,然后差值获取俩个点之间的数据,然后将所有点连接则是对应的平滑曲线。(此处没计算,用的FRichCurve中所自带点的计算),逻辑比较简单,在此不过多赘述。
需要添加模块: "SlateCore", "UMG"
才能编译成功
附源码:
- .h文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "SmoothedLineWidget.generated.h"
/**
*
*/
UCLASS()
class SPECIALCHART_API USmoothedLineWidget : public UUserWidget
{
GENERATED_BODY()
public:
USmoothedLineWidget(const FObjectInitializer& ObjectInitializer);
UFUNCTION(BlueprintCallable)
void SetValues(TArray<float> InValues);//计算对应的key值,默认在绘制前已调用
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FVector2D Size= FVector2D(100,100);//大小
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FVector2D Locationn = FVector2D(100, 100);//位置
UPROPERTY(EditAnywhere,BlueprintReadWrite)
float BrushSize=5;//笔刷大小
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FColor Color;//颜色
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<float> Values;//传入的线对应的值
virtual void NativePreConstruct() override;
protected:
virtual int32 NativePaint(
const FPaintArgs& Args,
const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect,
FSlateWindowElementList& OutDrawElements,
int32 LayerId,
const FWidgetStyle& InWidgetStyle,
bool bParentEnabled) const override;//绘制函数
private:
void DrawSmoothedLine(
FSlateWindowElementList& OutDrawElement,
int InLayerId,
const FGeometry& InAllottedGeometry,
TArray<FVector2D> InPoints,
float InThickness,
FColor InColor
)const;//线的绘制
//线所包含的顶点
TArray<FVector2D> MultiplyPoint;
};
- .cpp文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "SmoothedLineWidget.h"
#include "Components/CanvasPanelSlot.h"
USmoothedLineWidget::USmoothedLineWidget(const FObjectInitializer& ObjectInitializer)
:Super(ObjectInitializer)
{
}
void USmoothedLineWidget::SetValues(TArray<float> InValues)
{
if (InValues.Num() < 2)
return;
MultiplyPoint.Empty();
float WidgetWidth = Size.X;
float WidgetHeight = Size.Y;
float Space = WidgetWidth / (InValues.Num() - 1);
for (int32 Index = 0; Index < InValues.Num(); Index++)
{
FVector2D KeyPosition(Space * Index, WidgetHeight - InValues[Index]);
MultiplyPoint.Add(KeyPosition);
}
}
void USmoothedLineWidget::NativePreConstruct()
{
Super::NativePreConstruct();
SetValues(Values);
}
int32 USmoothedLineWidget::NativePaint(const FPaintArgs& Args,
const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect,
FSlateWindowElementList& OutDrawElements,
int32 LayerId,
const FWidgetStyle& InWidgetStyle,
bool bParentEnabled) const
{
DrawSmoothedLine(
OutDrawElements,
LayerId,
AllottedGeometry,
MultiplyPoint,
BrushSize,
Color);
return LayerId++;
}
void USmoothedLineWidget::DrawSmoothedLine(
FSlateWindowElementList& OutDrawElement,
int InLayerId,
const FGeometry& InAllottedGeometry,
TArray<FVector2D> InPoints,
float InThickness,
FColor InColor) const
{
if (InPoints.Num() < 2)
return;
FRichCurve* RichCurve = new FRichCurve();
for (FVector2D InPoint : InPoints)
{
FKeyHandle KeyHandle = RichCurve->AddKey(InPoint.X, InPoint.Y);
RichCurve->SetKeyInterpMode(KeyHandle, ERichCurveInterpMode::RCIM_Cubic);
}
UCanvasPanelSlot* CanvsdPanelSlot = Cast<UCanvasPanelSlot>(this->Slot);
TArray<FVector2D> ResultPoints;
float WidgetWidth = Size.X;
float WidgetHeight = Size.Y;
int32 Begin = 0;
int32 End = (int32)WidgetWidth;
for (int32 X = Begin; X < End; X++)
{
float Y = RichCurve->Eval(X);
FVector2D ResultPoint(X+ Locationn.X, Y+ Locationn.Y);
ResultPoints.Add(ResultPoint);
}
delete RichCurve;
FSlateDrawElement::MakeLines(
OutDrawElement,
InLayerId,
InAllottedGeometry.ToPaintGeometry(),
ResultPoints,
ESlateDrawEffect::None,
InColor,
true,
InThickness
);
}