haxis/Source/UnrealProject/GUI/Menu/SubMenu.cpp

320 lines
7.4 KiB
C++

// Project Lab - NHTV Igad
#include "UnrealProject.h"
#include "SubMenu.h"
#include "PlayerControllerBase.h"
#include "MenuButton.h"
#include "DefaultGameInstance.h"
#include "MenuScreenBase.h"
#include "EffectFunctionLibrary.h"
#include "ScreenOverlay.h"
USoundBase* confirmAudioClass;
USoundBase* backAudioClass;
USoundBase* selectionChangedAudioClass;
USoundBase* clickAudioClass;
USubMenu::USubMenu(const FObjectInitializer& init)
{
selectionChangedAudioClass = ConstructorHelpers::FObjectFinder<USoundBase>(TEXT("/Game/Assets/GUI/Components/InterfaceSounds/Select2")).Object;
backAudioClass = ConstructorHelpers::FObjectFinder<USoundBase>(TEXT("/Game/Assets/GUI/Components/InterfaceSounds/Select0")).Object;
confirmAudioClass = ConstructorHelpers::FObjectFinder<USoundBase>(TEXT("/Game/Assets/GUI/Components/InterfaceSounds/Select1")).Object;
clickAudioClass = ConstructorHelpers::FObjectFinder<USoundBase>(TEXT("/Game/Assets/Sound/T_SkillDrop")).Object;
}
void USubMenu::NativeConstruct()
{
m_focus = false;
m_layoutDirection = 0;
container = Cast<UPanelWidget>(WidgetTree->FindWidget("SubMenuContainer"));
if(!container)
{
container = Cast<UPanelWidget>(GetRootWidget());
if(!container)
{
GERROR("No \"Container\" found in widget " + GetName() + ", root widget was not a PanelWidget");
}
}
Super::NativeConstruct();
m_selectedItem = 0;
RescanItems();
}
void USubMenu::NativeDestruct()
{
Super::NativeDestruct();
}
void USubMenu::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
Super::NativeTick(MyGeometry, InDeltaTime);
if(HasFocus())
{
for(UMenuItemBase* item : m_items)
{
item->FocusTick(InDeltaTime);
}
}
}
void USubMenu::m_ScanContainer(UWidget* widget, int32 depth /*= 0*/)
{
// Loop through panel widgets
UPanelWidget* panel = Cast<UPanelWidget>(widget);
if(panel)
{
for(int32 i = 0; i < panel->GetChildrenCount(); i++)
{
m_ScanContainer(panel->GetChildAt(i), depth+1);
}
return;
}
// Process Menu items
UMenuItemBase* item = Cast<UMenuItemBase>(widget);
if(item)
{
bool hidden = item->GetVisibility() == ESlateVisibility::Hidden || item->GetVisibility() == ESlateVisibility::Collapsed;
if(!hidden)
{
m_items.Add(item);
// Assign item to a submenu
item->m_subMenu = this;
}
return;
}
UPanelUserWidget* puw = Cast<UPanelUserWidget>(widget);
if(puw)
{
m_ScanContainer(puw->GetRootWidget());
return;
}
}
void USubMenu::RescanItems()
{
m_items.SetNum(0);
if(container)
{
if(Cast<UHorizontalBox>(container))
{
m_layoutDirection = 1;
}
else
{
m_layoutDirection = 0;
}
// Scan for buttons
m_ScanContainer(container);
int32 childCount = m_items.Num();
// Clamp selection
m_selectedItem = FMath::Clamp(m_selectedItem, 0, childCount - 1);
// Set active selection
for(int32 i = 0; i < childCount; i++)
{
UMenuItemBase* item = m_items[i];
item->index = i;
if(i == m_selectedItem)
{
item->NativeOnSelectionChanged(true, true);
}
else
{
item->NativeOnSelectionChanged(false, true);
}
}
// Reselect single items
if(childCount == 1)
{
m_items[0]->NativeOnSelectionChanged(false, true);
m_items[0]->NativeOnSelectionChanged(true, true);
}
if(childCount > 0)
{
// Selection event
onItemSelected.Broadcast(m_items[m_selectedItem]);
}
}
else
{
GWWARNING(L"SubMenu Container not set");
return;
}
}
void USubMenu::CloseSubMenu()
{
if(m_screen)
m_screen->CloseSubMenu(this);
}
void USubMenu::OnEnter(class UMenuScreenBase* screen)
{
check(screen);
m_screen = screen;
SetButtonHints();
onOpened.Broadcast();
m_SetFocus(true);
}
void USubMenu::OnLeave()
{
onClosed.Broadcast();
m_screen = nullptr;
m_SetFocus(false);
}
bool USubMenu::HasFocus() const
{
return m_focus;
}
void USubMenu::OnSuspend(USubMenu* newSubMenu, bool loseFocus)
{
if(loseFocus)
m_SetFocus(false);
onSuspend.Broadcast();
}
void USubMenu::OnRestore(USubMenu* removedMenu)
{
SetButtonHints();
m_SetFocus(true);
onRestore.Broadcast();
}
class UButtonHintBar* USubMenu::GetButtonHintBar() const
{
return GetScreen()->GetButtonHintBar();
}
class UCharacterSettings* USubMenu::GetCharacterSettings() const
{
return GetGameInstance()->GetCharacterSettings();
}
class UPrefs* USubMenu::GetPrefs() const
{
return GetGameInstance()->GetPrefs();
}
class UDefaultGameInstance* USubMenu::GetGameInstance() const
{
return Cast<UDefaultGameInstance>(GetWorld()->GetGameInstance());
}
void USubMenu::NativeOnMenuAction(EMenuActionBinding binding)
{
if(m_items.Num() > 0)
m_items[m_selectedItem]->NativeOnMenuAction(binding);
switch(binding)
{
case EMenuActionBinding::Down:
if(m_items.Num() > 0 && m_layoutDirection == 0)
SelectNewItemByIndex(FMath::Clamp(m_selectedItem + 1, 0, GetNumItems()-1), true);
break;
case EMenuActionBinding::Up:
if(m_items.Num() > 0 && m_layoutDirection == 0)
SelectNewItemByIndex(FMath::Clamp(m_selectedItem - 1, 0, GetNumItems()-1), true);
break;
case EMenuActionBinding::Left:
if(m_items.Num() > 0 && m_layoutDirection == 1)
SelectNewItemByIndex(FMath::Clamp(m_selectedItem - 1, 0, GetNumItems() - 1), true);
break;
case EMenuActionBinding::Right:
if(m_items.Num() > 0 && m_layoutDirection == 1)
SelectNewItemByIndex(FMath::Clamp(m_selectedItem + 1, 0, GetNumItems() - 1), true);
break;
case EMenuActionBinding::Confirm:
break;
case EMenuActionBinding::Back:
onBack.Broadcast();
UEffectFunctionLibrary::PlaySoundEffect2D(GetWorld(), backAudioClass);
break;
}
Super::NativeOnMenuAction(binding);
}
void USubMenu::NativeOnSelectionConfirmed(UMenuItemBase* item)
{
UEffectFunctionLibrary::PlaySoundEffect2D(GetWorld(), clickAudioClass);
onItemSelectionConfirmed.Broadcast(m_items[m_selectedItem]);
}
UMenuItemBase* USubMenu::GetItem(int32 index) const
{
if(index >= m_items.Num() || index < 0)
{
GWWARNING(L"Item index out of range");
return nullptr;
}
return m_items[index];
}
int32 USubMenu::GetNumItems() const
{
return m_items.Num();
}
int32 USubMenu::GetSelectedItem() const
{
return m_selectedItem;
}
void USubMenu::SelectNewItemByIndex(int32 idx)
{
SelectNewItemByIndex(idx, false);
}
void USubMenu::SelectNewItemByIndex(int32 idx, bool controller)
{
if(idx >= m_items.Num() || idx < 0)
{
GWWARNING(L"Item index out of range");
return;
}
if(m_selectedItem != idx)
{
check(m_selectedItem < m_items.Num());
m_items[m_selectedItem]->NativeOnSelectionChanged(false, controller);
m_items[idx]->NativeOnSelectionChanged(true, controller);
m_selectedItem = idx;
onItemSelected.Broadcast(m_items[m_selectedItem]);
SetButtonHints();
UEffectFunctionLibrary::PlaySoundEffect2D(GetWorld(), selectionChangedAudioClass);
}
}
void USubMenu::SelectNewItem(UMenuItemBase* item)
{
int32 idx = 0;
if (m_items.Find(item, idx))
{
SelectNewItemByIndex(idx);
}
}
int32 USubMenu::GetItemIndex(UMenuItemBase* item)
{
int32 idx = 0;
if (m_items.Find(item, idx))
return idx;
return -1;
}
UMenuScreenBase* USubMenu::GetScreen() const
{
return m_screen;
}
void USubMenu::m_SetFocus(bool focus)
{
m_focus = focus;
// Get Selected button
UMenuItemBase* item = GetItem(GetSelectedItem());
if (item)
{
item->NativeOnSelectionChanged(true, false);
}
}