// Fill out your copyright notice in the Description page of Project Settings.
#include "CircleWidget.h"
int32 UCircleWidget::NativePaint(const FPaintArgs& Args,
const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect,
FSlateWindowElementList& OutDrawElement,
int32 LayerId,
const FWidgetStyle& InWidgetStyle,
bool bParentEnable) const
{
DrawCirclePart(
OutDrawElement,
AllottedGeometry,
LayerId,
InnerR,
OuterR,
StartAngle,
EndAngle,
CircleColor
);
return LayerId++;
}
void UCircleWidget::DrawCirclePart(
FSlateWindowElementList& OutDrawElement,
const FGeometry& AllottedGeometry,
int LayerId, float IR, float OR,
int32 InBeginAngle, int32 InEndAngle,
const FColor& InColor) const
{
if(InEndAngle <= InBeginAngle) return ;//如果开始角都小于结束角则退出
FVector2D CenterPosition = FVector2D(OuterR, OuterR);
TArray<FSlateVertex> SlateVertexes;//创建一个顶点数组,用于存放绘制的顶点
TArray<SlateIndex> SlateIndexes;//创建一个下标数组
for(int32 Angle = InBeginAngle; Angle <= InEndAngle; Angle++)//每过一个角度进行一次,角度四个顶点的运算
{
//声明内弧与外弧的四个顶点
FSlateVertex CurrentOVertex;
FSlateVertex NextOVextex;
FSlateVertex CurrentIVertex;
FSlateVertex NextIVertex;
//为四个顶点着色
CurrentOVertex.Color = InColor;
NextOVextex.Color = InColor;
CurrentIVertex.Color = InColor;
NextIVertex.Color = InColor;
//计算内弧、外弧四个顶点的位置
FVector2D CurrentIVPosition = FVector2D(
CenterPosition.X + IR * FMath::Cos(FMath::DegreesToRadians(Angle)),
CenterPosition.Y - IR * FMath::Sin(FMath::DegreesToRadians(Angle))
);
FVector2D NextIVPosition = FVector2D(
CenterPosition.X + IR * FMath::Cos(FMath::DegreesToRadians(Angle + 1)),
CenterPosition.Y - IR * FMath::Sin(FMath::DegreesToRadians(Angle + 1))
);
FVector2D CurrentOVPosition = FVector2D(
CenterPosition.X + OR * FMath::Cos(FMath::DegreesToRadians(Angle)),
CenterPosition.Y - OR * FMath::Sin(FMath::DegreesToRadians(Angle))
);
FVector2D NextOVPosition = FVector2D(
CenterPosition.X + OR * FMath::Cos(FMath::DegreesToRadians(Angle + 1)),
CenterPosition.Y - OR * FMath::Sin(FMath::DegreesToRadians(Angle + 1))
);
//从本地空间变换到渲染空间
const FSlateRenderTransform& SlateRenderTransform = AllottedGeometry.ToPaintGeometry().GetAccumulatedRenderTransform();
CurrentOVPosition = SlateRenderTransform.TransformPoint(CurrentOVPosition);
NextOVPosition = SlateRenderTransform.TransformPoint(NextOVPosition);
CurrentIVPosition = SlateRenderTransform.TransformPoint(CurrentIVPosition);
NextIVPosition = SlateRenderTransform.TransformPoint(NextIVPosition);
//给四个顶点的位置赋值(渲染空间的值)
CurrentOVertex.Position = CurrentOVPosition;
NextOVextex.Position = NextOVPosition;
CurrentIVertex.Position = CurrentIVPosition;
NextIVertex.Position = NextIVPosition;
//将顶点信息放入数组并将其索引给到对应值
int32 IndexOfCurrentOV = SlateVertexes.Add(CurrentOVertex);
int32 IndexOfNextOV = SlateVertexes.Add(NextOVextex);
int32 IndexOfCurrentIV = SlateVertexes.Add(CurrentIVertex);
int32 IndexOfNextIV = SlateVertexes.Add(NextIVertex);
//利用索引画出对应两个三角形,放入索引数组,第一个三角形
SlateIndexes.Add(IndexOfCurrentOV);
SlateIndexes.Add(IndexOfNextOV);
SlateIndexes.Add(IndexOfCurrentIV);
//第二个三角形
SlateIndexes.Add(IndexOfCurrentIV);
SlateIndexes.Add(IndexOfNextIV);
SlateIndexes.Add(IndexOfNextOV);
}
//设置uv值
for(FSlateVertex& SlateVertex : SlateVertexes)
{
SlateVertex.TexCoords[0] = 0.f;
SlateVertex.TexCoords[1] = 0.f;
}
//开始获取各个顶点进行图形绘制
const FSlateBrush* Brush = FCoreStyle::Get().GetBrush("ColorSpectrum.Specturm");
FSlateResourceHandle ResourcedHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(*Brush);
FSlateDrawElement::MakeCustomVerts(
OutDrawElement,
LayerId,
ResourcedHandle,
SlateVertexes,
SlateIndexes,
nullptr,
0,
0
);
}
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "CircleWidget.generated.h"
/**
*
*/
UCLASS()
class MYPROJECT_API UCircleWidget : public UUserWidget
{
GENERATED_BODY()
protected:
virtual int32 NativePaint(
const FPaintArgs& Args,
const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect,
FSlateWindowElementList& OutDrawElement,
int32 LayerId,
const FWidgetStyle& InWidgetStyle,
bool bParentEnable) const override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 360))
float EndAngle;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 360))
float StartAngle;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 960))
float InnerR;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 960))
float OuterR;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FColor CircleColor;
private:
void DrawCirclePart(FSlateWindowElementList& OutDrawElement,
const FGeometry& AllottedGeometry,
int LayerId, float IR, float OR,
int32 InBeginAngle, int32 InEndAngle,
const FColor& InColor) const;
};
可以用于吃鸡回血的这个动画:
// Fill out your copyright notice in the Description page of Project Settings.
#include "CircleWidget.h"
#include <vehicle/PxVehicleSDK.h>
int32 UCircleWidget::NativePaint(const FPaintArgs& Args,
const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect,
FSlateWindowElementList& OutDrawElement,
int32 LayerId,
const FWidgetStyle& InWidgetStyle,
bool bParentEnable) const
{
float TotalValue = 0.f;
for(int32 Index = 0; Index < Angles.Num(); Index++) TotalValue += Angles[Index];
TArray<float> CircleAngles;
for(int32 Index = 0; Index < Angles.Num(); Index++)
{
int32 Angle = (Angles[Index] / TotalValue) * 360;
CircleAngles.Add(Angle);
}
int32 AddAngle = 0;
int LoopSize = FMath::Min(Angles.Num(), CircleColor.Num());
for(int32 Index = 0; Index < LoopSize; Index++)
{
DrawCirclePart(
OutDrawElement,
AllottedGeometry,
LayerId,
InnerR,
OuterR,
AddAngle,
AddAngle + CircleAngles[Index],
CircleColor[Index]
);
AddAngle += CircleAngles[Index];
}
return LayerId++;
}
void UCircleWidget::DrawCirclePart(
FSlateWindowElementList& OutDrawElement,
const FGeometry& AllottedGeometry,
int LayerId, float IR, float OR,
int32 InBeginAngle, int32 InEndAngle,
const FColor& InColor) const
{
if(InEndAngle <= InBeginAngle) return ;//如果开始角都小于结束角则退出
FVector2D CenterPosition = FVector2D(OuterR, OuterR);
TArray<FSlateVertex> SlateVertexes;//创建一个顶点数组,用于存放绘制的顶点
TArray<SlateIndex> SlateIndexes;//创建一个下标数组
for(int32 Angle = InBeginAngle; Angle <= InEndAngle; Angle++)//每过一个角度进行一次,角度四个顶点的运算
{
//声明内弧与外弧的四个顶点
FSlateVertex CurrentOVertex;
FSlateVertex NextOVextex;
FSlateVertex CurrentIVertex;
FSlateVertex NextIVertex;
//为四个顶点着色
CurrentOVertex.Color = InColor;
NextOVextex.Color = InColor;
CurrentIVertex.Color = InColor;
NextIVertex.Color = InColor;
//计算内弧、外弧四个顶点的位置
FVector2D CurrentIVPosition = FVector2D(
CenterPosition.X + IR * FMath::Cos(FMath::DegreesToRadians(Angle)),
CenterPosition.Y - IR * FMath::Sin(FMath::DegreesToRadians(Angle))
);
FVector2D NextIVPosition = FVector2D(
CenterPosition.X + IR * FMath::Cos(FMath::DegreesToRadians(Angle + 1)),
CenterPosition.Y - IR * FMath::Sin(FMath::DegreesToRadians(Angle + 1))
);
FVector2D CurrentOVPosition = FVector2D(
CenterPosition.X + OR * FMath::Cos(FMath::DegreesToRadians(Angle)),
CenterPosition.Y - OR * FMath::Sin(FMath::DegreesToRadians(Angle))
);
FVector2D NextOVPosition = FVector2D(
CenterPosition.X + OR * FMath::Cos(FMath::DegreesToRadians(Angle + 1)),
CenterPosition.Y - OR * FMath::Sin(FMath::DegreesToRadians(Angle + 1))
);
//从本地空间变换到渲染空间
const FSlateRenderTransform& SlateRenderTransform = AllottedGeometry.ToPaintGeometry().GetAccumulatedRenderTransform();
CurrentOVPosition = SlateRenderTransform.TransformPoint(CurrentOVPosition);
NextOVPosition = SlateRenderTransform.TransformPoint(NextOVPosition);
CurrentIVPosition = SlateRenderTransform.TransformPoint(CurrentIVPosition);
NextIVPosition = SlateRenderTransform.TransformPoint(NextIVPosition);
//给四个顶点的位置赋值(渲染空间的值)
CurrentOVertex.Position = CurrentOVPosition;
NextOVextex.Position = NextOVPosition;
CurrentIVertex.Position = CurrentIVPosition;
NextIVertex.Position = NextIVPosition;
//将顶点信息放入数组并将其索引给到对应值
int32 IndexOfCurrentOV = SlateVertexes.Add(CurrentOVertex);
int32 IndexOfNextOV = SlateVertexes.Add(NextOVextex);
int32 IndexOfCurrentIV = SlateVertexes.Add(CurrentIVertex);
int32 IndexOfNextIV = SlateVertexes.Add(NextIVertex);
//利用索引画出对应两个三角形,放入索引数组,第一个三角形
SlateIndexes.Add(IndexOfCurrentOV);
SlateIndexes.Add(IndexOfNextOV);
SlateIndexes.Add(IndexOfCurrentIV);
//第二个三角形
SlateIndexes.Add(IndexOfCurrentIV);
SlateIndexes.Add(IndexOfNextIV);
SlateIndexes.Add(IndexOfNextOV);
}
//设置uv值
for(FSlateVertex& SlateVertex : SlateVertexes)
{
SlateVertex.TexCoords[0] = 0.f;
SlateVertex.TexCoords[1] = 0.f;
}
//开始获取各个顶点进行图形绘制
const FSlateBrush* Brush = FCoreStyle::Get().GetBrush("ColorSpectrum.Specturm");
FSlateResourceHandle ResourcedHandle = FSlateApplication::Get().GetRenderer()->GetResourceHandle(*Brush);
FSlateDrawElement::MakeCustomVerts(
OutDrawElement,
LayerId,
ResourcedHandle,
SlateVertexes,
SlateIndexes,
nullptr,
0,
0
);
}
void UCircleWidget::SetValues(TArray<float> InValues, TArray<FColor> Colors)
{
if(InValues.Num() < 1) return ;
Angles.Empty();
CircleColor = Colors;
float Total = 0;
for(int32 Index = 0; Index < InValues.Num(); Index++)
{
Total += InValues[Index];
}
float CurrentTotal = 0;
for(int32 Index = 0; Index < InValues.Num(); Index++)
{
CurrentTotal = InValues[Index];
int Angle = (CurrentTotal / Total) * 360;
Angles.Add(Angle);
}
}
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "CircleWidget.generated.h"
/**
*
*/
UCLASS()
class MYPROJECT_API UCircleWidget : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void SetValues(TArray<float> InValues, TArray<FColor> Colors);
protected:
virtual int32 NativePaint(
const FPaintArgs& Args,
const FGeometry& AllottedGeometry,
const FSlateRect& MyCullingRect,
FSlateWindowElementList& OutDrawElement,
int32 LayerId,
const FWidgetStyle& InWidgetStyle,
bool bParentEnable) const override;
// UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 360))
// float EndAngle;
//
// UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 360))
// float StartAngle;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 960))
float InnerR;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ClampMin = 0, ClampMax = 960))
float OuterR;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<FColor> CircleColor;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<float> Angles;
private:
void DrawCirclePart(FSlateWindowElementList& OutDrawElement,
const FGeometry& AllottedGeometry,
int LayerId, float IR, float OR,
int32 InBeginAngle, int32 InEndAngle,
const FColor& InColor) const;
};
同样也能进行动态设置,该类是按照比例来画环形图