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

338 lines
7.9 KiB
C++

// Project Lab - NHTV Igad
#include "UnrealProject.h"
#include "MenuScreen.h"
#include "ButtonHintBar.h"
#include "SubMenu.h"
#include "MenuButton.h"
void UMenuScreen::NativeConstruct()
{
Super::NativeConstruct();
m_sideViewActive = false;
m_buttonHintBar = Cast<UButtonHintBar>(WidgetTree->FindWidget("ButtonHintBar"));
m_menuContainer = Cast<UOverlay>(WidgetTree->FindWidget("MenuContainer"));
m_sideViewContainer = Cast<UOverlay>(WidgetTree->FindWidget("SideViewContainer"));
m_menuTitle = Cast<UTextBlock>(WidgetTree->FindWidget("MenuTitle"));
m_sideViewTitle = Cast<UTextBlock>(WidgetTree->FindWidget("SideViewTitle"));
}
UMenuPanel* UMenuScreen::OpenScreenMenu(TSubclassOf<UMenuPanel> cls)
{
UMenuPanel* menu = CreateWidget<UMenuPanel>(GetWorld(), cls);
if(!menu)
{
GERROR("Failed to create menu for screen " + GetName());
return nullptr;
}
m_menuContainer->AddChildToOverlay(menu);
OpenSubMenu(menu);
menu->FadeIn();
return menu;
}
USideView* UMenuScreen::OpenSideView(TSubclassOf<class USideView> cls)
{
USideView* view = CreateWidget<USideView>(GetWorld(), cls);
if(!view)
{
GERROR("Failed to create side view for screen " + GetName());
return nullptr;
}
UPersistentSideView* pview = Cast<UPersistentSideView>(view);
UOverlaySlot* slot = m_sideViewContainer->AddChildToOverlay(view);
slot->SetHorizontalAlignment(HAlign_Fill);
slot->SetVerticalAlignment(VAlign_Fill);
if(pview)
m_OpenSubMenu(view, false);
else
OpenSubMenu(view);
view->FadeIn();
// Switch side view active event
if(!m_sideViewActive)
{
SwitchSideViewVisible(true);
m_sideViewActive = true;
}
return view;
}
void UMenuScreen::CloseAllSideViews()
{
TArray<USideView*> viewsToRemove;
for(int32 i = 0; i < m_sideViewContainer->GetChildrenCount(); i++)
{
USideView* sv = Cast<USideView>(m_sideViewContainer->GetChildAt(i));
if(sv && !sv->IsA<UPersistentSideView>())
viewsToRemove.Add(sv);
}
for(USideView* sv : viewsToRemove)
{
CloseSubMenu(sv);
}
}
void UMenuScreen::OpenPersistentSideView(UPersistentSideView* sideView)
{
UMenuScreen::OpenSubMenu(sideView);
}
void UMenuScreen::ClosePersistentSideView(UPersistentSideView* sideView)
{
m_CloseSubMenu(sideView, true);
}
void UMenuScreen::OpenSubMenu(class USubMenu* submenu)
{
m_OpenSubMenu(submenu);
}
void UMenuScreen::CloseSubMenu(class USubMenu* submenu)
{
m_CloseSubMenu(submenu);
}
void UMenuScreen::m_OpenSubMenu(class USubMenu* submenu, bool transferFocus)
{
CloseAllSideViews();
if(transferFocus)
Super::OpenSubMenu(submenu);
UMenuScreenSubMenu* mssm = Cast<UMenuScreenSubMenu>(submenu);
if(!m_menuTitle || !mssm)
return;
// Update titles and sub-titles
UMenuPanel* panel = Cast<UMenuPanel>(submenu);
if(panel)
m_menuTitle->SetText(FText::FromString(mssm->menuName));
USideView* view = Cast<USideView>(submenu);
if(view)
{
m_sideViewTitle->SetText(FText::FromString(mssm->menuName));
m_currentSideViews.Add(view);
}
}
void UMenuScreen::m_CloseSubMenu(class USubMenu* submenu, bool persist)
{
UMenuScreenSubMenu* mssm = Cast<UMenuScreenSubMenu>(submenu);
if(mssm)
mssm->m_isBeingClosed = true;
UMenuPanel* panel = Cast<UMenuPanel>(submenu);
if(panel)
{
CloseAllSideViews();
panel->onAnimationEnded.RemoveAll(this);
panel->onAnimationEnded.AddUObject(this, &UMenuScreen::m_OnFadeOutComplete);
panel->FadeOut();
}
USideView* view = Cast<USideView>(submenu);
if(view && !persist)
{
view->onAnimationEnded.RemoveAll(this);
view->onAnimationEnded.AddUObject(this, &UMenuScreen::m_OnFadeOutComplete);
view->FadeOut();
// Switch side view active event
if(m_currentSideViews.Num() > 0 && m_sideViewActive)
{
SwitchSideViewVisible(false);
m_sideViewActive = false;
}
m_currentSideViews.Remove(view);
}
Super::CloseSubMenu(submenu);
// Update titles and sub-titles
if(panel)
{
if(m_subMenus.Num() > 0)
{
UMenuPanel* newMenu = Cast<UMenuPanel>(m_subMenus.Last());
if(newMenu)
m_menuTitle->SetText(FText::FromString(newMenu->menuName));
else
goto _set_no_panel_text;
}
else
{
_set_no_panel_text:
m_menuTitle->SetText(FText());
}
}
else if(view && !persist)
{
if(m_subMenus.Num() > 0)
{
USideView* newMenu = Cast<USideView>(m_subMenus.Last());
if(newMenu)
m_sideViewTitle->SetText(FText::FromString(newMenu->menuName));
else
goto _set_no_view_text;
}
else
{
_set_no_view_text:
m_sideViewTitle->SetText(FText());
}
}
if(mssm)
mssm->m_isBeingClosed = false;
}
void UMenuScreen::m_OnFadeOutComplete(UMenuScreenSubMenu* panel, int32 type)
{
if(type == 2) // Fade Out
{
panel->RemoveFromParent();
}
}
static float animationDuration = 0.35f;
void UMenuScreenSubMenu::NativeConstruct()
{
m_animationType = 0;
m_animationTime = 0.0f;
m_isBeingClosed = false;
Super::NativeConstruct();
}
UMenuScreenSubMenu::UMenuScreenSubMenu(const FObjectInitializer& init)
: Super(init)
{
menuName = "<Unnamed Menu!>";
}
void UMenuScreenSubMenu::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
Super::NativeTick(MyGeometry, InDeltaTime);
float r = FMath::Clamp(m_animationTime / animationDuration, 0.0f, 1.0f);
if(m_animationType == 1) // Fade In
{
SetRenderTranslation(FVector2D(0.0f - ((1.0f - r)*(1.0f - r)) * 100.0f, 0.0f));
FLinearColor color = FLinearColor(1.0f, 1.0f, 1.0f, r);
SetColorAndOpacity(color);
}
else if(m_animationType == 2) // Fade Out
{
SetRenderTranslation(FVector2D(0.0f + (r*r) * 100.0f, 0.0f));
FLinearColor color = FLinearColor(1.0f, 1.0f, 1.0f, (1.0f-r));
SetColorAndOpacity(color);
}
if(m_animationType != 0)
{
if(r >= 1.0f)
{
onAnimationEnded.Broadcast(this, m_animationType);
m_animationType = 0;
}
m_animationTime += InDeltaTime;
}
}
void UMenuScreenSubMenu::OnSuspend(USubMenu* newSubMenu, bool loseFocus)
{
// Don't fade out / lose focus when side view is opened
USideView* sv = Cast<USideView>(newSubMenu);
if(sv)
loseFocus = false;
else
FadeOut();
Super::OnSuspend(newSubMenu, loseFocus);
}
void UMenuScreenSubMenu::OnRestore(USubMenu* removedMenu)
{
// To prevent playing the fade in animation again when we receive focus from closing side views when we are actually closing this menu
if(!m_isBeingClosed && !Cast<USideView>(removedMenu))
FadeIn();
Super::OnRestore(removedMenu);
}
void UMenuScreenSubMenu::FadeIn()
{
m_animationTime = 0.0f;
m_animationType = 1;
}
void UMenuScreenSubMenu::FadeOut()
{
m_animationTime = 0.0f;
m_animationType = 2;
}
UMenuPanel* UMenuScreenSubMenu::OpenScreenMenu(TSubclassOf<class UMenuPanel> cls)
{
UMenuScreen* screen = Cast<UMenuScreen>(GetScreen());
if(screen)
{
return screen->OpenScreenMenu(cls);
}
return nullptr;
}
USideView* UMenuScreenSubMenu::OpenSideView(TSubclassOf<class USideView> cls)
{
UMenuScreen* screen = Cast<UMenuScreen>(GetScreen());
if(screen)
{
screen->CloseAllSideViews();
return screen->OpenSideView(cls);
}
return nullptr;
}
class UMenuButton* UMenuScreenSubMenu::AddButton(FString label)
{
if(!container)
return nullptr;
UMenuButton* button = CreateWidget<UMenuButton>(GetWorld(), defaultButtonClass);
if(!button)
return nullptr;
container->AddChild(button);
RescanItems();
button->SetButtonText(label);
return button;
}
void UMenuScreenSubMenu::RescanItems()
{
m_backButton = nullptr;
Super::RescanItems();
for(UMenuItemBase* item : m_items)
{
UMenuButton* button = Cast<UMenuButton>(item);
if(button)
{
if(button->GetName() == "Back")
{
m_backButton = button;
break;
}
}
}
}
void UMenuScreenSubMenu::NativeOnMenuAction(EMenuActionBinding binding)
{
Super::NativeOnMenuAction(binding);
if(binding == EMenuActionBinding::Back)
{
if(m_backButton)
{
m_backButton->SimulatePressed();
}
}
}