搬了lyra的hudlayout
This commit is contained in:
203
Plugins/CommonGame/Source/Private/GameUIPolicy.cpp
Normal file
203
Plugins/CommonGame/Source/Private/GameUIPolicy.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "GameUIPolicy.h"
|
||||
#include "Engine/GameInstance.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "GameUIManagerSubsystem.h"
|
||||
#include "CommonLocalPlayer.h"
|
||||
#include "PrimaryGameLayout.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "LogCommonGame.h"
|
||||
|
||||
#include UE_INLINE_GENERATED_CPP_BY_NAME(GameUIPolicy)
|
||||
|
||||
// Static
|
||||
UGameUIPolicy* UGameUIPolicy::GetGameUIPolicy(const UObject* WorldContextObject)
|
||||
{
|
||||
if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull))
|
||||
{
|
||||
if (UGameInstance* GameInstance = World->GetGameInstance())
|
||||
{
|
||||
if (UGameUIManagerSubsystem* UIManager = UGameInstance::GetSubsystem<UGameUIManagerSubsystem>(GameInstance))
|
||||
{
|
||||
return UIManager->GetCurrentUIPolicy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UGameUIManagerSubsystem* UGameUIPolicy::GetOwningUIManager() const
|
||||
{
|
||||
return CastChecked<UGameUIManagerSubsystem>(GetOuter());
|
||||
}
|
||||
|
||||
UWorld* UGameUIPolicy::GetWorld() const
|
||||
{
|
||||
return GetOwningUIManager()->GetGameInstance()->GetWorld();
|
||||
}
|
||||
|
||||
UPrimaryGameLayout* UGameUIPolicy::GetRootLayout(const UCommonLocalPlayer* LocalPlayer) const
|
||||
{
|
||||
const FRootViewportLayoutInfo* LayoutInfo = RootViewportLayouts.FindByKey(LocalPlayer);
|
||||
return LayoutInfo ? LayoutInfo->RootLayout : nullptr;
|
||||
}
|
||||
|
||||
void UGameUIPolicy::NotifyPlayerAdded(UCommonLocalPlayer* LocalPlayer)
|
||||
{
|
||||
LocalPlayer->OnPlayerControllerSet.AddWeakLambda(this, [this](UCommonLocalPlayer* LocalPlayer, APlayerController* PlayerController)
|
||||
{
|
||||
NotifyPlayerRemoved(LocalPlayer);
|
||||
|
||||
if (FRootViewportLayoutInfo* LayoutInfo = RootViewportLayouts.FindByKey(LocalPlayer))
|
||||
{
|
||||
AddLayoutToViewport(LocalPlayer, LayoutInfo->RootLayout);
|
||||
LayoutInfo->bAddedToViewport = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateLayoutWidget(LocalPlayer);
|
||||
}
|
||||
});
|
||||
|
||||
if (FRootViewportLayoutInfo* LayoutInfo = RootViewportLayouts.FindByKey(LocalPlayer))
|
||||
{
|
||||
AddLayoutToViewport(LocalPlayer, LayoutInfo->RootLayout);
|
||||
LayoutInfo->bAddedToViewport = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateLayoutWidget(LocalPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
void UGameUIPolicy::NotifyPlayerRemoved(UCommonLocalPlayer* LocalPlayer)
|
||||
{
|
||||
if (FRootViewportLayoutInfo* LayoutInfo = RootViewportLayouts.FindByKey(LocalPlayer))
|
||||
{
|
||||
RemoveLayoutFromViewport(LocalPlayer, LayoutInfo->RootLayout);
|
||||
LayoutInfo->bAddedToViewport = false;
|
||||
|
||||
if (LocalMultiplayerInteractionMode == ELocalMultiplayerInteractionMode::SingleToggle && !LocalPlayer->IsPrimaryPlayer())
|
||||
{
|
||||
UPrimaryGameLayout* RootLayout = LayoutInfo->RootLayout;
|
||||
if (RootLayout && !RootLayout->IsDormant())
|
||||
{
|
||||
// We're removing a secondary player's root while it's in control - transfer control back to the primary player's root
|
||||
RootLayout->SetIsDormant(true);
|
||||
for (const FRootViewportLayoutInfo& RootLayoutInfo : RootViewportLayouts)
|
||||
{
|
||||
if (RootLayoutInfo.LocalPlayer->IsPrimaryPlayer())
|
||||
{
|
||||
if (UPrimaryGameLayout* PrimaryRootLayout = RootLayoutInfo.RootLayout)
|
||||
{
|
||||
PrimaryRootLayout->SetIsDormant(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UGameUIPolicy::NotifyPlayerDestroyed(UCommonLocalPlayer* LocalPlayer)
|
||||
{
|
||||
NotifyPlayerRemoved(LocalPlayer);
|
||||
LocalPlayer->OnPlayerControllerSet.RemoveAll(this);
|
||||
const int32 LayoutInfoIdx = RootViewportLayouts.IndexOfByKey(LocalPlayer);
|
||||
if (LayoutInfoIdx != INDEX_NONE)
|
||||
{
|
||||
UPrimaryGameLayout* Layout = RootViewportLayouts[LayoutInfoIdx].RootLayout;
|
||||
RootViewportLayouts.RemoveAt(LayoutInfoIdx);
|
||||
|
||||
RemoveLayoutFromViewport(LocalPlayer, Layout);
|
||||
|
||||
OnRootLayoutReleased(LocalPlayer, Layout);
|
||||
}
|
||||
}
|
||||
|
||||
void UGameUIPolicy::AddLayoutToViewport(UCommonLocalPlayer* LocalPlayer, UPrimaryGameLayout* Layout)
|
||||
{
|
||||
UE_LOG(LogCommonGame, Log, TEXT("[%s] is adding player [%s]'s root layout [%s] to the viewport"), *GetName(), *GetNameSafe(LocalPlayer), *GetNameSafe(Layout));
|
||||
|
||||
Layout->SetPlayerContext(FLocalPlayerContext(LocalPlayer));
|
||||
Layout->AddToPlayerScreen(1000);
|
||||
|
||||
OnRootLayoutAddedToViewport(LocalPlayer, Layout);
|
||||
}
|
||||
|
||||
void UGameUIPolicy::RemoveLayoutFromViewport(UCommonLocalPlayer* LocalPlayer, UPrimaryGameLayout* Layout)
|
||||
{
|
||||
TWeakPtr<SWidget> LayoutSlateWidget = Layout->GetCachedWidget();
|
||||
if (LayoutSlateWidget.IsValid())
|
||||
{
|
||||
UE_LOG(LogCommonGame, Log, TEXT("[%s] is removing player [%s]'s root layout [%s] from the viewport"), *GetName(), *GetNameSafe(LocalPlayer), *GetNameSafe(Layout));
|
||||
|
||||
Layout->RemoveFromParent();
|
||||
if (LayoutSlateWidget.IsValid())
|
||||
{
|
||||
UE_LOG(LogCommonGame, Log, TEXT("Player [%s]'s root layout [%s] has been removed from the viewport, but other references to its underlying Slate widget still exist. Noting in case we leak it."), *GetNameSafe(LocalPlayer), *GetNameSafe(Layout));
|
||||
}
|
||||
|
||||
OnRootLayoutRemovedFromViewport(LocalPlayer, Layout);
|
||||
}
|
||||
}
|
||||
|
||||
void UGameUIPolicy::OnRootLayoutAddedToViewport(UCommonLocalPlayer* LocalPlayer, UPrimaryGameLayout* Layout)
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
if (GIsEditor && LocalPlayer->IsPrimaryPlayer())
|
||||
{
|
||||
// So our controller will work in PIE without needing to click in the viewport
|
||||
FSlateApplication::Get().SetUserFocusToGameViewport(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void UGameUIPolicy::OnRootLayoutRemovedFromViewport(UCommonLocalPlayer* LocalPlayer, UPrimaryGameLayout* Layout)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UGameUIPolicy::OnRootLayoutReleased(UCommonLocalPlayer* LocalPlayer, UPrimaryGameLayout* Layout)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UGameUIPolicy::RequestPrimaryControl(UPrimaryGameLayout* Layout)
|
||||
{
|
||||
if (LocalMultiplayerInteractionMode == ELocalMultiplayerInteractionMode::SingleToggle && Layout->IsDormant())
|
||||
{
|
||||
for (const FRootViewportLayoutInfo& LayoutInfo : RootViewportLayouts)
|
||||
{
|
||||
UPrimaryGameLayout* RootLayout = LayoutInfo.RootLayout;
|
||||
if (RootLayout && !RootLayout->IsDormant())
|
||||
{
|
||||
RootLayout->SetIsDormant(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Layout->SetIsDormant(false);
|
||||
}
|
||||
}
|
||||
|
||||
void UGameUIPolicy::CreateLayoutWidget(UCommonLocalPlayer* LocalPlayer)
|
||||
{
|
||||
if (APlayerController* PlayerController = LocalPlayer->GetPlayerController(GetWorld()))
|
||||
{
|
||||
TSubclassOf<UPrimaryGameLayout> LayoutWidgetClass = GetLayoutWidgetClass(LocalPlayer);
|
||||
if (ensure(LayoutWidgetClass && !LayoutWidgetClass->HasAnyClassFlags(CLASS_Abstract)))
|
||||
{
|
||||
UPrimaryGameLayout* NewLayoutObject = CreateWidget<UPrimaryGameLayout>(PlayerController, LayoutWidgetClass);
|
||||
RootViewportLayouts.Emplace(LocalPlayer, NewLayoutObject, true);
|
||||
|
||||
AddLayoutToViewport(LocalPlayer, NewLayoutObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TSubclassOf<UPrimaryGameLayout> UGameUIPolicy::GetLayoutWidgetClass(UCommonLocalPlayer* LocalPlayer)
|
||||
{
|
||||
return LayoutClass.LoadSynchronous();
|
||||
}
|
||||
Reference in New Issue
Block a user