177 lines
4.7 KiB
C++
177 lines
4.7 KiB
C++
//
|
|
// This class implements the layout calculatations for a radial
|
|
// menu.
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Components/Widget.h"
|
|
#include "RadialMenu.generated.h"
|
|
|
|
class SRadialMenu;
|
|
class UTexture2D;
|
|
|
|
|
|
USTRUCT(BlueprintType)
|
|
struct FRadialMenuConfig
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
int32 NumItems = 8;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
float ItemHeight = 20.0f;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
float InnerRadius = 20.0f;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
float MinSpoke = 20.0f;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
float Spread = 20.0f;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
float LineThickness = 4.0f;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
FLinearColor LineColor = FLinearColor::White;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
TObjectPtr<UTexture2D> DotTexture;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
float DotRadius = 3.0f;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
int32 SelectedItem = -1;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
FLinearColor SelectedColor = FLinearColor::Yellow;
|
|
|
|
UPROPERTY(EditAnywhere, Category="RadialMenu")
|
|
float SelectedThickness = 2.0f;
|
|
};
|
|
|
|
|
|
USTRUCT(BlueprintType)
|
|
struct FRadialMenuItem
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
UPROPERTY(BlueprintReadOnly)
|
|
FVector2D Point1 = {0,0};
|
|
|
|
UPROPERTY(BlueprintReadOnly)
|
|
FVector2D Point2 = {0,0};
|
|
|
|
UPROPERTY(BlueprintReadOnly)
|
|
FVector2D Point3 = {0,0};
|
|
|
|
UPROPERTY(BlueprintReadOnly)
|
|
bool RightSide = false;
|
|
|
|
static TArray<FRadialMenuItem> Calculate(const FRadialMenuConfig &Config);
|
|
|
|
private:
|
|
using View = TArrayView<FRadialMenuItem>;
|
|
|
|
// Give the unit vector for the selected spoke. NSide is
|
|
// the number of spokes on the side of the wheel that
|
|
// we're calculating, and NTotal is the total number of
|
|
// spokes on both sides. The spokes on a given side are
|
|
// organized top-to-bottom, and the angle between the
|
|
// spokes is always equal to (1/NTotal) of the circle.
|
|
static FVector2D SpokeVector(int32 I, int32 NSide, int32 NTotal);
|
|
|
|
// Populate Point1 and Point2, these are the
|
|
// endpoints of the spoke segment. Spokes are
|
|
// designed to always be long enough to make room
|
|
// for MinSpoke, but also to make enough room to
|
|
// keep the menu items from overlapping.
|
|
static void CalculateSpokes(View V, int32 TotalItems, float ItemHeight, float InnerRadius, float MinSpoke);
|
|
|
|
// Search for the widest spoke, and return its X coordinate.
|
|
static double WidestSpoke(View V);
|
|
|
|
// Populate Point3, this is the endpoint of the spread
|
|
// line that goes horizontal.
|
|
static void CalculateSpread(View V, double Offset);
|
|
|
|
// Flip everything in the specified view horizontally.
|
|
static void FlipHorizontal(View V);
|
|
};
|
|
|
|
|
|
UCLASS(BlueprintType, Blueprintable)
|
|
class URadialMenuWidget : public UWidget
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
UFUNCTION(BlueprintCallable)
|
|
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)
|
|
bool SetSelectedItem(int32 NewSelectedItem);
|
|
|
|
UFUNCTION(BlueprintCallable)
|
|
void SetSelectedColor(FLinearColor NewSelectedColor);
|
|
|
|
UFUNCTION(BlueprintCallable)
|
|
void SetSelectedThickness(float NewSelectedThickness);
|
|
|
|
UFUNCTION(BlueprintCallable)
|
|
const TArray<FRadialMenuItem> &GetItems() const { return Items; }
|
|
|
|
// Returns true if the selected item changed.
|
|
UFUNCTION(BlueprintCallable)
|
|
bool AddPointer(FVector2D Direction, float Scale);
|
|
|
|
UFUNCTION(BlueprintCallable)
|
|
FVector2D GetPointer() const { return PointerVector; }
|
|
|
|
UFUNCTION(BlueprintCallable)
|
|
FLinearColor GetItemColor(int N) const;
|
|
|
|
protected:
|
|
UPROPERTY(EditAnywhere)
|
|
FRadialMenuConfig Config;
|
|
|
|
TArray<FRadialMenuItem> Items;
|
|
|
|
FVector2D PointerVector = {0,0};
|
|
|
|
virtual TSharedRef<SWidget> RebuildWidget() override;
|
|
virtual void ReleaseSlateResources(bool bReleaseChildren) override;
|
|
virtual void SynchronizeProperties() override;
|
|
|
|
TSharedPtr<SRadialMenu> MySlateWidget;
|
|
};
|