#include "PromptWidget.h" #include "PlayerControllerBase.h" #include "Widgets/SOverlay.h" #include "Widgets/Images/SImage.h" #include "Widgets/Text/STextBlock.h" #include "Widgets/Layout/SScaleBox.h" // // Atlas contents: // // Row 1: Keyboard Button no Glyph, Left Mouse, Middle Mouse, Right Mouse // Row 2: Left Trigger, Right Trigger, Left Shoulder, Right Shoulder // Row 3: XBFace Down, XBFace Left, XBFace Up, XBFace Right // Row 4: PSFace Down, PSFace Left, PSFace Up, PSFace Right // Row 5: Arrow Down, Arrow Left, Arrow Up, Arrow Right // Row 6: DPad Down, DPad Left, DPad Up, DPad Right // Row 7: Space Bar, unused, unused, unused // Row 8: unused, unused, unused, unused. int32 UlxPromptWidget::ChooseIcon(bool Playstation, FKey Key) const { // Mouse buttons (row 1) if (Key == EKeys::LeftMouseButton) return 1; if (Key == EKeys::MiddleMouseButton) return 2; if (Key == EKeys::RightMouseButton) return 3; // Gamepad triggers and shoulders (row 2) if (Key == EKeys::Gamepad_LeftTrigger) return 4; if (Key == EKeys::Gamepad_RightTrigger) return 5; if (Key == EKeys::Gamepad_LeftShoulder) return 6; if (Key == EKeys::Gamepad_RightShoulder) return 7; // Gamepad Face buttons (rows 3 and 4) if (Key == EKeys::Gamepad_FaceButton_Bottom) return Playstation ? 12 : 8; if (Key == EKeys::Gamepad_FaceButton_Left) return Playstation ? 13 : 9; if (Key == EKeys::Gamepad_FaceButton_Top) return Playstation ? 14 : 10; if (Key == EKeys::Gamepad_FaceButton_Right) return Playstation ? 15 : 11; // Arrow keys (row 5) if (Key == EKeys::Down) return 16; if (Key == EKeys::Left) return 17; if (Key == EKeys::Up) return 18; if (Key == EKeys::Right) return 19; // Gamepad D-Pad (row 6) if (Key == EKeys::Gamepad_DPad_Down) return 20; if (Key == EKeys::Gamepad_DPad_Left) return 21; if (Key == EKeys::Gamepad_DPad_Up) return 22; if (Key == EKeys::Gamepad_DPad_Right) return 23; // Space bar (row 7) if (Key == EKeys::SpaceBar) return 24; // No icon for this key. Use the blank icon with a label. return 0; } void UlxPromptWidget::ChooseAppearance(int32 &OutIcon, FString &OutGlyph) { UWorld* World = GetWorld(); APlayerController* PC = World ? World->GetFirstPlayerController() : nullptr; AlxPlayerControllerBase* LPC = Cast(PC); ElxInputMode Mode = LPC ? LPC->CurrentInputMode : ElxInputMode::KeyboardMouse; FKey Key = (Mode == ElxInputMode::KeyboardMouse) ? KeyboardKey : GamepadKey; OutIcon = ChooseIcon(Mode == ElxInputMode::PlayStationGamepad, Key); if (OutIcon == 0) OutGlyph = Key.GetDisplayName().ToString(); else OutGlyph = TEXT(""); } FBox2f UlxPromptWidget::GetIconUVs(int32 IconIndex) { const float ColWidth = 1.0f / 4.0f; const float RowHeight = 1.0f / 8.0f; float U = (IconIndex % 4) * ColWidth; float V = (IconIndex / 4) * RowHeight; return FBox2f(FVector2f(U, V), FVector2f(U + ColWidth, V + RowHeight)); } FMargin UlxPromptWidget::GetScaledMargins() const { return FMargin( GlyphMargins.Left * Size.X, GlyphMargins.Top * Size.Y, GlyphMargins.Right * Size.X, GlyphMargins.Bottom * Size.Y); } void UlxPromptWidget::SynchronizeProperties() { Super::SynchronizeProperties(); if (!MyImage.IsValid()) return; int32 Icon = 0; FString Glyph; ChooseAppearance(Icon, Glyph); MyBrush.SetUVRegion(GetIconUVs(Icon)); MyImage->InvalidateImage(); MyImage->SetDesiredSizeOverride(Size); MyGlyphSlot->SetPadding(GetScaledMargins()); MyGlyph->SetColorAndOpacity(GlyphColor); if (!Glyph.IsEmpty()) { MyGlyph->SetText(FText::FromString(Glyph)); MyGlyph->SetVisibility(EVisibility::HitTestInvisible); } else { MyGlyph->SetVisibility(EVisibility::Collapsed); } } void UlxPromptWidget::SetSize(FVector2D InSize) { if (Size != InSize) { Size = InSize; SynchronizeProperties(); } } void UlxPromptWidget::SetGlyphMargins(FMargin InMargins) { if (GlyphMargins != InMargins) { GlyphMargins = InMargins; SynchronizeProperties(); } } void UlxPromptWidget::SetGlyphColor(FLinearColor InColor) { if (GlyphColor != InColor) { GlyphColor = InColor; SynchronizeProperties(); } } void UlxPromptWidget::SetKeys(FKey InGamepadKey, FKey InKeyboardKey) { if ((GamepadKey != InGamepadKey) || (KeyboardKey != InKeyboardKey)) { GamepadKey = InGamepadKey; KeyboardKey = InKeyboardKey; SynchronizeProperties(); } } TSharedRef UlxPromptWidget::RebuildWidget() { int32 Icon = 0; FString Glyph; ChooseAppearance(Icon, Glyph); MyBrush.SetResourceObject(ButtonAtlas); MyBrush.ImageSize = Size; MyBrush.SetUVRegion(GetIconUVs(Icon)); SAssignNew(MyImage, SImage).Image(&MyBrush); EVisibility GlyphVisibility = Glyph.IsEmpty() ? EVisibility::Collapsed : EVisibility::HitTestInvisible; SAssignNew(MyGlyph, STextBlock) .Text(FText::FromString(Glyph)) .ColorAndOpacity(GlyphColor) .Visibility(GlyphVisibility); SAssignNew(MyScaleBox, SScaleBox) .Stretch(EStretch::ScaleToFit) [ MyGlyph.ToSharedRef() ]; MyOverlay = SNew(SOverlay) + SOverlay::Slot() [ MyImage.ToSharedRef() ]; MyOverlay->AddSlot().Padding(GetScaledMargins()).HAlign(HAlign_Fill).VAlign(VAlign_Fill).Expose(MyGlyphSlot) [ MyScaleBox.ToSharedRef() ]; return MyOverlay.ToSharedRef(); } void UlxPromptWidget::ReleaseSlateResources(bool bReleaseChildren) { Super::ReleaseSlateResources(bReleaseChildren); MyOverlay.Reset(); MyImage.Reset(); MyScaleBox.Reset(); MyGlyph.Reset(); MyGlyphSlot = nullptr; }