void UPinnedAssetSubsystem::AddAssetPath(FString Path, EPathType Type, bool IsPinned)
{
bool SaveData = false;
if (!ContainsPath(Path))
{
AssetDataList.Add(FPinnedAssetData(Path, !IsPinned, Type));
SaveData = true;
if (OnListChangedDelegate.IsBound())
OnListChangedDelegate.Execute(AssetDataList);
}
else
{
int Index = -1;
if (FindPath(Path, Index))
{
if (AssetDataList[Index].TabIndex == 0 || !IsPinned)
return;
AssetDataList[Index].TabIndex = 0;
SaveData = true;
if (OnListChangedDelegate.IsBound())
OnListChangedDelegate.Execute(AssetDataList);
}
}
if (SaveData)
{
TArray<FString> SaveList;
for (const auto& Data : AssetDataList)
{
SaveList.Add(Data.GetSaveString());
}
FFileHelper::SaveStringArrayToFile(SaveList, *FilePath);
}
}
void UPinnedAssetSubsystem::RemoveAssetPath(FString Path)
{
int Index = -1;
if (FindPath(Path, Index))
{
AssetDataList.RemoveAt(Index);
TArray<FString> SaveList;
for (const auto& Data : AssetDataList)
{
SaveList.Add(Data.GetSaveString());
}
FFileHelper::SaveStringArrayToFile(SaveList, *FilePath);
if (OnListChangedDelegate.IsBound())
OnListChangedDelegate.Execute(AssetDataList);
}
}
// Returns true if asset/folder is pinned, and false if asset/folder is recently opened
bool UPinnedAssetSubsystem::GetStatus(FString Path)
{
int Index = -1;
if (FindPath(Path, Index))
return AssetDataList[Index].TabIndex != 1;
return false;
}
// Asset or Folder
EPathType UPinnedAssetSubsystem::GetPathType(FString Path)
{
int Index = -1;
if (FindPath(Path, Index))
return AssetDataList[Index].PathType;
return EPathType::None;
}
const TArray<FPinnedAssetData>& UPinnedAssetSubsystem::GetAssetDataList()
{
return AssetDataList;
}
bool UPinnedAssetSubsystem::ContainsPath(FString Path)
{
for (const FPinnedAssetData& Data : AssetDataList)
if (Data.AssetPath.Equals(Path))
return true;
return false;
}
bool UPinnedAssetSubsystem::FindPath(FString Path, int& OutIndex)
{
int Index = 0;
for (const FPinnedAssetData& Data : AssetDataList)
{
if (Data.AssetPath.Equals(Path))
{
OutIndex = Index;
return true;
}
Index++;
}
OutIndex = -1;
return false;
}
void UPinnedAssetSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
FolderIcon = LoadObject<UTexture2D>(nullptr, TEXT("/Script/Engine.Texture2D'/AssetPinner/Icon/Folder_Base_256x.Folder_Base_256x'"));
FilePath = FPaths::GameUserDeveloperDir() + "PinnedAssetData.txt";
TArray<FString> LoadList;
FFileHelper::LoadFileToStringArray(LoadList, *FilePath);
bool IsPinned = false;
for (auto& line : LoadList)
{
TArray<FString> SplitString;
line.ParseIntoArray(SplitString, TEXT(" "));
AssetDataList.Add(FPinnedAssetData(
SplitString[0],
FCString::Atoi(*SplitString[1]),
SplitString.IsValidIndex(2) ? (EPathType)FCString::Atoi(*SplitString[2]) : EPathType::Asset
));
}
for (int i = 0; i < AssetDataList.Num(); i++)
{
FPackagePath OutPath;
FPackagePath PackagePath;
if (FPackagePath::TryFromPackageName(AssetDataList[i].AssetPath, PackagePath) || AssetDataList[i].PathType != EPathType::Asset)
{
if (!FPackageName::DoesPackageExist(PackagePath, &OutPath) && AssetDataList[i].PathType == EPathType::Asset)
{
UE_LOG(LogTemp, Warning, TEXT("Cannot find file: %s"), *AssetDataList[i].AssetPath);
AssetDataList.RemoveAt(i);
i--;
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Cannot find file: %s"), *AssetDataList[i].AssetPath);
AssetDataList.RemoveAt(i);
i--;
}
}
}
void PinAssetAction::PinAssets(const TArray<FAssetData>& SelectedAssets)
{
for (auto& AssetData : SelectedAssets)
{
FString AssetPath = AssetData.PackageName.ToString();
UPinnedAssetSubsystem* Subsystem = nullptr;
if (GEditor)
Subsystem = GEditor->GetEditorSubsystem<UPinnedAssetSubsystem>();
if (Subsystem)
Subsystem->AddAssetPath(AssetPath);
}
}
void FAssetPinnerModule::AddContentBrowserContextMenuExtender()
{
FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));
TArray<FContentBrowserMenuExtender_SelectedAssets>& CBMenuAssetExtenderDelegates = ContentBrowserModule.GetAllAssetViewContextMenuExtenders();
TArray<FContentBrowserMenuExtender_SelectedPaths>& CBMenuPathExtenderDelegates = ContentBrowserModule.GetAllPathViewContextMenuExtenders();
CBMenuAssetExtenderDelegates.Add(FContentBrowserMenuExtender_SelectedAssets::CreateStatic(&OnExtendContentBrowserAssetSelectionMenu));
ContentBrowserAssetExtenderDelegateHandle = CBMenuAssetExtenderDelegates.Last().GetHandle();
CBMenuPathExtenderDelegates.Add(FContentBrowserMenuExtender_SelectedPaths::CreateStatic(&OnExtendContentBrowserPathSelectionMenu));
ContentBrowserPathExtenderDelegateHandle = CBMenuPathExtenderDelegates.Last().GetHandle();
}
void FAssetPinnerModule::RemoveContentBrowserContextMenuExtender()
{
FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));
TArray<FContentBrowserMenuExtender_SelectedAssets>& CBMenuExtenderDelegates = ContentBrowserModule.GetAllAssetViewContextMenuExtenders();
CBMenuExtenderDelegates.RemoveAll([this](const FContentBrowserMenuExtender_SelectedAssets& Delegate) { return Delegate.GetHandle() == ContentBrowserAssetExtenderDelegateHandle; });
TArray<FContentBrowserMenuExtender_SelectedPaths>& CBMenuPathExtenderDelegates = ContentBrowserModule.GetAllPathViewContextMenuExtenders();
CBMenuPathExtenderDelegates.RemoveAll([this](const FContentBrowserMenuExtender_SelectedPaths& Delegate) { return Delegate.GetHandle() == ContentBrowserPathExtenderDelegateHandle; });
}
void FAssetPinnerModule::AddMenuExtention(FMenuBuilder& MenuBuilder)
{
MenuBuilder.BeginSection("Test section", LOCTEXT("ASSET_CONTEXT", "Pin Asset"));
{
// Add Menu Entry Here
MenuBuilder.AddMenuEntry(
LOCTEXT("ButtonName", "Test"),
LOCTEXT("Button ToolTip", "A test button"),
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ViewportActorPreview.Pinned"),
FUIAction(FExecuteAction::CreateLambda([]()
{
FAssetPinnerModule::PrintString();
})),
NAME_None,
EUserInterfaceActionType::Button);
}
MenuBuilder.EndSection();
}
TSharedRef<FExtender> FAssetPinnerModule::OnExtendContentBrowserAssetSelectionMenu(const TArray<FAssetData>& SelectedAssets)
{
TSharedRef<FExtender> Extender = MakeShared<FExtender>();
Extender->AddMenuExtension(
"AssetContextCollections",
EExtensionHook::After,
nullptr,
FMenuExtensionDelegate::CreateStatic(&ExecutePinAsset, SelectedAssets)
);
return Extender;
}
TSharedRef<FExtender> FAssetPinnerModule::OnExtendContentBrowserPathSelectionMenu(const TArray<FString>& SelectedAssets)
{
TSharedRef<FExtender> Extender = MakeShared<FExtender>();
Extender->AddMenuExtension(
"PathContextBulkOperations",
EExtensionHook::After,
nullptr,
FMenuExtensionDelegate::CreateStatic(&ExecutePinPath, SelectedAssets)
);
return Extender;
}
void FAssetPinnerModule::ExecutePinAsset(FMenuBuilder& MenuBuilder, const TArray<FAssetData> SelectedAssets)
{
MenuBuilder.BeginSection("Pin Asset", LOCTEXT("ASSET_CONTEXT", "Pin Asset"));
{
// Add Menu Entry Here
MenuBuilder.AddMenuEntry(
LOCTEXT("ButtonName", "Pin"),
LOCTEXT("Button ToolTip", "Pin Asset"),
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ViewportActorPreview.Pinned"),
FUIAction(FExecuteAction::CreateLambda([SelectedAssets]()
{
for (auto& AssetData : SelectedAssets)
{
FString AssetPath = AssetData.PackageName.ToString();
UPinnedAssetSubsystem* Subsystem = nullptr;
if (GEditor)
Subsystem = GEditor->GetEditorSubsystem<UPinnedAssetSubsystem>();
if (Subsystem)
Subsystem->AddAssetPath(AssetPath);
}
})),
NAME_None,
EUserInterfaceActionType::Button);
}
MenuBuilder.EndSection();
}
void FAssetPinnerModule::ExecutePinPath(FMenuBuilder& MenuBuilder, const TArray<FString> SelectedAssets)
{
MenuBuilder.BeginSection("Pin Asset", LOCTEXT("ASSET_CONTEXT", "Pin Asset"));
{
// Add Menu Entry Here
MenuBuilder.AddMenuEntry(
LOCTEXT("ButtonName", "Pin Path"),
LOCTEXT("Button ToolTip", "Pin Path"),
FSlateIcon(FAppStyle::GetAppStyleSetName(), "ViewportActorPreview.Pinned"),
FUIAction(FExecuteAction::CreateLambda([SelectedAssets]()
{
UPinnedAssetSubsystem* Subsystem = GEditor->GetEditorSubsystem<UPinnedAssetSubsystem>();
if (Subsystem)
Subsystem->AddAssetPath(SelectedAssets[0], EPathType::Folder);
})),
NAME_None,
EUserInterfaceActionType::Button);
}
MenuBuilder.EndSection();
}
void UPinnedWindowBase::NativeConstruct()
{
Super::NativeConstruct();
if (!GEngine)
return;
PinnedAssetSubsystem = GEditor->GetEditorSubsystem<UPinnedAssetSubsystem>();
if (!PinnedAssetSubsystem)
return;
PinnedAssetSubsystem->OnListChangedDelegate.BindDynamic(this, &UPinnedWindowBase::OnListChangedCallback);
TArray<FString> Data;
ConfigPath = FPaths::GameUserDeveloperDir() + "PinnedAssetConfig.txt";
if (FPaths::ValidatePath(ConfigPath))
{
FFileHelper::LoadFileToStringArray(Data, *ConfigPath);
if (!Data.IsEmpty())
{
if (Data[0].IsNumeric())
{
Size = FCString::Atof(*Data[0]);
Data.RemoveAt(0);
}
}
}
if (PinnedSection)
SectionMap.Add(FSection("Pinned", PinnedSection, true));
if (RecentSection)
SectionMap.Add(FSection("Recent", RecentSection, true));
if (TabList)
{
UTab* PinnedTab = CreateWidget<UTab>(this, TabWidget);
PinnedTab->SetInfo(FText::FromString("Pinned"), this, PinnedSection, true);
PinnedTab->OnTabClickedDelegate.BindDynamic(this, &UPinnedWindowBase::OnTabClicked);
ActiveTab = PinnedTab;
ActiveTab->SetSelected(true);
UTab* HistoryTab = CreateWidget<UTab>(this, TabWidget);
HistoryTab->OnTabClickedDelegate.BindDynamic(this, &UPinnedWindowBase::OnTabClicked);
HistoryTab->SetInfo(FText::FromString("History"), this, RecentSection, true);
TabList->AddChild(PinnedTab);
TabList->AddChild(HistoryTab);
}
Refresh(PinnedAssetSubsystem->GetAssetDataList());
if (NewTabButton)
NewTabButton->OnClicked.AddDynamic(this, &UPinnedWindowBase::OnNewTabClicked);
}
void UPinnedWindowBase::NativeDestruct()
{
FString SaveConfig;
SaveConfig += FString::SanitizeFloat(Size) + '\n';
FFileHelper::SaveStringToFile(SaveConfig, *ConfigPath);
}
EditState UPinnedWindowBase::CheckInEditMode()
{
return EditMode;
}
void UPinnedWindowBase::OnListChangedCallback(const TArray<FPinnedAssetData>& List)
{
Refresh(List);
}
void UPinnedWindowBase::Refresh(const TArray<FPinnedAssetData>& List)
{
if (!AssetSlotWidget) return;
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
Slots.Empty();
for (auto& Section : SectionMap)
Section.SectionWidget->ClearPinnedAsset();
for (const auto& Data : List)
{
TArray<FAssetData> Assets;
AssetRegistry.GetAssetsByPackageName(FName(Data.AssetPath), Assets);
if (Assets.Num() <= 0 && Data.PathType == EPathType::Asset)
continue;
UPinnedAssetSlotBase* NewSlot = CreateWidget<UPinnedAssetSlotBase>(this, AssetSlotWidget);
NewSlot->SetAssetData(Data);
NewSlot->SetThumbnail(Assets.IsValidIndex(0) ? Assets[0] : nullptr, PinnedAssetSubsystem);
NewSlot->SetSize(Size, Size * Ratio);
Slots.Add(NewSlot);
SectionMap[Data.TabIndex].SectionWidget->AddPinnedAsset(NewSlot);
}
return;
}
FReply UPinnedWindowBase::NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
{
if (InKeyEvent.GetKey() == EKeys::LeftControl)
{
EditMode = EditState::InEditMode;
PinnedSection->SetEnableScrolling(false);
RecentSection->SetEnableScrolling(false);
}
return FReply::Handled();
}
FReply UPinnedWindowBase::NativeOnKeyUp(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent)
{
if (InKeyEvent.GetKey() == EKeys::LeftControl)
{
EditMode = EditState::NotInEditMode;
PinnedSection->SetEnableScrolling(true);
RecentSection->SetEnableScrolling(true);
}
return FReply::Handled();
}
FReply UPinnedWindowBase::NativeOnMouseWheel(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
if (EditMode == EditState::InEditMode)
{
Size += InMouseEvent.GetWheelDelta() * 10;
Size = FMath::Max(Size, MinSize);
for (auto PinSlot : Slots)
{
PinSlot->SetSize(Size, Size * Ratio);
}
return FReply::Handled();
}
return FReply::Handled();
}
FReply UPinnedWindowBase::NativeOnFocusReceived(const FGeometry& InGeometry, const FFocusEvent& InFocusEvent)
{
EditMode = EditState::NotInEditMode;
return FReply::Handled();
}
void UPinnedWindowBase::NativeOnFocusLost(const FFocusEvent& InFocusEvent)
{
EditMode = EditState::Unfocused;
}
void UPinnedSectionBase::ClearPinnedAsset()
{
WrapBox->ClearChildren();
}
void UPinnedSectionBase::AddPinnedAsset(UPinnedAssetSlotBase* NewPinnedSlot)
{
WrapBox->AddChildToWrapBox(NewPinnedSlot);
}
void UPinnedSectionBase::SetEnableScrolling(bool IsEnabled)
{
ScrollBox->SetIsEnabled(IsEnabled);
}
void UPinnedAssetSlotBase::SetAssetData(const FPinnedAssetData& Data)
{
AssetPath = Data.AssetPath;
if (Name)
Name->SetText(FText::FromString(FPackageName::GetShortName(*Data.AssetPath)));
Background->AssetPath = Data.AssetPath;
PathType = Data.PathType;
}
void UPinnedAssetSlotBase::SetThumbnail(const FAssetData& AssetData, const UPinnedAssetSubsystem* PinnedAssetSubsystem)
{
USizeBoxSlot* SlotPtr = nullptr;
if (PathType == EPathType::Folder)
{
UImage* Image = WidgetTree->ConstructWidget<UImage>(UImage::StaticClass(), TEXT("Thumbnail"));
Image->SetBrushFromTexture(PinnedAssetSubsystem->FolderIcon);
SlotPtr = Cast<USizeBoxSlot>(ThumbnailHolder->AddChild(Image));
}
else if (PathType == EPathType::Asset)
{
Thumbnail = WidgetTree->ConstructWidget<UAssetThumbnailWidget>(UAssetThumbnailWidget::StaticClass(), TEXT("Thumbnail"));
Thumbnail->SetAsset(AssetData);
SlotPtr = Cast<USizeBoxSlot>(ThumbnailHolder->AddChild(Thumbnail));
}
if (SlotPtr)
{
SlotPtr->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Fill);
SlotPtr->SetVerticalAlignment(EVerticalAlignment::VAlign_Fill);
}
}
FString UPinnedAssetSlotBase::GetAssetPath()
{
return AssetPath;
}
void UPinnedAssetSlotBase::SetSize(int Width, int Height)
{
SizeBox->SetHeightOverride(Height);
SizeBox->SetWidthOverride(Width);
if (Thumbnail)
Thumbnail->SetResolution(FIntPoint(Width));
}
FReply UPinnedAssetSlotBase::NativeOnMouseButtonDoubleClick(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
if (!InMouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton))
return FReply::Unhandled();
if (PathType == EPathType::Folder)
{
TArray<FString> Assets{ AssetPath };
FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));
ContentBrowserModule.Get().SyncBrowserToFolders(Assets);
return FReply::Handled();
}
TArray<FAssetData> Assets;
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
AssetRegistry.GetAssetsByPackageName(FName(AssetPath), Assets);
if (Assets.Num() <= 0)
return FReply::Handled();
UObject* Asset = Assets[0].GetAsset();
if (!Asset)
{
UE_LOG(LogTemp, Error, TEXT("Open Asset Window Failed - Asset is not valid"));
return FReply::Handled();
}
UAssetEditorSubsystem* Subsystem = GEditor ? GEditor->GetEditorSubsystem<UAssetEditorSubsystem>() : nullptr;
if (!Subsystem)
{
UE_LOG(LogTemp, Error, TEXT("Open Asset Window Failed - Asset Editor Subsystem is not valid"));
return FReply::Handled();
}
bool success = Subsystem->OpenEditorForAsset(Asset);
if (success)
{
UE_LOG(LogTemp, Log, TEXT("Open Asset Window Succeeded"));
}
else
UE_LOG(LogTemp, Error, TEXT("Open Asset Window Failed"));
return FReply::Handled();
}
void UPinnedAssetSlotBase::NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
Background->SetBrushColor(HoverColor);
}
void UPinnedAssetSlotBase::NativeOnMouseLeave(const FPointerEvent& InMouseEvent)
{
Background->SetBrushColor(BaseColor);
}
USTRUCT()
struct ASSETPINNER_API FPinnedAssetData
{
GENERATED_BODY()
FPinnedAssetData() = default;
FPinnedAssetData(FString InAssetPath, int InTabIndex, EPathType InPathType)
{
AssetPath = InAssetPath;
TabIndex = InTabIndex;
PathType = InPathType;
}
FString GetSaveString() const { return AssetPath + ' ' + FString::FromInt(TabIndex) + ' ' + FString::FromInt((int)PathType); };
FString AssetPath;
int TabIndex;
EPathType PathType;
};
USTRUCT()
struct FSection
{
GENERATED_BODY()
FString Name;
UPROPERTY()
UPinnedSectionBase* SectionWidget;
UPROPERTY()
bool bIsPersistent;
FSection() = default;
FSection(FString InName, UPinnedSectionBase* InSectionWidget, bool InIsPersistent = false)
{
Name = InName;
SectionWidget = InSectionWidget;
bIsPersistent = InIsPersistent;
}
};
FReply SExtendedSlateBorder::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
FReply Reply = FReply::Unhandled();
if (MouseEvent.GetEffectingButton() == EKeys::RightMouseButton)
{
if (MyGeometry.IsUnderLocation(MouseEvent.GetScreenSpacePosition()))
{
// Right clicked, so summon a context menu if the cursor is within the widget
FWidgetPath WidgetPath = MouseEvent.GetEventPath() != nullptr ? *MouseEvent.GetEventPath() : FWidgetPath();
TSharedPtr<SWidget> MenuContentWidget = BuildContextMenuContent();
if (MenuContentWidget.IsValid())
{
static const bool bFocusImmediately = true;
TSharedPtr<IMenu> ContextMenu;
ContextMenu = FSlateApplication::Get().PushMenu(
MouseEvent.GetWindow(),
WidgetPath,
MenuContentWidget.ToSharedRef(),
MouseEvent.GetScreenSpacePosition(),
FPopupTransitionEffect(FPopupTransitionEffect::ContextMenu),
bFocusImmediately
);
}
}
// Release mouse capture
Reply = FReply::Handled();
}
return Reply;
}
TSharedPtr<SWidget> SExtendedSlateBorder::BuildContextMenuContent()
{
#define LOCTEXT_NAMESPACE "AssetPinnerContextMenu"
// Set the menu to automatically close when the user commits to a choice
const bool bShouldCloseWindowAfterMenuSelection = true;
// This is a context menu which could be summoned from within another menu if this text block is in a menu
// it should not close the menu it is inside
bool bCloseSelfOnly = true;
FMenuBuilder MenuBuilder(bShouldCloseWindowAfterMenuSelection, TSharedPtr< const FUICommandList >(), nullptr, bCloseSelfOnly, &FCoreStyle::Get());
{
ContextMenuExtender.ExecuteIfBound(MenuBuilder);
}
return MenuBuilder.MakeWidget();
#undef LOCTEXT_NAMESPACE
}
TSharedRef<SWidget> UExtendedBorder::RebuildWidget()
{
MyBorder = SNew(SExtendedSlateBorder)
.FlipForRightToLeftFlowDirection(bFlipForRightToLeftFlowDirection)
.ContextMenuExtender(FMenuExtensionDelegate::CreateUObject(this, &UExtendedBorder::ExtendContextMenu));
if (GetChildrenCount() > 0)
{
Cast<UBorderSlot>(GetContentSlot())->BuildSlot(MyBorder.ToSharedRef());
}
return MyBorder.ToSharedRef();
}
void UExtendedBorder::ExtendContextMenu(FMenuBuilder& Builder)
{
#define LOCTEXT_NAMESPACE "AssetPinnerContextMenu"
Builder.BeginSection("EditSection", LOCTEXT("Heading", "Edit Action"));
{
FUIAction PinAssetAction(
FExecuteAction::CreateUObject(this, &UExtendedBorder::Pin),
FCanExecuteAction::CreateUObject(this, &UExtendedBorder::CanPin)
);
FUIAction UnpinAssetAction(
FExecuteAction::CreateUObject(this, &UExtendedBorder::Unpin)
);
Builder.AddMenuEntry(
NSLOCTEXT("AssetPinner", "PinAssetLabel", "Pin Asset"),
NSLOCTEXT("AssetPinner", "PinAssetTooltip", "Move the asset to pinned section"),
FSlateIcon(),
PinAssetAction
);
Builder.AddMenuEntry(
NSLOCTEXT("AssetPinner", "UnpinAssetLabel", "Unpin Asset"),
NSLOCTEXT("AssetPinner", "UnpinAssetTooltip", "Remove the asset from pinned section"),
FSlateIcon(),
UnpinAssetAction
);
FMenuBuilder TabMenuBuilder(true, TSharedPtr< const FUICommandList >(), nullptr, false, &FCoreStyle::Get());
}
Builder.EndSection();
Builder.BeginSection("SearchSection", LOCTEXT("Heading", "Search Action"));
{
FUIAction LocateAssetAction(
FExecuteAction::CreateUObject(this, &UExtendedBorder::LocateInBrowser)
);
Builder.AddMenuEntry(
NSLOCTEXT("AssetPinner", "LocateAssetLabel", "Locate Asset"),
NSLOCTEXT("AssetPinner", "LocateAssetTooltip", "Locate the asset in the content browser"),
FSlateIcon(),
LocateAssetAction
);
}
Builder.EndSection();
#undef LOCTEXT_NAMESPACE
}
void UExtendedBorder::Pin()
{
UPinnedAssetSubsystem* Subsystem = GEditor->GetEditorSubsystem<UPinnedAssetSubsystem>();
if (!Subsystem)
return;
Subsystem->MoveAssetPath(AssetPath, 0);
}
bool UExtendedBorder::CanPin()
{
UPinnedAssetSubsystem* Subsystem = GEditor->GetEditorSubsystem<UPinnedAssetSubsystem>();
if (!Subsystem)
return false;
// False mean unpinned, and we only want this option available then
return !Subsystem->GetStatus(AssetPath);
}
void UExtendedBorder::Unpin()
{
UPinnedAssetSubsystem* Subsystem = GEditor->GetEditorSubsystem<UPinnedAssetSubsystem>();
if (!Subsystem)
return;
Subsystem->RemoveAssetPath(AssetPath);
}
void UExtendedBorder::LocateInBrowser()
{
UPinnedAssetSubsystem* Subsystem = GEditor->GetEditorSubsystem<UPinnedAssetSubsystem>();
if (!Subsystem)
return;
FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));
if (Subsystem->GetPathType(AssetPath) == EPathType::Folder)
{
TArray<FString> Path{ AssetPath };
ContentBrowserModule.Get().SyncBrowserToFolders(Path);
}
else
{
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
TArray<FAssetData> Assets;
AssetRegistry.GetAssetsByPackageName(FName(AssetPath), Assets);
if (Assets.Num() <= 0)
return;
ContentBrowserModule.Get().SyncBrowserToAssets(Assets);
}
}