Files
integration/Source/Integration/RadialMenu.cpp
2026-05-08 17:55:11 -04:00

87 lines
2.4 KiB
C++

#include "RadialMenu.h"
void URadialMenu::Configure(int32 NItems, float ItemHeight, float InnerRadius, float MinSpoke, float Spread)
{
CNItems = NItems;
CItemHeight = ItemHeight;
CInnerRadius = InnerRadius;
CMinSpoke = MinSpoke;
CSpread = Spread;
CNumRight = (NItems / 2);
CNumLeft = NItems - CNumRight;
Items.SetNum(NItems);
LeftItems = View(Items.GetData(), CNumLeft);
RightItems = View(Items.GetData() + CNumLeft, CNumRight);
CalculateSide(LeftItems);
CalculateSide(RightItems);
FlipHorizontal(LeftItems);
}
FVector2D URadialMenu::PieSliceToVector(double Slice, double Slices)
{
double HalfRevolutions = (Slice + 0.5) / Slices;
double Radians = (HalfRevolutions * UE_PI);
return FVector2D(FMath::Sin(Radians), -FMath::Cos(Radians));
}
void URadialMenu::FlipHorizontal(View V)
{
for (FRadialMenuItem& Item : V)
{
Item.Point1.X = -Item.Point1.X;
Item.Point2.X = -Item.Point2.X;
Item.Point3.X = -Item.Point3.X;
Item.RightSide = !Item.RightSide;
}
}
void URadialMenu::CalculateSide(View V)
{
// Point1 is simple. RightSide is always initialized to
// true, it may get reversed in FlipHorizontal.
for (int32 I = 0; I < V.Num(); I++)
{
V[I].RightSide = true;
V[I].Point1 = PieSliceToVector(I, V.Num()) * CInnerRadius;
}
// Calculate point2 for all spokes.
double NextLineMin = CItemHeight * 0.5;
int32 Mid = (V.Num() / 2);
if (V.Num() & 1)
{
V[Mid].Point2 = FVector2D(CInnerRadius + CMinSpoke, 0.0);
NextLineMin = CItemHeight;
Mid += 1;
}
for (int32 I = Mid; I < V.Num(); I++)
{
FVector2D UnitVec = PieSliceToVector(I, V.Num());
double Y = (UnitVec.Y * (CInnerRadius + CMinSpoke));
if (Y < NextLineMin) Y = NextLineMin;
NextLineMin = Y + CItemHeight;
FVector2D Point2 = UnitVec * (Y / UnitVec.Y);
V[I].Point2 = Point2;
V[V.Num() - I].Point2 = Point2 * FVector2D(1.0,-1.0);
}
// The rule we use for calculating point2 may result in
// a very short horizontal spoke. If so, fix it.
if ((V.Num() & 1) && (V.Num() >= 3))
{
Mid = V.Num() / 2;
if (V[Mid].Point2.X < V[Mid + 1].Point2.X)
V[Mid].Point2.X = V[Mid + 1].Point2.X;
}
// Calculate Point3.
for (int32 I = 0; I < V.Num(); I++)
{
V[I].Point3 = V[I].Point2 + FVector2D(CSpread, 0.0);
}
}