320 lines
7.4 KiB
C++
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);
|
|
}
|
|
}
|