RealtimeStyleTransferRuntime/Source/LyraGame/GameModes/AsyncAction_ExperienceReady...

96 lines
2.8 KiB
C++
Raw Normal View History

2022-05-23 18:41:30 +00:00
// Copyright Epic Games, Inc. All Rights Reserved.
2022-09-13 07:18:28 +00:00
#include "GameModes/AsyncAction_ExperienceReady.h"
2022-05-23 18:41:30 +00:00
#include "Engine/Engine.h"
2022-09-13 07:18:28 +00:00
#include "Engine/World.h"
#include "GameFramework/GameStateBase.h"
2022-05-23 18:41:30 +00:00
#include "GameModes/LyraExperienceManagerComponent.h"
2022-09-13 07:18:28 +00:00
#include "Misc/AssertionMacros.h"
#include "TimerManager.h"
#include "UObject/WeakObjectPtr.h"
2022-05-23 18:41:30 +00:00
UAsyncAction_ExperienceReady::UAsyncAction_ExperienceReady(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
UAsyncAction_ExperienceReady* UAsyncAction_ExperienceReady::WaitForExperienceReady(UObject* InWorldContextObject)
{
UAsyncAction_ExperienceReady* Action = nullptr;
if (UWorld* World = GEngine->GetWorldFromContextObject(InWorldContextObject, EGetWorldErrorMode::LogAndReturnNull))
{
Action = NewObject<UAsyncAction_ExperienceReady>();
Action->WorldPtr = World;
Action->RegisterWithGameInstance(World);
}
return Action;
}
void UAsyncAction_ExperienceReady::Activate()
{
if (UWorld* World = WorldPtr.Get())
{
if (AGameStateBase* GameState = World->GetGameState())
{
Step2_ListenToExperienceLoading(GameState);
}
else
{
World->GameStateSetEvent.AddUObject(this, &ThisClass::Step1_HandleGameStateSet);
}
}
else
{
// No world so we'll never finish naturally
SetReadyToDestroy();
}
}
void UAsyncAction_ExperienceReady::Step1_HandleGameStateSet(AGameStateBase* GameState)
{
if (UWorld* World = WorldPtr.Get())
{
World->GameStateSetEvent.RemoveAll(this);
}
Step2_ListenToExperienceLoading(GameState);
}
void UAsyncAction_ExperienceReady::Step2_ListenToExperienceLoading(AGameStateBase* GameState)
{
check(GameState);
ULyraExperienceManagerComponent* ExperienceComponent = GameState->FindComponentByClass<ULyraExperienceManagerComponent>();
check(ExperienceComponent);
if (ExperienceComponent->IsExperienceLoaded())
{
UWorld* World = GameState->GetWorld();
check(World);
// The experience happened to be already loaded, but still delay a frame to
// make sure people don't write stuff that relies on this always being true
//@TODO: Consider not delaying for dynamically spawned stuff / any time after the loading screen has dropped?
//@TODO: Maybe just inject a random 0-1s delay in the experience load itself?
World->GetTimerManager().SetTimerForNextTick(FTimerDelegate::CreateUObject(this, &ThisClass::Step4_BroadcastReady));
}
else
{
ExperienceComponent->CallOrRegister_OnExperienceLoaded(FOnLyraExperienceLoaded::FDelegate::CreateUObject(this, &ThisClass::Step3_HandleExperienceLoaded));
}
}
void UAsyncAction_ExperienceReady::Step3_HandleExperienceLoaded(const ULyraExperienceDefinition* CurrentExperience)
{
Step4_BroadcastReady();
}
void UAsyncAction_ExperienceReady::Step4_BroadcastReady()
{
OnReady.Broadcast();
SetReadyToDestroy();
}