172 lines
5.6 KiB
C++
172 lines
5.6 KiB
C++
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||
|
|
||
|
#include "GameFeatureAction_AddWidget.h"
|
||
|
#include "Components/GameFrameworkComponentManager.h"
|
||
|
#include "GameFeaturesSubsystemSettings.h"
|
||
|
#include "Engine/AssetManager.h"
|
||
|
#include "CommonUIExtensions.h"
|
||
|
#include "Engine/Engine.h"
|
||
|
|
||
|
#define LOCTEXT_NAMESPACE "LyraGameFeatures"
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////
|
||
|
// UGameFeatureAction_AddWidgets
|
||
|
|
||
|
void UGameFeatureAction_AddWidgets::OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context)
|
||
|
{
|
||
|
Super::OnGameFeatureDeactivating(Context);
|
||
|
|
||
|
FPerContextData* ActiveData = ContextData.Find(Context);
|
||
|
if ensure(ActiveData)
|
||
|
{
|
||
|
Reset(*ActiveData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if WITH_EDITORONLY_DATA
|
||
|
void UGameFeatureAction_AddWidgets::AddAdditionalAssetBundleData(FAssetBundleData& AssetBundleData)
|
||
|
{
|
||
|
for (const FLyraHUDElementEntry& Entry : Widgets)
|
||
|
{
|
||
|
AssetBundleData.AddBundleAsset(UGameFeaturesSubsystemSettings::LoadStateClient, Entry.WidgetClass.ToSoftObjectPath());
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if WITH_EDITOR
|
||
|
EDataValidationResult UGameFeatureAction_AddWidgets::IsDataValid(TArray<FText>& ValidationErrors)
|
||
|
{
|
||
|
EDataValidationResult Result = CombineDataValidationResults(Super::IsDataValid(ValidationErrors), EDataValidationResult::Valid);
|
||
|
|
||
|
{
|
||
|
int32 EntryIndex = 0;
|
||
|
for (const FLyraHUDLayoutRequest& Entry : Layout)
|
||
|
{
|
||
|
if (Entry.LayoutClass.IsNull())
|
||
|
{
|
||
|
Result = EDataValidationResult::Invalid;
|
||
|
ValidationErrors.Add(FText::Format(LOCTEXT("LayoutHasNullClass", "Null WidgetClass at index {0} in Layout"), FText::AsNumber(EntryIndex)));
|
||
|
}
|
||
|
|
||
|
if (!Entry.LayerID.IsValid())
|
||
|
{
|
||
|
Result = EDataValidationResult::Invalid;
|
||
|
ValidationErrors.Add(FText::Format(LOCTEXT("LayoutHasNoTag", "LayerID is not set at index {0} in Widgets"), FText::AsNumber(EntryIndex)));
|
||
|
}
|
||
|
|
||
|
++EntryIndex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
int32 EntryIndex = 0;
|
||
|
for (const FLyraHUDElementEntry& Entry : Widgets)
|
||
|
{
|
||
|
if (Entry.WidgetClass.IsNull())
|
||
|
{
|
||
|
Result = EDataValidationResult::Invalid;
|
||
|
ValidationErrors.Add(FText::Format(LOCTEXT("EntryHasNullClass", "Null WidgetClass at index {0} in Widgets"), FText::AsNumber(EntryIndex)));
|
||
|
}
|
||
|
|
||
|
if (!Entry.SlotID.IsValid())
|
||
|
{
|
||
|
Result = EDataValidationResult::Invalid;
|
||
|
ValidationErrors.Add(FText::Format(LOCTEXT("EntryHasNoTag", "SlotID is not set at index {0} in Widgets"), FText::AsNumber(EntryIndex)));
|
||
|
}
|
||
|
++EntryIndex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void UGameFeatureAction_AddWidgets::AddToWorld(const FWorldContext& WorldContext, const FGameFeatureStateChangeContext& ChangeContext)
|
||
|
{
|
||
|
UWorld* World = WorldContext.World();
|
||
|
UGameInstance* GameInstance = WorldContext.OwningGameInstance;
|
||
|
FPerContextData& ActiveData = ContextData.FindOrAdd(ChangeContext);
|
||
|
|
||
|
if ((GameInstance != nullptr) && (World != nullptr) && World->IsGameWorld())
|
||
|
{
|
||
|
if (UGameFrameworkComponentManager* ComponentManager = UGameInstance::GetSubsystem<UGameFrameworkComponentManager>(GameInstance))
|
||
|
{
|
||
|
TSoftClassPtr<AActor> HUDActorClass = ALyraHUD::StaticClass();
|
||
|
|
||
|
TSharedPtr<FComponentRequestHandle> ExtensionRequestHandle = ComponentManager->AddExtensionHandler(
|
||
|
HUDActorClass,
|
||
|
UGameFrameworkComponentManager::FExtensionHandlerDelegate::CreateUObject(this, &ThisClass::HandleActorExtension, ChangeContext));
|
||
|
ActiveData.ComponentRequests.Add(ExtensionRequestHandle);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UGameFeatureAction_AddWidgets::Reset(FPerContextData& ActiveData)
|
||
|
{
|
||
|
ActiveData.ComponentRequests.Empty();
|
||
|
ActiveData.LayoutsAdded.Empty();
|
||
|
|
||
|
for (FUIExtensionHandle& Handle : ActiveData.ExtensionHandles)
|
||
|
{
|
||
|
Handle.Unregister();
|
||
|
}
|
||
|
ActiveData.ExtensionHandles.Reset();
|
||
|
}
|
||
|
|
||
|
void UGameFeatureAction_AddWidgets::HandleActorExtension(AActor* Actor, FName EventName, FGameFeatureStateChangeContext ChangeContext)
|
||
|
{
|
||
|
FPerContextData& ActiveData = ContextData.FindOrAdd(ChangeContext);
|
||
|
if ((EventName == UGameFrameworkComponentManager::NAME_ExtensionRemoved) || (EventName == UGameFrameworkComponentManager::NAME_ReceiverRemoved))
|
||
|
{
|
||
|
RemoveWidgets(Actor, ActiveData);
|
||
|
}
|
||
|
else if ((EventName == UGameFrameworkComponentManager::NAME_ExtensionAdded) || (EventName == UGameFrameworkComponentManager::NAME_GameActorReady))
|
||
|
{
|
||
|
AddWidgets(Actor, ActiveData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UGameFeatureAction_AddWidgets::AddWidgets(AActor* Actor, FPerContextData& ActiveData)
|
||
|
{
|
||
|
ALyraHUD* HUD = CastChecked<ALyraHUD>(Actor);
|
||
|
|
||
|
if (ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(HUD->GetOwningPlayerController()->Player))
|
||
|
{
|
||
|
for (const FLyraHUDLayoutRequest& Entry : Layout)
|
||
|
{
|
||
|
if (TSubclassOf<UCommonActivatableWidget> ConcreteWidgetClass = Entry.LayoutClass.Get())
|
||
|
{
|
||
|
ActiveData.LayoutsAdded.Add(UCommonUIExtensions::PushContentToLayer_ForPlayer(LocalPlayer, Entry.LayerID, ConcreteWidgetClass));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UUIExtensionSubsystem* ExtensionSubsystem = HUD->GetWorld()->GetSubsystem<UUIExtensionSubsystem>();
|
||
|
for (const FLyraHUDElementEntry& Entry : Widgets)
|
||
|
{
|
||
|
ActiveData.ExtensionHandles.Add(ExtensionSubsystem->RegisterExtensionAsWidgetForContext(Entry.SlotID, LocalPlayer, Entry.WidgetClass.Get(), -1));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UGameFeatureAction_AddWidgets::RemoveWidgets(AActor* Actor, FPerContextData& ActiveData)
|
||
|
{
|
||
|
ALyraHUD* HUD = CastChecked<ALyraHUD>(Actor);
|
||
|
|
||
|
for (TWeakObjectPtr<UCommonActivatableWidget>& AddedLayout : ActiveData.LayoutsAdded)
|
||
|
{
|
||
|
if (AddedLayout.IsValid())
|
||
|
{
|
||
|
AddedLayout->DeactivateWidget();
|
||
|
}
|
||
|
}
|
||
|
ActiveData.LayoutsAdded.Reset();
|
||
|
|
||
|
for (FUIExtensionHandle& Handle : ActiveData.ExtensionHandles)
|
||
|
{
|
||
|
Handle.Unregister();
|
||
|
}
|
||
|
ActiveData.ExtensionHandles.Reset();
|
||
|
}
|
||
|
|
||
|
#undef LOCTEXT_NAMESPACE
|