Neues Menüsystem implementiert
Ein flexibles Menüsystem wurde hinzugefügt, das ein Hauptmenü und ein In-Game-Menü umfasst. Das Hauptmenü bietet Optionen wie "Neues Spiel starten", "Optionen" und "Credits". Das In-Game-Menü ermöglicht Pausenfunktionen wie "Fortsetzen", "Optionen" und "Zum Desktop beenden". Neue Klassen wurden eingeführt, darunter `MenuManagerSubsystem` zur Verwaltung von Menübildschirmen, `MenuScreenWidget` als Basisklasse für Menüs sowie spezifische Widgets wie `MainMenuWidget`, `InGameMenuWidget` und `OptionsMenuWidget`. Zusätzlich wurden stilisierte Schaltflächen (`MenuButtonWidget`) und ein neuer `MenuPlayerController` für menübasierte Levels implementiert. Änderungen an `KingshearthLegacyPlayerController` ermöglichen die Steuerung des In-Game-Menüs. Binäre Assets für Menüs und UI wurden hinzugefügt.
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
#include "MenuManagerSubsystem.h"
|
||||
#include "MenuScreenWidget.h"
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "UObject/UObjectGlobals.h"
|
||||
|
||||
void UMenuManagerSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
Super::Initialize(Collection);
|
||||
FCoreUObjectDelegates::PreLoadMap.AddUObject(this, &UMenuManagerSubsystem::HandlePreLoadMap);
|
||||
}
|
||||
|
||||
void UMenuManagerSubsystem::Deinitialize()
|
||||
{
|
||||
FCoreUObjectDelegates::PreLoadMap.RemoveAll(this);
|
||||
Super::Deinitialize();
|
||||
}
|
||||
|
||||
void UMenuManagerSubsystem::HandlePreLoadMap(const FString& MapName)
|
||||
{
|
||||
ClearStack();
|
||||
}
|
||||
|
||||
UMenuScreenWidget* UMenuManagerSubsystem::PushScreen(TSubclassOf<UMenuScreenWidget> ScreenClass)
|
||||
{
|
||||
if (!ScreenClass)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
APlayerController* OwningController = GetGameInstance() ? GetGameInstance()->GetFirstLocalPlayerController() : nullptr;
|
||||
if (!OwningController)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UMenuScreenWidget* NewScreen = CreateWidget<UMenuScreenWidget>(OwningController, ScreenClass);
|
||||
if (!NewScreen)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Hide (not just cover) whatever screen was on top - it stops rendering and stops taking
|
||||
// input, rather than sitting underneath the new screen doing both pointlessly.
|
||||
if (UMenuScreenWidget* PreviousTop = GetActiveScreen())
|
||||
{
|
||||
PreviousTop->SetVisibility(ESlateVisibility::Collapsed);
|
||||
}
|
||||
|
||||
NewScreen->AddToPlayerScreen(static_cast<int32>(BaseZOrder + ScreenStack.Num()));
|
||||
ScreenStack.Add(NewScreen);
|
||||
RefreshInputMode();
|
||||
return NewScreen;
|
||||
}
|
||||
|
||||
void UMenuManagerSubsystem::PopScreen()
|
||||
{
|
||||
if (ScreenStack.Num() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UMenuScreenWidget* TopScreen = ScreenStack.Pop();
|
||||
if (TopScreen)
|
||||
{
|
||||
TopScreen->NotifyScreenClosing();
|
||||
TopScreen->RemoveFromParent();
|
||||
}
|
||||
|
||||
if (UMenuScreenWidget* NewTop = GetActiveScreen())
|
||||
{
|
||||
NewTop->SetVisibility(ESlateVisibility::Visible);
|
||||
}
|
||||
|
||||
RefreshInputMode();
|
||||
}
|
||||
|
||||
void UMenuManagerSubsystem::ClearStack()
|
||||
{
|
||||
for (UMenuScreenWidget* Screen : ScreenStack)
|
||||
{
|
||||
if (Screen)
|
||||
{
|
||||
Screen->NotifyScreenClosing();
|
||||
Screen->RemoveFromParent();
|
||||
}
|
||||
}
|
||||
ScreenStack.Reset();
|
||||
RefreshInputMode();
|
||||
}
|
||||
|
||||
UMenuScreenWidget* UMenuManagerSubsystem::GetActiveScreen() const
|
||||
{
|
||||
return ScreenStack.Num() > 0 ? ScreenStack.Last() : nullptr;
|
||||
}
|
||||
|
||||
void UMenuManagerSubsystem::RefreshInputMode()
|
||||
{
|
||||
APlayerController* OwningController = GetGameInstance() ? GetGameInstance()->GetFirstLocalPlayerController() : nullptr;
|
||||
if (!OwningController)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (UMenuScreenWidget* Top = GetActiveScreen())
|
||||
{
|
||||
FInputModeUIOnly InputMode;
|
||||
InputMode.SetWidgetToFocus(Top->TakeWidget());
|
||||
InputMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
|
||||
OwningController->SetInputMode(InputMode);
|
||||
OwningController->SetShowMouseCursor(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
OwningController->SetInputMode(FInputModeGameOnly());
|
||||
OwningController->SetShowMouseCursor(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user