Working on radial menus

This commit is contained in:
2026-05-15 18:14:38 -04:00
parent 5d2377df1d
commit 1328f6e5f7
8 changed files with 225 additions and 65 deletions

View File

@@ -1,5 +1,7 @@
#include "RadialMenu.h"
#include "Rendering/DrawElements.h"
#include "Engine/Texture2D.h"
#include "Styling/SlateBrush.h"
#include "Widgets/SLeafWidget.h"
@@ -122,6 +124,31 @@ public:
Invalidate(EInvalidateWidgetReason::Layout);
}
void SetLineThickness(float NewLineThickness)
{
LineThickness = NewLineThickness;
Invalidate(EInvalidateWidgetReason::Paint);
}
void SetLineColor(FLinearColor NewLineColor)
{
LineColor = NewLineColor;
Invalidate(EInvalidateWidgetReason::Paint);
}
void SetDotTexture(UTexture2D* NewDotTexture)
{
DotTexture = NewDotTexture;
DotBrush.SetResourceObject(NewDotTexture);
Invalidate(EInvalidateWidgetReason::Paint);
}
void SetDotRadius(float NewDotRadius)
{
DotRadius = NewDotRadius;
Invalidate(EInvalidateWidgetReason::Paint);
}
protected:
virtual FVector2D ComputeDesiredSize(float) const override
{
@@ -151,7 +178,6 @@ protected:
if (!Layout.IsValid()) return LayerId;
const FVector2D Center = AllottedGeometry.GetLocalSize() * 0.5;
const FLinearColor Color = InWidgetStyle.GetColorAndOpacityTint();
const FPaintGeometry PaintGeom = AllottedGeometry.ToPaintGeometry();
for (const FRadialMenuItem &Item : Layout->GetItems())
@@ -160,25 +186,127 @@ protected:
Points.Add(Center + Item.Point1);
Points.Add(Center + Item.Point2);
Points.Add(Center + Item.Point3);
FSlateDrawElement::MakeLines(OutDrawElements, LayerId, PaintGeom, Points, ESlateDrawEffect::None, Color, true, 1.0f);
FSlateDrawElement::MakeLines(OutDrawElements, LayerId, PaintGeom, Points, ESlateDrawEffect::None, LineColor, true, LineThickness);
}
if (DotRadius <= 0.0f) return LayerId;
if (!DotTexture.IsValid()) return LayerId;
const FVector2D DotSize(DotRadius * 2.0f);
for (const FRadialMenuItem &Item : Layout->GetItems())
{
for (const FVector2D& Point : { Item.Point1, Item.Point3 })
{
const FVector2D LocalPoint = Center + Point;
FSlateDrawElement::MakeBox(
OutDrawElements,
LayerId,
AllottedGeometry.ToPaintGeometry(DotSize, FSlateLayoutTransform(LocalPoint - FVector2D(DotRadius))),
&DotBrush,
ESlateDrawEffect::None,
LineColor);
}
}
return LayerId;
}
private:
TWeakObjectPtr<URadialMenuLayout> Layout;
float LineThickness = 1.0f;
FLinearColor LineColor = FLinearColor::White;
TWeakObjectPtr<UTexture2D> DotTexture;
FSlateBrush DotBrush;
float DotRadius = 0.0f;
};
void URadialMenuWidget::Configure(int32 NItems, float ItemHeight, float InnerRadius, float MinSpoke, float Spread)
void URadialMenuWidget::SetNumItems(int32 NewNumItems)
{
if (NumItems == NewNumItems) return;
NumItems = NewNumItems;
SynchronizeProperties();
}
void URadialMenuWidget::SetItemHeight(float NewItemHeight)
{
if (ItemHeight == NewItemHeight) return;
ItemHeight = NewItemHeight;
SynchronizeProperties();
}
void URadialMenuWidget::SetInnerRadius(float NewInnerRadius)
{
if (InnerRadius == NewInnerRadius) return;
InnerRadius = NewInnerRadius;
SynchronizeProperties();
}
void URadialMenuWidget::SetMinSpoke(float NewMinSpoke)
{
if (MinSpoke == NewMinSpoke) return;
MinSpoke = NewMinSpoke;
SynchronizeProperties();
}
void URadialMenuWidget::SetSpread(float NewSpread)
{
if (Spread == NewSpread) return;
Spread = NewSpread;
SynchronizeProperties();
}
void URadialMenuWidget::SetLineThickness(float NewLineThickness)
{
if (LineThickness == NewLineThickness) return;
LineThickness = NewLineThickness;
SynchronizeProperties();
}
void URadialMenuWidget::SetLineColor(FLinearColor NewLineColor)
{
if (LineColor == NewLineColor) return;
LineColor = NewLineColor;
SynchronizeProperties();
}
void URadialMenuWidget::SetDotTexture(UTexture2D* NewDotTexture)
{
if (DotTexture == NewDotTexture) return;
DotTexture = NewDotTexture;
SynchronizeProperties();
}
void URadialMenuWidget::SetDotRadius(float NewDotRadius)
{
if (DotRadius == NewDotRadius) return;
DotRadius = NewDotRadius;
SynchronizeProperties();
}
void URadialMenuWidget::SynchronizeProperties()
{
Super::SynchronizeProperties();
if (!Layout)
{
Layout = NewObject<URadialMenuLayout>(this);
}
Layout->Configure(NItems, ItemHeight, InnerRadius, MinSpoke, Spread);
Layout->Configure(NumItems, ItemHeight, InnerRadius, MinSpoke, Spread);
if (MySlateWidget.IsValid())
{
MySlateWidget->SetLineThickness(LineThickness);
MySlateWidget->SetLineColor(LineColor);
MySlateWidget->SetDotTexture(DotTexture);
MySlateWidget->SetDotRadius(DotRadius);
MySlateWidget->Refresh();
}
}
@@ -190,6 +318,7 @@ TSharedRef<SWidget> URadialMenuWidget::RebuildWidget()
Layout = NewObject<URadialMenuLayout>(this);
}
MySlateWidget = SNew(SRadialMenu, Layout);
SynchronizeProperties();
return MySlateWidget.ToSharedRef();
}

View File

@@ -10,6 +10,7 @@
#include "RadialMenu.generated.h"
class SRadialMenu;
class UTexture2D;
USTRUCT(BlueprintType)
@@ -86,7 +87,31 @@ class URadialMenuWidget : public UWidget
public:
UFUNCTION(BlueprintCallable)
void Configure(int32 NItems, float ItemHeight, float InnerRadius, float MinSpoke, float Spread);
void SetNumItems(int32 NewNumItems);
UFUNCTION(BlueprintCallable)
void SetItemHeight(float NewItemHeight);
UFUNCTION(BlueprintCallable)
void SetInnerRadius(float NewInnerRadius);
UFUNCTION(BlueprintCallable)
void SetMinSpoke(float NewMinSpoke);
UFUNCTION(BlueprintCallable)
void SetSpread(float NewSpread);
UFUNCTION(BlueprintCallable)
void SetLineThickness(float NewLineThickness);
UFUNCTION(BlueprintCallable)
void SetLineColor(FLinearColor NewLineColor);
UFUNCTION(BlueprintCallable)
void SetDotTexture(UTexture2D* NewDotTexture);
UFUNCTION(BlueprintCallable)
void SetDotRadius(float NewDotRadius);
UFUNCTION(BlueprintCallable)
URadialMenuLayout* GetLayout() const { return Layout; }
@@ -94,11 +119,38 @@ public:
protected:
virtual TSharedRef<SWidget> RebuildWidget() override;
virtual void ReleaseSlateResources(bool bReleaseChildren) override;
virtual void SynchronizeProperties() override;
private:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Setter, Category="RadialMenu", meta=(ClampMin="0", AllowPrivateAccess="true"))
int32 NumItems = 8;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Setter, Category="RadialMenu", meta=(AllowPrivateAccess="true"))
float ItemHeight = 20.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Setter, Category="RadialMenu", meta=(AllowPrivateAccess="true"))
float InnerRadius = 20.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Setter, Category="RadialMenu", meta=(AllowPrivateAccess="true"))
float MinSpoke = 20.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Setter, Category="RadialMenu", meta=(AllowPrivateAccess="true"))
float Spread = 20.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Setter, Category="RadialMenu", meta=(AllowPrivateAccess="true"))
float LineThickness = 2.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Setter, Category="RadialMenu", meta=(AllowPrivateAccess="true"))
FLinearColor LineColor = FLinearColor::White;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Setter, Category="RadialMenu", meta=(AllowPrivateAccess="true"))
TObjectPtr<UTexture2D> DotTexture;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Setter, Category="RadialMenu", meta=(AllowPrivateAccess="true"))
float DotRadius = 0.0f;
UPROPERTY()
TObjectPtr<URadialMenuLayout> Layout;
TSharedPtr<SRadialMenu> MySlateWidget;
};