You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
UETOOL-332 - Collections 2.0 UETOOL-373 - Check robustness of Collections 2.0 The collection manager will now fix-up any references to redirectors within its collections once the asset registry has finished discovering all the available assets. It also adds a watcher so it can pick up any moves or deletes as they happen. All of this fix-up is applied to the in-memory copy of the collection, and doesn't get persisted to disk until it needs to be (because referenced redirectors are being deleted). This helps to minimize issues with source control availability and shared/private collections. This change also makes sure that objects that are being referenced by a collection will leave a redirector behind, and also adds some extra context (such as the collection name) to some of the source control errors that may be reported when saving a collection. [CL 2602519 by Jamie Dale in Main branch]
549 lines
17 KiB
C++
549 lines
17 KiB
C++
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#include "ContentBrowserPCH.h"
|
|
#include "ContentBrowserModule.h"
|
|
#include "ObjectTools.h"
|
|
#include "WorkspaceMenuStructureModule.h"
|
|
#include "IDocumentation.h"
|
|
#include "Editor/MainFrame/Public/MainFrame.h"
|
|
#include "SAssetDialog.h"
|
|
#include "TutorialMetaData.h"
|
|
#include "SDockTab.h"
|
|
#include "NativeClassHierarchy.h"
|
|
#include "CollectionAssetRegistryBridge.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "ContentBrowser"
|
|
|
|
FContentBrowserSingleton::FContentBrowserSingleton()
|
|
: CollectionAssetRegistryBridge(MakeShareable(new FCollectionAssetRegistryBridge()))
|
|
, SettingsStringID(0)
|
|
{
|
|
// Register the tab spawners for all content browsers
|
|
const FSlateIcon ContentBrowserIcon(FEditorStyle::GetStyleSetName(), "ContentBrowser.TabIcon");
|
|
const IWorkspaceMenuStructure& MenuStructure = WorkspaceMenu::GetMenuStructure();
|
|
TSharedRef<FWorkspaceItem> ContentBrowserGroup = MenuStructure.GetToolsCategory()->AddGroup(
|
|
LOCTEXT( "WorkspaceMenu_ContentBrowserCategory", "Content Browser" ),
|
|
LOCTEXT( "ContentBrowserMenuTooltipText", "Open a Content Browser tab." ),
|
|
ContentBrowserIcon,
|
|
true);
|
|
|
|
for ( int32 BrowserIdx = 0; BrowserIdx < ARRAY_COUNT(ContentBrowserTabIDs); BrowserIdx++ )
|
|
{
|
|
const FName TabID = FName(*FString::Printf(TEXT("ContentBrowserTab%d"), BrowserIdx + 1));
|
|
ContentBrowserTabIDs[BrowserIdx] = TabID;
|
|
|
|
const FText DefaultDisplayName = GetContentBrowserLabelWithIndex( BrowserIdx );
|
|
|
|
FGlobalTabmanager::Get()->RegisterNomadTabSpawner( TabID, FOnSpawnTab::CreateRaw(this, &FContentBrowserSingleton::SpawnContentBrowserTab, BrowserIdx) )
|
|
.SetDisplayName(DefaultDisplayName)
|
|
.SetTooltipText( LOCTEXT( "ContentBrowserMenuTooltipText", "Open a Content Browser tab." ) )
|
|
.SetGroup( ContentBrowserGroup )
|
|
.SetIcon(ContentBrowserIcon);
|
|
}
|
|
|
|
// Register a couple legacy tab ids
|
|
FGlobalTabmanager::Get()->AddLegacyTabType( "LevelEditorContentBrowser", "ContentBrowserTab1" );
|
|
FGlobalTabmanager::Get()->AddLegacyTabType( "MajorContentBrowserTab", "ContentBrowserTab2" );
|
|
|
|
// Register to be notified when properties are edited
|
|
FEditorDelegates::LoadSelectedAssetsIfNeeded.AddRaw(this, &FContentBrowserSingleton::OnEditorLoadSelectedAssetsIfNeeded);
|
|
}
|
|
|
|
FContentBrowserSingleton::~FContentBrowserSingleton()
|
|
{
|
|
FEditorDelegates::LoadSelectedAssetsIfNeeded.RemoveAll(this);
|
|
|
|
if ( FSlateApplication::IsInitialized() )
|
|
{
|
|
for ( int32 BrowserIdx = 0; BrowserIdx < ARRAY_COUNT(ContentBrowserTabIDs); BrowserIdx++ )
|
|
{
|
|
FGlobalTabmanager::Get()->UnregisterNomadTabSpawner( ContentBrowserTabIDs[BrowserIdx] );
|
|
}
|
|
}
|
|
}
|
|
|
|
TSharedRef<SWidget> FContentBrowserSingleton::CreateAssetPicker(const FAssetPickerConfig& AssetPickerConfig)
|
|
{
|
|
return SNew( SAssetPicker )
|
|
.IsEnabled( FSlateApplication::Get().GetNormalExecutionAttribute() )
|
|
.AssetPickerConfig(AssetPickerConfig);
|
|
}
|
|
|
|
TSharedRef<SWidget> FContentBrowserSingleton::CreatePathPicker(const FPathPickerConfig& PathPickerConfig)
|
|
{
|
|
return SNew( SPathPicker )
|
|
.IsEnabled( FSlateApplication::Get().GetNormalExecutionAttribute() )
|
|
.PathPickerConfig(PathPickerConfig);
|
|
}
|
|
|
|
TSharedRef<class SWidget> FContentBrowserSingleton::CreateCollectionPicker(const FCollectionPickerConfig& CollectionPickerConfig)
|
|
{
|
|
return SNew( SCollectionPicker )
|
|
.IsEnabled( FSlateApplication::Get().GetNormalExecutionAttribute() )
|
|
.CollectionPickerConfig(CollectionPickerConfig);
|
|
}
|
|
|
|
void FContentBrowserSingleton::CreateOpenAssetDialog(const FOpenAssetDialogConfig& InConfig,
|
|
const FOnAssetsChosenForOpen& InOnAssetsChosenForOpen,
|
|
const FOnAssetDialogCancelled& InOnAssetDialogCancelled)
|
|
{
|
|
const bool bModal = false;
|
|
TSharedRef<SAssetDialog> AssetDialog = SNew(SAssetDialog, InConfig);
|
|
AssetDialog->SetOnAssetsChosenForOpen(InOnAssetsChosenForOpen);
|
|
AssetDialog->SetOnAssetDialogCancelled(InOnAssetDialogCancelled);
|
|
SharedCreateAssetDialogWindow(AssetDialog, InConfig, bModal);
|
|
}
|
|
|
|
TArray<FAssetData> FContentBrowserSingleton::CreateModalOpenAssetDialog(const FOpenAssetDialogConfig& InConfig)
|
|
{
|
|
struct FModalResults
|
|
{
|
|
void OnAssetsChosenForOpen(const TArray<FAssetData>& SelectedAssets)
|
|
{
|
|
SavedResults = SelectedAssets;
|
|
}
|
|
|
|
TArray<FAssetData> SavedResults;
|
|
};
|
|
|
|
FModalResults ModalWindowResults;
|
|
FOnAssetsChosenForOpen OnAssetsChosenForOpenDelegate = FOnAssetsChosenForOpen::CreateRaw(&ModalWindowResults, &FModalResults::OnAssetsChosenForOpen);
|
|
|
|
const bool bModal = true;
|
|
TSharedRef<SAssetDialog> AssetDialog = SNew(SAssetDialog, InConfig);
|
|
AssetDialog->SetOnAssetsChosenForOpen(OnAssetsChosenForOpenDelegate);
|
|
SharedCreateAssetDialogWindow(AssetDialog, InConfig, bModal);
|
|
|
|
return ModalWindowResults.SavedResults;
|
|
}
|
|
|
|
void FContentBrowserSingleton::CreateSaveAssetDialog(const FSaveAssetDialogConfig& InConfig,
|
|
const FOnObjectPathChosenForSave& InOnObjectPathChosenForSave,
|
|
const FOnAssetDialogCancelled& InOnAssetDialogCancelled)
|
|
{
|
|
const bool bModal = false;
|
|
TSharedRef<SAssetDialog> AssetDialog = SNew(SAssetDialog, InConfig);
|
|
AssetDialog->SetOnObjectPathChosenForSave(InOnObjectPathChosenForSave);
|
|
AssetDialog->SetOnAssetDialogCancelled(InOnAssetDialogCancelled);
|
|
SharedCreateAssetDialogWindow(AssetDialog, InConfig, bModal);
|
|
}
|
|
|
|
FString FContentBrowserSingleton::CreateModalSaveAssetDialog(const FSaveAssetDialogConfig& InConfig)
|
|
{
|
|
struct FModalResults
|
|
{
|
|
void OnObjectPathChosenForSave(const FString& ObjectPath)
|
|
{
|
|
SavedResult = ObjectPath;
|
|
}
|
|
|
|
FString SavedResult;
|
|
};
|
|
|
|
FModalResults ModalWindowResults;
|
|
FOnObjectPathChosenForSave OnObjectPathChosenForSaveDelegate = FOnObjectPathChosenForSave::CreateRaw(&ModalWindowResults, &FModalResults::OnObjectPathChosenForSave);
|
|
|
|
const bool bModal = true;
|
|
TSharedRef<SAssetDialog> AssetDialog = SNew(SAssetDialog, InConfig);
|
|
AssetDialog->SetOnObjectPathChosenForSave(OnObjectPathChosenForSaveDelegate);
|
|
SharedCreateAssetDialogWindow(AssetDialog, InConfig, bModal);
|
|
|
|
return ModalWindowResults.SavedResult;
|
|
}
|
|
|
|
bool FContentBrowserSingleton::HasPrimaryContentBrowser() const
|
|
{
|
|
if ( PrimaryContentBrowser.IsValid() )
|
|
{
|
|
// There is a primary content browser
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
for (int32 BrowserIdx = 0; BrowserIdx < AllContentBrowsers.Num(); ++BrowserIdx)
|
|
{
|
|
if ( AllContentBrowsers[BrowserIdx].IsValid() )
|
|
{
|
|
// There is at least one valid content browser
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// There were no valid content browsers
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void FContentBrowserSingleton::FocusPrimaryContentBrowser(bool bFocusSearch)
|
|
{
|
|
// See if the primary content browser is still valid
|
|
if ( !PrimaryContentBrowser.IsValid() )
|
|
{
|
|
ChooseNewPrimaryBrowser();
|
|
}
|
|
|
|
if ( PrimaryContentBrowser.IsValid() )
|
|
{
|
|
FocusContentBrowser( PrimaryContentBrowser.Pin() );
|
|
}
|
|
else
|
|
{
|
|
// If we couldn't find a primary content browser, open one
|
|
SummonNewBrowser();
|
|
}
|
|
|
|
// Do we also want to focus on the search box of the content browser?
|
|
if ( bFocusSearch && PrimaryContentBrowser.IsValid() )
|
|
{
|
|
PrimaryContentBrowser.Pin()->SetKeyboardFocusOnSearch();
|
|
}
|
|
}
|
|
|
|
void FContentBrowserSingleton::CreateNewAsset(const FString& DefaultAssetName, const FString& PackagePath, UClass* AssetClass, UFactory* Factory)
|
|
{
|
|
FocusPrimaryContentBrowser(false);
|
|
|
|
if ( PrimaryContentBrowser.IsValid() )
|
|
{
|
|
PrimaryContentBrowser.Pin()->CreateNewAsset(DefaultAssetName, PackagePath, AssetClass, Factory);
|
|
}
|
|
}
|
|
|
|
void FContentBrowserSingleton::SyncBrowserToAssets(const TArray<FAssetData>& AssetDataList, bool bAllowLockedBrowsers)
|
|
{
|
|
TSharedPtr<SContentBrowser> ContentBrowserToSync;
|
|
|
|
if ( !PrimaryContentBrowser.IsValid() )
|
|
{
|
|
ChooseNewPrimaryBrowser();
|
|
}
|
|
|
|
if ( PrimaryContentBrowser.IsValid() && (bAllowLockedBrowsers || !PrimaryContentBrowser.Pin()->IsLocked()) )
|
|
{
|
|
// If the primary content browser is not locked, sync it
|
|
ContentBrowserToSync = PrimaryContentBrowser.Pin();
|
|
}
|
|
else
|
|
{
|
|
// If there is no primary or it is locked, find the first non-locked valid browser
|
|
for (int32 BrowserIdx = 0; BrowserIdx < AllContentBrowsers.Num(); ++BrowserIdx)
|
|
{
|
|
if ( AllContentBrowsers[BrowserIdx].IsValid() && (bAllowLockedBrowsers || !AllContentBrowsers[BrowserIdx].Pin()->IsLocked()) )
|
|
{
|
|
ContentBrowserToSync = AllContentBrowsers[BrowserIdx].Pin();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !ContentBrowserToSync.IsValid() )
|
|
{
|
|
// There are no valid, unlocked browsers, attempt to summon a new one.
|
|
SummonNewBrowser(bAllowLockedBrowsers);
|
|
|
|
// Now try to find a non-locked valid browser again, now that a new one may exist
|
|
for (int32 BrowserIdx = 0; BrowserIdx < AllContentBrowsers.Num(); ++BrowserIdx)
|
|
{
|
|
if ( AllContentBrowsers[BrowserIdx].IsValid() && (bAllowLockedBrowsers || !AllContentBrowsers[BrowserIdx].Pin()->IsLocked()) )
|
|
{
|
|
ContentBrowserToSync = AllContentBrowsers[BrowserIdx].Pin();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ContentBrowserToSync.IsValid() )
|
|
{
|
|
// Finally, focus and sync the browser that was found
|
|
FocusContentBrowser(ContentBrowserToSync);
|
|
ContentBrowserToSync->SyncToAssets(AssetDataList);
|
|
}
|
|
else
|
|
{
|
|
UE_LOG( LogContentBrowser, Log, TEXT( "Unable to sync content browser, all browsers appear to be locked" ) );
|
|
}
|
|
}
|
|
|
|
void FContentBrowserSingleton::SyncBrowserToAssets(const TArray<UObject*>& AssetList, bool bAllowLockedBrowsers)
|
|
{
|
|
// Convert UObject* array to FAssetData array
|
|
TArray<FAssetData> AssetDataList;
|
|
for (int32 AssetIdx = 0; AssetIdx < AssetList.Num(); ++AssetIdx)
|
|
{
|
|
if ( AssetList[AssetIdx] )
|
|
{
|
|
AssetDataList.Add( FAssetData(AssetList[AssetIdx]) );
|
|
}
|
|
}
|
|
|
|
SyncBrowserToAssets(AssetDataList, bAllowLockedBrowsers);
|
|
}
|
|
|
|
void FContentBrowserSingleton::GetSelectedAssets(TArray<FAssetData>& SelectedAssets)
|
|
{
|
|
if ( PrimaryContentBrowser.IsValid() )
|
|
{
|
|
PrimaryContentBrowser.Pin()->GetSelectedAssets(SelectedAssets);
|
|
}
|
|
}
|
|
|
|
void FContentBrowserSingleton::OnEditorLoadSelectedAssetsIfNeeded()
|
|
{
|
|
if ( PrimaryContentBrowser.IsValid() )
|
|
{
|
|
PrimaryContentBrowser.Pin()->LoadSelectedObjectsIfNeeded();
|
|
}
|
|
}
|
|
|
|
FContentBrowserSingleton& FContentBrowserSingleton::Get()
|
|
{
|
|
static const FName ModuleName = "ContentBrowser";
|
|
FContentBrowserModule& Module = FModuleManager::GetModuleChecked<FContentBrowserModule>(ModuleName);
|
|
return static_cast<FContentBrowserSingleton&>(Module.Get());
|
|
}
|
|
|
|
void FContentBrowserSingleton::SetPrimaryContentBrowser(const TSharedRef<SContentBrowser>& NewPrimaryBrowser)
|
|
{
|
|
if ( PrimaryContentBrowser.IsValid() && PrimaryContentBrowser.Pin().ToSharedRef() == NewPrimaryBrowser )
|
|
{
|
|
// This is already the primary content browser
|
|
return;
|
|
}
|
|
|
|
if ( PrimaryContentBrowser.IsValid() )
|
|
{
|
|
PrimaryContentBrowser.Pin()->SetIsPrimaryContentBrowser(false);
|
|
}
|
|
|
|
PrimaryContentBrowser = NewPrimaryBrowser;
|
|
NewPrimaryBrowser->SetIsPrimaryContentBrowser(true);
|
|
}
|
|
|
|
void FContentBrowserSingleton::ContentBrowserClosed(const TSharedRef<SContentBrowser>& ClosedBrowser)
|
|
{
|
|
// Find the browser in the all browsers list
|
|
for (int32 BrowserIdx = AllContentBrowsers.Num() - 1; BrowserIdx >= 0; --BrowserIdx)
|
|
{
|
|
if ( !AllContentBrowsers[BrowserIdx].IsValid() || AllContentBrowsers[BrowserIdx].Pin() == ClosedBrowser )
|
|
{
|
|
AllContentBrowsers.RemoveAt(BrowserIdx);
|
|
}
|
|
}
|
|
|
|
if ( !PrimaryContentBrowser.IsValid() || ClosedBrowser == PrimaryContentBrowser.Pin() )
|
|
{
|
|
ChooseNewPrimaryBrowser();
|
|
}
|
|
|
|
BrowserToLastKnownTabManagerMap.Add(ClosedBrowser->GetInstanceName(), ClosedBrowser->GetTabManager());
|
|
}
|
|
|
|
TSharedRef<FNativeClassHierarchy> FContentBrowserSingleton::GetNativeClassHierarchy()
|
|
{
|
|
if(!NativeClassHierarchy.IsValid())
|
|
{
|
|
NativeClassHierarchy = MakeShareable(new FNativeClassHierarchy());
|
|
}
|
|
return NativeClassHierarchy.ToSharedRef();
|
|
}
|
|
|
|
void FContentBrowserSingleton::SharedCreateAssetDialogWindow(const TSharedRef<SAssetDialog>& AssetDialog, const FSharedAssetDialogConfig& InConfig, bool bModal) const
|
|
{
|
|
const FVector2D DefaultWindowSize(1152.0f, 648.0f);
|
|
const FVector2D WindowSize = InConfig.WindowSizeOverride.IsZero() ? DefaultWindowSize : InConfig.WindowSizeOverride;
|
|
const FText WindowTitle = InConfig.DialogTitleOverride.IsEmpty() ? LOCTEXT("GenericAssetDialogWindowHeader", "Asset Dialog") : InConfig.DialogTitleOverride;
|
|
|
|
TSharedRef<SWindow> DialogWindow =
|
|
SNew(SWindow)
|
|
.Title(WindowTitle)
|
|
.ClientSize(WindowSize);
|
|
|
|
DialogWindow->SetContent(AssetDialog);
|
|
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame"));
|
|
const TSharedPtr<SWindow>& MainFrameParentWindow = MainFrameModule.GetParentWindow();
|
|
if (MainFrameParentWindow.IsValid())
|
|
{
|
|
if (bModal)
|
|
{
|
|
FSlateApplication::Get().AddModalWindow(DialogWindow, MainFrameParentWindow.ToSharedRef());
|
|
}
|
|
else if (FGlobalTabmanager::Get()->GetRootWindow().IsValid())
|
|
{
|
|
FSlateApplication::Get().AddWindowAsNativeChild(DialogWindow, MainFrameParentWindow.ToSharedRef());
|
|
}
|
|
else
|
|
{
|
|
FSlateApplication::Get().AddWindow(DialogWindow);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ensureMsgf(!bModal, TEXT("Could not create asset dialog because modal windows must have a parent and this was called at a time where the mainframe window does not exist.")))
|
|
{
|
|
FSlateApplication::Get().AddWindow(DialogWindow);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FContentBrowserSingleton::ChooseNewPrimaryBrowser()
|
|
{
|
|
// Find the first valid browser and trim any invalid browsers along the way
|
|
for (int32 BrowserIdx = 0; BrowserIdx < AllContentBrowsers.Num(); ++BrowserIdx)
|
|
{
|
|
if ( AllContentBrowsers[BrowserIdx].IsValid() )
|
|
{
|
|
SetPrimaryContentBrowser(AllContentBrowsers[BrowserIdx].Pin().ToSharedRef());
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Trim any invalid content browsers
|
|
AllContentBrowsers.RemoveAt(BrowserIdx);
|
|
BrowserIdx--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void FContentBrowserSingleton::FocusContentBrowser(const TSharedPtr<SContentBrowser>& BrowserToFocus)
|
|
{
|
|
if ( BrowserToFocus.IsValid() )
|
|
{
|
|
TSharedRef<SContentBrowser> Browser = BrowserToFocus.ToSharedRef();
|
|
TSharedPtr<FTabManager> TabManager = Browser->GetTabManager();
|
|
if ( TabManager.IsValid() )
|
|
{
|
|
TabManager->InvokeTab(Browser->GetInstanceName());
|
|
}
|
|
}
|
|
}
|
|
|
|
void FContentBrowserSingleton::SummonNewBrowser(bool bAllowLockedBrowsers)
|
|
{
|
|
TSet<FName> OpenBrowserIDs;
|
|
|
|
// Find all currently open browsers to help find the first open slot
|
|
for (int32 BrowserIdx = AllContentBrowsers.Num() - 1; BrowserIdx >= 0; --BrowserIdx)
|
|
{
|
|
const TWeakPtr<SContentBrowser>& Browser = AllContentBrowsers[BrowserIdx];
|
|
if ( Browser.IsValid() )
|
|
{
|
|
OpenBrowserIDs.Add(Browser.Pin()->GetInstanceName());
|
|
}
|
|
}
|
|
|
|
FName NewTabName;
|
|
for ( int32 BrowserIdx = 0; BrowserIdx < ARRAY_COUNT(ContentBrowserTabIDs); BrowserIdx++ )
|
|
{
|
|
FName TestTabID = ContentBrowserTabIDs[BrowserIdx];
|
|
if ( !OpenBrowserIDs.Contains(TestTabID) && (bAllowLockedBrowsers || !IsLocked(TestTabID)) )
|
|
{
|
|
// Found the first index that is not currently open
|
|
NewTabName = TestTabID;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( NewTabName != NAME_None )
|
|
{
|
|
const TWeakPtr<FTabManager>& TabManagerToInvoke = BrowserToLastKnownTabManagerMap.FindRef(NewTabName);
|
|
if ( TabManagerToInvoke.IsValid() )
|
|
{
|
|
TabManagerToInvoke.Pin()->InvokeTab(NewTabName);
|
|
}
|
|
else
|
|
{
|
|
FGlobalTabmanager::Get()->InvokeTab(NewTabName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No available slots... don't summon anything
|
|
}
|
|
}
|
|
|
|
TSharedRef<SDockTab> FContentBrowserSingleton::SpawnContentBrowserTab( const FSpawnTabArgs& SpawnTabArgs, int32 BrowserIdx )
|
|
{
|
|
TAttribute<FText> Label = TAttribute<FText>::Create( TAttribute<FText>::FGetter::CreateRaw( this, &FContentBrowserSingleton::GetContentBrowserTabLabel, BrowserIdx ) );
|
|
|
|
TSharedRef<SDockTab> NewTab = SNew(SDockTab)
|
|
.TabRole(ETabRole::NomadTab)
|
|
.Label( Label )
|
|
.ToolTip( IDocumentation::Get()->CreateToolTip( Label, nullptr, "Shared/ContentBrowser", "Tab" ) );
|
|
|
|
TSharedRef<SContentBrowser> NewBrowser =
|
|
SNew( SContentBrowser, SpawnTabArgs.GetTabId().TabType )
|
|
.IsEnabled( FSlateApplication::Get().GetNormalExecutionAttribute() )
|
|
.ContainingTab( NewTab );
|
|
|
|
AllContentBrowsers.Add(NewBrowser);
|
|
|
|
if ( !PrimaryContentBrowser.IsValid() )
|
|
{
|
|
ChooseNewPrimaryBrowser();
|
|
}
|
|
|
|
// Add wrapper for tutorial highlighting
|
|
TSharedRef<SBox> Wrapper =
|
|
SNew(SBox)
|
|
.AddMetaData<FTutorialMetaData>(FTutorialMetaData(TEXT("ContentBrowser"), TEXT("ContentBrowserTab1")))
|
|
[
|
|
NewBrowser
|
|
];
|
|
|
|
NewTab->SetContent( Wrapper );
|
|
|
|
return NewTab;
|
|
}
|
|
|
|
bool FContentBrowserSingleton::IsLocked(const FName& InstanceName) const
|
|
{
|
|
// First try all the open browsers, as their locked state might be newer than the configs
|
|
for (int32 AllBrowsersIdx = AllContentBrowsers.Num() - 1; AllBrowsersIdx >= 0; --AllBrowsersIdx)
|
|
{
|
|
const TWeakPtr<SContentBrowser>& Browser = AllContentBrowsers[AllBrowsersIdx];
|
|
if ( Browser.IsValid() && Browser.Pin()->GetInstanceName() == InstanceName )
|
|
{
|
|
return Browser.Pin()->IsLocked();
|
|
}
|
|
}
|
|
|
|
// Fallback to getting the locked state from the config instead
|
|
bool bIsLocked = false;
|
|
GConfig->GetBool(*SContentBrowser::SettingsIniSection, *(InstanceName.ToString() + TEXT(".Locked")), bIsLocked, GEditorPerProjectIni);
|
|
return bIsLocked;
|
|
}
|
|
|
|
FText FContentBrowserSingleton::GetContentBrowserLabelWithIndex( int32 BrowserIdx )
|
|
{
|
|
return FText::Format(LOCTEXT("ContentBrowserTabNameWithIndex", "Content Browser {0}"), FText::AsNumber(BrowserIdx + 1));
|
|
}
|
|
|
|
FText FContentBrowserSingleton::GetContentBrowserTabLabel(int32 BrowserIdx)
|
|
{
|
|
int32 NumOpenContentBrowsers = 0;
|
|
for (int32 AllBrowsersIdx = AllContentBrowsers.Num() - 1; AllBrowsersIdx >= 0; --AllBrowsersIdx)
|
|
{
|
|
const TWeakPtr<SContentBrowser>& Browser = AllContentBrowsers[AllBrowsersIdx];
|
|
if ( Browser.IsValid() )
|
|
{
|
|
NumOpenContentBrowsers++;
|
|
}
|
|
else
|
|
{
|
|
AllContentBrowsers.RemoveAt(AllBrowsersIdx);
|
|
}
|
|
}
|
|
|
|
if ( NumOpenContentBrowsers > 1 )
|
|
{
|
|
return GetContentBrowserLabelWithIndex( BrowserIdx );
|
|
}
|
|
else
|
|
{
|
|
return LOCTEXT("ContentBrowserTabName", "Content Browser");
|
|
}
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE |