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

130 lines
4.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "LevelEditorDragDropHandler.h"
#include "Editor/EditorEngine.h"
#include "Engine/World.h"
#include "ObjectTools.h"
#include "AssetRegistry/AssetData.h"
#include "Engine/BrushBuilder.h"
#include "GameFramework/Actor.h"
#include "AssetSelection.h"
#include "Materials/MaterialInterface.h"
#include "UnrealEdGlobals.h"
#include "Editor/UnrealEdEngine.h"
#include "Editor.h"
#include "HitProxies.h"
#include "Misc/MessageDialog.h"
#define LOCTEXT_NAMESPACE "UnrealEd"
ULevelEditorDragDropHandler::ULevelEditorDragDropHandler()
{
}
bool ULevelEditorDragDropHandler::PassesFilter(UWorld* World, const FAssetData& AssetData, TUniquePtr<FLevelEditorDragDropWorldSurrogateReferencingObject>* OutWorldSurrogateReferencingObject)
{
if (World && bRunAssetFilter)
{
auto AssetPassesFilter = [](const FAssetData& InAssetData, const UObject* InReferencingAsset, FText* OutFailureReason = nullptr)
{
FAssetReferenceFilterContext AssetReferenceFilterContext;
AssetReferenceFilterContext.AddReferencingAsset(FAssetData(InReferencingAsset));
TSharedPtr<IAssetReferenceFilter> AssetReferenceFilter = GEditor->MakeAssetReferenceFilter(AssetReferenceFilterContext);
return AssetReferenceFilter.IsValid() ? AssetReferenceFilter->PassesFilter(InAssetData, OutFailureReason) : true;
};
ULevel* CurrentLevel = World->GetCurrentLevel();
UWorld* CurrentLevelOuterWorld = CurrentLevel ? Cast<UWorld>(CurrentLevel->GetOuter()) : nullptr;
UWorld* ReferencingWorld = CurrentLevelOuterWorld ? CurrentLevelOuterWorld : World;
FText FailureReason;
bool bPassesFilter = AssetPassesFilter(AssetData, ReferencingWorld, &FailureReason);
// Try to find with referencing asset matching the AssetData
if (OnLevelEditorDragDropWorldSurrogateReferencingObjectDelegate.IsBound())
{
TUniquePtr<FLevelEditorDragDropWorldSurrogateReferencingObject> Object = OnLevelEditorDragDropWorldSurrogateReferencingObjectDelegate.Execute(ReferencingWorld, AssetData.GetSoftObjectPath());
const UObject* ReferencingAsset = Object.IsValid() ? Object->GetValue() : nullptr;
bool bPassesFilterUsingWorldSurrogate = ReferencingAsset ? AssetPassesFilter(AssetData, ReferencingAsset) : false;
if (bPassesFilterUsingWorldSurrogate)
{
if (OutWorldSurrogateReferencingObject)
{
*OutWorldSurrogateReferencingObject = MoveTemp(Object);
}
bPassesFilter = true;
}
}
if (!bPassesFilter)
{
bCanDrop = false;
HintText = FailureReason;
return false;
}
}
return true;
}
bool ULevelEditorDragDropHandler::PreviewDropObjectsAtCoordinates(int32 MouseX, int32 MouseY, UWorld* World, FViewport* Viewport, const FAssetData& AssetData)
{
bCanDrop = true;
HintText = FText::GetEmpty();
if (!AssetData.IsValid())
{
bCanDrop = false;
return false;
}
return PassesFilter(World, AssetData);
}
bool ULevelEditorDragDropHandler::PreDropObjectsAtCoordinates(int32 MouseX, int32 MouseY, UWorld* World, FViewport* Viewport, const TArray<UObject*>& DroppedObjects, TArray<AActor*>& OutNewActors)
{
WorldSurrogateReferencingObject.Reset();
if (World && bRunAssetFilter)
{
if (DroppedObjects.IsEmpty() ||
(!PassesFilter(World, FAssetData(DroppedObjects[0]), &WorldSurrogateReferencingObject)))
{
return false;
}
auto GetValue = [](const TUniquePtr<FLevelEditorDragDropWorldSurrogateReferencingObject>& InSurrogateObject)
{
const FLevelEditorDragDropWorldSurrogateReferencingObject* Object = InSurrogateObject.Get();
return Object ? Object->GetValue() : nullptr;
};
for (int i=1; i<DroppedObjects.Num(); ++i)
{
TUniquePtr<FLevelEditorDragDropWorldSurrogateReferencingObject> DroppedSurrogateObject;
if (!PassesFilter(World, FAssetData(DroppedObjects[i]), &DroppedSurrogateObject) ||
(GetValue(DroppedSurrogateObject) != GetValue(WorldSurrogateReferencingObject)))
{
FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("DroppedObjectsDifferentSourcePluginPath", "Dropped objects are not part of the same source plugin path."));
WorldSurrogateReferencingObject.Reset();
return false;
}
}
return !WorldSurrogateReferencingObject.IsValid() || WorldSurrogateReferencingObject->OnPreDropObjects(World, DroppedObjects);
}
return true;
}
bool ULevelEditorDragDropHandler::PostDropObjectsAtCoordinates(int32 MouseX, int32 MouseY, UWorld* World, FViewport* Viewport, const TArray<UObject*>& DroppedObjects)
{
if (WorldSurrogateReferencingObject.IsValid())
{
bool bSuccess = WorldSurrogateReferencingObject->OnPostDropObjects(World, DroppedObjects);
WorldSurrogateReferencingObject.Reset();
return bSuccess;
}
return true;
}
#undef LOCTEXT_NAMESPACE