74 lines
2.7 KiB
C++
74 lines
2.7 KiB
C++
// RadialSliceWidget.cpp
|
|
|
|
#include "RadialSliceWidget.h"
|
|
#include "Components/Image.h"
|
|
#include "Components/CanvasPanelSlot.h"
|
|
#include "Materials/MaterialInstanceDynamic.h"
|
|
|
|
void URadialSliceWidget::NativeConstruct()
|
|
{
|
|
Super::NativeConstruct();
|
|
}
|
|
|
|
void URadialSliceWidget::Setup(UMaterialInterface* InSliceMaterial,
|
|
float StartAngleDeg, float AngleSizeDeg, UTexture2D* Icon, bool bEnabled)
|
|
{
|
|
bSliceEnabled = bEnabled;
|
|
|
|
if (InSliceMaterial && WedgeImage)
|
|
{
|
|
WedgeMID = UMaterialInstanceDynamic::Create(InSliceMaterial, this);
|
|
WedgeImage->SetBrushFromMaterial(WedgeMID);
|
|
|
|
// Per-slice angular span (normalized 0..1). The material draws only the
|
|
// arc between these two, so each slice is an independent wedge.
|
|
WedgeMID->SetScalarParameterValue(TEXT("StartAngle"), StartAngleDeg / 360.f);
|
|
WedgeMID->SetScalarParameterValue(TEXT("AngleSize"), AngleSizeDeg / 360.f);
|
|
WedgeMID->SetScalarParameterValue(TEXT("Highlight"), 0.f);
|
|
WedgeMID->SetScalarParameterValue(TEXT("Enabled"), bEnabled ? 1.f : 0.f);
|
|
}
|
|
|
|
if (IconImage)
|
|
{
|
|
if (Icon)
|
|
{
|
|
IconImage->SetBrushFromTexture(Icon);
|
|
}
|
|
IconImage->SetRenderOpacity(bEnabled ? 0.55f : 0.3f);
|
|
|
|
// Push the icon out along this slice's centerline so it sits inside the
|
|
// wedge rather than at the menu's center. Center angle is measured
|
|
// clockwise from 12 o'clock, matching the wedge the material draws.
|
|
const float CenterAngleDeg = StartAngleDeg + AngleSizeDeg * 0.5f;
|
|
const float CenterAngleRad = FMath::DegreesToRadians(CenterAngleDeg);
|
|
const float OffsetX = FMath::Sin(CenterAngleRad) * IconRadius;
|
|
const float OffsetY = -FMath::Cos(CenterAngleRad) * IconRadius;
|
|
|
|
if (UCanvasPanelSlot* IconSlot = Cast<UCanvasPanelSlot>(IconImage->Slot))
|
|
{
|
|
// Anchor + align to center so Position is relative to the menu's
|
|
// middle; then offset out to the slice center.
|
|
IconSlot->SetAnchors(FAnchors(0.5f, 0.5f));
|
|
IconSlot->SetAlignment(FVector2D(0.5f, 0.5f));
|
|
IconSlot->SetPosition(FVector2D(OffsetX, OffsetY));
|
|
}
|
|
}
|
|
}
|
|
|
|
void URadialSliceWidget::UpdateHighlight(bool bIsHovered, float UndilatedDelta)
|
|
{
|
|
const float Target = bIsHovered && bSliceEnabled ? 1.f : 0.f;
|
|
CurrentHighlight = FMath::FInterpTo(CurrentHighlight, Target,
|
|
UndilatedDelta, HighlightInterpSpeed);
|
|
|
|
if (WedgeMID)
|
|
{
|
|
WedgeMID->SetScalarParameterValue(TEXT("Highlight"), CurrentHighlight);
|
|
}
|
|
|
|
if (IconImage && bSliceEnabled)
|
|
{
|
|
// Icon brightens from its dim resting state up to full on hover.
|
|
IconImage->SetRenderOpacity(FMath::Lerp(0.55f, 1.0f, CurrentHighlight));
|
|
}
|
|
} |