// Copyright Epic Games, Inc. All Rights Reserved. #include "LandscapeEditorUtils.h" #include "LandscapeSettings.h" #include "LandscapeEditorModule.h" #include "LandscapeEdit.h" #include "LandscapeEdMode.h" #include "LandscapeEditorObject.h" #include "LandscapeTiledImage.h" #include "LandscapeStreamingProxy.h" #include "DesktopPlatformModule.h" #include "EditorModeManager.h" #include "EditorModes.h" #include "Algo/Transform.h" #include "WorldPartition/WorldPartition.h" #include "WorldPartition/WorldPartitionHelpers.h" #include "Framework/Application/SlateApplication.h" #include "Misc/MessageDialog.h" #include "AssetRegistry/AssetData.h" #include "AssetRegistry/AssetRegistryModule.h" #include "Algo/LevenshteinDistance.h" namespace LandscapeEditorUtils { int32 GetMaxSizeInComponents() { const ULandscapeSettings* Settings = GetDefault(); return Settings->MaxComponents; } TOptional GetImportExportFilename(const FString& InDialogTitle, const FString& InStartPath, const FString& InDialogTypeString, bool bInImporting) { FString Filename; IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); if (DesktopPlatform == nullptr) { return TOptional(); } TArray Filenames; ILandscapeEditorModule& LandscapeEditorModule = FModuleManager::GetModuleChecked("LandscapeEditor"); FEdModeLandscape* LandscapeEdMode = static_cast(GLevelEditorModeTools().GetActiveMode(FBuiltinEditorModes::EM_Landscape)); bool bSuccess; if (bInImporting) { bSuccess = DesktopPlatform->OpenFileDialog( FSlateApplication::Get().FindBestParentWindowHandleForDialogs(nullptr), InDialogTitle, InStartPath, TEXT(""), InDialogTypeString, EFileDialogFlags::None, Filenames); } else { bSuccess = DesktopPlatform->SaveFileDialog( FSlateApplication::Get().FindBestParentWindowHandleForDialogs(nullptr), InDialogTitle, InStartPath, TEXT(""), InDialogTypeString, EFileDialogFlags::None, Filenames); } if (bSuccess) { FString TiledFileNamePattern; if (bInImporting && FLandscapeTiledImage::CheckTiledNamePath(Filenames[0], TiledFileNamePattern) && FMessageDialog::Open(EAppMsgType::YesNo, FText::FromString(FString::Format(TEXT("Use '{0}' Tiled Image?"), { TiledFileNamePattern }))) == EAppReturnType::Yes) { Filename = TiledFileNamePattern; } else { Filename = Filenames[0]; } } return TOptional(Filename); } void SaveLandscapeProxies(UWorld* World, TArrayView Proxies) { // Save the proxies TRACE_CPUPROFILER_EVENT_SCOPE(SaveCreatedActors); UWorldPartition::FDisableNonDirtyActorTrackingScope Scope(World->GetWorldPartition(), true); LandscapeEditorUtils::SaveObjects(Proxies); } const TArray GetLandscapeTargetLayerInfoAssets() { TArray LayerInfoAssets; const UClass* AssetClass = ULandscapeLayerInfoObject::StaticClass(); const FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked("AssetRegistry"); FARFilter Filter; const FName PackageName = *AssetClass->GetPackage()->GetName(); const FName AssetName = AssetClass->GetFName(); Filter.ClassPaths.Add(FTopLevelAssetPath(PackageName, AssetName)); AssetRegistryModule.Get().GetAssets(Filter, LayerInfoAssets); return LayerInfoAssets; } const FAssetData* FindLandscapeTargetLayerInfoAsset(const FName& LayerName, const FString& TargetLayerAssetPackagePath) { const TArray& LayerInfoAssets = GetLandscapeTargetLayerInfoAssets(); int32 BestScore = -1.0f; const FAssetData* BestLayerInfoObj = nullptr; for (const FAssetData& LayerInfoAsset : LayerInfoAssets) { const ULandscapeLayerInfoObject* LayerInfo = CastChecked(LayerInfoAsset.GetAsset()); FString CurrentPackagePath = LayerInfoAsset.PackagePath.ToString() + "/"; // Only include assets in the package or its sub folders if (LayerInfo && LayerInfo->LayerName == LayerName && CurrentPackagePath.Contains(TargetLayerAssetPackagePath)) { float WorstCase = static_cast(TargetLayerAssetPackagePath.Len() + CurrentPackagePath.Len()); WorstCase = FMath::Max(WorstCase, 1.f); const float Score = 1.0f - (static_cast(Algo::LevenshteinDistance(TargetLayerAssetPackagePath, CurrentPackagePath)) / WorstCase); if (Score > BestScore) { BestScore = Score; BestLayerInfoObj = &LayerInfoAsset; } } } return BestLayerInfoObj; } }