Files
PHY/Plugins/GGS/Source/GenericUISystem/Private/UI/GUIS_GameUISubsystem.cpp
2026-03-03 01:23:02 +08:00

227 lines
6.8 KiB
C++

// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#include "UI/GUIS_GameUISubsystem.h"
#include "GameFramework/Pawn.h"
#include "GUIS_GenericUISystemSettings.h"
#include "CommonUserWidget.h"
#include "GUIS_LogChannels.h"
#include "Engine/GameInstance.h"
#include "Input/CommonUIInputTypes.h"
#include "UI/GUIS_GameUIContext.h"
#include "UI/GUIS_GameUIPolicy.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GUIS_GameUISubsystem)
class FSubsystemCollectionBase;
class UClass;
void UGUIS_GameUISubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
if (UGUIS_GenericUISystemSettings::Get()->GameUIPolicyClass.IsNull())
{
UE_LOG(LogGUIS, Error, TEXT("GUIS_GameUISubsystem::Initialize Failed, Missing GameUIPolicyClass in GenericUISystemSettings!!!"));
return;
}
if (!CurrentPolicy)
{
TSubclassOf<UGUIS_GameUIPolicy> PolicyClass = UGUIS_GenericUISystemSettings::Get()->GameUIPolicyClass.LoadSynchronous();
if (PolicyClass)
{
UGUIS_GameUIPolicy* NewPolicy = NewObject<UGUIS_GameUIPolicy>(this, PolicyClass);
if (NewPolicy)
{
SwitchToPolicy(NewPolicy);
}
else
{
UE_LOG(LogGUIS, Error, TEXT("GUIS_GameUISubsystem::Initialize Failed, failed to create Game UI Policy from class:%s!"), *PolicyClass->GetName());
}
}
else
{
UE_LOG(LogGUIS, Error, TEXT("GUIS_GameUISubsystem::Initialize Failed, Missing GameUIPolicyClass in GenericUISystemSettings!!!"));
}
}
}
void UGUIS_GameUISubsystem::Deinitialize()
{
Super::Deinitialize();
SwitchToPolicy(nullptr);
}
bool UGUIS_GameUISubsystem::ShouldCreateSubsystem(UObject* Outer) const
{
if (CastChecked<UGameInstance>(Outer)->IsDedicatedServerInstance())
{
return false;
}
TArray<UClass*> ChildClasses;
GetDerivedClasses(GetClass(), ChildClasses, false);
if (ChildClasses.Num() == 0)
{
UE_LOG(LogGUIS, Display, TEXT("No override implementation found for UGUIS_GameUISubsystem, So creating it."))
return true;
}
return false;
}
void UGUIS_GameUISubsystem::AddPlayer(ULocalPlayer* LocalPlayer)
{
NotifyPlayerAdded(LocalPlayer);
}
void UGUIS_GameUISubsystem::RemovePlayer(ULocalPlayer* LocalPlayer)
{
NotifyPlayerDestroyed(LocalPlayer);
}
void UGUIS_GameUISubsystem::NotifyPlayerAdded(ULocalPlayer* LocalPlayer)
{
if (ensure(LocalPlayer) && CurrentPolicy)
{
CurrentPolicy->NotifyPlayerAdded(LocalPlayer);
}
}
void UGUIS_GameUISubsystem::NotifyPlayerRemoved(ULocalPlayer* LocalPlayer)
{
if (LocalPlayer && CurrentPolicy)
{
CurrentPolicy->NotifyPlayerRemoved(LocalPlayer);
}
}
void UGUIS_GameUISubsystem::NotifyPlayerDestroyed(ULocalPlayer* LocalPlayer)
{
if (LocalPlayer && CurrentPolicy)
{
CurrentPolicy->NotifyPlayerDestroyed(LocalPlayer);
}
}
void UGUIS_GameUISubsystem::RegisterUIActionBinding(UCommonUserWidget* Target, FDataTableRowHandle InputAction, bool bShouldDisplayInActionBar, const FGUIS_UIActionExecutedDelegate& Callback,
FGUIS_UIActionBindingHandle& BindingHandle)
{
if (IsValid(Target))
{
FBindUIActionArgs BindArgs(InputAction, bShouldDisplayInActionBar, FSimpleDelegate::CreateLambda([InputAction, Callback]()
{
Callback.ExecuteIfBound(InputAction.RowName);
}));
BindingHandle.Handle = Target->RegisterUIActionBinding(BindArgs);
BindingHandles.Add(BindingHandle.Handle);
}
}
void UGUIS_GameUISubsystem::UnregisterBinding(FGUIS_UIActionBindingHandle& BindingHandle)
{
if (BindingHandle.Handle.IsValid())
{
UE_LOG(LogGUIS, Display, TEXT("Unregister binding for %s"), *BindingHandle.Handle.GetDisplayName().ToString())
BindingHandle.Handle.Unregister();
BindingHandles.Remove(BindingHandle.Handle);
}
}
void UGUIS_GameUISubsystem::RegisterUIActionBindingForPlayer(ULocalPlayer* LocalPlayer, UCommonUserWidget* Target, FDataTableRowHandle InputAction, bool bShouldDisplayInActionBar,
const FGUIS_UIActionExecutedDelegate& Callback, FGUIS_UIActionBindingHandle& BindingHandle)
{
if (LocalPlayer && CurrentPolicy)
{
CurrentPolicy->AddUIAction(LocalPlayer, Target, InputAction, bShouldDisplayInActionBar, Callback, BindingHandle);
}
}
void UGUIS_GameUISubsystem::UnregisterUIActionBindingForPlayer(ULocalPlayer* LocalPlayer, FGUIS_UIActionBindingHandle& BindingHandle)
{
if (LocalPlayer && CurrentPolicy)
{
CurrentPolicy->RemoveUIAction(LocalPlayer, BindingHandle);
}
}
void UGUIS_GameUISubsystem::RegisterUIContextForPlayer(ULocalPlayer* LocalPlayer, UGUIS_GameUIContext* Context, FGUIS_UIContextBindingHandle& BindingHandle)
{
if (LocalPlayer && CurrentPolicy && Context)
{
if (CurrentPolicy->AddContext(LocalPlayer, Context))
{
BindingHandle = FGUIS_UIContextBindingHandle(LocalPlayer, Context->GetClass());
}
}
}
void UGUIS_GameUISubsystem::RegisterUIContextForActor(AActor* Actor, UGUIS_GameUIContext* Context, FGUIS_UIContextBindingHandle& BindingHandle)
{
if (!IsValid(Actor))
{
UE_LOG(LogGUIS, Error, TEXT("Trying to register ui context for invalid pawn!"))
return;
}
APawn* Pawn = Cast<APawn>(Actor);
if (Pawn == nullptr || !Pawn->IsLocallyControlled())
{
UE_LOG(LogGUIS, Error, TEXT("Trying to register ui context for actor(%s) which is not locally controlled pawn!"), *Pawn->GetName())
return;
}
APlayerController* PC = Cast<APlayerController>(Pawn->GetController());
if (PC == nullptr)
{
UE_LOG(LogGUIS, Error, TEXT("Trying to register ui context for pawn(%s) which doesn't have valid player controller"), *Pawn->GetName())
return;
}
RegisterUIContextForPlayer(PC->GetLocalPlayer(), Context, BindingHandle);
}
bool UGUIS_GameUISubsystem::FindUIContextForPlayer(ULocalPlayer* LocalPlayer, TSubclassOf<UGUIS_GameUIContext> ContextClass, UGUIS_GameUIContext*& OutContext)
{
if (LocalPlayer && CurrentPolicy && ContextClass != nullptr)
{
if (UGUIS_GameUIContext* Context = CurrentPolicy->GetContext(LocalPlayer, ContextClass))
{
if (Context->GetClass() == ContextClass)
{
OutContext = Context;
return true;
}
}
}
return false;
}
bool UGUIS_GameUISubsystem::FindUIContextFromHandle(FGUIS_UIContextBindingHandle& BindingHandle, TSubclassOf<UGUIS_GameUIContext> ContextClass, UGUIS_GameUIContext*& OutContext)
{
if (BindingHandle.LocalPlayer && BindingHandle.ContextClass && CurrentPolicy)
{
OutContext = CurrentPolicy->FindContext(BindingHandle.LocalPlayer, BindingHandle.ContextClass);
}
return OutContext != nullptr;
}
void UGUIS_GameUISubsystem::UnregisterUIContextForPlayer(FGUIS_UIContextBindingHandle& BindingHandle)
{
if (BindingHandle.LocalPlayer && BindingHandle.ContextClass && CurrentPolicy)
{
CurrentPolicy->RemoveContext(BindingHandle.LocalPlayer, BindingHandle.ContextClass);
BindingHandle.LocalPlayer = nullptr;
BindingHandle.ContextClass = nullptr;
}
}
void UGUIS_GameUISubsystem::SwitchToPolicy(UGUIS_GameUIPolicy* InPolicy)
{
if (CurrentPolicy != InPolicy)
{
CurrentPolicy = InPolicy;
}
}