96 lines
2.8 KiB
C++
96 lines
2.8 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "GameModes/AsyncAction_ExperienceReady.h"
|
|
|
|
#include "Engine/Engine.h"
|
|
#include "Engine/World.h"
|
|
#include "GameFramework/GameStateBase.h"
|
|
#include "GameModes/LyraExperienceManagerComponent.h"
|
|
#include "Misc/AssertionMacros.h"
|
|
#include "TimerManager.h"
|
|
#include "UObject/WeakObjectPtr.h"
|
|
|
|
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();
|
|
}
|