// Copyright Epic Games, Inc. All Rights Reserved. #include "PocketLevelInstance.h" #include "PocketLevel.h" #include "Engine/LevelStreamingDynamic.h" #include "Engine/Level.h" #include "Engine/LocalPlayer.h" #include "GameFramework/Actor.h" #include "GameFramework/PlayerController.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); }