// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "AssetRegistry/AssetData.h" #include "Input/Reply.h" class AActor; struct FTypedElementHandle; class IAssetFactoryInterface; class UActorFactory; class ULevel; class UMaterialInterface; // forward decl. class UActorFactory; struct AssetMarshalDefs { static const TCHAR AssetDelimiter = TEXT('|'); static const TCHAR NameTypeDelimiter = TEXT(' '); static const TCHAR* FormatName() { return TEXT("UnrealEd/Assets"); } }; namespace AssetUtil { /** Extract the names of the assets which are being dragged*/ UNREALED_API TArray ExtractAssetDataFromDrag( const FDragDropEvent& DragDropEvent ); UNREALED_API TArray ExtractAssetDataFromDrag(const TSharedPtr& Operation); /** * Given an array of asset names, loads the assets into an array of objects * * @param AssetNames (In) Array of Asset names to get UObjects for * @param bAllWereLoaded (Out) Optional param which indicates if all assets were loaded */ UNREALED_API TArray GetObjects(const TArray& AssetNames, bool* bAllWereLoaded = NULL); /** Given an asset name, finds the object for the asset*/ UNREALED_API UObject* GetObject(const FString& AssetName); /** Does drag event contain any asset types which have components that support drag/drop?*/ UNREALED_API FReply CanHandleAssetDrag( const FDragDropEvent &DragDropEvent ); } /** * Generic information about the level selection set (actors or surfaces) */ struct FSelectedActorInfo { /** String representing the selected class */ FString SelectionStr; /** The selected class type */ UClass* SelectionClass; /** The level that is shared between all actors, or NULL if selected actors aren't in the same level */ ULevel* SharedLevel; /** The world that is shared between all actors, or NULL if selected actors aren't in the same level */ UWorld* SharedWorld; /** How many are selected */ uint32 NumSelected; /** How many nav points are selected */ uint32 NumNavPoints; /** The number of selected actors that arent in a group */ uint32 NumSelectedUngroupedActors; /** Number of properties of selected actors that are not yet propagated from the simulation world to the editor world */ uint32 NumSimulationChanges; /** We have at least one actor that is attached to something */ uint32 bHaveAttachedActor:1; /** Are all the selected actors the same type */ uint32 bAllSelectedActorsOfSameType:1; /** Are all the selected actors brushes */ uint32 bAllSelectedAreBrushes:1; /** true if a locked group is selected */ uint32 bHaveSelectedLockedGroup:1; /** true if an unlocked group is selected */ uint32 bHaveSelectedUnlockedGroup:1; /** true if a sub-group is selected */ uint32 bHaveSelectedSubGroup:1; /** true if all selected actors belong to the same level */ uint32 bSelectedActorsBelongToSameLevel:1; /** true if all selected actors belong to the current level */ uint32 bAllSelectedActorsBelongToCurrentLevel:1; /** true if all selected actors belong to the same world */ uint32 bAllSelectedActorsBelongToSameWorld:1; /** true if all selected actors have collision models */ uint32 bAllSelectedStaticMeshesHaveCollisionModels:1; /** true if a brush is in the selection */ uint32 bHaveBrush:1; /** true if there is a bsp brush in the selection */ uint32 bHaveBSPBrush:1; /** true if a volume brush is in the selection */ uint32 bHaveVolume:1; /** true if a builder brush is in the selection */ uint32 bHaveBuilderBrush:1; /** true if an actor in the selection has a static mesh component */ uint32 bHaveStaticMeshComponent:1; /** true if an actor in the selection is a static mesh*/ uint32 bHaveStaticMesh:1; /** true if an actor in the selection is a light */ uint32 bHaveLight:1; /** true if an actor in the selection is a pawn */ uint32 bHavePawn:1; /** true if an actor in the selection is a skeletal mesh */ uint32 bHaveSkeletalMesh:1; /** true if an actor in the selection is an emitter */ uint32 bHaveEmitter:1; /** true if an actor in the selection is hidden */ uint32 bHaveHidden:1; /** true if a landscape is in the selection */ uint32 bHaveLandscape:1; /** true if an experimental actor (or actor containing such a component) is selected */ uint32 bHaveExperimentalClass:1; /** true if an early access actor (or actor containing such a component) is selected */ uint32 bHaveEarlyAccessClass:1; /** true if an actor in the selection has an override for the asset it browses to in the Content Browser*/ uint32 bHaveBrowseOverride:1; FSelectedActorInfo() : SelectionClass(NULL) , SharedLevel(NULL) , SharedWorld(NULL) , NumSelected(0) , NumNavPoints(0) , NumSelectedUngroupedActors(0) , NumSimulationChanges(0) , bHaveAttachedActor(false) , bAllSelectedActorsOfSameType(true) , bAllSelectedAreBrushes(false) , bHaveSelectedLockedGroup(false) , bHaveSelectedUnlockedGroup(false) , bHaveSelectedSubGroup(false) , bSelectedActorsBelongToSameLevel(true) , bAllSelectedActorsBelongToCurrentLevel(true) , bAllSelectedActorsBelongToSameWorld(true) , bAllSelectedStaticMeshesHaveCollisionModels(true) , bHaveBrush(false) , bHaveBSPBrush(false) , bHaveVolume(false) , bHaveBuilderBrush(false) , bHaveStaticMeshComponent(false) , bHaveStaticMesh(false) , bHaveLight(false) , bHavePawn(false) , bHaveSkeletalMesh(false) , bHaveEmitter(false) , bHaveHidden(false) , bHaveLandscape(false) , bHaveExperimentalClass(false) , bHaveEarlyAccessClass(false) , bHaveBrowseOverride(false) { } /** * @return true if the selection set has an actor that can be converted to a different actor */ bool HasConvertableAsset() const { return NumSelected && !bHaveBuilderBrush; } }; namespace AssetSelectionUtils { /** * Checks if a class type can be placed in a level * * @param Class The class to check * @return true if the class is placeable */ UNREALED_API bool IsClassPlaceable(const UClass* Class); /** * Checks if a Blueprint based on a class type can be placed in a level * * @param Class The class to check * @return true if the Blueprint based on this class is placeable */ UNREALED_API bool IsChildBlueprintPlaceable(const UClass* Class); /** * Gets the selected assets in the content browser * * @param SelectedLoadedAssets (Out) The list of assets which are loaded * @param SelectedUnloadedAssets (Out) The ist of assets which are selected but are unloaded */ UNREALED_API void GetSelectedAssets( TArray& OutSelectedAssets ); /** * Gets generic info about the selected actors or surfaces in the world * * @param SelectedActors The selected actors to build info about * @return Information about the selection */ UNREALED_API FSelectedActorInfo BuildSelectedActorInfo( const TArray& SelectedActors ); /** * A wrapper for the BuildSelectedActorInfo function that passes the SelectedActors array form GEditor * * @return Information about the selection */ UNREALED_API FSelectedActorInfo GetSelectedActorInfo(); /** * @return the number of selected bsp surfaces */ UNREALED_API int32 GetNumSelectedSurfaces( UWorld* InWorld ); /** * @return whether any surface is selected */ UNREALED_API bool IsAnySurfaceSelected( UWorld* InWorld ); /** * @return true if the builder brush is in the list of selected actors; false, otherwise. */ UNREALED_API bool IsBuilderBrushSelected(); }; namespace ActorPlacementUtils { UNREALED_API bool IsLevelValidForActorPlacement(ULevel* Level, TArray& InActorTransforms); } class FActorFactoryAssetProxy { public: /** * Information about an add actor menu item */ struct FMenuItem { /** Actor factory used to spawn the actor when the menu item is clicked */ UActorFactory* FactoryToUse; /** The asset data to use with the factory */ FAssetData AssetData; FMenuItem( UActorFactory* InFactoryToUse, const FAssetData& InAssetData ) : FactoryToUse( InFactoryToUse ) , AssetData( InAssetData ) {} }; /** * Builds a list of strings for populating the actor factory context menu items. This menu is shown when * the user right-clicks in a level viewport. * * @param AssetData The asset the factories should consider when building the menus. * @param OutMenuItems receives the list of menu items to use for populating an actor factory menu. * @param ExcludeStandAloneFactories if true, only factories that can create actors with the currently selected assets will be added */ static UNREALED_API void GenerateActorFactoryMenuItems( const FAssetData& AssetData, TArray* OutMenuItems, bool ExcludeStandAloneFactories ); /** * Find the appropriate actor factory for an asset by type. * * @param AssetData contains information about an asset that to get a factory for * @param bRequireValidObject indicates whether a valid asset object is required. specify false to allow the asset * class's CDO to be used in place of the asset if no asset is part of the drag-n-drop * * @return the factory that is responsible for creating actors for the specified asset type. */ static UNREALED_API UActorFactory* GetFactoryForAsset( const FAssetData& DropData, bool bRequireValidObject=false ); /** * Find the appropriate actor factory for an asset. * * @param AssetObj The asset that to find the appropriate actor factory for * * @return The factory that is responsible for creating actors for the specified asset */ static UNREALED_API UActorFactory* GetFactoryForAssetObject( UObject* AssetObj ); //~ TODO: UE_DEPRECATED(5.4, "Use UE::AssetPlacementUtil::PlaceAssetInCurrentLevel instead") /** * Places an actor instance using the factory appropriate for the type of asset * * @param AssetObj the asset that is contained in the d&d operation * @param ObjectFlags The object flags to place on the actor when it is spawned * @param FactoryToUse optional actor factory to use to create the actor; if not specified, * the highest priority factory that is valid will be used * * @return the actor that was created by the factory, or NULL if there aren't any factories for this asset (or * the actor couldn't be created for some other reason) */ static UNREALED_API AActor* AddActorForAsset( UObject* AssetObj, bool SelectActor = true, EObjectFlags ObjectFlags = RF_Transactional, UActorFactory* FactoryToUse = NULL, const FName Name = NAME_None ); //~ TODO: UE_DEPRECATED(5.4) /** * Places an actor instance using the factory appropriate for the type of asset using the current object selection as the asset * * @param ActorClass The type of actor to create * @param ActorLocation specify null to position the actor at the mouse location, otherwise it will be placed at the origin. * @param ObjectFlags The object flags to place on the actor when it is spawned * @param FactoryToUse optional actor factory to use to create the actor; if not specified, * the highest priority factory that is valid will be used * * @return the actor that was created by the factory, or NULL if there aren't any factories for this asset (or * the actor couldn't be created for some other reason) */ static UNREALED_API AActor* AddActorFromSelection( UClass* ActorClass, const FVector* ActorLocation=NULL, bool SelectActor = true, EObjectFlags ObjectFlags = RF_Transactional, UActorFactory* ActorFactory = NULL, const FName Name = NAME_None ); /** * Determines if the provided actor is capable of having a material applied to it. * * @param TargetActor Actor to check for the validity of material application * * @return true if the actor is valid for material application; false otherwise */ static UNREALED_API bool IsActorValidForMaterialApplication( AActor* TargetActor ); /** * Attempts to apply the material to the specified actor. * * @param TargetActor the actor to apply the material to * @param MaterialToApply the material to apply to the actor * @param OptionalMaterialSlot the material slot to apply it to. * * @return true if the material was successfully applied to the actor */ static UNREALED_API bool ApplyMaterialToActor( AActor* TargetActor, UMaterialInterface* MaterialToApply, int32 OptionalMaterialSlot = -1 ); private: /** * Constructor * * Private, as this class is [currently] not intended to be instantiated */ FActorFactoryAssetProxy() { } }; namespace UE::AssetPlacementUtil { struct FExtraPlaceAssetOptions { bool bSelectOutput = true; EObjectFlags ObjectFlags = RF_Transactional; TScriptInterface FactoryToUse = NULL; FName Name = NAME_None; }; /** * Places an asset instance using the factory appropriate for the type of asset * * @param AssetObj the asset that is contained in the d&d operation * * @return the object that was created by the factory, or NULL if there aren't any factories for this asset (or * the object couldn't be created for some other reason) */ UNREALED_API TArray PlaceAssetInCurrentLevel(UObject* AssetObj, const FExtraPlaceAssetOptions& ExtraParams); }