Example #1
0
void SAssetDialog::CommitObjectPathForSave()
{
	if ( ensure(DialogType == EAssetDialogType::Save) )
	{
		if ( bLastInputValidityCheckSuccessful )
		{
			const FString ObjectPath = GetObjectPathForSave();

			bool bProceedWithSave = true;

			// If we were asked to warn on existing assets, do it now
			if ( ExistingAssetPolicy == ESaveAssetDialogExistingAssetPolicy::AllowButWarn )
			{
				FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
				FAssetData ExistingAsset = AssetRegistryModule.Get().GetAssetByObjectPath(FName(*ObjectPath));
				if ( ExistingAsset.IsValid() && AssetClassNames.Contains(ExistingAsset.AssetClass) )
				{
					EAppReturnType::Type ShouldReplace = FMessageDialog::Open( EAppMsgType::YesNo, FText::Format(LOCTEXT("ReplaceAssetMessage", "{ExistingAsset} already exists. Do you want to replace it?"), FText::FromString(CurrentlyEnteredAssetName)) );
					bProceedWithSave = (ShouldReplace == EAppReturnType::Yes);
				}
			}

			if ( bProceedWithSave )
			{
				OnObjectPathChosenForSave.ExecuteIfBound(ObjectPath);
				CloseDialog();
			}
		}
	}
}
Example #2
0
void FActorFactoryAssetProxy::GenerateActorFactoryMenuItems( const FAssetData& AssetData, TArray<FMenuItem>* OutMenuItems, bool ExcludeStandAloneFactories  )
{
	FText UnusedErrorMessage;
	const FAssetData NoAssetData;
	for ( int32 FactoryIdx = 0; FactoryIdx < GEditor->ActorFactories.Num(); FactoryIdx++ )
	{
		UActorFactory* Factory = GEditor->ActorFactories[FactoryIdx];

		const bool FactoryWorksWithoutAsset = Factory->CanCreateActorFrom( NoAssetData, UnusedErrorMessage );
		const bool FactoryWorksWithAsset = AssetData.IsValid() && Factory->CanCreateActorFrom( AssetData, UnusedErrorMessage );
		const bool FactoryWorks = FactoryWorksWithAsset || FactoryWorksWithoutAsset;

		if ( FactoryWorks )
		{
			FMenuItem MenuItem = FMenuItem( Factory, NoAssetData );
			if ( FactoryWorksWithAsset )
			{
				MenuItem = FMenuItem( Factory, AssetData );
			}

			if ( FactoryWorksWithAsset || ( !ExcludeStandAloneFactories && FactoryWorksWithoutAsset ) )
			{
				OutMenuItems->Add( MenuItem );
			}
		}
	}
}
Example #3
0
void SAssetDialog::OnAssetSelected(const FAssetData& AssetData)
{
	CurrentlySelectedAssets = GetCurrentSelectionDelegate.Execute();
	
	if ( AssetData.IsValid() )
	{
		SetCurrentlySelectedPath(AssetData.PackagePath.ToString());
		SetCurrentlyEnteredAssetName(AssetData.AssetName.ToString());
	}
}
bool UVoreealBasicVolumeActorFactory::CanCreateActorFrom(const FAssetData& AssetData, FText& OutErrorMsg)
{
	if (AssetData.IsValid() && AssetData.GetClass()->IsChildOf(UBasicVolume::StaticClass()))
	{
		return true;
	}
	else
	{
		OutErrorMsg = NSLOCTEXT("Voreeal", "CanCreateActorFrom_NoVoxelVolume", "No voxel volume was specified.");
		return false;
	}
}
bool UPaperFlipbookActorFactory::CanCreateActorFrom(const FAssetData& AssetData, FText& OutErrorMsg)
{
	if (AssetData.IsValid() && AssetData.GetClass()->IsChildOf(UPaperFlipbook::StaticClass()))
	{
		return true;
	}
	else
	{
		OutErrorMsg = NSLOCTEXT("Paper2D", "CanCreateActorFrom_NoFlipbook", "No flipbook was specified.");
		return false;
	}
}
static bool CanCreateAnimBlueprint(const FAssetData& Skeleton, UClass const * ParentClass)
{
	if (Skeleton.IsValid() && ParentClass != NULL)
	{
		if (UAnimBlueprintGeneratedClass const * GeneratedParent = Cast<const UAnimBlueprintGeneratedClass>(ParentClass))
		{
			if (Skeleton.GetExportTextName() != FAssetData(GeneratedParent->GetTargetSkeleton()).GetExportTextName())
			{
				return false;
			}
		}
	}
	return true;
}
void FPrimaryAssetIdCustomization::OnSetObject(const FAssetData& AssetData)
{
	UAssetManager& Manager = UAssetManager::Get();

	if (StructPropertyHandle.IsValid() && StructPropertyHandle->IsValidHandle())
	{
		FPrimaryAssetId AssetId;
		if (AssetData.IsValid())
		{
			AssetId = Manager.GetPrimaryAssetIdForData(AssetData);
			ensure(AssetId.IsValid());
		}

		StructPropertyHandle->SetValueFromFormattedString(AssetId.ToString());
	}
}
bool UTerrainSplineActorFactory::CanCreateActorFrom(const FAssetData& AssetData, FText& OutErrorMsg)
{
	if (GetDefault<UPaperRuntimeSettings>()->bEnableTerrainSplineEditing)
	{
		if (AssetData.IsValid() && AssetData.GetClass()->IsChildOf(UPaperTerrainMaterial::StaticClass()))
		{
			return true;
		}
		else
		{
			return Super::CanCreateActorFrom(AssetData, OutErrorMsg);
		}
	}
	else
	{
		return false;
	}
}
bool SPropertyEditorAsset::CanSetBasedOnCustomClasses( const FAssetData& InAssetData ) const
{
	bool bAllowedToSetBasedOnFilter = true;
	if( InAssetData.IsValid() && CustomClassFilters.Num() > 0 )
	{
		bAllowedToSetBasedOnFilter = false;
		UClass* AssetClass = InAssetData.GetClass();
		for( const UClass* AllowedClass : CustomClassFilters )
		{
			if( AssetClass->IsChildOf( AllowedClass ) )
			{
				bAllowedToSetBasedOnFilter = true;
				break;
			}
		}
	}

	return bAllowedToSetBasedOnFilter;
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION

void SReflectorTreeWidgetItem::HandleHyperlinkNavigate()
{
	FAssetData AssetData = WidgetInfo->GetWidgetAssetData();
	if ( AssetData.IsValid() )
	{
		if ( OnAccessAsset.IsBound() )
		{
			AssetData.GetPackage();
			OnAccessAsset.Execute(AssetData.GetAsset());
			return;
		}
	}

	if ( OnAccessSourceCode.IsBound() )
	{
		OnAccessSourceCode.Execute(GetWidgetFile(), GetWidgetLineNumber(), 0);
	}
}
bool SPropertyEditorAsset::CanSetBasedOnCustomClasses( const FAssetData& InAssetData ) const
{
	bool bAllowedToSetBasedOnFilter = true;
	if( InAssetData.IsValid() && CustomClassFilters.Num() > 0 )
	{
		bAllowedToSetBasedOnFilter = false;
		UClass* AssetClass = InAssetData.GetClass();
		for( const UClass* AllowedClass : CustomClassFilters )
		{
			const bool bAllowedClassIsInterface = AllowedClass->HasAnyClassFlags(CLASS_Interface);
			if( AssetClass->IsChildOf( AllowedClass ) || (bAllowedClassIsInterface && AssetClass->ImplementsInterface(AllowedClass)) )
			{
				bAllowedToSetBasedOnFilter = true;
				break;
			}
		}
	}

	return bAllowedToSetBasedOnFilter;
}
	TArray<FAssetData> ExtractAssetDataFromDrag(const TSharedPtr<FDragDropOperation>& Operation)
	{
		TArray<FAssetData> DroppedAssetData;

		if (!Operation.IsValid())
		{
			return DroppedAssetData;
		}

		if (Operation->IsOfType<FExternalDragOperation>())
		{
			TSharedPtr<FExternalDragOperation> DragDropOp = StaticCastSharedPtr<FExternalDragOperation>(Operation);
			if ( DragDropOp->HasText() )
			{
				TArray<FString> DroppedAssetStrings;
				const TCHAR AssetDelimiter[] = { AssetMarshalDefs::AssetDelimiter, TEXT('\0') };
				DragDropOp->GetText().ParseIntoArray(DroppedAssetStrings, AssetDelimiter, true);

				FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
				IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();

				for (int Index = 0; Index < DroppedAssetStrings.Num(); Index++)
				{
					// Truncate each string so that it doesn't exceed the maximum allowed length of characters to be converted to an FName
					FString TruncatedString = DroppedAssetStrings[ Index ].Left( NAME_SIZE );
					FAssetData AssetData = AssetRegistry.GetAssetByObjectPath( FName( *TruncatedString ) );
					if ( AssetData.IsValid() )
					{
						DroppedAssetData.Add( AssetData );
					}
				}
			}
		}
		else if (Operation->IsOfType<FAssetDragDropOp>())
		{
			TSharedPtr<FAssetDragDropOp> DragDropOp = StaticCastSharedPtr<FAssetDragDropOp>( Operation );
			DroppedAssetData.Append( DragDropOp->AssetData );
		}

		return DroppedAssetData;
	}
void UEdGraphNode_Reference::CacheAssetData(const FAssetData& AssetData)
{
	if ( AssetData.IsValid() )
	{
		bUsesThumbnail = true;
		CachedAssetData = AssetData;
	}
	else
	{
		CachedAssetData = FAssetData();
		bUsesThumbnail = false;

		if ( PackageNames.Num() == 1 )
		{
			const FString PackageNameStr = PackageNames[0].ToString();
			if ( FPackageName::IsValidLongPackageName(PackageNameStr, true) )
			{
				if ( PackageNameStr.StartsWith(TEXT("/Script")) )
				{
					CachedAssetData.AssetClass = FName(TEXT("Code"));
				}
				else
				{
					const FString PotentiallyMapFilename = FPackageName::LongPackageNameToFilename(PackageNameStr, FPackageName::GetMapPackageExtension());
					const bool bIsMapPackage = FPlatformFileManager::Get().GetPlatformFile().FileExists(*PotentiallyMapFilename);
					if ( bIsMapPackage )
					{
						CachedAssetData.AssetClass = FName(TEXT("World"));
					}
				}
			}
		}
		else
		{
			CachedAssetData.AssetClass = FName(TEXT("Multiple Nodes"));
		}
	}

}
Example #14
0
	TArray<FAssetData> ExtractAssetDataFromDrag(const TSharedPtr<FDragDropOperation>& Operation)
	{
		TArray<FAssetData> DroppedAssetData;

		if (!Operation.IsValid())
		{
			return DroppedAssetData;
		}

		if (Operation->IsOfType<FExternalDragOperation>())
		{
			TSharedPtr<FExternalDragOperation> DragDropOp = StaticCastSharedPtr<FExternalDragOperation>(Operation);
			if ( DragDropOp->HasText() )
			{
				TArray<FString> DroppedAssetStrings;
				const TCHAR AssetDelimiter[] = { AssetMarshalDefs::AssetDelimiter, TEXT('\0') };
				DragDropOp->GetText().ParseIntoArray(DroppedAssetStrings, AssetDelimiter, true);

				FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
				IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();

				for (int Index = 0; Index < DroppedAssetStrings.Num(); Index++)
				{
					FAssetData AssetData = AssetRegistry.GetAssetByObjectPath( *DroppedAssetStrings[ Index ] );
					if ( AssetData.IsValid() )
					{
						DroppedAssetData.Add( AssetData );
					}
				}
			}
		}
		else if (Operation->IsOfType<FAssetDragDropOp>())
		{
			TSharedPtr<FAssetDragDropOp> DragDropOp = StaticCastSharedPtr<FAssetDragDropOp>( Operation );
			DroppedAssetData.Append( DragDropOp->AssetData );
		}

		return DroppedAssetData;
	}
Example #15
0
void FPropertyEditor::OnAssetSelected( const FAssetData& AssetData )
{
	// Set the object found from the asset picker
	GetPropertyHandle()->SetValueFromFormattedString( AssetData.IsValid() ? AssetData.GetAsset()->GetPathName() : TEXT("None") );
}
	virtual bool FixupObject(const FName& InObjectPath, FName& OutNewObjectPath) override
	{
		OutNewObjectPath = NAME_None;

		if (InObjectPath.ToString().StartsWith(TEXT("/Script/")))
		{
			// We can't use FindObject while we're saving
			if (!GIsSavingPackage)
			{
				const FString ClassPathStr = InObjectPath.ToString();

				UClass* FoundClass = FindObject<UClass>(ANY_PACKAGE, *ClassPathStr);
				if (!FoundClass)
				{
					// Use the linker to search for class name redirects (from the loaded ActiveClassRedirects)
					const FString ClassName = FPackageName::ObjectPathToObjectName(ClassPathStr);
					const FName NewClassName = FLinkerLoad::FindNewNameForClass(*ClassName, false);

					if (!NewClassName.IsNone())
					{
						// Our new class name might be lacking the path, so try and find it so we can use the full path in the collection
						FoundClass = FindObject<UClass>(ANY_PACKAGE, *NewClassName.ToString());
						if (FoundClass)
						{
							OutNewObjectPath = *FoundClass->GetPathName();
						}
					}
				}
			}
		}
		else
		{
			// Keep track of visted redirectors in case we loop.
			TSet<FName> VisitedRedirectors;

			// Use the asset registry to avoid loading the object
			FAssetData ObjectAssetData = AssetRegistryModule.Get().GetAssetByObjectPath(InObjectPath);
			while (ObjectAssetData.IsValid() && ObjectAssetData.IsRedirector())
			{
				// Check to see if we've already seen this path before, it's possible we might have found a redirector loop.
				if ( VisitedRedirectors.Contains(ObjectAssetData.ObjectPath) )
				{
					UE_LOG(LogContentBrowser, Error, TEXT("Redirector Loop Found!"));
					for ( FName Redirector : VisitedRedirectors )
					{
						UE_LOG(LogContentBrowser, Error, TEXT("Redirector: %s"), *Redirector.ToString());
					}

					ObjectAssetData = FAssetData();
					break;
				}

				VisitedRedirectors.Add(ObjectAssetData.ObjectPath);

				// Get the destination object from the meta-data rather than load the redirector object, as 
				// loading a redirector will also load the object it points to, which could cause a large hitch
				FString DestinationObjectPath;
				if (ObjectAssetData.GetTagValue("DestinationObject", DestinationObjectPath))
				{
					ConstructorHelpers::StripObjectClass(DestinationObjectPath);
					ObjectAssetData = AssetRegistryModule.Get().GetAssetByObjectPath(*DestinationObjectPath);
				}
				else
				{
					ObjectAssetData = FAssetData();
				}
			}

			OutNewObjectPath = ObjectAssetData.ObjectPath;
		}

		return OutNewObjectPath != NAME_None && InObjectPath != OutNewObjectPath;
	}
Example #17
0
void SSizeMap::GatherDependenciesRecursively( FAssetRegistryModule& AssetRegistryModule, TSharedPtr<FAssetThumbnailPool>& InAssetThumbnailPool, TMap<FName, TSharedPtr<FTreeMapNodeData>>& VisitedAssetPackageNames, const TArray<FName>& AssetPackageNames, const TSharedPtr<FTreeMapNodeData>& Node, TSharedPtr<FTreeMapNodeData>& SharedRootNode, int32& NumAssetsWhichFailedToLoad )
{
	for( const FName AssetPackageName : AssetPackageNames )
	{
		// Have we already added this asset to the tree?  If so, we'll either move it to a "shared" group or (if it's referenced again by the same
		// root-level asset) ignore it
		if( VisitedAssetPackageNames.Contains( AssetPackageName ) )
		{ 
			// OK, we've determined that this asset has already been referenced by something else in our tree.  We'll move it to a "shared" group
			// so all of the assets that are referenced in multiple places can be seen together.
			TSharedPtr<FTreeMapNodeData> ExistingNode = VisitedAssetPackageNames[ AssetPackageName ];

			// Is the existing node not already under the "shared" group?  Note that it might still be (indirectly) under
			// the "shared" group, in which case we'll still want to move it up to the root since we've figured out that it is
			// actually shared between multiple assets which themselves may be shared
			if( ExistingNode->Parent != SharedRootNode.Get() )
			{
				// Don't bother moving any of the assets at the root level into a "shared" bucket.  We're only trying to best
				// represent the memory used when all of the root-level assets have become loaded.  It's OK if root-level assets
				// are referenced by other assets in the set -- we don't need to indicate they are shared explicitly
				FTreeMapNodeData* ExistingNodeParent = ExistingNode->Parent;
				check( ExistingNodeParent != nullptr );
				const bool bExistingNodeIsAtRootLevel = ExistingNodeParent->Parent == nullptr || RootAssetPackageNames.Contains( AssetPackageName );
				if( !bExistingNodeIsAtRootLevel )
				{
					// OK, the current asset (AssetPackageName) is definitely not a root level asset, but its already in the tree
					// somewhere as a non-shared, non-root level asset.  We need to make sure that this Node's reference is not from the
					// same root-level asset as the ExistingNodeInTree.  Otherwise, there's no need to move it to a 'shared' group.
					FTreeMapNodeData* MyParentNode = Node.Get();
					check( MyParentNode != nullptr );
					FTreeMapNodeData* MyRootLevelAssetNode = MyParentNode;
					while( MyRootLevelAssetNode->Parent != nullptr && MyRootLevelAssetNode->Parent->Parent != nullptr )
					{
						MyRootLevelAssetNode = MyRootLevelAssetNode->Parent;
					}
					if( MyRootLevelAssetNode->Parent == nullptr )
					{
						// No root asset (Node must be a root level asset itself!)
						MyRootLevelAssetNode = nullptr;
					}
					
					// Find the existing node's root level asset node
					FTreeMapNodeData* ExistingNodeRootLevelAssetNode = ExistingNodeParent;
					while( ExistingNodeRootLevelAssetNode->Parent->Parent != nullptr )
					{
						ExistingNodeRootLevelAssetNode = ExistingNodeRootLevelAssetNode->Parent;
					}

					// If we're being referenced by another node within the same asset, no need to move it to a 'shared' group.  
					if( MyRootLevelAssetNode != ExistingNodeRootLevelAssetNode )
					{
						// This asset was already referenced by something else (or was in our top level list of assets to display sizes for)
						if( !SharedRootNode.IsValid() )
						{
							// Find the root-most tree node
							FTreeMapNodeData* RootNode = MyParentNode;
							while( RootNode->Parent != nullptr )
							{
								RootNode = RootNode->Parent;
							}

							SharedRootNode = MakeShareable( new FTreeMapNodeData() );
							RootNode->Children.Add( SharedRootNode );
							SharedRootNode->Parent = RootNode;	// Keep back-pointer to parent node
						}

						// Reparent the node that we've now determined to be shared
						ExistingNode->Parent->Children.Remove( ExistingNode );
						SharedRootNode->Children.Add( ExistingNode );
						ExistingNode->Parent = SharedRootNode.Get();
					}
				}
			}
		}
		else
		{
			// This asset is new to us so far!  Let's add it to the tree.  Later as we descend through references, we might find that the
			// asset is referenced by something else as well, in which case we'll pull it out and move it to a "shared" top-level box
					
			// Don't bother showing code references
			const FString AssetPackageNameString = AssetPackageName.ToString();
			if( !AssetPackageNameString.StartsWith( TEXT( "/Script/" ) ) )
			{
				FTreeMapNodeDataRef ChildTreeMapNode = MakeShareable( new FTreeMapNodeData() );
				Node->Children.Add( ChildTreeMapNode );
				ChildTreeMapNode->Parent = Node.Get();	// Keep back-pointer to parent node

				VisitedAssetPackageNames.Add( AssetPackageName, ChildTreeMapNode );

				FNodeSizeMapData& NodeSizeMapData = NodeSizeMapDataMap.Add( ChildTreeMapNode );

				// Set some defaults for this node.  These will be used if we can't actually locate the asset.
				// @todo sizemap urgent: We need a better indication in the UI when there are one or more missing assets.  Because missing assets have a size 
				//    of zero, they are nearly impossible to zoom into.  At the least, we should have some Output Log spew when assets cannot be loaded
				NodeSizeMapData.AssetData.AssetName = AssetPackageName;
				NodeSizeMapData.AssetData.AssetClass = FName( *LOCTEXT( "MissingAsset", "MISSING!" ).ToString() );
				NodeSizeMapData.AssetSize = 0;
				NodeSizeMapData.bHasKnownSize = false;

				// Find the asset using the asset registry
				// @todo sizemap: Asset registry-based reference gathering is faster but possibly not as exhaustive (no PostLoad created references, etc.)  Maybe should be optional?
				// @todo sizemap: With AR-based reference gathering, sometimes the size map is missing root level dependencies until you reopen it a few times (Buggy BP)
				// @todo sizemap: With AR-based reference gathering, reference changes at editor-time do not appear in the Size Map until you restart
				// @todo sizemap: With AR-based reference gathering, opening the size map for all engine content caused the window to not respond until a restart
				// @todo sizemap: We don't really need the asset registry given we need to load the objects to figure out their size, unless we make that AR-searchable.
				//   ---> This would allow us to not have to wait for AR initialization.  But if we made size AR-searchable, we could run very quickly for large data sets!
				const bool bUseAssetRegistryForDependencies = false;

				const FString AssetPathString = AssetPackageNameString + TEXT(".") + FPackageName::GetLongPackageAssetName( AssetPackageNameString );
				const FAssetData FoundAssetData = AssetRegistryModule.Get().GetAssetByObjectPath( FName( *AssetPathString ) );
				if( FoundAssetData.IsValid() )
				{
					NodeSizeMapData.AssetData = FoundAssetData;

					// Now actually load up the asset.  We need it in memory in order to accurately determine its size.
					// @todo sizemap: We could async load these packages to make the editor experience a bit nicer (smoother progress)
					UObject* Asset = StaticLoadObject( UObject::StaticClass(), nullptr, *AssetPathString );
					if( Asset != nullptr )
					{
						TArray<FName> ReferencedAssetPackageNames;
						if( bUseAssetRegistryForDependencies )
						{
							AssetRegistryModule.Get().GetDependencies( AssetPackageName, ReferencedAssetPackageNames );
						}
						else
						{
							SizeMapInternals::FAssetReferenceFinder References( Asset );
							for( UObject* Object : References.GetReferencedAssets() )
							{
								ReferencedAssetPackageNames.Add( FName( *Object->GetOutermost()->GetPathName() ) );
							}
						}

						// For textures, make sure we're getting the worst case size, not the size of the currently loaded set of mips
						// @todo sizemap: We should instead have a special EResourceSizeMode that asks for the worst case size.  Some assets (like UTextureCube) currently always report resident mip size, even when asked for inclusive size
						if( Asset->IsA( UTexture2D::StaticClass() ) )
						{
							NodeSizeMapData.AssetSize = Asset->GetResourceSize( EResourceSizeMode::Inclusive );
						}
						else
						{
							NodeSizeMapData.AssetSize = Asset->GetResourceSize( EResourceSizeMode::Exclusive );
						}

						NodeSizeMapData.bHasKnownSize = NodeSizeMapData.AssetSize != UObject::RESOURCE_SIZE_NONE && NodeSizeMapData.AssetSize != 0;
						if( !NodeSizeMapData.bHasKnownSize )
						{
							// Asset has no meaningful size
							NodeSizeMapData.AssetSize = 0;

							// @todo sizemap urgent: Try to serialize to figure out how big it is (not into sub-assets though!)
							// FObjectMemoryAnalyzer ObjectMemoryAnalyzer( Asset );
						}

								
						// Now visit all of the assets that we are referencing
						GatherDependenciesRecursively( AssetRegistryModule, InAssetThumbnailPool, VisitedAssetPackageNames, ReferencedAssetPackageNames, ChildTreeMapNode, SharedRootNode, NumAssetsWhichFailedToLoad );
					}
					else
					{
						++NumAssetsWhichFailedToLoad;
					}
				}
				else
				{
					++NumAssetsWhichFailedToLoad;
				}
			}
		}
	}
}