You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
2193 lines
65 KiB
C++
2193 lines
65 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#include "AssetViewWidgets.h"
|
|
#include "UObject/UnrealType.h"
|
|
#include "Widgets/SOverlay.h"
|
|
#include "Engine/GameViewportClient.h"
|
|
#include "SlateOptMacros.h"
|
|
#include "Framework/Application/SlateApplication.h"
|
|
#include "Widgets/Images/SImage.h"
|
|
#include "Materials/Material.h"
|
|
#include "ISourceControlProvider.h"
|
|
#include "ISourceControlModule.h"
|
|
#include "SourceControlHelpers.h"
|
|
#include "EditorFramework/AssetImportData.h"
|
|
#include "Engine/Texture2D.h"
|
|
#include "ARFilter.h"
|
|
#include "AssetRegistryModule.h"
|
|
#include "IAssetTools.h"
|
|
#include "AssetToolsModule.h"
|
|
#include "CollectionManagerTypes.h"
|
|
#include "ICollectionManager.h"
|
|
#include "CollectionManagerModule.h"
|
|
#include "AssetViewTypes.h"
|
|
#include "SThumbnailEditModeTools.h"
|
|
#include "AutoReimport/AssetSourceFilenameCache.h"
|
|
#include "CollectionViewUtils.h"
|
|
#include "DragAndDrop/AssetDragDropOp.h"
|
|
#include "DragDropHandler.h"
|
|
#include "Internationalization/BreakIterator.h"
|
|
#include "Widgets/Text/SInlineEditableTextBlock.h"
|
|
#include "Misc/EngineBuildSettings.h"
|
|
#include "ContentBrowserLog.h"
|
|
#include "ObjectTools.h"
|
|
#include "AssetThumbnail.h"
|
|
#include "Settings/ContentBrowserSettings.h"
|
|
#include "ContentBrowserModule.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "ContentBrowser"
|
|
|
|
|
|
///////////////////////////////
|
|
// FAssetViewModeUtils
|
|
///////////////////////////////
|
|
|
|
FReply FAssetViewModeUtils::OnViewModeKeyDown( const TSet< TSharedPtr<FAssetViewItem> >& SelectedItems, const FKeyEvent& InKeyEvent )
|
|
{
|
|
// All asset views use Ctrl-C to copy references to assets
|
|
if ( InKeyEvent.IsControlDown() && InKeyEvent.GetCharacter() == 'C' )
|
|
{
|
|
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
|
|
|
|
TArray<FAssetData> SelectedAssets;
|
|
for ( auto ItemIt = SelectedItems.CreateConstIterator(); ItemIt; ++ItemIt)
|
|
{
|
|
const TSharedPtr<FAssetViewItem>& Item = *ItemIt;
|
|
if(Item.IsValid())
|
|
{
|
|
if(Item->GetType() == EAssetItemType::Folder)
|
|
{
|
|
// we need to recurse & copy references to all folder contents
|
|
FARFilter Filter;
|
|
Filter.PackagePaths.Add(*StaticCastSharedPtr<FAssetViewFolder>(Item)->FolderPath);
|
|
|
|
// Add assets found in the asset registry
|
|
AssetRegistryModule.Get().GetAssets(Filter, SelectedAssets);
|
|
}
|
|
else
|
|
{
|
|
SelectedAssets.Add(StaticCastSharedPtr<FAssetViewAsset>(Item)->Data);
|
|
}
|
|
}
|
|
}
|
|
|
|
ContentBrowserUtils::CopyAssetReferencesToClipboard(SelectedAssets);
|
|
|
|
return FReply::Handled();
|
|
}
|
|
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
|
|
///////////////////////////////
|
|
// FAssetViewModeUtils
|
|
///////////////////////////////
|
|
|
|
TSharedRef<SWidget> FAssetViewItemHelper::CreateListItemContents(SAssetListItem* const InListItem, const TSharedRef<SWidget>& InThumbnail, FName& OutItemShadowBorder)
|
|
{
|
|
return CreateListTileItemContents(InListItem, InThumbnail, OutItemShadowBorder);
|
|
}
|
|
|
|
TSharedRef<SWidget> FAssetViewItemHelper::CreateTileItemContents(SAssetTileItem* const InTileItem, const TSharedRef<SWidget>& InThumbnail, FName& OutItemShadowBorder)
|
|
{
|
|
return CreateListTileItemContents(InTileItem, InThumbnail, OutItemShadowBorder);
|
|
}
|
|
|
|
template <typename T>
|
|
TSharedRef<SWidget> FAssetViewItemHelper::CreateListTileItemContents(T* const InTileOrListItem, const TSharedRef<SWidget>& InThumbnail, FName& OutItemShadowBorder)
|
|
{
|
|
TSharedRef<SOverlay> ItemContentsOverlay = SNew(SOverlay);
|
|
|
|
if (InTileOrListItem->IsFolder())
|
|
{
|
|
OutItemShadowBorder = FName("NoBorder");
|
|
|
|
TSharedPtr<FAssetViewFolder> AssetFolderItem = StaticCastSharedPtr<FAssetViewFolder>(InTileOrListItem->AssetItem);
|
|
|
|
ECollectionShareType::Type CollectionFolderShareType = ECollectionShareType::CST_All;
|
|
if (AssetFolderItem->bCollectionFolder)
|
|
{
|
|
ContentBrowserUtils::IsCollectionPath(AssetFolderItem->FolderPath, nullptr, &CollectionFolderShareType);
|
|
}
|
|
|
|
const FSlateBrush* FolderBaseImage = AssetFolderItem->bDeveloperFolder
|
|
? FEditorStyle::GetBrush("ContentBrowser.ListViewDeveloperFolderIcon.Base")
|
|
: FEditorStyle::GetBrush("ContentBrowser.ListViewFolderIcon.Base");
|
|
|
|
const FSlateBrush* FolderTintImage = AssetFolderItem->bDeveloperFolder
|
|
? FEditorStyle::GetBrush("ContentBrowser.ListViewDeveloperFolderIcon.Mask")
|
|
: FEditorStyle::GetBrush("ContentBrowser.ListViewFolderIcon.Mask");
|
|
|
|
// Folder base
|
|
ItemContentsOverlay->AddSlot()
|
|
[
|
|
SNew(SImage)
|
|
.Image(FolderBaseImage)
|
|
.ColorAndOpacity(InTileOrListItem, &T::GetAssetColor)
|
|
];
|
|
|
|
if (AssetFolderItem->bCollectionFolder)
|
|
{
|
|
FLinearColor IconColor = FLinearColor::White;
|
|
switch(CollectionFolderShareType)
|
|
{
|
|
case ECollectionShareType::CST_Local:
|
|
IconColor = FColor(196, 15, 24);
|
|
break;
|
|
case ECollectionShareType::CST_Private:
|
|
IconColor = FColor(192, 196, 0);
|
|
break;
|
|
case ECollectionShareType::CST_Shared:
|
|
IconColor = FColor(0, 136, 0);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
auto GetCollectionIconBoxSize = [InTileOrListItem]() -> FOptionalSize
|
|
{
|
|
return FOptionalSize(InTileOrListItem->GetThumbnailBoxSize().Get() * 0.3f);
|
|
};
|
|
|
|
auto GetCollectionIconBrush = [=]() -> const FSlateBrush*
|
|
{
|
|
const TCHAR* IconSizeSuffix = (GetCollectionIconBoxSize().Get() <= 16.0f) ? TEXT(".Small") : TEXT(".Large");
|
|
return FEditorStyle::GetBrush(ECollectionShareType::GetIconStyleName(CollectionFolderShareType, IconSizeSuffix));
|
|
};
|
|
|
|
// Collection share type
|
|
ItemContentsOverlay->AddSlot()
|
|
.HAlign(HAlign_Center)
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(SBox)
|
|
.WidthOverride_Lambda(GetCollectionIconBoxSize)
|
|
.HeightOverride_Lambda(GetCollectionIconBoxSize)
|
|
[
|
|
SNew(SImage)
|
|
.Image_Lambda(GetCollectionIconBrush)
|
|
.ColorAndOpacity(IconColor)
|
|
]
|
|
];
|
|
}
|
|
|
|
// Folder tint
|
|
ItemContentsOverlay->AddSlot()
|
|
[
|
|
SNew(SImage)
|
|
.Image(FolderTintImage)
|
|
];
|
|
}
|
|
else
|
|
{
|
|
OutItemShadowBorder = FName("ContentBrowser.ThumbnailShadow");
|
|
|
|
// The actual thumbnail
|
|
ItemContentsOverlay->AddSlot()
|
|
[
|
|
InThumbnail
|
|
];
|
|
|
|
// Source control state
|
|
ItemContentsOverlay->AddSlot()
|
|
.HAlign(HAlign_Right)
|
|
.VAlign(VAlign_Top)
|
|
[
|
|
SNew(SBox)
|
|
.MaxDesiredWidth(InTileOrListItem, &T::GetStateIconImageSize)
|
|
.MaxDesiredHeight(InTileOrListItem, &T::GetStateIconImageSize)
|
|
[
|
|
SNew(SImage)
|
|
.Image(InTileOrListItem, &T::GetSCCStateImage)
|
|
]
|
|
];
|
|
|
|
// Extra external state hook
|
|
ItemContentsOverlay->AddSlot()
|
|
.HAlign(HAlign_Left)
|
|
.VAlign(VAlign_Top)
|
|
[
|
|
SNew(SBox)
|
|
.MaxDesiredWidth(InTileOrListItem, &T::GetExtraStateIconMaxWidth)
|
|
.MaxDesiredHeight(InTileOrListItem, &T::GetStateIconImageSize)
|
|
[
|
|
InTileOrListItem->GenerateExtraStateIconWidget(TAttribute<float>(InTileOrListItem, &T::GetExtraStateIconWidth))
|
|
]
|
|
];
|
|
|
|
// Dirty state
|
|
ItemContentsOverlay->AddSlot()
|
|
.HAlign(HAlign_Left)
|
|
.VAlign(VAlign_Bottom)
|
|
[
|
|
SNew(SBox)
|
|
.MaxDesiredWidth(InTileOrListItem, &T::GetStateIconImageSize)
|
|
.MaxDesiredHeight(InTileOrListItem, &T::GetStateIconImageSize)
|
|
[
|
|
SNew(SImage)
|
|
.Image(InTileOrListItem, &T::GetDirtyImage)
|
|
]
|
|
];
|
|
|
|
// Tools for thumbnail edit mode
|
|
ItemContentsOverlay->AddSlot()
|
|
[
|
|
SNew(SThumbnailEditModeTools, InTileOrListItem->AssetThumbnail)
|
|
.SmallView(!InTileOrListItem->CanDisplayPrimitiveTools())
|
|
.Visibility(InTileOrListItem, &T::GetThumbnailEditModeUIVisibility)
|
|
];
|
|
}
|
|
|
|
return ItemContentsOverlay;
|
|
}
|
|
|
|
|
|
///////////////////////////////
|
|
// Asset view item tool tip
|
|
///////////////////////////////
|
|
|
|
class SAssetViewItemToolTip : public SToolTip
|
|
{
|
|
public:
|
|
SLATE_BEGIN_ARGS(SAssetViewItemToolTip)
|
|
: _AssetViewItem()
|
|
{ }
|
|
|
|
SLATE_ARGUMENT(TSharedPtr<SAssetViewItem>, AssetViewItem)
|
|
|
|
SLATE_END_ARGS()
|
|
|
|
void Construct(const FArguments& InArgs)
|
|
{
|
|
AssetViewItem = InArgs._AssetViewItem;
|
|
|
|
SToolTip::Construct(
|
|
SToolTip::FArguments()
|
|
.TextMargin(1.0f)
|
|
.BorderImage(FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.ToolTipBorder"))
|
|
);
|
|
}
|
|
|
|
// IToolTip interface
|
|
virtual bool IsEmpty() const override
|
|
{
|
|
return !AssetViewItem.IsValid();
|
|
}
|
|
|
|
virtual void OnOpening() override
|
|
{
|
|
TSharedPtr<SAssetViewItem> AssetViewItemPin = AssetViewItem.Pin();
|
|
if (AssetViewItemPin.IsValid())
|
|
{
|
|
SetContentWidget(AssetViewItemPin->CreateToolTipWidget());
|
|
}
|
|
}
|
|
|
|
virtual void OnClosed() override
|
|
{
|
|
SetContentWidget(SNullWidget::NullWidget);
|
|
}
|
|
|
|
private:
|
|
TWeakPtr<SAssetViewItem> AssetViewItem;
|
|
};
|
|
|
|
|
|
///////////////////////////////
|
|
// Asset view modes
|
|
///////////////////////////////
|
|
|
|
FReply SAssetTileView::OnKeyDown( const FGeometry& InGeometry, const FKeyEvent& InKeyEvent )
|
|
{
|
|
FReply Reply = FAssetViewModeUtils::OnViewModeKeyDown(SelectedItems, InKeyEvent);
|
|
|
|
if ( Reply.IsEventHandled() )
|
|
{
|
|
return Reply;
|
|
}
|
|
else
|
|
{
|
|
return STileView<TSharedPtr<FAssetViewItem>>::OnKeyDown(InGeometry, InKeyEvent);
|
|
}
|
|
}
|
|
|
|
void SAssetTileView::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
|
|
{
|
|
// Regreshing an asset view is an intensive task. Do not do this while a user
|
|
// is dragging arround content for maximum responsiveness.
|
|
// Also prevents a re-entrancy crash caused by potentially complex thumbnail generators.
|
|
if (!FSlateApplication::Get().IsDragDropping())
|
|
{
|
|
STileView<TSharedPtr<FAssetViewItem>>::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);
|
|
}
|
|
}
|
|
|
|
bool SAssetTileView::HasWidgetForAsset(const FName& AssetPathName)
|
|
{
|
|
for (const TSharedPtr<FAssetViewItem>& Item : WidgetGenerator.ItemsWithGeneratedWidgets)
|
|
{
|
|
if (Item.IsValid() && Item->GetType() == EAssetItemType::Normal)
|
|
{
|
|
const FName& ObjectPath = StaticCastSharedPtr<FAssetViewAsset>(Item)->Data.ObjectPath;
|
|
if (ObjectPath == AssetPathName)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
FReply SAssetListView::OnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
|
|
{
|
|
FReply Reply = FAssetViewModeUtils::OnViewModeKeyDown(SelectedItems, InKeyEvent);
|
|
|
|
if ( Reply.IsEventHandled() )
|
|
{
|
|
return Reply;
|
|
}
|
|
else
|
|
{
|
|
return SListView<TSharedPtr<FAssetViewItem>>::OnKeyDown(InGeometry, InKeyEvent);
|
|
}
|
|
}
|
|
|
|
void SAssetListView::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
|
|
{
|
|
// Regreshing an asset view is an intensive task. Do not do this while a user
|
|
// is dragging arround content for maximum responsiveness.
|
|
// Also prevents a re-entrancy crash caused by potentially complex thumbnail generators.
|
|
if (!FSlateApplication::Get().IsDragDropping())
|
|
{
|
|
SListView<TSharedPtr<FAssetViewItem>>::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);
|
|
}
|
|
}
|
|
|
|
bool SAssetListView::HasWidgetForAsset(const FName& AssetPathName)
|
|
{
|
|
for (const TSharedPtr<FAssetViewItem>& Item : WidgetGenerator.ItemsWithGeneratedWidgets)
|
|
{
|
|
if (Item.IsValid() && Item->GetType() == EAssetItemType::Normal)
|
|
{
|
|
const FName& ObjectPath = StaticCastSharedPtr<FAssetViewAsset>(Item)->Data.ObjectPath;
|
|
if (ObjectPath == AssetPathName)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
FReply SAssetColumnView::OnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
|
|
{
|
|
FReply Reply = FAssetViewModeUtils::OnViewModeKeyDown(SelectedItems, InKeyEvent);
|
|
|
|
if ( Reply.IsEventHandled() )
|
|
{
|
|
return Reply;
|
|
}
|
|
else
|
|
{
|
|
return SListView<TSharedPtr<FAssetViewItem>>::OnKeyDown(InGeometry, InKeyEvent);
|
|
}
|
|
}
|
|
|
|
|
|
void SAssetColumnView::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
|
|
{
|
|
// Regreshing an asset view is an intensive task. Do not do this while a user
|
|
// is dragging arround content for maximum responsiveness.
|
|
// Also prevents a re-entrancy crash caused by potentially complex thumbnail generators.
|
|
if (!FSlateApplication::Get().IsDragDropping())
|
|
{
|
|
return SListView<TSharedPtr<FAssetViewItem>>::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////
|
|
// SAssetViewItem
|
|
///////////////////////////////
|
|
|
|
SAssetViewItem::~SAssetViewItem()
|
|
{
|
|
if (AssetItem.IsValid())
|
|
{
|
|
AssetItem->OnAssetDataChanged.RemoveAll(this);
|
|
}
|
|
|
|
OnItemDestroyed.ExecuteIfBound(AssetItem);
|
|
|
|
if (!GExitPurge)
|
|
{
|
|
// This hack is here to make abnormal shutdowns less frequent. Crashes here are the result UI's being shut down as a result of GC at edtior shutdown. This code attemps to call FindObject which is not allowed during GC.
|
|
SetForceMipLevelsToBeResident(false);
|
|
}
|
|
}
|
|
|
|
void SAssetViewItem::Construct( const FArguments& InArgs )
|
|
{
|
|
AssetItem = InArgs._AssetItem;
|
|
OnRenameBegin = InArgs._OnRenameBegin;
|
|
OnRenameCommit = InArgs._OnRenameCommit;
|
|
OnVerifyRenameCommit = InArgs._OnVerifyRenameCommit;
|
|
OnItemDestroyed = InArgs._OnItemDestroyed;
|
|
ShouldAllowToolTip = InArgs._ShouldAllowToolTip;
|
|
ThumbnailEditMode = InArgs._ThumbnailEditMode;
|
|
HighlightText = InArgs._HighlightText;
|
|
OnAssetsOrPathsDragDropped = InArgs._OnAssetsOrPathsDragDropped;
|
|
OnFilesDragDropped = InArgs._OnFilesDragDropped;
|
|
OnIsAssetValidForCustomToolTip = InArgs._OnIsAssetValidForCustomToolTip;
|
|
OnGetCustomAssetToolTip = InArgs._OnGetCustomAssetToolTip;
|
|
OnVisualizeAssetToolTip = InArgs._OnVisualizeAssetToolTip;
|
|
OnAssetToolTipClosing = InArgs._OnAssetToolTipClosing;
|
|
|
|
bDraggedOver = false;
|
|
|
|
bPackageDirty = false;
|
|
OnAssetDataChanged();
|
|
|
|
AssetItem->OnAssetDataChanged.AddSP(this, &SAssetViewItem::OnAssetDataChanged);
|
|
|
|
AssetDirtyBrush = FEditorStyle::GetBrush("ContentBrowser.ContentDirty");
|
|
SCCStateBrush = nullptr;
|
|
|
|
// Set our tooltip - this will refresh each time it's opened to make sure it's up-to-date
|
|
SetToolTip(SNew(SAssetViewItemToolTip).AssetViewItem(SharedThis(this)));
|
|
|
|
SourceControlStateDelay = 0.0f;
|
|
bSourceControlStateRequested = false;
|
|
|
|
ISourceControlModule::Get().RegisterProviderChanged(FSourceControlProviderChanged::FDelegate::CreateSP(this, &SAssetViewItem::HandleSourceControlProviderChanged));
|
|
SourceControlStateChangedDelegateHandle = ISourceControlModule::Get().GetProvider().RegisterSourceControlStateChanged_Handle(FSourceControlStateChanged::FDelegate::CreateSP(this, &SAssetViewItem::HandleSourceControlStateChanged));
|
|
|
|
// Source control state may have already been cached, make sure the control is in sync with
|
|
// cached state as the delegate is not going to be invoked again until source control state
|
|
// changes. This will be necessary any time the widget is destroyed and recreated after source
|
|
// control state has been cached; for instance when the widget is killed via FWidgetGenerator::OnEndGenerationPass
|
|
// or a view is refreshed due to user filtering/navigating):
|
|
HandleSourceControlStateChanged();
|
|
}
|
|
|
|
void SAssetViewItem::Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime )
|
|
{
|
|
const float PrevSizeX = LastGeometry.Size.X;
|
|
|
|
LastGeometry = AllottedGeometry;
|
|
|
|
// Set cached wrap text width based on new "LastGeometry" value.
|
|
// We set this only when changed because binding a delegate to text wrapping attributes is expensive
|
|
if( PrevSizeX != AllottedGeometry.Size.X && InlineRenameWidget.IsValid() )
|
|
{
|
|
InlineRenameWidget->SetWrapTextAt( GetNameTextWrapWidth() );
|
|
}
|
|
|
|
UpdatePackageDirtyState();
|
|
|
|
UpdateSourceControlState((float)InDeltaTime);
|
|
}
|
|
|
|
TSharedPtr<IToolTip> SAssetViewItem::GetToolTip()
|
|
{
|
|
return ShouldAllowToolTip.Get() ? SCompoundWidget::GetToolTip() : NULL;
|
|
}
|
|
|
|
bool SAssetViewItem::ValidateDragDrop( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent, bool& OutIsKnownDragOperation ) const
|
|
{
|
|
OutIsKnownDragOperation = false;
|
|
return IsFolder() && DragDropHandler::ValidateDragDropOnAssetFolder(MyGeometry, DragDropEvent, StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderPath, OutIsKnownDragOperation);
|
|
}
|
|
|
|
void SAssetViewItem::OnDragEnter( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent )
|
|
{
|
|
ValidateDragDrop(MyGeometry, DragDropEvent, bDraggedOver); // updates bDraggedOver
|
|
}
|
|
|
|
void SAssetViewItem::OnDragLeave( const FDragDropEvent& DragDropEvent )
|
|
{
|
|
if(IsFolder())
|
|
{
|
|
TSharedPtr<FDragDropOperation> Operation = DragDropEvent.GetOperation();
|
|
if (Operation.IsValid())
|
|
{
|
|
Operation->SetCursorOverride(TOptional<EMouseCursor::Type>());
|
|
|
|
if (Operation->IsOfType<FAssetDragDropOp>())
|
|
{
|
|
TSharedPtr<FAssetDragDropOp> DragDropOp = StaticCastSharedPtr<FAssetDragDropOp>(Operation);
|
|
DragDropOp->ResetToDefaultToolTip();
|
|
}
|
|
}
|
|
}
|
|
|
|
bDraggedOver = false;
|
|
}
|
|
|
|
FReply SAssetViewItem::OnDragOver( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent )
|
|
{
|
|
ValidateDragDrop(MyGeometry, DragDropEvent, bDraggedOver); // updates bDraggedOver
|
|
return (bDraggedOver) ? FReply::Handled() : FReply::Unhandled();
|
|
}
|
|
|
|
FReply SAssetViewItem::OnDrop( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent )
|
|
{
|
|
if (ValidateDragDrop(MyGeometry, DragDropEvent, bDraggedOver)) // updates bDraggedOver
|
|
{
|
|
bDraggedOver = false;
|
|
|
|
check(AssetItem->GetType() == EAssetItemType::Folder);
|
|
|
|
TSharedPtr<FDragDropOperation> Operation = DragDropEvent.GetOperation();
|
|
if (!Operation.IsValid())
|
|
{
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
if (Operation->IsOfType<FExternalDragOperation>())
|
|
{
|
|
TSharedPtr<FExternalDragOperation> DragDropOp = StaticCastSharedPtr<FExternalDragOperation>(Operation);
|
|
OnFilesDragDropped.ExecuteIfBound(DragDropOp->GetFiles(), StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderPath);
|
|
return FReply::Handled();
|
|
}
|
|
|
|
if (Operation->IsOfType<FAssetDragDropOp>())
|
|
{
|
|
TSharedPtr<FAssetDragDropOp> DragDropOp = StaticCastSharedPtr<FAssetDragDropOp>(Operation);
|
|
OnAssetsOrPathsDragDropped.ExecuteIfBound(DragDropOp->GetAssets(), DragDropOp->GetAssetPaths(), StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderPath);
|
|
return FReply::Handled();
|
|
}
|
|
}
|
|
|
|
if (bDraggedOver)
|
|
{
|
|
// We were able to handle this operation, but could not due to another error - still report this drop as handled so it doesn't fall through to other widgets
|
|
bDraggedOver = false;
|
|
return FReply::Handled();
|
|
}
|
|
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
bool SAssetViewItem::IsNameReadOnly() const
|
|
{
|
|
if (ThumbnailEditMode.Get())
|
|
{
|
|
// Read-only while editing thumbnails
|
|
return true;
|
|
}
|
|
|
|
if (!AssetItem.IsValid())
|
|
{
|
|
// Read-only if no valid asset item
|
|
return true;
|
|
}
|
|
|
|
if (AssetItem->GetType() != EAssetItemType::Folder)
|
|
{
|
|
// Read-only if we can't be renamed
|
|
return !ContentBrowserUtils::CanRenameAsset(StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data);
|
|
}
|
|
else
|
|
{
|
|
// Read-only if we can't be renamed
|
|
return !ContentBrowserUtils::CanRenameFolder(StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderPath);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void SAssetViewItem::HandleBeginNameChange( const FText& OriginalText )
|
|
{
|
|
OnRenameBegin.ExecuteIfBound(AssetItem, OriginalText.ToString(), LastGeometry.GetLayoutBoundingRect());
|
|
}
|
|
|
|
void SAssetViewItem::HandleNameCommitted( const FText& NewText, ETextCommit::Type CommitInfo )
|
|
{
|
|
OnRenameCommit.ExecuteIfBound(AssetItem, NewText.ToString(), LastGeometry.GetLayoutBoundingRect(), CommitInfo);
|
|
}
|
|
|
|
bool SAssetViewItem::HandleVerifyNameChanged( const FText& NewText, FText& OutErrorMessage )
|
|
{
|
|
return !OnVerifyRenameCommit.IsBound() || OnVerifyRenameCommit.Execute(AssetItem, NewText, LastGeometry.GetLayoutBoundingRect(), OutErrorMessage);
|
|
}
|
|
|
|
void SAssetViewItem::OnAssetDataChanged()
|
|
{
|
|
CachePackageName();
|
|
AssetPackage = FindObjectSafe<UPackage>(NULL, *CachedPackageName);
|
|
UpdatePackageDirtyState();
|
|
|
|
AssetTypeActions.Reset();
|
|
if ( AssetItem->GetType() != EAssetItemType::Folder )
|
|
{
|
|
UClass* AssetClass = FindObject<UClass>(ANY_PACKAGE, *StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data.AssetClass.ToString());
|
|
if (AssetClass)
|
|
{
|
|
FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));
|
|
AssetTypeActions = AssetToolsModule.Get().GetAssetTypeActionsForClass(AssetClass).Pin();
|
|
}
|
|
}
|
|
|
|
if ( InlineRenameWidget.IsValid() )
|
|
{
|
|
InlineRenameWidget->SetText( GetNameText() );
|
|
}
|
|
|
|
CacheDisplayTags();
|
|
}
|
|
|
|
void SAssetViewItem::DirtyStateChanged()
|
|
{
|
|
}
|
|
|
|
FText SAssetViewItem::GetAssetClassText() const
|
|
{
|
|
if (!AssetItem.IsValid())
|
|
{
|
|
return FText();
|
|
}
|
|
|
|
if (AssetItem->GetType() == EAssetItemType::Folder)
|
|
{
|
|
return LOCTEXT("FolderName", "Folder");
|
|
}
|
|
|
|
if (AssetTypeActions.IsValid())
|
|
{
|
|
FText Name = AssetTypeActions.Pin()->GetName();
|
|
|
|
if (!Name.IsEmpty())
|
|
{
|
|
return Name;
|
|
}
|
|
}
|
|
|
|
return FText::FromName(StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data.AssetClass);
|
|
}
|
|
|
|
const FSlateBrush* SAssetViewItem::GetSCCStateImage() const
|
|
{
|
|
return ThumbnailEditMode.Get() ? FEditorStyle::GetNoBrush() : SCCStateBrush;
|
|
}
|
|
|
|
void SAssetViewItem::HandleSourceControlProviderChanged(ISourceControlProvider& OldProvider, ISourceControlProvider& NewProvider)
|
|
{
|
|
OldProvider.UnregisterSourceControlStateChanged_Handle(SourceControlStateChangedDelegateHandle);
|
|
SourceControlStateChangedDelegateHandle = NewProvider.RegisterSourceControlStateChanged_Handle(FSourceControlStateChanged::FDelegate::CreateSP(this, &SAssetViewItem::HandleSourceControlStateChanged));
|
|
|
|
// Reset this so the state will be queried from the new provider on the next Tick
|
|
SourceControlStateDelay = 0.0f;
|
|
bSourceControlStateRequested = false;
|
|
SCCStateBrush = nullptr;
|
|
|
|
HandleSourceControlStateChanged();
|
|
}
|
|
|
|
void SAssetViewItem::HandleSourceControlStateChanged()
|
|
{
|
|
if ( ISourceControlModule::Get().IsEnabled() && AssetItem.IsValid() && (AssetItem->GetType() == EAssetItemType::Normal) && !AssetItem->IsTemporaryItem() && !FPackageName::IsScriptPackage(CachedPackageName) )
|
|
{
|
|
FSourceControlStatePtr SourceControlState = ISourceControlModule::Get().GetProvider().GetState(CachedPackageFileName, EStateCacheUsage::Use);
|
|
if(SourceControlState.IsValid())
|
|
{
|
|
SCCStateBrush = FEditorStyle::GetBrush(SourceControlState->GetIconName());
|
|
}
|
|
}
|
|
}
|
|
|
|
const FSlateBrush* SAssetViewItem::GetDirtyImage() const
|
|
{
|
|
return IsDirty() ? AssetDirtyBrush : NULL;
|
|
}
|
|
|
|
TSharedRef<SWidget> SAssetViewItem::GenerateExtraStateIconWidget(TAttribute<float> InMaxExtraStateIconWidth) const
|
|
{
|
|
TArray<FOnGenerateAssetViewExtraStateIndicators>& ExtraStateIconGenerators = FModuleManager::GetModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser")).GetAllAssetViewExtraStateIconGenerators();
|
|
if (AssetItem->GetType() != EAssetItemType::Folder && ExtraStateIconGenerators.Num() > 0)
|
|
{
|
|
FAssetData& AssetData = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data;
|
|
TSharedPtr<SHorizontalBox> Content = SNew(SHorizontalBox);
|
|
for (const auto& Generator : ExtraStateIconGenerators)
|
|
{
|
|
if (Generator.IsBound())
|
|
{
|
|
Content->AddSlot()
|
|
.HAlign(HAlign_Left)
|
|
.MaxWidth(InMaxExtraStateIconWidth)
|
|
[
|
|
Generator.Execute(AssetData)
|
|
];
|
|
}
|
|
}
|
|
return Content.ToSharedRef();
|
|
}
|
|
return SNullWidget::NullWidget;
|
|
}
|
|
|
|
TSharedRef<SWidget> SAssetViewItem::GenerateExtraStateTooltipWidget() const
|
|
{
|
|
TArray<FOnGenerateAssetViewExtraStateIndicators>& ExtraStateTooltipGenerators = FModuleManager::GetModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser")).GetAllAssetViewExtraStateTooltipGenerators();
|
|
if (AssetItem->GetType() != EAssetItemType::Folder && ExtraStateTooltipGenerators.Num() > 0)
|
|
{
|
|
FAssetData& AssetData = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data;
|
|
TSharedPtr<SVerticalBox> Content = SNew(SVerticalBox);
|
|
for (const auto& Generator : ExtraStateTooltipGenerators)
|
|
{
|
|
if (Generator.IsBound())
|
|
{
|
|
Content->AddSlot()
|
|
[
|
|
Generator.Execute(AssetData)
|
|
];
|
|
}
|
|
}
|
|
return Content.ToSharedRef();
|
|
}
|
|
return SNullWidget::NullWidget;
|
|
}
|
|
|
|
EVisibility SAssetViewItem::GetThumbnailEditModeUIVisibility() const
|
|
{
|
|
return !IsFolder() && ThumbnailEditMode.Get() ? EVisibility::Visible : EVisibility::Collapsed;
|
|
}
|
|
|
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
TSharedRef<SWidget> SAssetViewItem::CreateToolTipWidget() const
|
|
{
|
|
if ( AssetItem.IsValid() )
|
|
{
|
|
bool bTryCustomAssetToolTip = true;
|
|
if (OnIsAssetValidForCustomToolTip.IsBound() && AssetItem->GetType() != EAssetItemType::Folder)
|
|
{
|
|
FAssetData& AssetData = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data;
|
|
bTryCustomAssetToolTip = OnIsAssetValidForCustomToolTip.Execute(AssetData);
|
|
}
|
|
|
|
if(bTryCustomAssetToolTip && OnGetCustomAssetToolTip.IsBound() && AssetItem->GetType() != EAssetItemType::Folder)
|
|
{
|
|
FAssetData& AssetData = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data;
|
|
return OnGetCustomAssetToolTip.Execute(AssetData);
|
|
}
|
|
else if(AssetItem->GetType() != EAssetItemType::Folder)
|
|
{
|
|
const FAssetData& AssetData = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data;
|
|
|
|
// The tooltip contains the name, class, path, and asset registry tags
|
|
const FText NameText = FText::FromName( AssetData.AssetName );
|
|
const FText ClassText = FText::Format( LOCTEXT("ClassName", "({0})"), GetAssetClassText() );
|
|
|
|
// Create a box to hold every line of info in the body of the tooltip
|
|
TSharedRef<SVerticalBox> InfoBox = SNew(SVerticalBox);
|
|
|
|
// Add Path
|
|
AddToToolTipInfoBox( InfoBox, LOCTEXT("TileViewTooltipPath", "Path"), FText::FromName(AssetData.PackagePath), false);
|
|
|
|
if(AssetData.PackageName != NAME_None)
|
|
{
|
|
int32 PackageNameLengthForCooking = ContentBrowserUtils::GetPackageLengthForCooking(AssetData.PackageName.ToString(), FEngineBuildSettings::IsInternalBuild());
|
|
|
|
int32 MaxCookPathLen = ContentBrowserUtils::GetMaxCookPathLen();
|
|
AddToToolTipInfoBox(InfoBox, LOCTEXT("TileViewTooltipPathLengthForCookingKey", "Cooking Filepath Length"), FText::Format(LOCTEXT("TileViewTooltipPathLengthForCookingValue", "{0} / {1}"),
|
|
FText::AsNumber(PackageNameLengthForCooking), FText::AsNumber(MaxCookPathLen)), PackageNameLengthForCooking > MaxCookPathLen ? true : false);
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogContentBrowser, Error, TEXT("AssetData for '%s' is invalid"), *AssetData.PackagePath.ToString());
|
|
}
|
|
|
|
// Add Collections
|
|
{
|
|
FCollectionManagerModule& CollectionManagerModule = FCollectionManagerModule::GetModule();
|
|
const FString CollectionNames = CollectionManagerModule.Get().GetCollectionsStringForObject(AssetData.ObjectPath, ECollectionShareType::CST_All, ECollectionRecursionFlags::Self, GetDefault<UContentBrowserSettings>()->bShowFullCollectionNameInToolTip);
|
|
if (!CollectionNames.IsEmpty())
|
|
{
|
|
AddToToolTipInfoBox(InfoBox, LOCTEXT("AssetToolTipKey_Collections", "Collections"), FText::FromString(CollectionNames), false);
|
|
}
|
|
}
|
|
|
|
// Add tags
|
|
for (const auto& DisplayTagItem : CachedDisplayTags)
|
|
{
|
|
AddToToolTipInfoBox(InfoBox, DisplayTagItem.DisplayKey, DisplayTagItem.DisplayValue, DisplayTagItem.bImportant);
|
|
}
|
|
|
|
// Add asset source files
|
|
TOptional<FAssetImportInfo> ImportInfo = FAssetSourceFilenameCache::ExtractAssetImportInfo(AssetData);
|
|
if (ImportInfo.IsSet())
|
|
{
|
|
for (const auto& File : ImportInfo->SourceFiles)
|
|
{
|
|
FText SourceLabel = LOCTEXT("TileViewTooltipSourceFile", "Source File");
|
|
if (File.DisplayLabelName.Len() > 0)
|
|
{
|
|
SourceLabel = FText::FromString(FText(LOCTEXT("TileViewTooltipSourceFile", "Source File")).ToString() + TEXT(" (") + File.DisplayLabelName + TEXT(")"));
|
|
}
|
|
AddToToolTipInfoBox( InfoBox, SourceLabel, FText::FromString(File.RelativeFilename), false );
|
|
}
|
|
}
|
|
|
|
TSharedRef<SVerticalBox> OverallTooltipVBox = SNew(SVerticalBox);
|
|
|
|
// Top section (asset name, type, is checked out)
|
|
OverallTooltipVBox->AddSlot()
|
|
.AutoHeight()
|
|
.Padding(0, 0, 0, 4)
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(6)
|
|
.BorderImage(FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.ContentBorder"))
|
|
[
|
|
SNew(SVerticalBox)
|
|
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(0, 0, 4, 0)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(NameText)
|
|
.Font(FEditorStyle::GetFontStyle("ContentBrowser.TileViewTooltip.NameFont"))
|
|
]
|
|
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(STextBlock).Text(ClassText)
|
|
.HighlightText(HighlightText)
|
|
]
|
|
]
|
|
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(STextBlock)
|
|
.Visibility(this, &SAssetViewItem::GetCheckedOutByOtherTextVisibility)
|
|
.Text(this, &SAssetViewItem::GetCheckedOutByOtherText)
|
|
.ColorAndOpacity(FLinearColor(0.1f, 0.5f, 1.f, 1.f))
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
[
|
|
GenerateExtraStateTooltipWidget()
|
|
]
|
|
]
|
|
];
|
|
|
|
// Middle section (user description, if present)
|
|
FText UserDescription = GetAssetUserDescription();
|
|
if (!UserDescription.IsEmpty())
|
|
{
|
|
OverallTooltipVBox->AddSlot()
|
|
.AutoHeight()
|
|
.Padding(0, 0, 0, 4)
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(6)
|
|
.BorderImage(FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.ContentBorder"))
|
|
[
|
|
SNew(STextBlock)
|
|
.WrapTextAt(300.0f)
|
|
.Font(FEditorStyle::GetFontStyle("ContentBrowser.TileViewTooltip.AssetUserDescriptionFont"))
|
|
.Text(UserDescription)
|
|
]
|
|
];
|
|
}
|
|
|
|
// Bottom section (asset registry tags)
|
|
OverallTooltipVBox->AddSlot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(6)
|
|
.BorderImage(FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.ContentBorder"))
|
|
[
|
|
InfoBox
|
|
]
|
|
];
|
|
|
|
|
|
return SNew(SBorder)
|
|
.Padding(6)
|
|
.BorderImage( FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.NonContentBorder") )
|
|
[
|
|
OverallTooltipVBox
|
|
];
|
|
}
|
|
else
|
|
{
|
|
const FText& FolderName = StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderName;
|
|
const FString& FolderPath = StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderPath;
|
|
|
|
// Create a box to hold every line of info in the body of the tooltip
|
|
TSharedRef<SVerticalBox> InfoBox = SNew(SVerticalBox);
|
|
|
|
AddToToolTipInfoBox( InfoBox, LOCTEXT("TileViewTooltipPath", "Path"), FText::FromString(FolderPath), false );
|
|
|
|
return SNew(SBorder)
|
|
.Padding(6)
|
|
.BorderImage( FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.NonContentBorder") )
|
|
[
|
|
SNew(SVerticalBox)
|
|
|
|
+SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 0, 0, 4)
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(6)
|
|
.BorderImage( FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.ContentBorder") )
|
|
[
|
|
SNew(SVerticalBox)
|
|
|
|
+SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(0, 0, 4, 0)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text( FolderName )
|
|
.Font( FEditorStyle::GetFontStyle("ContentBrowser.TileViewTooltip.NameFont") )
|
|
]
|
|
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text( LOCTEXT("FolderNameBracketed", "(Folder)") )
|
|
]
|
|
]
|
|
]
|
|
]
|
|
|
|
+SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(6)
|
|
.BorderImage( FEditorStyle::GetBrush("ContentBrowser.TileViewTooltip.ContentBorder") )
|
|
[
|
|
InfoBox
|
|
]
|
|
]
|
|
];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Return an empty tooltip since the asset item wasn't valid
|
|
return SNullWidget::NullWidget;
|
|
}
|
|
}
|
|
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
|
|
EVisibility SAssetViewItem::GetCheckedOutByOtherTextVisibility() const
|
|
{
|
|
return GetCheckedOutByOtherText().IsEmpty() ? EVisibility::Collapsed : EVisibility::Visible;
|
|
}
|
|
|
|
FText SAssetViewItem::GetCheckedOutByOtherText() const
|
|
{
|
|
if ( AssetItem.IsValid() && AssetItem->GetType() != EAssetItemType::Folder && !GIsSavingPackage && !IsGarbageCollecting() )
|
|
{
|
|
const FAssetData& AssetData = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data;
|
|
ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
|
|
FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(SourceControlHelpers::PackageFilename(AssetData.PackageName.ToString()), EStateCacheUsage::Use);
|
|
FString UserWhichHasPackageCheckedOut;
|
|
if (SourceControlState.IsValid() && ( SourceControlState->IsCheckedOutOther(&UserWhichHasPackageCheckedOut) || SourceControlState->IsCheckedOutOrModifiedInOtherBranch()))
|
|
{
|
|
return SourceControlState->GetDisplayTooltip();
|
|
}
|
|
}
|
|
|
|
return FText::GetEmpty();
|
|
}
|
|
|
|
|
|
FText SAssetViewItem::GetAssetUserDescription() const
|
|
{
|
|
if (AssetItem.IsValid() && AssetTypeActions.IsValid())
|
|
{
|
|
if (AssetItem->GetType() != EAssetItemType::Folder)
|
|
{
|
|
const FAssetData& AssetData = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data;
|
|
return AssetTypeActions.Pin()->GetAssetDescription(AssetData);
|
|
}
|
|
}
|
|
|
|
return FText::GetEmpty();
|
|
}
|
|
|
|
|
|
void SAssetViewItem::AddToToolTipInfoBox(const TSharedRef<SVerticalBox>& InfoBox, const FText& Key, const FText& Value, bool bImportant) const
|
|
{
|
|
FWidgetStyle ImportantStyle;
|
|
ImportantStyle.SetForegroundColor(FLinearColor(1, 0.5, 0, 1));
|
|
|
|
InfoBox->AddSlot()
|
|
.AutoHeight()
|
|
.Padding(0, 1)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(0, 0, 4, 0)
|
|
[
|
|
SNew(STextBlock) .Text( FText::Format(LOCTEXT("AssetViewTooltipFormat", "{0}:"), Key ) )
|
|
.ColorAndOpacity(bImportant ? ImportantStyle.GetSubduedForegroundColor() : FSlateColor::UseSubduedForeground())
|
|
]
|
|
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock) .Text( Value )
|
|
.ColorAndOpacity(bImportant ? ImportantStyle.GetForegroundColor() : FSlateColor::UseForeground())
|
|
.HighlightText((Key.ToString() == TEXT("Path")) ? HighlightText : FText())
|
|
.WrapTextAt(700.0f)
|
|
]
|
|
];
|
|
}
|
|
|
|
void SAssetViewItem::UpdatePackageDirtyState()
|
|
{
|
|
bool bNewIsDirty = false;
|
|
|
|
// Only update the dirty state for non-temporary asset items that aren't a built in script
|
|
if ( AssetItem.IsValid() && !AssetItem->IsTemporaryItem() && AssetItem->GetType() != EAssetItemType::Folder && !FPackageName::IsScriptPackage(CachedPackageName) )
|
|
{
|
|
if ( AssetPackage.IsValid() )
|
|
{
|
|
bNewIsDirty = AssetPackage->IsDirty();
|
|
}
|
|
}
|
|
|
|
if ( bNewIsDirty != bPackageDirty )
|
|
{
|
|
bPackageDirty = bNewIsDirty;
|
|
DirtyStateChanged();
|
|
}
|
|
}
|
|
|
|
bool SAssetViewItem::IsDirty() const
|
|
{
|
|
return bPackageDirty;
|
|
}
|
|
|
|
void SAssetViewItem::UpdateSourceControlState(float InDeltaTime)
|
|
{
|
|
SourceControlStateDelay += InDeltaTime;
|
|
|
|
static ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
|
|
if ( !bSourceControlStateRequested && SourceControlStateDelay > 1.0f && SourceControlModule.IsEnabled() && AssetItem.IsValid() )
|
|
{
|
|
// Only update the SCC state for non-temporary asset items that aren't a built in script
|
|
if ( !AssetItem->IsTemporaryItem() && AssetItem->GetType() != EAssetItemType::Folder && !FPackageName::IsScriptPackage(CachedPackageName) && !FPackageName::IsMemoryPackage(CachedPackageName) && !FPackageName::IsTempPackage(CachedPackageName))
|
|
{
|
|
// Request the most recent SCC state for this asset
|
|
SourceControlModule.QueueStatusUpdate(CachedPackageFileName);
|
|
}
|
|
|
|
bSourceControlStateRequested = true;
|
|
}
|
|
}
|
|
|
|
void SAssetViewItem::CachePackageName()
|
|
{
|
|
if(AssetItem.IsValid())
|
|
{
|
|
if(AssetItem->GetType() != EAssetItemType::Folder)
|
|
{
|
|
CachedPackageName = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data.PackageName.ToString();
|
|
CachedPackageFileName = SourceControlHelpers::PackageFilename(CachedPackageName);
|
|
}
|
|
else
|
|
{
|
|
CachedPackageName = StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderName.ToString();
|
|
}
|
|
}
|
|
}
|
|
|
|
void SAssetViewItem::CacheDisplayTags()
|
|
{
|
|
CachedDisplayTags.Reset();
|
|
|
|
if (AssetItem->GetType() == EAssetItemType::Folder)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const FAssetData& AssetData = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data;
|
|
|
|
// Find the asset CDO so we can get the meta-data for the tags
|
|
UClass* AssetClass = FindObject<UClass>(ANY_PACKAGE, *AssetData.AssetClass.ToString());
|
|
const UObject* AssetCDO = AssetClass ? GetDefault<UObject>(AssetClass) : nullptr;
|
|
|
|
// If no asset CDO is available then we cannot determine the meta-data for the tags, so just bail
|
|
if (!AssetCDO)
|
|
{
|
|
return;
|
|
}
|
|
|
|
struct FTagDisplayMetaData
|
|
{
|
|
FTagDisplayMetaData()
|
|
: MetaData()
|
|
, Type(UObject::FAssetRegistryTag::TT_Hidden)
|
|
, DisplayFlags(UObject::FAssetRegistryTag::TD_None)
|
|
{
|
|
}
|
|
|
|
UObject::FAssetRegistryTagMetadata MetaData;
|
|
UObject::FAssetRegistryTag::ETagType Type;
|
|
uint32 DisplayFlags;
|
|
};
|
|
|
|
// Build up the meta-data needed to correctly process the tags for display
|
|
TMap<FName, FTagDisplayMetaData> TagMetaDataMap;
|
|
{
|
|
// Add the internal meta-data
|
|
{
|
|
TMap<FName, UObject::FAssetRegistryTagMetadata> TmpMetaData;
|
|
AssetCDO->GetAssetRegistryTagMetadata(TmpMetaData);
|
|
|
|
for (const auto& TmpMetaDataPair : TmpMetaData)
|
|
{
|
|
FTagDisplayMetaData& TagMetaData = TagMetaDataMap.FindOrAdd(TmpMetaDataPair.Key);
|
|
TagMetaData.MetaData = TmpMetaDataPair.Value;
|
|
}
|
|
}
|
|
|
|
// Add the type and display flags
|
|
{
|
|
TArray<UObject::FAssetRegistryTag> TmpTags;
|
|
AssetCDO->GetAssetRegistryTags(TmpTags);
|
|
|
|
for (const UObject::FAssetRegistryTag& TmpTag : TmpTags)
|
|
{
|
|
FTagDisplayMetaData& TagMetaData = TagMetaDataMap.FindOrAdd(TmpTag.Name);
|
|
TagMetaData.Type = TmpTag.Type;
|
|
TagMetaData.DisplayFlags = TmpTag.DisplayFlags;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add all asset registry tags and values
|
|
for (const auto& TagAndValuePair : AssetData.TagsAndValues)
|
|
{
|
|
const FTagDisplayMetaData TagMetaData = TagMetaDataMap.FindRef(TagAndValuePair.Key);
|
|
|
|
// Skip tags that are set to be hidden
|
|
if (TagMetaData.Type == UObject::FAssetRegistryTag::TT_Hidden)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
UProperty* TagField = FindField<UProperty>(AssetClass, TagAndValuePair.Key);
|
|
|
|
// Build the display name for this tag
|
|
FText DisplayName;
|
|
if (!TagMetaData.MetaData.DisplayName.IsEmpty())
|
|
{
|
|
DisplayName = TagMetaData.MetaData.DisplayName;
|
|
}
|
|
else if (TagField)
|
|
{
|
|
DisplayName = TagField->GetDisplayNameText();
|
|
}
|
|
else
|
|
{
|
|
// We have no type information by this point, so no idea if it's a bool :(
|
|
const bool bIsBool = false;
|
|
DisplayName = FText::FromString(FName::NameToDisplayString(TagAndValuePair.Key.ToString(), bIsBool));
|
|
}
|
|
|
|
// Build the display value for this tag
|
|
FText DisplayValue;
|
|
{
|
|
auto ReformatNumberStringForDisplay = [](const FString& InNumberString) -> FText
|
|
{
|
|
// Respect the number of decimal places in the source string when converting for display
|
|
int32 NumDecimalPlaces = 0;
|
|
{
|
|
int32 DotIndex = INDEX_NONE;
|
|
if (InNumberString.FindChar(TEXT('.'), DotIndex))
|
|
{
|
|
NumDecimalPlaces = InNumberString.Len() - DotIndex - 1;
|
|
}
|
|
}
|
|
|
|
if (NumDecimalPlaces > 0)
|
|
{
|
|
// Convert the number as a double
|
|
double Num = 0.0;
|
|
LexFromString(Num, *InNumberString);
|
|
|
|
const FNumberFormattingOptions NumFormatOpts = FNumberFormattingOptions()
|
|
.SetMinimumFractionalDigits(NumDecimalPlaces)
|
|
.SetMaximumFractionalDigits(NumDecimalPlaces);
|
|
|
|
return FText::AsNumber(Num, &NumFormatOpts);
|
|
}
|
|
else
|
|
{
|
|
const bool bIsSigned = InNumberString.Len() > 0 && (InNumberString[0] == TEXT('-') || InNumberString[0] == TEXT('+'));
|
|
|
|
if (bIsSigned)
|
|
{
|
|
// Convert the number as a signed int
|
|
int64 Num = 0;
|
|
LexFromString(Num, *InNumberString);
|
|
|
|
return FText::AsNumber(Num);
|
|
}
|
|
else
|
|
{
|
|
// Convert the number as an unsigned int
|
|
uint64 Num = 0;
|
|
LexFromString(Num, *InNumberString);
|
|
|
|
return FText::AsNumber(Num);
|
|
}
|
|
}
|
|
|
|
return FText::GetEmpty();
|
|
};
|
|
|
|
bool bHasSetDisplayValue = false;
|
|
|
|
// Numerical tags need to format the specified number based on the display flags
|
|
if (!bHasSetDisplayValue && TagMetaData.Type == UObject::FAssetRegistryTag::TT_Numerical && TagAndValuePair.Value.IsNumeric())
|
|
{
|
|
bHasSetDisplayValue = true;
|
|
|
|
const bool bAsMemory = !!(TagMetaData.DisplayFlags & UObject::FAssetRegistryTag::TD_Memory);
|
|
|
|
if (bAsMemory)
|
|
{
|
|
// Memory should be a 64-bit unsigned number of bytes
|
|
uint64 NumBytes = 0;
|
|
LexFromString(NumBytes, *TagAndValuePair.Value);
|
|
|
|
DisplayValue = FText::AsMemory(NumBytes);
|
|
}
|
|
else
|
|
{
|
|
DisplayValue = ReformatNumberStringForDisplay(TagAndValuePair.Value);
|
|
}
|
|
}
|
|
|
|
// Dimensional tags need to be split into their component numbers, with each component number re-format
|
|
if (!bHasSetDisplayValue && TagMetaData.Type == UObject::FAssetRegistryTag::TT_Dimensional)
|
|
{
|
|
TArray<FString> NumberStrTokens;
|
|
TagAndValuePair.Value.ParseIntoArray(NumberStrTokens, TEXT("x"), true);
|
|
|
|
if (NumberStrTokens.Num() > 0 && NumberStrTokens.Num() <= 3)
|
|
{
|
|
bHasSetDisplayValue = true;
|
|
|
|
switch (NumberStrTokens.Num())
|
|
{
|
|
case 1:
|
|
DisplayValue = ReformatNumberStringForDisplay(NumberStrTokens[0]);
|
|
break;
|
|
|
|
case 2:
|
|
DisplayValue = FText::Format(LOCTEXT("DisplayTag2xFmt", "{0} \u00D7 {1}"), ReformatNumberStringForDisplay(NumberStrTokens[0]), ReformatNumberStringForDisplay(NumberStrTokens[1]));
|
|
break;
|
|
|
|
case 3:
|
|
DisplayValue = FText::Format(LOCTEXT("DisplayTag3xFmt", "{0} \u00D7 {1} \u00D7 {2}"), ReformatNumberStringForDisplay(NumberStrTokens[0]), ReformatNumberStringForDisplay(NumberStrTokens[1]), ReformatNumberStringForDisplay(NumberStrTokens[2]));
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Chronological tags need to format the specified timestamp based on the display flags
|
|
if (!bHasSetDisplayValue && TagMetaData.Type == UObject::FAssetRegistryTag::TT_Chronological)
|
|
{
|
|
bHasSetDisplayValue = true;
|
|
|
|
FDateTime Timestamp;
|
|
if (FDateTime::Parse(TagAndValuePair.Value, Timestamp))
|
|
{
|
|
const bool bDisplayDate = !!(TagMetaData.DisplayFlags & UObject::FAssetRegistryTag::TD_Date);
|
|
const bool bDisplayTime = !!(TagMetaData.DisplayFlags & UObject::FAssetRegistryTag::TD_Time);
|
|
const FString TimeZone = (TagMetaData.DisplayFlags & UObject::FAssetRegistryTag::TD_InvariantTz) ? FText::GetInvariantTimeZone() : FString();
|
|
|
|
if (bDisplayDate && bDisplayTime)
|
|
{
|
|
DisplayValue = FText::AsDateTime(Timestamp, EDateTimeStyle::Short, EDateTimeStyle::Short, TimeZone);
|
|
}
|
|
else if (bDisplayDate)
|
|
{
|
|
DisplayValue = FText::AsDate(Timestamp, EDateTimeStyle::Short, TimeZone);
|
|
}
|
|
else if (bDisplayTime)
|
|
{
|
|
DisplayValue = FText::AsTime(Timestamp, EDateTimeStyle::Short, TimeZone);
|
|
}
|
|
}
|
|
}
|
|
|
|
// The tag value might be localized text, so we need to parse it for display
|
|
if (!bHasSetDisplayValue && FTextStringHelper::IsComplexText(*TagAndValuePair.Value))
|
|
{
|
|
bHasSetDisplayValue = FTextStringHelper::ReadFromBuffer(*TagAndValuePair.Value, DisplayValue) != nullptr;
|
|
}
|
|
|
|
// Do our best to build something valid from the string value
|
|
if (!bHasSetDisplayValue)
|
|
{
|
|
bHasSetDisplayValue = true;
|
|
|
|
// Since all we have at this point is a string, we can't be very smart here.
|
|
// We need to strip some noise off class paths in some cases, but can't load the asset to inspect its UPROPERTYs manually due to performance concerns.
|
|
FString ValueString = FPackageName::ExportTextPathToObjectPath(TagAndValuePair.Value);
|
|
|
|
const TCHAR StringToRemove[] = TEXT("/Script/");
|
|
if (ValueString.StartsWith(StringToRemove))
|
|
{
|
|
// Remove the class path for native classes, and also remove Engine. for engine classes
|
|
const int32 SizeOfPrefix = ARRAY_COUNT(StringToRemove) - 1;
|
|
ValueString = ValueString.Mid(SizeOfPrefix, ValueString.Len() - SizeOfPrefix).Replace(TEXT("Engine."), TEXT(""));
|
|
}
|
|
|
|
if (TagField)
|
|
{
|
|
UProperty* TagProp = nullptr;
|
|
UEnum* TagEnum = nullptr;
|
|
if (UByteProperty* ByteProp = Cast<UByteProperty>(TagField))
|
|
{
|
|
TagProp = ByteProp;
|
|
TagEnum = ByteProp->Enum;
|
|
}
|
|
else if (UEnumProperty* EnumProp = Cast<UEnumProperty>(TagField))
|
|
{
|
|
TagProp = EnumProp;
|
|
TagEnum = EnumProp->GetEnum();
|
|
}
|
|
|
|
// Strip off enum prefixes if they exist
|
|
if (TagProp)
|
|
{
|
|
if (TagEnum)
|
|
{
|
|
const FString EnumPrefix = TagEnum->GenerateEnumPrefix();
|
|
if (EnumPrefix.Len() && ValueString.StartsWith(EnumPrefix))
|
|
{
|
|
ValueString = ValueString.RightChop(EnumPrefix.Len() + 1); // +1 to skip over the underscore
|
|
}
|
|
}
|
|
|
|
ValueString = FName::NameToDisplayString(ValueString, false);
|
|
}
|
|
}
|
|
|
|
DisplayValue = FText::FromString(MoveTemp(ValueString));
|
|
}
|
|
|
|
// Add suffix to the value, if one is defined for this tag
|
|
if (!TagMetaData.MetaData.Suffix.IsEmpty())
|
|
{
|
|
DisplayValue = FText::Format(LOCTEXT("DisplayTagSuffixFmt", "{0} {1}"), DisplayValue, TagMetaData.MetaData.Suffix);
|
|
}
|
|
}
|
|
|
|
if (!DisplayValue.IsEmpty())
|
|
{
|
|
const bool bImportant = !TagMetaData.MetaData.ImportantValue.IsEmpty() && TagMetaData.MetaData.ImportantValue == TagAndValuePair.Value;
|
|
CachedDisplayTags.Add(FTagDisplayItem(TagAndValuePair.Key, DisplayName, DisplayValue, bImportant));
|
|
}
|
|
}
|
|
}
|
|
|
|
const FSlateBrush* SAssetViewItem::GetBorderImage() const
|
|
{
|
|
return bDraggedOver ? FEditorStyle::GetBrush("Menu.Background") : FEditorStyle::GetBrush("NoBorder");
|
|
}
|
|
|
|
bool SAssetViewItem::IsFolder() const
|
|
{
|
|
return AssetItem.IsValid() && AssetItem->GetType() == EAssetItemType::Folder;
|
|
}
|
|
|
|
FText SAssetViewItem::GetNameText() const
|
|
{
|
|
if(AssetItem.IsValid())
|
|
{
|
|
if(AssetItem->GetType() != EAssetItemType::Folder)
|
|
{
|
|
return FText::FromName(StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data.AssetName);
|
|
}
|
|
else
|
|
{
|
|
return StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderName;
|
|
}
|
|
}
|
|
|
|
return FText();
|
|
}
|
|
|
|
FSlateColor SAssetViewItem::GetAssetColor() const
|
|
{
|
|
if(AssetItem.IsValid())
|
|
{
|
|
if(AssetItem->GetType() == EAssetItemType::Folder)
|
|
{
|
|
TSharedPtr<FAssetViewFolder> AssetFolderItem = StaticCastSharedPtr<FAssetViewFolder>(AssetItem);
|
|
|
|
TSharedPtr<FLinearColor> Color;
|
|
if (AssetFolderItem->bCollectionFolder)
|
|
{
|
|
FName CollectionName;
|
|
ECollectionShareType::Type CollectionFolderShareType = ECollectionShareType::CST_All;
|
|
ContentBrowserUtils::IsCollectionPath(AssetFolderItem->FolderPath, &CollectionName, &CollectionFolderShareType);
|
|
|
|
Color = CollectionViewUtils::LoadColor( CollectionName.ToString(), CollectionFolderShareType );
|
|
}
|
|
else
|
|
{
|
|
Color = ContentBrowserUtils::LoadColor( AssetFolderItem->FolderPath );
|
|
}
|
|
|
|
if ( Color.IsValid() )
|
|
{
|
|
return *Color.Get();
|
|
}
|
|
}
|
|
else if(AssetTypeActions.IsValid())
|
|
{
|
|
return AssetTypeActions.Pin()->GetTypeColor().ReinterpretAsLinear();
|
|
}
|
|
}
|
|
return ContentBrowserUtils::GetDefaultColor();
|
|
}
|
|
|
|
void SAssetViewItem::SetForceMipLevelsToBeResident(bool bForce) const
|
|
{
|
|
if(AssetItem.IsValid() && AssetItem->GetType() == EAssetItemType::Normal)
|
|
{
|
|
const FAssetData& AssetData = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data;
|
|
if(AssetData.IsValid() && AssetData.IsAssetLoaded())
|
|
{
|
|
UObject* Asset = AssetData.GetAsset();
|
|
if(Asset != nullptr)
|
|
{
|
|
if(UTexture2D* Texture2D = Cast<UTexture2D>(Asset))
|
|
{
|
|
Texture2D->bForceMiplevelsToBeResident = bForce;
|
|
}
|
|
else if(UMaterial* Material = Cast<UMaterial>(Asset))
|
|
{
|
|
Material->SetForceMipLevelsToBeResident(bForce, bForce, -1.0f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SAssetViewItem::OnVisualizeTooltip(const TSharedPtr<SWidget>& TooltipContent)
|
|
{
|
|
if(OnVisualizeAssetToolTip.IsBound() && TooltipContent.IsValid() && AssetItem->GetType() != EAssetItemType::Folder)
|
|
{
|
|
FAssetData& AssetData = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data;
|
|
return OnVisualizeAssetToolTip.Execute(TooltipContent, AssetData);
|
|
}
|
|
|
|
// No custom behaviour, return false to allow slate to visualize the widget
|
|
return false;
|
|
}
|
|
|
|
void SAssetViewItem::OnToolTipClosing()
|
|
{
|
|
OnAssetToolTipClosing.ExecuteIfBound();
|
|
}
|
|
|
|
///////////////////////////////
|
|
// SAssetListItem
|
|
///////////////////////////////
|
|
|
|
SAssetListItem::~SAssetListItem()
|
|
{
|
|
|
|
}
|
|
|
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
void SAssetListItem::Construct( const FArguments& InArgs )
|
|
{
|
|
SAssetViewItem::Construct( SAssetViewItem::FArguments()
|
|
.AssetItem(InArgs._AssetItem)
|
|
.OnRenameBegin(InArgs._OnRenameBegin)
|
|
.OnRenameCommit(InArgs._OnRenameCommit)
|
|
.OnVerifyRenameCommit(InArgs._OnVerifyRenameCommit)
|
|
.OnItemDestroyed(InArgs._OnItemDestroyed)
|
|
.ShouldAllowToolTip(InArgs._ShouldAllowToolTip)
|
|
.ThumbnailEditMode(InArgs._ThumbnailEditMode)
|
|
.HighlightText(InArgs._HighlightText)
|
|
.OnAssetsOrPathsDragDropped(InArgs._OnAssetsOrPathsDragDropped)
|
|
.OnFilesDragDropped(InArgs._OnFilesDragDropped)
|
|
.OnIsAssetValidForCustomToolTip(InArgs._OnIsAssetValidForCustomToolTip)
|
|
.OnGetCustomAssetToolTip(InArgs._OnGetCustomAssetToolTip)
|
|
.OnVisualizeAssetToolTip(InArgs._OnVisualizeAssetToolTip)
|
|
.OnAssetToolTipClosing( InArgs._OnAssetToolTipClosing )
|
|
);
|
|
|
|
AssetThumbnail = InArgs._AssetThumbnail;
|
|
ItemHeight = InArgs._ItemHeight;
|
|
|
|
const float ThumbnailPadding = InArgs._ThumbnailPadding;
|
|
|
|
TSharedPtr<SWidget> Thumbnail;
|
|
if ( AssetItem.IsValid() && AssetThumbnail.IsValid() )
|
|
{
|
|
FAssetThumbnailConfig ThumbnailConfig;
|
|
ThumbnailConfig.bAllowFadeIn = true;
|
|
ThumbnailConfig.bAllowHintText = InArgs._AllowThumbnailHintLabel;
|
|
ThumbnailConfig.bForceGenericThumbnail = (AssetItem->GetType() == EAssetItemType::Creation);
|
|
ThumbnailConfig.bAllowAssetSpecificThumbnailOverlay = (AssetItem->GetType() != EAssetItemType::Creation);
|
|
ThumbnailConfig.ThumbnailLabel = InArgs._ThumbnailLabel;
|
|
ThumbnailConfig.HighlightedText = InArgs._HighlightText;
|
|
ThumbnailConfig.HintColorAndOpacity = InArgs._ThumbnailHintColorAndOpacity;
|
|
Thumbnail = AssetThumbnail->MakeThumbnailWidget(ThumbnailConfig);
|
|
}
|
|
else
|
|
{
|
|
Thumbnail = SNew(SImage) .Image( FEditorStyle::GetDefaultBrush() );
|
|
}
|
|
|
|
FName ItemShadowBorderName;
|
|
TSharedRef<SWidget> ItemContents = FAssetViewItemHelper::CreateListItemContents(this, Thumbnail.ToSharedRef(), ItemShadowBorderName);
|
|
|
|
ChildSlot
|
|
[
|
|
SNew(SBorder)
|
|
.BorderImage(this, &SAssetViewItem::GetBorderImage)
|
|
.Padding(0)
|
|
.AddMetaData<FTagMetaData>(FTagMetaData(AssetItem->GetType() == EAssetItemType::Normal ? StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data.ObjectPath : NAME_None))
|
|
[
|
|
SNew(SHorizontalBox)
|
|
|
|
// Viewport
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew( SBox )
|
|
.Padding(ThumbnailPadding - 4.f)
|
|
.WidthOverride( this, &SAssetListItem::GetThumbnailBoxSize )
|
|
.HeightOverride( this, &SAssetListItem::GetThumbnailBoxSize )
|
|
[
|
|
// Drop shadow border
|
|
SNew(SBorder)
|
|
.Padding(4.f)
|
|
.BorderImage(FEditorStyle::GetBrush(ItemShadowBorderName))
|
|
[
|
|
ItemContents
|
|
]
|
|
]
|
|
]
|
|
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(6, 0, 0, 0)
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(SVerticalBox)
|
|
|
|
+SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 1)
|
|
[
|
|
SAssignNew(InlineRenameWidget, SInlineEditableTextBlock)
|
|
.Font(FEditorStyle::GetFontStyle("ContentBrowser.AssetTileViewNameFont"))
|
|
.Text( GetNameText() )
|
|
.OnBeginTextEdit(this, &SAssetListItem::HandleBeginNameChange)
|
|
.OnTextCommitted(this, &SAssetListItem::HandleNameCommitted)
|
|
.OnVerifyTextChanged(this, &SAssetListItem::HandleVerifyNameChanged)
|
|
.HighlightText(InArgs._HighlightText)
|
|
.IsSelected(InArgs._IsSelected)
|
|
.IsReadOnly(this, &SAssetListItem::IsNameReadOnly)
|
|
]
|
|
|
|
+SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.Padding(0, 1)
|
|
[
|
|
// Class
|
|
SAssignNew(ClassText, STextBlock)
|
|
.Font(FEditorStyle::GetFontStyle("ContentBrowser.AssetListViewClassFont"))
|
|
.Text(GetAssetClassText())
|
|
.HighlightText(InArgs._HighlightText)
|
|
]
|
|
]
|
|
]
|
|
];
|
|
|
|
if(AssetItem.IsValid())
|
|
{
|
|
AssetItem->RenamedRequestEvent.BindSP(InlineRenameWidget.Get(), &SInlineEditableTextBlock::EnterEditingMode);
|
|
AssetItem->RenameCanceledEvent.BindSP(InlineRenameWidget.Get(), &SInlineEditableTextBlock::ExitEditingMode);
|
|
}
|
|
|
|
SetForceMipLevelsToBeResident(true);
|
|
}
|
|
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
|
|
void SAssetListItem::OnAssetDataChanged()
|
|
{
|
|
SAssetViewItem::OnAssetDataChanged();
|
|
|
|
if (ClassText.IsValid())
|
|
{
|
|
ClassText->SetText(GetAssetClassText());
|
|
}
|
|
|
|
if (AssetItem->GetType() != EAssetItemType::Folder && AssetThumbnail.IsValid())
|
|
{
|
|
AssetThumbnail->SetAsset(StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data);
|
|
}
|
|
}
|
|
|
|
float SAssetListItem::GetExtraStateIconWidth() const
|
|
{
|
|
return GetStateIconImageSize().Get();
|
|
}
|
|
|
|
FOptionalSize SAssetListItem::GetExtraStateIconMaxWidth() const
|
|
{
|
|
return GetThumbnailBoxSize().Get() * 0.7;
|
|
}
|
|
|
|
FOptionalSize SAssetListItem::GetStateIconImageSize() const
|
|
{
|
|
float IconSize = GetThumbnailBoxSize().Get() * 0.3;
|
|
return IconSize > 12 ? IconSize : 12;
|
|
}
|
|
|
|
FOptionalSize SAssetListItem::GetThumbnailBoxSize() const
|
|
{
|
|
return FOptionalSize( ItemHeight.Get() );
|
|
}
|
|
|
|
///////////////////////////////
|
|
// SAssetTileItem
|
|
///////////////////////////////
|
|
|
|
SAssetTileItem::~SAssetTileItem()
|
|
{
|
|
|
|
}
|
|
|
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
void SAssetTileItem::Construct( const FArguments& InArgs )
|
|
{
|
|
SAssetViewItem::Construct( SAssetViewItem::FArguments()
|
|
.AssetItem(InArgs._AssetItem)
|
|
.OnRenameBegin(InArgs._OnRenameBegin)
|
|
.OnRenameCommit(InArgs._OnRenameCommit)
|
|
.OnVerifyRenameCommit(InArgs._OnVerifyRenameCommit)
|
|
.OnItemDestroyed(InArgs._OnItemDestroyed)
|
|
.ShouldAllowToolTip(InArgs._ShouldAllowToolTip)
|
|
.ThumbnailEditMode(InArgs._ThumbnailEditMode)
|
|
.HighlightText(InArgs._HighlightText)
|
|
.OnAssetsOrPathsDragDropped(InArgs._OnAssetsOrPathsDragDropped)
|
|
.OnFilesDragDropped(InArgs._OnFilesDragDropped)
|
|
.OnIsAssetValidForCustomToolTip(InArgs._OnIsAssetValidForCustomToolTip)
|
|
.OnGetCustomAssetToolTip(InArgs._OnGetCustomAssetToolTip)
|
|
.OnVisualizeAssetToolTip(InArgs._OnVisualizeAssetToolTip)
|
|
.OnAssetToolTipClosing( InArgs._OnAssetToolTipClosing )
|
|
);
|
|
|
|
AssetThumbnail = InArgs._AssetThumbnail;
|
|
ItemWidth = InArgs._ItemWidth;
|
|
ThumbnailPadding = IsFolder() ? InArgs._ThumbnailPadding + 5.0f : InArgs._ThumbnailPadding;
|
|
|
|
TSharedPtr<SWidget> Thumbnail;
|
|
if ( AssetItem.IsValid() && AssetThumbnail.IsValid() )
|
|
{
|
|
FAssetThumbnailConfig ThumbnailConfig;
|
|
ThumbnailConfig.bAllowFadeIn = true;
|
|
ThumbnailConfig.bAllowHintText = InArgs._AllowThumbnailHintLabel;
|
|
ThumbnailConfig.bForceGenericThumbnail = (AssetItem->GetType() == EAssetItemType::Creation);
|
|
ThumbnailConfig.bAllowAssetSpecificThumbnailOverlay = (AssetItem->GetType() != EAssetItemType::Creation);
|
|
ThumbnailConfig.ThumbnailLabel = InArgs._ThumbnailLabel;
|
|
ThumbnailConfig.HighlightedText = InArgs._HighlightText;
|
|
ThumbnailConfig.HintColorAndOpacity = InArgs._ThumbnailHintColorAndOpacity;
|
|
Thumbnail = AssetThumbnail->MakeThumbnailWidget(ThumbnailConfig);
|
|
}
|
|
else
|
|
{
|
|
Thumbnail = SNew(SImage) .Image( FEditorStyle::GetDefaultBrush() );
|
|
}
|
|
|
|
FName ItemShadowBorderName;
|
|
TSharedRef<SWidget> ItemContents = FAssetViewItemHelper::CreateTileItemContents(this, Thumbnail.ToSharedRef(), ItemShadowBorderName);
|
|
|
|
ChildSlot
|
|
[
|
|
SNew(SBorder)
|
|
.BorderImage(this, &SAssetViewItem::GetBorderImage)
|
|
.Padding(0)
|
|
.AddMetaData<FTagMetaData>(FTagMetaData((AssetItem->GetType() == EAssetItemType::Normal) ? StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data.ObjectPath : ((AssetItem->GetType() == EAssetItemType::Folder) ? FName(*StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderPath) : NAME_None)))
|
|
[
|
|
SNew(SVerticalBox)
|
|
|
|
// Thumbnail
|
|
+SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
.HAlign(HAlign_Center)
|
|
[
|
|
// The remainder of the space is reserved for the name.
|
|
SNew(SBox)
|
|
.Padding(ThumbnailPadding - 4.f)
|
|
.WidthOverride(this, &SAssetTileItem::GetThumbnailBoxSize)
|
|
.HeightOverride( this, &SAssetTileItem::GetThumbnailBoxSize )
|
|
[
|
|
// Drop shadow border
|
|
SNew(SBorder)
|
|
.Padding(4.f)
|
|
.BorderImage(FEditorStyle::GetBrush(ItemShadowBorderName))
|
|
[
|
|
ItemContents
|
|
]
|
|
]
|
|
]
|
|
|
|
+SVerticalBox::Slot()
|
|
.Padding(FMargin(1.f, 0))
|
|
.HAlign(HAlign_Center)
|
|
.VAlign(VAlign_Center)
|
|
.FillHeight(1.f)
|
|
[
|
|
SAssignNew(InlineRenameWidget, SInlineEditableTextBlock)
|
|
.Font( this, &SAssetTileItem::GetThumbnailFont )
|
|
.Text( GetNameText() )
|
|
.OnBeginTextEdit(this, &SAssetTileItem::HandleBeginNameChange)
|
|
.OnTextCommitted(this, &SAssetTileItem::HandleNameCommitted)
|
|
.OnVerifyTextChanged(this, &SAssetTileItem::HandleVerifyNameChanged)
|
|
.HighlightText(InArgs._HighlightText)
|
|
.IsSelected(InArgs._IsSelected)
|
|
.IsReadOnly(this, &SAssetTileItem::IsNameReadOnly)
|
|
.Justification(ETextJustify::Center)
|
|
.LineBreakPolicy(FBreakIterator::CreateCamelCaseBreakIterator())
|
|
]
|
|
]
|
|
|
|
];
|
|
|
|
if(AssetItem.IsValid())
|
|
{
|
|
AssetItem->RenamedRequestEvent.BindSP(InlineRenameWidget.Get(), &SInlineEditableTextBlock::EnterEditingMode);
|
|
AssetItem->RenameCanceledEvent.BindSP(InlineRenameWidget.Get(), &SInlineEditableTextBlock::ExitEditingMode);
|
|
}
|
|
|
|
SetForceMipLevelsToBeResident(true);
|
|
}
|
|
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
|
|
void SAssetTileItem::OnAssetDataChanged()
|
|
{
|
|
SAssetViewItem::OnAssetDataChanged();
|
|
|
|
if (AssetItem->GetType() != EAssetItemType::Folder && AssetThumbnail.IsValid())
|
|
{
|
|
AssetThumbnail->SetAsset(StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data);
|
|
}
|
|
}
|
|
|
|
float SAssetTileItem::GetExtraStateIconWidth() const
|
|
{
|
|
return GetStateIconImageSize().Get();
|
|
}
|
|
|
|
FOptionalSize SAssetTileItem::GetExtraStateIconMaxWidth() const
|
|
{
|
|
return GetThumbnailBoxSize().Get() * 0.8;
|
|
}
|
|
|
|
FOptionalSize SAssetTileItem::GetStateIconImageSize() const
|
|
{
|
|
float IconSize = GetThumbnailBoxSize().Get() * 0.2;
|
|
return IconSize > 12 ? IconSize : 12;
|
|
}
|
|
|
|
FOptionalSize SAssetTileItem::GetThumbnailBoxSize() const
|
|
{
|
|
return FOptionalSize(ItemWidth.Get());
|
|
}
|
|
|
|
FSlateFontInfo SAssetTileItem::GetThumbnailFont() const
|
|
{
|
|
FOptionalSize ThumbSize = GetThumbnailBoxSize();
|
|
if ( ThumbSize.IsSet() )
|
|
{
|
|
float Size = ThumbSize.Get();
|
|
if ( Size < 50 )
|
|
{
|
|
const static FName SmallFontName("ContentBrowser.AssetTileViewNameFontVerySmall");
|
|
return FEditorStyle::GetFontStyle(SmallFontName);
|
|
}
|
|
else if ( Size < 85 )
|
|
{
|
|
const static FName SmallFontName("ContentBrowser.AssetTileViewNameFontSmall");
|
|
return FEditorStyle::GetFontStyle(SmallFontName);
|
|
}
|
|
}
|
|
|
|
const static FName RegularFont("ContentBrowser.AssetTileViewNameFont");
|
|
return FEditorStyle::GetFontStyle(RegularFont);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////
|
|
// SAssetColumnItem
|
|
///////////////////////////////
|
|
|
|
/** Custom box for the Name column of an asset */
|
|
class SAssetColumnItemNameBox : public SCompoundWidget
|
|
{
|
|
public:
|
|
SLATE_BEGIN_ARGS( SAssetColumnItemNameBox ) {}
|
|
|
|
/** The color of the asset */
|
|
SLATE_ATTRIBUTE( FMargin, Padding )
|
|
|
|
/** The widget content presented in the box */
|
|
SLATE_DEFAULT_SLOT(FArguments, Content)
|
|
|
|
SLATE_END_ARGS()
|
|
|
|
~SAssetColumnItemNameBox() {}
|
|
|
|
void Construct( const FArguments& InArgs, const TSharedRef<SAssetColumnItem>& InOwnerAssetColumnItem )
|
|
{
|
|
OwnerAssetColumnItem = InOwnerAssetColumnItem;
|
|
|
|
ChildSlot
|
|
[
|
|
SNew(SBox)
|
|
.Padding(InArgs._Padding)
|
|
[
|
|
InArgs._Content.Widget
|
|
]
|
|
];
|
|
}
|
|
|
|
virtual TSharedPtr<IToolTip> GetToolTip() override
|
|
{
|
|
if ( OwnerAssetColumnItem.IsValid() )
|
|
{
|
|
return OwnerAssetColumnItem.Pin()->GetToolTip();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/** Forward the event to the view item that this name box belongs to */
|
|
virtual void OnToolTipClosing() override
|
|
{
|
|
if ( OwnerAssetColumnItem.IsValid() )
|
|
{
|
|
OwnerAssetColumnItem.Pin()->OnToolTipClosing();
|
|
}
|
|
}
|
|
|
|
private:
|
|
TWeakPtr<SAssetViewItem> OwnerAssetColumnItem;
|
|
};
|
|
|
|
void SAssetColumnItem::Construct( const FArguments& InArgs )
|
|
{
|
|
SAssetViewItem::Construct( SAssetViewItem::FArguments()
|
|
.AssetItem(InArgs._AssetItem)
|
|
.OnRenameBegin(InArgs._OnRenameBegin)
|
|
.OnRenameCommit(InArgs._OnRenameCommit)
|
|
.OnVerifyRenameCommit(InArgs._OnVerifyRenameCommit)
|
|
.OnItemDestroyed(InArgs._OnItemDestroyed)
|
|
.HighlightText(InArgs._HighlightText)
|
|
.OnAssetsOrPathsDragDropped(InArgs._OnAssetsOrPathsDragDropped)
|
|
.OnFilesDragDropped(InArgs._OnFilesDragDropped)
|
|
.OnIsAssetValidForCustomToolTip(InArgs._OnIsAssetValidForCustomToolTip)
|
|
.OnGetCustomAssetToolTip(InArgs._OnGetCustomAssetToolTip)
|
|
.OnVisualizeAssetToolTip(InArgs._OnVisualizeAssetToolTip)
|
|
.OnAssetToolTipClosing(InArgs._OnAssetToolTipClosing)
|
|
);
|
|
|
|
HighlightText = InArgs._HighlightText;
|
|
}
|
|
|
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
TSharedRef<SWidget> SAssetColumnItem::GenerateWidgetForColumn( const FName& ColumnName, FIsSelected InIsSelected )
|
|
{
|
|
TSharedPtr<SWidget> Content;
|
|
|
|
// A little right padding so text from this column does not run directly into text from the next.
|
|
static const FMargin ColumnItemPadding( 5, 0, 5, 0 );
|
|
|
|
if ( ColumnName == "Name" )
|
|
{
|
|
const FSlateBrush* IconBrush;
|
|
if(IsFolder())
|
|
{
|
|
if(AssetItem.IsValid() && StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->bDeveloperFolder)
|
|
{
|
|
IconBrush = FEditorStyle::GetBrush("ContentBrowser.ColumnViewDeveloperFolderIcon");
|
|
}
|
|
else
|
|
{
|
|
IconBrush = FEditorStyle::GetBrush("ContentBrowser.ColumnViewFolderIcon");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IconBrush = FEditorStyle::GetBrush("ContentBrowser.ColumnViewAssetIcon");
|
|
}
|
|
|
|
// Make icon overlays (eg, SCC and dirty status) a reasonable size in relation to the icon size (note: it is assumed this icon is square)
|
|
const float IconOverlaySize = IconBrush->ImageSize.X * 0.6f;
|
|
|
|
Content = SNew(SHorizontalBox)
|
|
.AddMetaData<FTagMetaData>(FTagMetaData(AssetItem->GetType() == EAssetItemType::Normal ? StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data.ObjectPath : NAME_None))
|
|
// Icon
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(0, 0, 4, 0)
|
|
[
|
|
SNew(SOverlay)
|
|
|
|
// The actual icon
|
|
+SOverlay::Slot()
|
|
[
|
|
SNew(SImage)
|
|
.Image( IconBrush )
|
|
.ColorAndOpacity(this, &SAssetColumnItem::GetAssetColor)
|
|
]
|
|
|
|
// Source control state
|
|
+SOverlay::Slot()
|
|
.HAlign(HAlign_Right)
|
|
.VAlign(VAlign_Top)
|
|
[
|
|
SNew(SBox)
|
|
.WidthOverride(IconOverlaySize)
|
|
.HeightOverride(IconOverlaySize)
|
|
[
|
|
SNew(SImage)
|
|
.Image(this, &SAssetColumnItem::GetSCCStateImage)
|
|
]
|
|
]
|
|
|
|
// Extra external state hook
|
|
+ SOverlay::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.VAlign(VAlign_Top)
|
|
[
|
|
SNew(SBox)
|
|
.HeightOverride(IconOverlaySize)
|
|
.MaxDesiredWidth(IconOverlaySize)
|
|
[
|
|
GenerateExtraStateIconWidget(IconOverlaySize)
|
|
]
|
|
]
|
|
|
|
// Dirty state
|
|
+SOverlay::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.VAlign(VAlign_Bottom)
|
|
[
|
|
SNew(SBox)
|
|
.WidthOverride(IconOverlaySize)
|
|
.HeightOverride(IconOverlaySize)
|
|
[
|
|
SNew(SImage)
|
|
.Image(this, &SAssetColumnItem::GetDirtyImage)
|
|
]
|
|
]
|
|
]
|
|
|
|
// Editable Name
|
|
+SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
[
|
|
SAssignNew(InlineRenameWidget, SInlineEditableTextBlock)
|
|
.Text( GetNameText() )
|
|
.OnBeginTextEdit(this, &SAssetColumnItem::HandleBeginNameChange)
|
|
.OnTextCommitted(this, &SAssetColumnItem::HandleNameCommitted)
|
|
.OnVerifyTextChanged(this, &SAssetColumnItem::HandleVerifyNameChanged)
|
|
.HighlightText(HighlightText)
|
|
.IsSelected(InIsSelected)
|
|
.IsReadOnly(this, &SAssetColumnItem::IsNameReadOnly)
|
|
];
|
|
|
|
if(AssetItem.IsValid())
|
|
{
|
|
AssetItem->RenamedRequestEvent.BindSP(InlineRenameWidget.Get(), &SInlineEditableTextBlock::EnterEditingMode);
|
|
AssetItem->RenameCanceledEvent.BindSP(InlineRenameWidget.Get(), &SInlineEditableTextBlock::ExitEditingMode);
|
|
}
|
|
|
|
return SNew(SBorder)
|
|
.BorderImage(this, &SAssetViewItem::GetBorderImage)
|
|
.Padding(0)
|
|
.VAlign(VAlign_Center)
|
|
.HAlign(HAlign_Left)
|
|
[
|
|
SNew( SAssetColumnItemNameBox, SharedThis(this) )
|
|
.Padding( ColumnItemPadding )
|
|
[
|
|
Content.ToSharedRef()
|
|
]
|
|
];
|
|
}
|
|
else if ( ColumnName == "Class" )
|
|
{
|
|
Content = SAssignNew(ClassText, STextBlock)
|
|
.ToolTipText( this, &SAssetColumnItem::GetAssetClassText )
|
|
.Text( GetAssetClassText() )
|
|
.HighlightText( HighlightText );
|
|
}
|
|
else if ( ColumnName == "Path" )
|
|
{
|
|
Content = SAssignNew(PathText, STextBlock)
|
|
.ToolTipText( this, &SAssetColumnItem::GetAssetPathText )
|
|
.Text( GetAssetPathText() )
|
|
.HighlightText( HighlightText );
|
|
}
|
|
else
|
|
{
|
|
Content = SNew(STextBlock)
|
|
.ToolTipText( TAttribute<FText>::Create( TAttribute<FText>::FGetter::CreateSP(this, &SAssetColumnItem::GetAssetTagText, ColumnName) ) )
|
|
.Text( TAttribute<FText>::Create( TAttribute<FText>::FGetter::CreateSP(this, &SAssetColumnItem::GetAssetTagText, ColumnName) ) );
|
|
}
|
|
|
|
return SNew(SBox)
|
|
.Padding( ColumnItemPadding )
|
|
.VAlign(VAlign_Center)
|
|
.HAlign(HAlign_Left)
|
|
[
|
|
Content.ToSharedRef()
|
|
];
|
|
}
|
|
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
|
|
void SAssetColumnItem::OnAssetDataChanged()
|
|
{
|
|
SAssetViewItem::OnAssetDataChanged();
|
|
|
|
if ( ClassText.IsValid() )
|
|
{
|
|
ClassText->SetText( GetAssetClassText() );
|
|
}
|
|
|
|
if ( PathText.IsValid() )
|
|
{
|
|
PathText->SetText( GetAssetPathText() );
|
|
}
|
|
}
|
|
|
|
FString SAssetColumnItem::GetAssetNameToolTipText() const
|
|
{
|
|
if ( AssetItem.IsValid() )
|
|
{
|
|
if(AssetItem->GetType() == EAssetItemType::Folder)
|
|
{
|
|
FString Result = StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderName.ToString();
|
|
Result += TEXT("\n");
|
|
Result += LOCTEXT("FolderName", "Folder").ToString();
|
|
|
|
return Result;
|
|
}
|
|
else
|
|
{
|
|
const FString AssetName = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data.AssetName.ToString();
|
|
const FString AssetType = StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data.AssetClass.ToString();
|
|
|
|
FString Result = AssetName;
|
|
Result += TEXT("\n");
|
|
Result += AssetType;
|
|
|
|
return Result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return FString();
|
|
}
|
|
}
|
|
|
|
FText SAssetColumnItem::GetAssetPathText() const
|
|
{
|
|
if ( AssetItem.IsValid() )
|
|
{
|
|
if(AssetItem->GetType() != EAssetItemType::Folder)
|
|
{
|
|
return FText::FromName(StaticCastSharedPtr<FAssetViewAsset>(AssetItem)->Data.PackagePath);
|
|
}
|
|
else
|
|
{
|
|
return FText::FromString(StaticCastSharedPtr<FAssetViewFolder>(AssetItem)->FolderPath);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return FText();
|
|
}
|
|
}
|
|
|
|
FText SAssetColumnItem::GetAssetTagText(FName AssetTag) const
|
|
{
|
|
if ( AssetItem.IsValid() )
|
|
{
|
|
if(AssetItem->GetType() != EAssetItemType::Folder)
|
|
{
|
|
const TSharedPtr<FAssetViewAsset>& ItemAsAsset = StaticCastSharedPtr<FAssetViewAsset>(AssetItem);
|
|
|
|
// Check custom type
|
|
{
|
|
FText* FoundText = ItemAsAsset->CustomColumnDisplayText.Find(AssetTag);
|
|
if (FoundText)
|
|
{
|
|
return *FoundText;
|
|
}
|
|
}
|
|
|
|
// Check display tags
|
|
{
|
|
const FTagDisplayItem* FoundTagItem = CachedDisplayTags.FindByPredicate([AssetTag](const FTagDisplayItem& TagItem)
|
|
{
|
|
return TagItem.TagKey == AssetTag;
|
|
});
|
|
|
|
if (FoundTagItem)
|
|
{
|
|
return FoundTagItem->DisplayValue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FText();
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|