// 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(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)); } }