RealtimeStyleTransferRuntime/Plugins/PocketWorlds/Source/Private/PocketLevelInstance.cpp

139 lines
3.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "PocketLevelInstance.h"
#include "Containers/Array.h"
#include "Engine/Level.h"
#include "Engine/LevelStreaming.h"
#include "Engine/LevelStreamingDynamic.h"
#include "Engine/LocalPlayer.h"
#include "GameFramework/Actor.h"
#include "GameFramework/PlayerController.h"
#include "Math/Rotator.h"
#include "Math/Sphere.h"
#include "Math/Vector.h"
#include "PocketLevel.h"
#include "UObject/SoftObjectPtr.h"
UPocketLevelInstance::UPocketLevelInstance()
{
}
bool UPocketLevelInstance::Initialize(ULocalPlayer* InLocalPlayer, UPocketLevel* InPocketLevel, FVector InSpawnPoint)
{
LocalPlayer = InLocalPlayer;
World = LocalPlayer->GetWorld();
PocketLevel = InPocketLevel;
Bounds = FBoxSphereBounds(FSphere(InSpawnPoint, PocketLevel->Bounds.GetAbsMax()));
if (ensure(StreamingPocketLevel == nullptr))
{
if (ensure(!PocketLevel->Level.IsNull()))
{
bool bSuccess = false;
StreamingPocketLevel = ULevelStreamingDynamic::LoadLevelInstanceBySoftObjectPtr(LocalPlayer, PocketLevel->Level, Bounds.Origin, FRotator::ZeroRotator, bSuccess);
if (ensure(bSuccess && StreamingPocketLevel))
{
StreamingPocketLevel->OnLevelLoaded.AddUniqueDynamic(this, &ThisClass::HandlePocketLevelLoaded);
StreamingPocketLevel->OnLevelShown.AddUniqueDynamic(this, &ThisClass::HandlePocketLevelShown);
}
return bSuccess;
}
}
return false;
}
void UPocketLevelInstance::StreamIn()
{
if (StreamingPocketLevel)
{
StreamingPocketLevel->SetShouldBeVisible(true);
StreamingPocketLevel->SetShouldBeLoaded(true);
}
}
void UPocketLevelInstance::StreamOut()
{
if (StreamingPocketLevel)
{
StreamingPocketLevel->SetShouldBeVisible(false);
StreamingPocketLevel->SetShouldBeLoaded(false);
}
}
FDelegateHandle UPocketLevelInstance::AddReadyCallback(FPocketLevelInstanceEvent::FDelegate Callback)
{
if (StreamingPocketLevel->GetCurrentState() == ULevelStreaming::ECurrentState::LoadedVisible)
{
Callback.ExecuteIfBound(this);
}
return OnReadyEvent.Add(Callback);
}
void UPocketLevelInstance::RemoveReadyCallback(FDelegateHandle CallbackToRemove)
{
OnReadyEvent.Remove(CallbackToRemove);
}
void UPocketLevelInstance::BeginDestroy()
{
Super::BeginDestroy();
if (StreamingPocketLevel)
{
StreamingPocketLevel->bShouldBlockOnUnload = false;
StreamingPocketLevel->SetShouldBeLoaded(false);
StreamingPocketLevel->OnLevelShown.RemoveAll(this);
StreamingPocketLevel->OnLevelLoaded.RemoveAll(this);
StreamingPocketLevel = nullptr;
}
}
void UPocketLevelInstance::HandlePocketLevelLoaded()
{
if (StreamingPocketLevel)
{
// Make everything in the level setup so that it's setup on the client, and we treat
// everything as locally spawned, rather than bExchangedRoles = true, where it's spawned
// on the client, but the expectation is the server said do it, and the server is going to
// be telling us about them later.
if (ULevel* LoadedLevel = StreamingPocketLevel->GetLoadedLevel())
{
LoadedLevel->bClientOnlyVisible = true;
for (AActor* Actor : LoadedLevel->Actors)
{
if (Actor)
{
Actor->bExchangedRoles = true; // HACK, Remove when bClientOnlyVisible is all we need.
}
}
// TODO: Don't put ownership over shared pocket spaces.
if (LocalPlayer)
{
if (APlayerController* PC = LocalPlayer->GetPlayerController(GetWorld()))
{
for (AActor* Actor : LoadedLevel->Actors)
{
if (Actor)
{
Actor->SetOwner(PC);
}
}
}
}
}
}
}
void UPocketLevelInstance::HandlePocketLevelShown()
{
OnReadyEvent.Broadcast(this);
}