UE5 C++ Slate 画曲线

一.直接上代码

头文件

cpp 复制代码
#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Rendering/DrawElementTypes.h"
#include "SmoothLineWidget.generated.h"

/**
 * 
 */
UCLASS()
class GWXPJ_API USmoothLineWidget : public UUserWidget
{
	GENERATED_BODY()
public:
	UFUNCTION(BlueprintCallable)
	void SetValues(TArray<float> InValues);
protected:
	virtual int32 NativePaint(
		const FPaintArgs& Args,
		const FGeometry& AllottedGeometry,
		const FSlateRect& MyCullingRect,
		FSlateWindowElementList& OutDrawElements,
		int32 LayerId,
		const FWidgetStyle& InWidgetStyle,
		bool bParentEnabled) const;
	
	void DrawSmoothedLine(
		FSlateWindowElementList& OutDrawElement,
		uint32 LayerId,
		const FGeometry& InAllottedGeometry,
		TArray<FVector2D> InPoints,
		float InThickness,
		FColor InColor
	)const;
	TArray<FVector2D> MultiplyPoint;
};

CPP

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.


#include "GWXWidget.h"
#include "Components/CanvasPanelSlot.h"

void UGWXWidget::SetValues(TArray<float> InValues)
{
	if (InValues.Num() < 2)
	{
		return;
	}
	MultiplyPoint.Empty();

	UCanvasPanelSlot* CanvsdPanelSlot = Cast<UCanvasPanelSlot>(this->Slot);
	if (CanvsdPanelSlot == nullptr)
		return;

	float WidgetWidth = CanvsdPanelSlot->GetSize().X;
	float WidgetHeight = CanvsdPanelSlot->GetSize().Y;

	float Space = WidgetWidth / (InValues.Num() - 1);
	float HeightSpace = WidgetHeight / 2000;  //值域 + - 2000
	for (int32 Index = 0; Index < InValues.Num(); Index++)  //数据输入
	{
		FVector2D KeyPosition(Space * Index, WidgetHeight - InValues[Index]*HeightSpace);
		MultiplyPoint.Add(KeyPosition);
	}
}

int32 UGWXWidget::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,
		1.0f,
		FColor::Red
	);
	
	//
	float Numx = 10;  //X轴的取值点数
	float Numy = 10;	//Y轴的取值点数
	UCanvasPanelSlot* CanvsdPanelSlot = Cast<UCanvasPanelSlot>(this->Slot);
	if (!CanvsdPanelSlot)
	{
		return LayerId++;
	}
	float WidgetWidth = CanvsdPanelSlot->GetSize().X;
	float WidgetHeight = CanvsdPanelSlot->GetSize().Y;
	float Space = WidgetWidth / (Numx);
	//X 轴刻度
	for (int32 Index = 0;Index <= Numx;Index++)
	{
		FVector2D TextPosition = FVector2D(
			Space *Index,
			WidgetHeight
		);
		FSlateFontInfo SlateFontInfo = FCoreStyle::GetDefaultFontStyle("Regular",10);
		FSlateDrawElement::MakeText(
			OutDrawElements,
			LayerId,
			AllottedGeometry.ToOffsetPaintGeometry(TextPosition),
			FText::FromString(FString::FromInt(Index * 10)),
			SlateFontInfo,
			ESlateDrawEffect::None,
			FLinearColor::White
		);
	}
	// Y轴刻度 
	float HeightSpace = WidgetHeight / 2000*200;  //值域 + - 2000
	for (int32 Index = 0; Index <= Numy; Index++)
	{
		FVector2D TextPosition = FVector2D(
			-30,
			HeightSpace*Index-10
		);
		FSlateFontInfo SlateFontInfo = FCoreStyle::GetDefaultFontStyle("Regular", 10);
		FSlateDrawElement::MakeText(
			OutDrawElements,
			LayerId,
			AllottedGeometry.ToOffsetPaintGeometry(TextPosition),
			FText::FromString(FString::FromInt((Numy-Index) * 200)),
			SlateFontInfo,
			ESlateDrawEffect::None,
			FLinearColor::White
		);
	}
	return LayerId++;
} //变化

void UGWXWidget::DrawSmoothedLine(FSlateWindowElementList& OutDrawElement, uint32 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* CanvasPanelSlot = Cast<UCanvasPanelSlot>(this->Slot);
	if (CanvasPanelSlot == nullptr)
		return;

	TArray<FVector2D> ResultPoints;
	float WidgetWidth = CanvasPanelSlot->GetSize().X;

	int32 Begin = 0;
	int32 End = (int32)WidgetWidth;
	for (int32 X = Begin; X < End; X++)
	{
		float Y = RichCurve->Eval(X);
		FVector2D ResultPoint(X, Y);
		ResultPoints.Add(ResultPoint);
	}

	delete RichCurve;
	FSlateDrawElement::MakeLines(
		OutDrawElement,
		InLayerId,
		InAllottedGeometry.ToPaintGeometry(),
		ResultPoints,
		ESlateDrawEffect::None,
		InColor,
		true,
		InThickness
	);  
}

二. 首先我们必须包含 UMG 模块,因为要在C++里继承UserWidget。其次我们需要包好Slate和SlateCore 模块。因为这样才能使用Slate编程里的函数API

三.思路

1.这里我们SetValues用于外部调用。

2.NativePaint更像是一个循环。

这里我们看到。它更是UserWidget里用来画最大LayerID的,当LayerID增加,它就不停刷新。

这里也绘制了X轴,Y轴,使用的是FSlateDrawElement::MakeText

3.将数组两两放入曲线中,得到更顺滑的数组。最终核心的Slate 还是FSlateDrawElement::MakeLines函数,进行绘画。

三.效果

相关推荐
ue星空2 小时前
UE5C++UKismetMathLibrary源代码
c++·ue5
向葭奔赴♡2 小时前
Spring IOC/DI 与 MVC 从入门到实战
java·开发语言
minji...2 小时前
C++ 面向对象三大特性之一---多态
开发语言·c++
散峰而望2 小时前
基本魔法语言函数(一)(C语言)
c语言·开发语言·编辑器·github
2401_841495642 小时前
【数据结构】基于BF算法的树种病毒检测
java·数据结构·c++·python·算法·字符串·模式匹配
lucky_syq2 小时前
Scala与Spark算子:大数据处理的黄金搭档
开发语言·spark·scala
封奚泽优3 小时前
使用Labelme进行图像标注
开发语言·python·labelme
wjs20243 小时前
C 标准库 - <ctype.h>
开发语言
wjs20243 小时前
AngularJS与SQL的集成使用指南
开发语言