87 lines
2.4 KiB
C++
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);
|
|
}
|
|
}
|