#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); } }