Files
UnrealEngine/Engine/Source/Editor/UnrealEd/Private/EditorWorldUtils.cpp
2025-05-18 13:04:45 +08:00

112 lines
3.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "EditorWorldUtils.h"
#include "Editor.h"
#include "AssetRegistry/AssetRegistryHelpers.h"
DEFINE_LOG_CATEGORY_STATIC(EditorWorldUtilsLog, Log, All);
FScopedEditorWorld::FScopedEditorWorld()
: World(nullptr)
, PrevGWorld(nullptr)
{
}
FScopedEditorWorld::FScopedEditorWorld(UWorld* InWorld, const UWorld::InitializationValues& InInitializationValues, EWorldType::Type InWorldType)
: FScopedEditorWorld()
{
Init(InWorld, InInitializationValues, InWorldType);
}
FScopedEditorWorld::FScopedEditorWorld(const FStringView InLongPackageName, const UWorld::InitializationValues& InInitializationValues, EWorldType::Type InWorldType)
: FScopedEditorWorld(TSoftObjectPtr<UWorld>(FSoftObjectPath(InLongPackageName)), InInitializationValues, InWorldType)
{
}
FScopedEditorWorld::FScopedEditorWorld(const TSoftObjectPtr<UWorld>& InSoftWorld, const UWorld::InitializationValues& InInitializationValues, EWorldType::Type InWorldType)
: FScopedEditorWorld()
{
FSoftObjectPath WorldObjectPath(InSoftWorld.ToSoftObjectPath());
// Handle cases where the SoftObjectPath doesn't have a valid AssetName
if (WorldObjectPath.GetAssetFName().IsNone())
{
FString WorldObjectPathStr = WorldObjectPath.GetLongPackageName() + TEXT(".") + FPackageName::GetShortName(WorldObjectPath.GetLongPackageName());
WorldObjectPath = FSoftObjectPath(WorldObjectPathStr);
}
if (UPackage* WorldPackage = LoadWorldPackageForEditor(WorldObjectPath.GetLongPackageName()))
{
if (UWorld* RuntimeWorld = UWorld::FindWorldInPackage(WorldPackage))
{
Init(RuntimeWorld, InInitializationValues, InWorldType);
}
}
}
void FScopedEditorWorld::Init(UWorld* InWorld, const UWorld::InitializationValues& InInitializationValues, EWorldType::Type InWorldType)
{
check(InWorld);
check(!InWorld->bIsWorldInitialized);
World = InWorld;
// Add to root
World->AddToRoot();
// Set current GWorld / WorldContext
FWorldContext& WorldContext = GEditor->GetEditorWorldContext(true);
WorldContext.SetCurrentWorld(World);
PrevGWorld = GWorld;
GWorld = World;
// Initialize the world
World->WorldType = InWorldType;
World->InitWorld(InInitializationValues);
World->PersistentLevel->UpdateModelComponents();
World->UpdateWorldComponents(true /*bRerunConstructionScripts*/, false /*bCurrentLevelOnly*/);
World->UpdateLevelStreaming();
}
UWorld* FScopedEditorWorld::GetWorld() const
{
return World;
}
FScopedEditorWorld::~FScopedEditorWorld()
{
// Ensure the editor's transaction system is reset to remove any lingering editor state changes when the ScopedEditorWorld is destroyed.
// This prevents issues with persistent state data, such as in landscape mode tests, where the previous world state may interfere with consequent test runs.
if (GEditor)
{
const FText TransReset = FText::FromString(TEXT("Resetting the Transaction System for ScopedEditorWorld destruction."));
GEditor->Cleanse(true, true, TransReset);
}
if (World)
{
// Destroy world
World->DestroyWorld(false /*bBroadcastWorldDestroyedEvent*/);
// Unroot world
World->RemoveFromRoot();
// Restore previous GWorld / WorldContext
FWorldContext& WorldContext = GEditor->GetEditorWorldContext(true);
WorldContext.SetCurrentWorld(PrevGWorld);
GWorld = PrevGWorld;
}
}
UPackage* LoadWorldPackageForEditor(const FStringView InLongPackageName, EWorldType::Type InWorldType, uint32 InLoadFlags)
{
FSoftObjectPath WorldPackagePath(InLongPackageName);
UAssetRegistryHelpers::FixupRedirectedAssetPath(WorldPackagePath);
FString LongPackageName = WorldPackagePath.GetLongPackageName();
FName WorldPackageFName(LongPackageName);
UWorld::WorldTypePreLoadMap.FindOrAdd(WorldPackageFName) = InWorldType;
UPackage* WorldPackage = LoadPackage(nullptr, *LongPackageName, InLoadFlags);
UWorld::WorldTypePreLoadMap.Remove(WorldPackageFName);
return WorldPackage;
}