// 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(WidgetTree->FindWidget("ButtonHintBar")); m_menuContainer = Cast(WidgetTree->FindWidget("MenuContainer")); m_sideViewContainer = Cast(WidgetTree->FindWidget("SideViewContainer")); m_menuTitle = Cast(WidgetTree->FindWidget("MenuTitle")); m_sideViewTitle = Cast(WidgetTree->FindWidget("SideViewTitle")); } UMenuPanel* UMenuScreen::OpenScreenMenu(TSubclassOf cls) { UMenuPanel* menu = CreateWidget(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 cls) { USideView* view = CreateWidget(GetWorld(), cls); if(!view) { GERROR("Failed to create side view for screen " + GetName()); return nullptr; } UPersistentSideView* pview = Cast(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 viewsToRemove; for(int32 i = 0; i < m_sideViewContainer->GetChildrenCount(); i++) { USideView* sv = Cast(m_sideViewContainer->GetChildAt(i)); if(sv && !sv->IsA()) 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(submenu); if(!m_menuTitle || !mssm) return; // Update titles and sub-titles UMenuPanel* panel = Cast(submenu); if(panel) m_menuTitle->SetText(FText::FromString(mssm->menuName)); USideView* view = Cast(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(submenu); if(mssm) mssm->m_isBeingClosed = true; UMenuPanel* panel = Cast(submenu); if(panel) { CloseAllSideViews(); panel->onAnimationEnded.RemoveAll(this); panel->onAnimationEnded.AddUObject(this, &UMenuScreen::m_OnFadeOutComplete); panel->FadeOut(); } USideView* view = Cast(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(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(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 = ""; } 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(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(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 cls) { UMenuScreen* screen = Cast(GetScreen()); if(screen) { return screen->OpenScreenMenu(cls); } return nullptr; } USideView* UMenuScreenSubMenu::OpenSideView(TSubclassOf cls) { UMenuScreen* screen = Cast(GetScreen()); if(screen) { screen->CloseAllSideViews(); return screen->OpenSideView(cls); } return nullptr; } class UMenuButton* UMenuScreenSubMenu::AddButton(FString label) { if(!container) return nullptr; UMenuButton* button = CreateWidget(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(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(); } } }