2023-03-13 15:58:22 -04:00

1409 lines
46 KiB
C++

/**
* Copyright ©2019 Batty Bovine Productions, LLC. All Rights Reserved.
**/
#include "ControllerMenuWidget.h"
#include "ConstructorHelpers.h"
#include "ContentWidget.h"
#include "IControllerMenu_Implementation.h"
#include "PanelWidget.h"
#include "Blueprint/WidgetTree.h"
#include "Components/Button.h"
#include "Components/ComboBox.h"
#include "Components/GridPanel.h"
#include "Components/GridSlot.h"
#include "Components/ScrollBox.h"
#include "Components/TextSpinner.h"
#include "GameFramework/GameModeBase.h"
#include "GameFramework/PlayerInput.h"
#include "Kismet/GameplayStatics.h"
#include "Misc/ConfigCacheIni.h"
#include "Widgets/ControllerMenuMessageBoxWidget.h"
UControllerMenuWidget::UControllerMenuWidget(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
this->bIsFocusable = false;
this->bIsChildMenu = false;
if (GConfig)
{
GConfig->GetFloat(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("AxisMovementThreshold"), this->AxisMovementThreshold, GGameIni);
GConfig->GetFloat(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("MouseMovementThreshold"), this->MouseMovementThreshold, GGameIni);
GConfig->GetBool(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("CancelConfirm"), this->CancelConfirm, GGameIni);
}
this->bAxisYHasMoved = this->bAxisXHasMoved = false;
//this->InputComponent = CreateDefaultSubobject<UInputComponent>(TEXT("MenuInput"));
//this->InputComponent->RegisterComponent();
}
void UControllerMenuWidget::NativeOnInitialized()
{
Super::NativeOnInitialized();
// HACK: Enable focus for this widget, focus, then reset focus setting.
// This allows us to keep focus inside the widget while preventing Slate
// from using its own input handling, and also bypasses a warning about
// setting focus to an unfocusable widget.
this->bIsFocusable = true;
this->SetKeyboardFocus();
this->bIsFocusable = false;
// Bind both the close and open animation events now
if (this->OpenAnimation)
{
FWidgetAnimationDynamicEvent OpenEvent;
OpenEvent.BindDynamic(this, &UControllerMenuWidget::OpenAnimationFinished);
this->BindToAnimationFinished(this->OpenAnimation, OpenEvent);
}
if (this->CloseAnimation)
{
FWidgetAnimationDynamicEvent CloseEvent;
CloseEvent.BindDynamic(this, &UControllerMenuWidget::CloseAnimationFinished);
this->BindToAnimationFinished(this->CloseAnimation, CloseEvent);
}
this->InitializeMenuActions();
}
FReply UControllerMenuWidget::NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
{
if (InKeyEvent.GetKey().GetDisplayName().ToString().StartsWith("Gamepad"))
{
if (this->LastInputDevice != EControllerMenuInputDevice::Controller)
{
this->SetNewInputDevice(EControllerMenuInputDevice::Controller);
}
}
else
{
if (this->LastInputDevice != EControllerMenuInputDevice::Keyboard)
{
this->SetNewInputDevice(EControllerMenuInputDevice::Keyboard);
}
}
//FReply Reply = Super::NativeOnKeyDown(InGeometry, InKeyEvent);
//this->ResetUserFocus();
//return Reply;
return Super::NativeOnKeyDown(InGeometry, InKeyEvent);
}
FReply UControllerMenuWidget::NativeOnKeyUp(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
{
if (InKeyEvent.GetKey().GetDisplayName().ToString().StartsWith("Gamepad"))
{
if (this->LastInputDevice != EControllerMenuInputDevice::Controller)
{
this->SetNewInputDevice(EControllerMenuInputDevice::Controller);
}
}
else
{
if (this->LastInputDevice != EControllerMenuInputDevice::Keyboard)
{
this->SetNewInputDevice(EControllerMenuInputDevice::Keyboard);
}
}
//FReply Reply = Super::NativeOnKeyUp(InGeometry, InKeyEvent);
//this->ResetUserFocus();
//return Reply;
return Super::NativeOnKeyUp(InGeometry, InKeyEvent);
}
FReply UControllerMenuWidget::NativeOnMouseMove(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
if (this->LastInputDevice != EControllerMenuInputDevice::Mouse)
{
if (this->MouseMovementStartPosition == FVector2D::ZeroVector)
{
this->MouseMovementStartPosition = InMouseEvent.GetLastScreenSpacePosition();
}
const float MouseMovementDistance = (InMouseEvent.GetScreenSpacePosition() - this->MouseMovementStartPosition).Size();
if (MouseMovementDistance >= this->MouseMovementThreshold)
{
this->ClearWidgetFocus();
this->SetNewInputDevice(EControllerMenuInputDevice::Mouse);
}
}
return Super::NativeOnMouseMove(InGeometry, InMouseEvent);
}
FReply UControllerMenuWidget::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
if (this->LastInputDevice != EControllerMenuInputDevice::Mouse)
{
this->SetNewInputDevice(EControllerMenuInputDevice::Mouse);
}
//FReply Reply = Super::NativeOnMouseMove(InGeometry, InMouseEvent);
//this->ResetUserFocus();
//return Reply;
return Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent);
}
FReply UControllerMenuWidget::NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
if (this->LastInputDevice != EControllerMenuInputDevice::Mouse)
{
this->SetNewInputDevice(EControllerMenuInputDevice::Mouse);
}
//FReply Reply = Super::NativeOnMouseMove(InGeometry, InMouseEvent);
//this->ResetUserFocus();
//return Reply;
return Super::NativeOnMouseButtonUp(InGeometry, InMouseEvent);
}
void UControllerMenuWidget::OpenMenu_Implementation(int32 Depth)
{
if (!this->IsInViewport())
{
this->AddToViewport(Depth);
this->WidgetDepth = Depth;
}
this->PlayAnimation(this->OpenAnimation);
// Enable menu actions after menu is opened
this->BindMenuActions();
this->OnOpenOverride();
this->MenuOpened();
this->OnMenuOpened.Broadcast();
}
void UControllerMenuWidget::OpenAnimationFinished()
{
this->bIsInteractable = true;
if (this->FocusableWidgetArray.Num() > 0)
{
this->SetWidgetFocus(this->FocusableWidgetArray[0]);
}
this->MenuShown();
this->OnMenuShown.Broadcast();
}
void UControllerMenuWidget::OpenChildMenu(UControllerMenuWidget *Child, bool TransitionOut)
{
if (Child)
{
this->UnbindMenuActions();
this->ChildMenu = Child;
this->ChildMenu->bIsChildMenu = true;
this->ChildMenu->OpenMenu(this->WidgetDepth+1);
this->ChildMenu->ChildMenuExitedDelegate.BindUObject(this, &UControllerMenuWidget::ChildMenuExitedEvent);
this->ChildMenu->ChildMenuClosedDelegate.BindUObject(this, &UControllerMenuWidget::ChildMenuClosedEvent);
this->ChildMenuOpened();
this->bIsInteractable = false;
}
}
void UControllerMenuWidget::ChildMenuExitedEvent()
{
// Switch the pressed button back to the hovered style when coming back to this menu
this->SetWidgetFocus(this->GetFocusedWidget());
this->ChildMenuExited();
}
void UControllerMenuWidget::ChildMenuClosedEvent()
{
this->bIsInteractable = true;
this->ChildMenu->RemoveFromParent();
this->ChildMenu = nullptr;
this->BindMenuActions();
this->ChildMenuClosed();
}
void UControllerMenuWidget::ExitMenu_Implementation()
{
this->ClearWidgetFocus();
this->PlayAnimation(this->CloseAnimation);
this->OnCloseOverride();
this->MenuExited();
this->OnMenuExited.Broadcast();
this->ChildMenuExitedDelegate.ExecuteIfBound();
}
void UControllerMenuWidget::CloseAnimationFinished()
{
// Remove menu actions after closing the menu
this->UnbindMenuActions();
this->RemoveFromParent();
this->bIsInteractable = false;
this->MenuClosed();
this->OnMenuClosed.Broadcast();
this->ChildMenuClosedDelegate.ExecuteIfBound();
}
UControllerMenuMessageBoxWidget* UControllerMenuWidget::CreateMessageBox(const TSubclassOf<UControllerMenuWidget> Class, const FText Message, const FText AcceptText, const FText CancelText)
{
this->MessageBox = CreateWidget<UControllerMenuMessageBoxWidget>(this->GetGameInstance(), Class);
if (!this->MessageBox)
{
UE_LOG(ControllerMenuLog, Error, TEXT("Message Box could not be loaded"));
return nullptr;
}
this->UnbindMenuActions();
this->MessageBox->bIsChildMenu = true;
this->MessageBox->SetMessageBody(Message);
this->MessageBox->SetAcceptText(AcceptText);
this->MessageBox->SetCancelText(CancelText);
this->MessageBox->OpenMenu(this->WidgetDepth + 1);
this->MessageBox->ChildMenuExitedDelegate.BindUObject(this, &UControllerMenuWidget::MessageBoxExitedEvent);
this->MessageBox->ChildMenuClosedDelegate.BindUObject(this, &UControllerMenuWidget::MessageBoxClosedEvent);
this->bIsInteractable = false;
this->MessageBoxOpened();
return this->MessageBox;
}
void UControllerMenuWidget::MessageBoxExitedEvent()
{
// Switch the pressed button back to the hovered style when coming back to this menu
this->SetWidgetFocus(this->GetFocusedWidget());
this->MessageBoxExited();
}
void UControllerMenuWidget::MessageBoxClosedEvent()
{
this->bIsInteractable = true;
this->MessageBox->RemoveFromParent();
this->MessageBox = nullptr;
this->BindMenuActions();
this->MessageBoxClosed();
}
void UControllerMenuWidget::AddGridPanelWidgets(UGridPanel* GridPanel)
{
const TArray<UPanelSlot*> Slots = GridPanel->GetSlots();
// Find the number of rows and columns in this grid panel
int32 MaxColumn = 0;
int32 MaxRow = 0;
for (UPanelSlot* LocalSlot : Slots)
{
if (UGridSlot* GridSlot = Cast<UGridSlot>(LocalSlot))
{
if (GridSlot->GetColumn() > MaxColumn)
{
MaxColumn = GridSlot->GetColumn();
}
if (GridSlot->GetRow() > MaxRow)
{
MaxRow = GridSlot->GetRow();
}
}
}
// Create an array of widgets for us to fill out
UWidget*** OrderedWidgetArray = new UWidget**[MaxRow+1];
for(int32 i = 0; i <= MaxRow; i++)
{
OrderedWidgetArray[i] = new UWidget*[MaxColumn+1];
for (int32 j = 0; j <= MaxColumn; j++)
{
OrderedWidgetArray[i][j] = nullptr;
}
}
//TArray< TArray<UWidget*> > OrderedWidgetArray;
//OrderedWidgetArray.SetNum(MaxColumn);
//for(int32 i = 0; i < MaxColumn; i++)
//{
// OrderedWidgetArray[i].SetNumZeroed(MaxRow);
//}
// Add the widgets to the array in the appropriate slots
const TArray<UWidget*> Widgets = GridPanel->GetAllChildren();
for (UWidget* Widget : Widgets)
{
UGridSlot* GridSlot = Cast<UGridSlot>(Widget->Slot);
OrderedWidgetArray[GridSlot->GetRow()][GridSlot->GetColumn()] = Widget;
}
// Finally, add each widget to the focus map
for (int Row = 0; Row <= MaxRow; Row++)
{
UWidget** ColumnArray = OrderedWidgetArray[Row];
for (int Column = 0; Column <= MaxColumn; Column++)
{
UWidget* Widget = ColumnArray[Column];
if (Widget)
{
FControllerWidgetFocusMap FocusMap;
{
if (Row > 0)
{
UWidget* Up = OrderedWidgetArray[Row - 1][Column];
if (Cast<ITakesControllerFocus>(Up) || Cast<UButton>(Up))
{
FocusMap.Up = Up;
}
}
if (Row < MaxRow)
{
UWidget* Down = OrderedWidgetArray[Row + 1][Column];
if (Cast<ITakesControllerFocus>(Down) || Cast<UButton>(Down))
{
FocusMap.Down = Down;
}
}
if (Column > 0)
{
UWidget* Left = ColumnArray[Column - 1];
if (Cast<ITakesControllerFocus>(Left) || Cast<UButton>(Left))
{
FocusMap.Left = Left;
}
}
if (Column < MaxColumn)
{
UWidget* Right = ColumnArray[Column + 1];
if (Cast<ITakesControllerFocus>(Right) || Cast<UButton>(Right))
{
FocusMap.Right = Right;
}
}
if ((((MaxRow+1) * Column) + Row) > 0)
{
if (Row > 0)
{
UWidget* Previous = OrderedWidgetArray[Row - 1][Column];
if (Cast<ITakesControllerFocus>(Previous) || Cast<UButton>(Previous))
{
FocusMap.Previous = Previous;
}
}
else
{
UWidget* Previous = OrderedWidgetArray[Row][Column - 1];
if (Cast<ITakesControllerFocus>(Previous) || Cast<UButton>(Previous))
{
FocusMap.Previous = Previous;
}
}
}
else
{
UWidget* Previous = OrderedWidgetArray[MaxRow][MaxColumn];
if (Cast<ITakesControllerFocus>(Previous) || Cast<UButton>(Previous))
{
FocusMap.Previous = Previous;
}
}
if ((((MaxRow+1) * Column) + Row) < ((MaxRow+1) * (MaxColumn+1)) - 1)
{
if (Row < MaxRow)
{
UWidget* Next = OrderedWidgetArray[Row + 1][Column];
if (Cast<ITakesControllerFocus>(Next) || Cast<UButton>(Next))
{
FocusMap.Next = Next;
}
}
else
{
UWidget* Next = OrderedWidgetArray[0][Column + 1];
if (Cast<ITakesControllerFocus>(Next) || Cast<UButton>(Next))
{
FocusMap.Next = Next;
}
}
}
else
{
UWidget* Next = OrderedWidgetArray[0][0];
if (Cast<ITakesControllerFocus>(Next) || Cast<UButton>(Next))
{
FocusMap.Next = Next;
}
}
}
if (ITakesControllerFocus* ControllerWidget = Cast<ITakesControllerFocus>(Widget))
{
this->FocusableWidgetArray.Add(Widget);
this->WidgetFocusMapArray.Add(FocusMap);
this->NormalStyles.Emplace(Widget, ControllerWidget->Execute_GetNormalStyle(Widget));
this->HoveredStyles.Emplace(Widget, ControllerWidget->Execute_GetHoveredStyle(Widget));
this->PressedStyles.Emplace(Widget, ControllerWidget->Execute_GetPressedStyle(Widget));
this->NormalPaddings.Emplace(Widget, ControllerWidget->Execute_GetNormalPadding(Widget));
this->PressedPaddings.Emplace(Widget, ControllerWidget->Execute_GetPressedPadding(Widget));
ControllerWidget->Execute_SetFocusable(Widget, false);
}
else if (UButton* Button = Cast<UButton>(Widget))
{
this->FocusableWidgetArray.Add(Widget);
this->WidgetFocusMapArray.Add(FocusMap);
this->NormalStyles.Emplace(Widget, Button->WidgetStyle.Normal);
this->HoveredStyles.Emplace(Widget, Button->WidgetStyle.Hovered);
this->PressedStyles.Emplace(Widget, Button->WidgetStyle.Pressed);
this->NormalPaddings.Emplace(Widget, Button->WidgetStyle.NormalPadding);
this->PressedPaddings.Emplace(Widget, Button->WidgetStyle.PressedPadding);
Button->IsFocusable = false;
}
}
}
}
}
void UControllerMenuWidget::AddFocusableWidgetCustom(UWidget* Widget, UWidget* Up, UWidget* Down, UWidget* Left, UWidget* Right, UWidget* Previous, UWidget* Next)
{
this->FocusableWidgetArray.Add(Widget);
FControllerWidgetFocusMap WidgetFocusMap;
WidgetFocusMap.Up = Up;
WidgetFocusMap.Down = Down;
WidgetFocusMap.Left = Left;
WidgetFocusMap.Right = Right;
WidgetFocusMap.Previous = Previous;
WidgetFocusMap.Next = Next;
this->WidgetFocusMapArray.Add(WidgetFocusMap);
if (ITakesControllerFocus* ControllerWidget = Cast<ITakesControllerFocus>(Widget))
{
this->NormalStyles.Emplace(Widget, ControllerWidget->Execute_GetNormalStyle(Widget));
this->HoveredStyles.Emplace(Widget, ControllerWidget->Execute_GetHoveredStyle(Widget));
this->PressedStyles.Emplace(Widget, ControllerWidget->Execute_GetPressedStyle(Widget));
this->NormalPaddings.Emplace(Widget, ControllerWidget->Execute_GetNormalPadding(Widget));
this->PressedPaddings.Emplace(Widget, ControllerWidget->Execute_GetPressedPadding(Widget));
ControllerWidget->Execute_SetFocusable(Widget, false);
}
else if (UButton* Button = Cast<UButton>(Widget))
{
this->NormalStyles.Emplace(Widget, Button->WidgetStyle.Normal);
this->HoveredStyles.Emplace(Widget, Button->WidgetStyle.Hovered);
this->PressedStyles.Emplace(Widget, Button->WidgetStyle.Pressed);
this->NormalPaddings.Emplace(Widget, Button->WidgetStyle.NormalPadding);
this->PressedPaddings.Emplace(Widget, Button->WidgetStyle.PressedPadding);
Button->IsFocusable = false;
}
}
void UControllerMenuWidget::AddVerticalFocusableWidget(UWidget* Widget, UWidget* Left, UWidget* Right)
{
FControllerWidgetFocusMap WidgetFocusMap;
const int32 ArraySize = this->FocusableWidgetArray.Num();
if (ArraySize > 0)
{
WidgetFocusMap.Up = WidgetFocusMap.Previous = this->FocusableWidgetArray[ArraySize - 1];
WidgetFocusMap.Down = WidgetFocusMap.Next = this->FocusableWidgetArray[0];
this->WidgetFocusMapArray[0].Up = this->WidgetFocusMapArray[0].Previous = Widget;
this->WidgetFocusMapArray[ArraySize - 1].Down = this->WidgetFocusMapArray[ArraySize - 1].Next = Widget;
}
WidgetFocusMap.Left = Left;
WidgetFocusMap.Right = Right;
this->FocusableWidgetArray.Add(Widget);
this->WidgetFocusMapArray.Add(WidgetFocusMap);
if (ITakesControllerFocus* ControllerWidget = Cast<ITakesControllerFocus>(Widget))
{
this->NormalStyles.Emplace(Widget, ControllerWidget->Execute_GetNormalStyle(Widget));
this->HoveredStyles.Emplace(Widget, ControllerWidget->Execute_GetHoveredStyle(Widget));
this->PressedStyles.Emplace(Widget, ControllerWidget->Execute_GetPressedStyle(Widget));
this->NormalPaddings.Emplace(Widget, ControllerWidget->Execute_GetNormalPadding(Widget));
this->PressedPaddings.Emplace(Widget, ControllerWidget->Execute_GetPressedPadding(Widget));
ControllerWidget->Execute_SetFocusable(Widget, false);
}
else if (UButton* Button = Cast<UButton>(Widget))
{
this->NormalStyles.Emplace(Widget, Button->WidgetStyle.Normal);
this->HoveredStyles.Emplace(Widget, Button->WidgetStyle.Hovered);
this->PressedStyles.Emplace(Widget, Button->WidgetStyle.Pressed);
this->NormalPaddings.Emplace(Widget, Button->WidgetStyle.NormalPadding);
this->PressedPaddings.Emplace(Widget, Button->WidgetStyle.PressedPadding);
Button->IsFocusable = false;
}
}
void UControllerMenuWidget::AddHorizontalFocusableWidget(UWidget* Widget, UWidget* Up, UWidget* Down)
{
FControllerWidgetFocusMap WidgetFocusMap;
const int32 ArraySize = this->FocusableWidgetArray.Num();
if (ArraySize > 0)
{
WidgetFocusMap.Left = WidgetFocusMap.Previous = this->FocusableWidgetArray[ArraySize - 1];
WidgetFocusMap.Right = WidgetFocusMap.Next = this->FocusableWidgetArray[0];
this->WidgetFocusMapArray[0].Left = this->WidgetFocusMapArray[0].Previous = Widget;
this->WidgetFocusMapArray[ArraySize - 1].Right = this->WidgetFocusMapArray[ArraySize - 1].Next = Widget;
}
WidgetFocusMap.Up = Up;
WidgetFocusMap.Down = Down;
this->FocusableWidgetArray.Add(Widget);
this->WidgetFocusMapArray.Add(WidgetFocusMap);
if (ITakesControllerFocus* ControllerWidget = Cast<ITakesControllerFocus>(Widget))
{
this->NormalStyles.Emplace(Widget, ControllerWidget->Execute_GetNormalStyle(Widget));
this->HoveredStyles.Emplace(Widget, ControllerWidget->Execute_GetHoveredStyle(Widget));
this->PressedStyles.Emplace(Widget, ControllerWidget->Execute_GetPressedStyle(Widget));
this->NormalPaddings.Emplace(Widget, ControllerWidget->Execute_GetNormalPadding(Widget));
this->PressedPaddings.Emplace(Widget, ControllerWidget->Execute_GetPressedPadding(Widget));
ControllerWidget->Execute_SetFocusable(Widget, false);
}
else if (UButton* Button = Cast<UButton>(Widget))
{
this->NormalStyles.Emplace(Widget, Button->WidgetStyle.Normal);
this->HoveredStyles.Emplace(Widget, Button->WidgetStyle.Hovered);
this->PressedStyles.Emplace(Widget, Button->WidgetStyle.Pressed);
this->NormalPaddings.Emplace(Widget, Button->WidgetStyle.NormalPadding);
this->PressedPaddings.Emplace(Widget, Button->WidgetStyle.PressedPadding);
Button->IsFocusable = false;
}
}
void UControllerMenuWidget::EditWidgetFocus(UWidget* Widget, UWidget* Up, UWidget* Down, UWidget* Left, UWidget* Right, UWidget* Previous, UWidget* Next)
{
const int32 WidgetIndex = this->FocusableWidgetArray.Find(Widget);
if (WidgetIndex != INDEX_NONE)
{
FControllerWidgetFocusMap& Map = this->WidgetFocusMapArray[WidgetIndex];
Map.Up = Up ? Up : Map.Up;
Map.Down = Down ? Down : Map.Down;
Map.Left = Left ? Left : Map.Left;
Map.Right = Right ? Right : Map.Right;
Map.Previous = Previous ? Previous : Map.Previous;
Map.Next = Next ? Next : Map.Next;
}
}
void UControllerMenuWidget::SetCancelButton(UWidget* Button)
{
this->CancelButton = Button;
}
void UControllerMenuWidget::InitializeMenuActions()
{
if (GConfig)
{
FString AxisYAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("AxisYAction"), AxisYAction, GGameIni);
if (AxisYAction.IsEmpty())
{
FString UpAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("UpAction"), UpAction, GGameIni);
this->UpActionBinding = FInputActionBinding(FName(*UpAction), EInputEvent::IE_Pressed);
this->UpActionBinding.bExecuteWhenPaused = true;
this->UpActionBinding.bConsumeInput = true;
this->UpActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnUpPressedEvent);
FString DownAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("DownAction"), DownAction, GGameIni);
this->DownActionBinding = FInputActionBinding(FName(*DownAction), EInputEvent::IE_Pressed);
this->DownActionBinding.bExecuteWhenPaused = true;
this->DownActionBinding.bConsumeInput = true;
this->DownActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnDownPressedEvent);
}
else
{
this->AxisYBinding = FInputAxisBinding(FName(*AxisYAction));
this->AxisYBinding.bExecuteWhenPaused = true;
this->AxisYBinding.bConsumeInput = true;
this->AxisYBinding.AxisDelegate.BindDelegate(this, &UControllerMenuWidget::OnAxisYEvent);
}
FString AxisXAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("AxisXAction"), AxisXAction, GGameIni);
if (AxisXAction.IsEmpty())
{
FString LeftAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("LeftAction"), LeftAction, GGameIni);
this->LeftActionBinding = FInputActionBinding(FName(*LeftAction), EInputEvent::IE_Pressed);
this->LeftActionBinding.bExecuteWhenPaused = true;
this->LeftActionBinding.bConsumeInput = true;
this->LeftActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnLeftPressedEvent);
FString RightAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("RightAction"), RightAction, GGameIni);
this->RightActionBinding = FInputActionBinding(FName(*RightAction), EInputEvent::IE_Pressed);
this->RightActionBinding.bExecuteWhenPaused = true;
this->RightActionBinding.bConsumeInput = true;
this->RightActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnRightPressedEvent);
}
else
{
this->AxisXBinding = FInputAxisBinding(FName(*AxisXAction));
this->AxisXBinding.bExecuteWhenPaused = true;
this->AxisXBinding.bConsumeInput = true;
this->AxisXBinding.AxisDelegate.BindDelegate(this, &UControllerMenuWidget::OnAxisXEvent);
}
FString PreviousAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("PreviousAction"), PreviousAction, GGameIni);
this->PreviousActionBinding = FInputActionBinding(FName(*PreviousAction), EInputEvent::IE_Pressed);
this->PreviousActionBinding.bExecuteWhenPaused = true;
this->PreviousActionBinding.bConsumeInput = true;
this->PreviousActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnPreviousPressedEvent);
FString NextAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("NextAction"), NextAction, GGameIni);
this->NextActionBinding = FInputActionBinding(FName(*NextAction), EInputEvent::IE_Pressed);
this->NextActionBinding.bExecuteWhenPaused = true;
this->NextActionBinding.bConsumeInput = true;
this->NextActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnNextPressedEvent);
FString AcceptAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("AcceptAction"), AcceptAction, GGameIni);
const FName AcceptActionName(*AcceptAction);
this->AcceptPressActionBinding = FInputActionBinding(AcceptActionName, EInputEvent::IE_Pressed);
this->AcceptPressActionBinding.bExecuteWhenPaused = true;
this->AcceptPressActionBinding.bConsumeInput = true;
this->AcceptPressActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnAcceptPressedEvent);
this->AcceptReleaseActionBinding = FInputActionBinding(AcceptActionName, EInputEvent::IE_Released);
this->AcceptReleaseActionBinding.bExecuteWhenPaused = true;
this->AcceptReleaseActionBinding.bConsumeInput = true;
this->AcceptReleaseActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnAcceptReleasedEvent);
FString CancelAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("CancelAction"), CancelAction, GGameIni);
const FName CancelActionName(*CancelAction);
this->CancelPressActionBinding = FInputActionBinding(CancelActionName, EInputEvent::IE_Pressed);
this->CancelPressActionBinding.bExecuteWhenPaused = true;
this->CancelPressActionBinding.bConsumeInput = true;
this->CancelPressActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnCancelPressedEvent);
this->CancelReleaseActionBinding = FInputActionBinding(CancelActionName, EInputEvent::IE_Released);
this->CancelReleaseActionBinding.bExecuteWhenPaused = true;
this->CancelReleaseActionBinding.bConsumeInput = true;
this->CancelReleaseActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnCancelReleasedEvent);
FString PauseAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("PauseAction"), PauseAction, GGameIni);
this->PauseActionBinding = FInputActionBinding(FName(*PauseAction), EInputEvent::IE_Pressed);
this->PauseActionBinding.bExecuteWhenPaused = true;
this->PauseActionBinding.bConsumeInput = true;
this->PauseActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnPausePressedEvent);
//for (const FName CustomAction : this->CustomActions)
//{
// this->CustomActionBinding = FInputActionBinding(CustomAction, EInputEvent::IE_Pressed);
// this->CustomActionBinding.bExecuteWhenPaused = true;
// this->CustomActionBinding.bConsumeInput = false;
// this->CustomActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnCustomPressedEvent, CustomAction);
//}
}
}
void UControllerMenuWidget::BindMenuActions()
{
if (!this->InputComponent)
{
this->InitializeInputComponent();
if (!this->InputComponent)
{
return;
}
}
if (this->AxisYBinding.AxisName.IsNone())
{
this->InputComponent->AddActionBinding(this->UpActionBinding);
this->InputComponent->AddActionBinding(this->DownActionBinding);
}
else
{
this->InputComponent->AxisBindings.Emplace(this->AxisYBinding);
}
if (this->AxisXBinding.AxisName.IsNone())
{
this->InputComponent->AddActionBinding(this->LeftActionBinding);
this->InputComponent->AddActionBinding(this->RightActionBinding);
}
else
{
this->InputComponent->AxisBindings.Emplace(this->AxisXBinding);
}
this->InputComponent->AddActionBinding(this->PreviousActionBinding);
this->InputComponent->AddActionBinding(this->NextActionBinding);
this->InputComponent->AddActionBinding(this->AcceptPressActionBinding);
this->InputComponent->AddActionBinding(this->AcceptReleaseActionBinding);
this->InputComponent->AddActionBinding(this->CancelPressActionBinding);
this->InputComponent->AddActionBinding(this->CancelReleaseActionBinding);
this->InputComponent->AddActionBinding(this->PauseActionBinding);
//for (const FName CustomAction : this->CustomActions)
//{
// this->InputComponent->AddActionBinding(this->CustomActionBinding);
//}
}
void UControllerMenuWidget::UnbindMenuActions()
{
APlayerController* Controller = this->GetOwningPlayer();
if (Controller && GConfig)
{
FString AxisYAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("AxisYAction"), AxisYAction, GGameIni);
if (AxisYAction.IsEmpty())
{
FString UpAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("UpAction"), UpAction, GGameIni);
this->InputComponent->RemoveActionBinding(*UpAction, EInputEvent::IE_Pressed);
FString DownAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("DownAction"), DownAction, GGameIni);
this->InputComponent->RemoveActionBinding(*DownAction, EInputEvent::IE_Pressed);
}
else
{
const int32 LastBinding = this->InputComponent->AxisBindings.Num() - 1;
for (int32 i = LastBinding; i >= 0; i--)
{
FInputAxisBinding &Binding = this->InputComponent->AxisBindings[i];
if ((Binding.AxisName == this->AxisYBinding.AxisName) &&
(Binding.AxisDelegate.GetDelegateForManualSet().GetHandle() == this->AxisYBinding.AxisDelegate.GetDelegateForManualSet().GetHandle()))
{
this->InputComponent->AxisBindings.RemoveAt(i);
}
}
}
FString AxisXAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("AxisXAction"), AxisXAction, GGameIni);
if (AxisXAction.IsEmpty())
{
FString LeftAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("LeftAction"), LeftAction, GGameIni);
this->InputComponent->RemoveActionBinding(*LeftAction, EInputEvent::IE_Pressed);
FString RightAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("RightAction"), RightAction, GGameIni);
this->InputComponent->RemoveActionBinding(*RightAction, EInputEvent::IE_Pressed);
}
else
{
const int32 LastBinding = this->InputComponent->AxisBindings.Num() - 1;
for (int32 i = LastBinding; i >= 0; i--)
{
FInputAxisBinding &Binding = this->InputComponent->AxisBindings[i];
if ((Binding.AxisName == this->AxisXBinding.AxisName) &&
(Binding.AxisDelegate.GetDelegateForManualSet().GetHandle() == this->AxisXBinding.AxisDelegate.GetDelegateForManualSet().GetHandle()))
{
this->InputComponent->AxisBindings.RemoveAt(i);
}
}
}
FString PreviousAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("PreviousAction"), PreviousAction, GGameIni);
this->InputComponent->RemoveActionBinding(*PreviousAction, EInputEvent::IE_Pressed);
FString NextAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("NextAction"), NextAction, GGameIni);
this->InputComponent->RemoveActionBinding(*NextAction, EInputEvent::IE_Pressed);
FString AcceptAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("AcceptAction"), AcceptAction, GGameIni);
this->InputComponent->RemoveActionBinding(*AcceptAction, EInputEvent::IE_Pressed);
this->InputComponent->RemoveActionBinding(*AcceptAction, EInputEvent::IE_Released);
FString CancelAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("CancelAction"), CancelAction, GGameIni);
this->InputComponent->RemoveActionBinding(*CancelAction, EInputEvent::IE_Pressed);
this->InputComponent->RemoveActionBinding(*CancelAction, EInputEvent::IE_Released);
FString PauseAction;
GConfig->GetString(TEXT("/Script/ControllerMenu.ControllerMenuGlobalSettings"), TEXT("PauseAction"), PauseAction, GGameIni);
this->InputComponent->RemoveActionBinding(*PauseAction, EInputEvent::IE_Pressed);
//for (const FName CustomAction : this->CustomActions)
//{
// this->CustomActionBinding = FInputActionBinding(CustomAction, EInputEvent::IE_Pressed);
// this->CustomActionBinding.bExecuteWhenPaused = true;
// this->CustomActionBinding.bConsumeInput = true;
// this->CustomActionBinding.ActionDelegate.BindDelegate(this, &UControllerMenuWidget::OnCustomPressedEvent, CustomAction);
// this->InputComponent->AddActionBinding(this->CustomActionBinding);
//}
}
}
void UControllerMenuWidget::OnAxisYEvent(const float AxisValue)
{
if (!this->bAxisYHasMoved)
{
if (AxisValue >= this->AxisMovementThreshold)
{
this->OnUpPressedEvent();
this->bAxisYHasMoved = true;
}
else if (AxisValue <= -this->AxisMovementThreshold)
{
this->OnDownPressedEvent();
this->bAxisYHasMoved = true;
}
}
else
{
if (FMath::Abs(AxisValue) < this->AxisMovementThreshold)
{
this->bAxisYHasMoved = false;
}
}
}
void UControllerMenuWidget::OnAxisXEvent(const float AxisValue)
{
if (!this->bAxisXHasMoved)
{
if (AxisValue >= this->AxisMovementThreshold)
{
this->OnRightPressedEvent();
this->bAxisXHasMoved = true;
}
else if (AxisValue <= -this->AxisMovementThreshold)
{
this->OnLeftPressedEvent();
this->bAxisXHasMoved = true;
}
}
else
{
if (FMath::Abs(AxisValue) < this->AxisMovementThreshold)
{
this->bAxisXHasMoved = false;
}
}
}
void UControllerMenuWidget::NativeOnUpPressed()
{
if (this->FocusableWidgetArray.Num() > 0)
{
if (this->FocusedWidgetIndex >= 0 && this->FocusedWidgetIndex < this->FocusableWidgetArray.Num())
{
this->SetWidgetFocus(this->WidgetFocusMapArray[this->FocusedWidgetIndex].Up);
}
else
{
this->FocusedWidgetIndex = 0;
this->SetWidgetFocus(this->FocusableWidgetArray[this->FocusedWidgetIndex]);
}
}
}
void UControllerMenuWidget::NativeOnDownPressed()
{
if (this->FocusableWidgetArray.Num() > 0)
{
if (this->FocusedWidgetIndex >= 0 && this->FocusedWidgetIndex < this->FocusableWidgetArray.Num())
{
this->SetWidgetFocus(this->WidgetFocusMapArray[this->FocusedWidgetIndex].Down);
}
else
{
this->FocusedWidgetIndex = 0;
this->SetWidgetFocus(this->FocusableWidgetArray[this->FocusedWidgetIndex]);
}
}
}
void UControllerMenuWidget::NativeOnLeftPressed()
{
if (this->FocusableWidgetArray.Num() > 0)
{
if (this->FocusedWidgetIndex >= 0 && this->FocusedWidgetIndex < this->FocusableWidgetArray.Num())
{
this->SetWidgetFocus(this->WidgetFocusMapArray[this->FocusedWidgetIndex].Left);
}
else
{
this->FocusedWidgetIndex = 0;
this->SetWidgetFocus(this->FocusableWidgetArray[this->FocusedWidgetIndex]);
}
}
}
void UControllerMenuWidget::NativeOnRightPressed()
{
if (this->FocusableWidgetArray.Num() > 0)
{
if (this->FocusedWidgetIndex >= 0 && this->FocusedWidgetIndex < this->FocusableWidgetArray.Num())
{
this->SetWidgetFocus(this->WidgetFocusMapArray[this->FocusedWidgetIndex].Right);
}
else
{
this->FocusedWidgetIndex = 0;
this->SetWidgetFocus(this->FocusableWidgetArray[this->FocusedWidgetIndex]);
}
}
}
void UControllerMenuWidget::NativeOnPreviousPressed()
{
if (this->FocusableWidgetArray.Num() > 0)
{
if (this->FocusedWidgetIndex >= 0 && this->FocusedWidgetIndex < this->FocusableWidgetArray.Num())
{
this->SetWidgetFocus(this->WidgetFocusMapArray[this->FocusedWidgetIndex].Previous);
}
else
{
this->FocusedWidgetIndex = 0;
this->SetWidgetFocus(this->FocusableWidgetArray[this->FocusedWidgetIndex]);
}
}
}
void UControllerMenuWidget::NativeOnNextPressed()
{
if (this->FocusableWidgetArray.Num() > 0)
{
if (this->FocusedWidgetIndex >= 0 && this->FocusedWidgetIndex < this->FocusableWidgetArray.Num())
{
this->SetWidgetFocus(this->WidgetFocusMapArray[this->FocusedWidgetIndex].Next);
}
else
{
this->FocusedWidgetIndex = 0;
this->SetWidgetFocus(this->FocusableWidgetArray[this->FocusedWidgetIndex]);
}
}
}
void UControllerMenuWidget::NativeOnAcceptPressed()
{
if (UWidget* PressedWidget = this->GetFocusedWidget())
{
if (ITakesControllerFocus* PressedControllerWidget = Cast<ITakesControllerFocus>(PressedWidget))
{
PressedControllerWidget->Execute_Press(PressedWidget);
}
else if (UButton* PressedButton = Cast<UButton>(PressedWidget))
{
PressedButton->WidgetStyle.Normal = this->PressedStyles[PressedWidget];
PressedButton->WidgetStyle.NormalPadding = this->PressedPaddings[PressedWidget];
PressedButton->OnPressed.Broadcast();
}
this->Refocus(PressedWidget);
}
}
void UControllerMenuWidget::NativeOnCancelPressed()
{
if (this->CancelButton)
{
if (this->CancelConfirm && !this->HasWidgetFocus(this->CancelButton))
{
this->SetWidgetFocus(this->CancelButton);
return;
}
else if (ITakesControllerFocus* PressedControllerWidget = Cast<ITakesControllerFocus>(this->CancelButton))
{
UWidget* FocusedWidget = this->GetFocusedWidget();
if (ITakesControllerFocus* FocusedControllerWidget = Cast<ITakesControllerFocus>(FocusedWidget))
{
FocusedControllerWidget->Execute_Unhover(FocusedWidget);
}
else if (UButton* FocusedButton = Cast<UButton>(FocusedWidget))
{
FocusedButton->WidgetStyle.Normal = this->NormalStyles[this->CancelButton];
FocusedButton->WidgetStyle.NormalPadding = this->NormalPaddings[this->CancelButton];
}
PressedControllerWidget->Execute_Press(this->CancelButton);
}
else if (UButton* PressedButton = Cast<UButton>(this->CancelButton))
{
UWidget* FocusedWidget = this->GetFocusedWidget();
if (ITakesControllerFocus* FocusedControllerWidget = Cast<ITakesControllerFocus>(FocusedWidget))
{
FocusedControllerWidget->Execute_Unhover(FocusedWidget);
}
else if (UButton* FocusedButton = Cast<UButton>(FocusedWidget))
{
FocusedButton->WidgetStyle.Normal = this->NormalStyles[this->CancelButton];
FocusedButton->WidgetStyle.NormalPadding = this->NormalPaddings[this->CancelButton];
}
PressedButton->WidgetStyle.Normal = this->PressedStyles[this->CancelButton];
PressedButton->WidgetStyle.NormalPadding = this->PressedPaddings[this->CancelButton];
PressedButton->OnPressed.Broadcast();
}
this->Refocus(this->CancelButton);
}
}
void UControllerMenuWidget::NativeOnAcceptReleased()
{
if (UWidget* ReleasedWidget = this->GetFocusedWidget())
{
if (ITakesControllerFocus* ReleasedControllerWidget = Cast<ITakesControllerFocus>(ReleasedWidget))
{
ReleasedControllerWidget->Execute_Release(ReleasedWidget);
}
else if (UButton* ReleasedButton = Cast<UButton>(ReleasedWidget))
{
ReleasedButton->WidgetStyle.Normal = this->HoveredStyles[ReleasedWidget];
ReleasedButton->WidgetStyle.NormalPadding = this->NormalPaddings[ReleasedWidget];
ReleasedButton->OnReleased.Broadcast();
}
this->Refocus(ReleasedWidget);
}
}
void UControllerMenuWidget::NativeOnCancelReleased()
{
if (this->CancelButton && this->HasWidgetFocus(this->CancelButton))
{
if (ITakesControllerFocus* ReleasedControllerWidget = Cast<ITakesControllerFocus>(this->CancelButton))
{
ReleasedControllerWidget->Execute_Release(this->CancelButton);
}
else if (UButton* ReleasedButton = Cast<UButton>(this->CancelButton))
{
ReleasedButton->WidgetStyle.Normal = this->HoveredStyles[this->CancelButton];
ReleasedButton->WidgetStyle.NormalPadding = this->NormalPaddings[this->CancelButton];
ReleasedButton->OnReleased.Broadcast();
}
this->Refocus(this->CancelButton);
}
}
void UControllerMenuWidget::OnUpPressedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable)
{
//const FControllerWidgetFocusMap &WidgetFocusMap = this->WidgetFocusMapArray[this->FocusedWidgetIndex];
//if (WidgetFocusMap.Up)
//{
// this->FocusedWidgetIndex = this->FocusableWidgetArray.Find(WidgetFocusMap.Up);
// this->ResetFocus();
//}
this->NativeOnUpPressed();
this->OnUpPressed();
this->OnUpPressedDelegate.Broadcast();
}
}
void UControllerMenuWidget::OnDownPressedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable)
{
//const FControllerWidgetFocusMap &WidgetFocusMap = this->WidgetFocusMapArray[this->FocusedWidgetIndex];
//if (WidgetFocusMap.Down)
//{
// this->FocusedWidgetIndex = this->FocusableWidgetArray.Find(WidgetFocusMap.Down);
// this->ResetFocus();
//}
this->NativeOnDownPressed();
this->OnDownPressed();
this->OnDownPressedDelegate.Broadcast();
}
}
void UControllerMenuWidget::OnLeftPressedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable && this->FocusedWidgetIndex >= 0)
{
const FControllerWidgetFocusMap& WidgetFocusMap = this->WidgetFocusMapArray[this->FocusedWidgetIndex];
if (!WidgetFocusMap.Left)
{
if (UTextSpinner* TextSpinner = Cast<UTextSpinner>(this->GetFocusedWidget()))
{
TextSpinner->PreviousItem();
}
}
this->NativeOnLeftPressed();
this->OnLeftPressed();
this->OnLeftPressedDelegate.Broadcast();
}
}
void UControllerMenuWidget::OnRightPressedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable && this->FocusedWidgetIndex >= 0)
{
const FControllerWidgetFocusMap& WidgetFocusMap = this->WidgetFocusMapArray[this->FocusedWidgetIndex];
if (!WidgetFocusMap.Right)
{
if (UTextSpinner* TextSpinner = Cast<UTextSpinner>(this->GetFocusedWidget()))
{
TextSpinner->NextItem();
}
}
this->NativeOnRightPressed();
this->OnRightPressed();
this->OnRightPressedDelegate.Broadcast();
}
}
void UControllerMenuWidget::OnPreviousPressedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable)
{
//const FControllerWidgetFocusMap &WidgetFocusMap = this->WidgetFocusMapArray[this->FocusedWidgetIndex];
//if (WidgetFocusMap.Previous)
//{
// this->FocusedWidgetIndex = this->FocusableWidgetArray.Find(WidgetFocusMap.Previous);
// this->ResetFocus();
//}
this->NativeOnPreviousPressed();
this->OnPreviousPressed();
this->OnPreviousPressedDelegate.Broadcast();
}
}
void UControllerMenuWidget::OnNextPressedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable)
{
//const FControllerWidgetFocusMap &WidgetFocusMap = this->WidgetFocusMapArray[this->FocusedWidgetIndex];
//if (WidgetFocusMap.Next)
//{
// this->FocusedWidgetIndex = this->FocusableWidgetArray.Find(WidgetFocusMap.Next);
// this->ResetFocus();
//}
this->NativeOnNextPressed();
this->OnNextPressed();
this->OnNextPressedDelegate.Broadcast();
}
}
void UControllerMenuWidget::OnAcceptPressedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable)
{
this->NativeOnAcceptPressed();
this->OnAcceptPressed();
this->OnAcceptPressedDelegate.Broadcast();
}
}
void UControllerMenuWidget::OnCancelPressedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable)
{
this->NativeOnCancelPressed();
this->OnCancelPressed();
this->OnCancelPressedDelegate.Broadcast();
}
}
void UControllerMenuWidget::OnPausePressedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable)
{
this->NativeOnPausePressed();
this->OnPausePressed();
this->OnPausePressedDelegate.Broadcast();
}
}
void UControllerMenuWidget::OnCustomPressedEvent(const FName CustomAction)
{
if (this->bIsInteractable)
{
this->NativeOnCustomPressed(CustomAction);
this->OnCustomPressed(CustomAction);
//this->OnCustomPressedDelegate.Broadcast();
}
}
void UControllerMenuWidget::OnAcceptReleasedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable)
{
this->NativeOnAcceptReleased();
}
}
void UControllerMenuWidget::OnCancelReleasedEvent()
{
if (!this->IsAnyAnimationPlaying() && this->bIsInteractable)
{
this->NativeOnCancelReleased();
}
}
void UControllerMenuWidget::SetWidgetFocus(UWidget *NewWidget)
{
if (NewWidget && (NewWidget->IsVisible() && NewWidget->GetIsEnabled()))
{
if (UWidget *FocusedWidget = this->GetFocusedWidget())
{
if (ITakesControllerFocus *FocusedControllerWidget = Cast<ITakesControllerFocus>(FocusedWidget))
{
FocusedControllerWidget->Execute_Unhover(FocusedWidget);
}
else if (UButton *FocusedButton = Cast<UButton>(FocusedWidget))
{
FocusedButton->WidgetStyle.Normal = this->NormalStyles[FocusedWidget];
FocusedButton->WidgetStyle.NormalPadding = this->NormalPaddings[FocusedWidget];
FocusedButton->OnUnhovered.Broadcast();
}
}
this->FocusedWidgetIndex = this->FocusableWidgetArray.Find(NewWidget);
if (UWidget *FocusedWidget = this->GetFocusedWidget())
{
if (ITakesControllerFocus *FocusedControllerWidget = Cast<ITakesControllerFocus>(FocusedWidget))
{
FocusedControllerWidget->Execute_Hover(FocusedWidget);
}
else if (UButton *FocusedButton = Cast<UButton>(FocusedWidget))
{
FocusedButton->WidgetStyle.Normal = this->HoveredStyles[FocusedWidget];
FocusedButton->WidgetStyle.NormalPadding = this->NormalPaddings[FocusedWidget];
FocusedButton->OnHovered.Broadcast();
}
}
this->FocusChanged(this->GetFocusedWidget());
}
// HACK: Enable focus for this widget, focus, then reset focus setting.
// This allows us to keep focus inside the widget while preventing Slate
// from using its own input handling, and also bypasses a warning about
// setting focus to an unfocusable widget.
this->bIsFocusable = true;
this->SetKeyboardFocus();
this->bIsFocusable = false;
if (UWidget *FocusedWidget = this->GetFocusedWidget())
{
this->FindParentScrollBoxRecursive(FocusedWidget, FocusedWidget->GetParent());
}
}
void UControllerMenuWidget::FindParentScrollBoxRecursive(UWidget *FocusedWidget, UWidget *WidgetParent)
{
if (WidgetParent != nullptr)
{
if (UScrollBox *ScrollBox = Cast<UScrollBox>(WidgetParent))
{
ScrollBox->ScrollWidgetIntoView(FocusedWidget, true);
}
else
{
this->FindParentScrollBoxRecursive(FocusedWidget, WidgetParent->GetParent());
}
}
}
bool UControllerMenuWidget::HasWidgetFocus(UWidget* Widget) const
{
if (Widget)
{
return this->FocusedWidgetIndex == this->FocusableWidgetArray.Find(Widget);
}
return false;
}
void UControllerMenuWidget::ClearWidgetFocus()
{
if (UWidget* Widget = this->GetFocusedWidget())
{
if (ITakesControllerFocus* FocusedControllerWidget = Cast<ITakesControllerFocus>(Widget))
{
FocusedControllerWidget->Execute_Unhover(Widget);
}
else if (UButton* FocusedButton = Cast<UButton>(Widget))
{
FocusedButton->WidgetStyle.Normal = this->NormalStyles[Widget];
FocusedButton->WidgetStyle.NormalPadding = this->NormalPaddings[Widget];
}
}
this->FocusedWidgetIndex = -1;
this->FocusChanged(nullptr);
// HACK: Enable focus for this widget, focus, then reset focus setting.
// This allows us to keep focus inside the widget while preventing Slate
// from using its own input handling, and also bypasses a warning about
// setting focus to an unfocusable widget.
this->bIsFocusable = true;
this->SetKeyboardFocus();
this->bIsFocusable = false;
}
void UControllerMenuWidget::Refocus(const UWidget* FocusedWidget)
{
// If the current widget is not in focus any more, find a new widget to focus on
if (!FocusedWidget->GetIsEnabled())
{
const FControllerWidgetFocusMap& FocusMap = this->WidgetFocusMapArray[this->FocusedWidgetIndex];
if (FocusMap.Down) { this->SetWidgetFocus(FocusMap.Down); }
else if (FocusMap.Right) { this->SetWidgetFocus(FocusMap.Right); }
else if (FocusMap.Up) { this->SetWidgetFocus(FocusMap.Up); }
else if (FocusMap.Left) { this->SetWidgetFocus(FocusMap.Left); }
else if (FocusMap.Next) { this->SetWidgetFocus(FocusMap.Next); }
else if (FocusMap.Previous) { this->SetWidgetFocus(FocusMap.Previous); }
else { this->SetWidgetFocus(*this->FocusableWidgetArray.begin()); }
}
}
void UControllerMenuWidget::SetNewInputDevice(const EControllerMenuInputDevice& NewInputDevice)
{
if (this->LastInputDevice != NewInputDevice)
{
this->LastInputDevice = NewInputDevice;
if (NewInputDevice != EControllerMenuInputDevice::Mouse)
{
this->MouseMovementStartPosition = FVector2D::ZeroVector;
}
this->InputDeviceChanged(NewInputDevice);
}
}
FName UControllerMenuWidget::GetInputDeviceName() const
{
switch (this->LastInputDevice)
{
case EControllerMenuInputDevice::Mouse:
return TEXT("Mouse");
case EControllerMenuInputDevice::Touchscreen:
return TEXT("Touchscreen");
case EControllerMenuInputDevice::Keyboard:
return TEXT("Keyboard");
case EControllerMenuInputDevice::Controller:
return TEXT("Controller");
}
return TEXT("None");
}