SExtPathView.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. // Copyright 2017-2021 marynate. All Rights Reserved.
  2. #pragma once
  3. #include "IExtContentBrowserSingleton.h"
  4. #include "ExtAssetViewTypes.h"
  5. #include "ExtAssetData.h"
  6. #include "CoreMinimal.h"
  7. #include "SlateFwd.h"
  8. #include "Widgets/DeclarativeSyntaxSupport.h"
  9. #include "Input/Reply.h"
  10. #include "Widgets/SCompoundWidget.h"
  11. #include "AssetRegistry/AssetData.h"
  12. #include "Widgets/Views/STableViewBase.h"
  13. #include "Widgets/Views/STableRow.h"
  14. #include "Widgets/Views/STreeView.h"
  15. #include "Misc/TextFilter.h"
  16. #include "Delegates/DelegateCombinations.h"
  17. struct FHistoryData;
  18. struct FTreeItem;
  19. typedef TTextFilter< const FString& > FolderTextFilter;
  20. DECLARE_DELEGATE_OneParam(FOnAssetTreeSearchBoxChanged, const FText& /*SearchText*/);
  21. DECLARE_DELEGATE_TwoParams(FOnAssetTreeSearchBoxCommitted, const FText& /*InSearchText*/, ETextCommit::Type /*InCommitType*/);
  22. /**
  23. * The tree view of folders which contain content.
  24. */
  25. class SExtPathView : public SCompoundWidget
  26. {
  27. public:
  28. SLATE_BEGIN_ARGS( SExtPathView )
  29. : _FocusSearchBoxWhenOpened(true)
  30. , _ShowTreeTitle(false)
  31. , _SearchBarVisibility(EVisibility::Visible)
  32. , _ShowSeparator(true)
  33. , _AllowContextMenu(true)
  34. , _AllowClassesFolder(false)
  35. , _SelectionMode( ESelectionMode::Multi )
  36. {}
  37. /** Content displayed to the left of the search bar */
  38. SLATE_NAMED_SLOT( FArguments, SearchContent )
  39. /** Called when a tree paths was selected */
  40. SLATE_EVENT( FOnPathSelected, OnPathSelected )
  41. /** Called when a context menu is opening on a folder */
  42. SLATE_EVENT( FOnGetFolderContextMenu, OnGetFolderContextMenu )
  43. /** Called a context menu is opening on a path */
  44. SLATE_EVENT( FContentBrowserMenuExtender_SelectedPaths, OnGetPathContextMenuExtender )
  45. /** If true, the search box will be focus the frame after construction */
  46. SLATE_ARGUMENT( bool, FocusSearchBoxWhenOpened )
  47. /** If true, The tree title will be displayed */
  48. SLATE_ARGUMENT( bool, ShowTreeTitle )
  49. /** If EVisibility::Visible, The tree search bar will be displayed */
  50. SLATE_ATTRIBUTE( EVisibility, SearchBarVisibility )
  51. /** If true, The tree search bar separator be displayed */
  52. SLATE_ARGUMENT( bool, ShowSeparator )
  53. /** If false, the context menu will be suppressed */
  54. SLATE_ARGUMENT( bool, AllowContextMenu )
  55. /** If false, the classes folder will be suppressed */
  56. SLATE_ARGUMENT( bool, AllowClassesFolder )
  57. /** The selection mode for the tree view */
  58. SLATE_ARGUMENT( ESelectionMode::Type, SelectionMode )
  59. SLATE_END_ARGS()
  60. /** Destructor */
  61. ~SExtPathView();
  62. /** Constructs this widget with InArgs */
  63. virtual void Construct( const FArguments& InArgs );
  64. /** Tick path view */
  65. virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;
  66. /** Selects the closest matches to the supplied paths in the tree. "/" delimited */
  67. virtual void SetSelectedPaths(const TArray<FString>& Paths);
  68. /** Clears selection of all paths */
  69. void ClearSelection();
  70. /** Returns the number of selected paths */
  71. int32 GetNumPathsSelected() const;
  72. /** Returns the first selected path in the tree view */
  73. FString GetSelectedPath() const;
  74. /** Returns all selected paths in the tree view */
  75. TArray<FString> GetSelectedPaths() const;
  76. /** Adds nodes to the tree in order to construct the specified path. If bUserNamed is true, the user will name the folder and Path includes the default name. */
  77. virtual TSharedPtr<FTreeItem> AddPath(const FString& Path, const FString* RootPathPtr = nullptr, bool bUserNamed = false);
  78. /** Attempts to removed the folder at the end of the specified path from the tree. Returns true when successful. */
  79. bool RemovePath(const FString& Path);
  80. /** Sets up an inline rename for the specified folder */
  81. void RenameFolder(const FString& FolderToRename);
  82. /**
  83. * Selects the paths containing the specified assets.
  84. *
  85. * @param AssetDataList - A list of assets to sync the view to
  86. *
  87. * @param bAllowImplicitSync - true to allow the view to sync to parent folders if they are already selected,
  88. * false to force the view to select the explicit Parent folders of each asset
  89. */
  90. void SyncToAssets( const TArray<FExtAssetData>& AssetDataList, const bool bAllowImplicitSync = false );
  91. /**
  92. * Selects the given paths.
  93. *
  94. * @param FolderList - A list of folders to sync the view to
  95. *
  96. * @param bAllowImplicitSync - true to allow the view to sync to parent folders if they are already selected,
  97. * false to force the view to select the explicit Parent folders of each asset
  98. */
  99. void SyncToFolders( const TArray<FString>& FolderList, const bool bAllowImplicitSync = false );
  100. /**
  101. * Selects the given items.
  102. *
  103. * @param ItemSelection - A list of assets and folders to sync the view to
  104. *
  105. * @param bAllowImplicitSync - true to allow the view to sync to parent folders if they are already selected,
  106. * false to force the view to select the explicit Parent folders of each asset
  107. */
  108. void SyncTo( const FExtContentBrowserSelection& ItemSelection, const bool bAllowImplicitSync = false );
  109. /** Finds the item that represents the specified path, if it exists. */
  110. TSharedPtr<FTreeItem> FindItemRecursive(const FString& Path) const;
  111. /** Sets the state of the path view to the one described by the history data */
  112. void ApplyHistoryData( const FHistoryData& History );
  113. /** Saves any settings to config that should be persistent between editor sessions */
  114. virtual void SaveSettings(const FString& IniFilename, const FString& IniSection, const FString& SettingsString) const;
  115. /** Loads any settings to config that should be persistent between editor sessions */
  116. virtual void LoadSettings(const FString& IniFilename, const FString& IniSection, const FString& SettingsString);
  117. /** Populates the tree with all folders that are not filtered out */
  118. virtual void Populate();
  119. /** Sets an alternate tree title*/
  120. void SetTreeTitle(FText InTitle)
  121. {
  122. TreeTitle = InTitle;
  123. };
  124. FText GetTreeTitle() const;
  125. EVisibility GetTreeTitleVisibility() const;
  126. FText GetPluginVersionText() const
  127. {
  128. return PluginVersionText;
  129. }
  130. /** Handler for when search terms change in the asset tree search box */
  131. virtual void OnAssetTreeSearchBoxChanged(const FText& InSearchText);
  132. /** Handler for when search term is committed in the asset tree search box */
  133. virtual void OnAssetTreeSearchBoxCommitted(const FText& InSearchText, ETextCommit::Type InCommitType);
  134. #if ECB_LEGACY
  135. public:
  136. /** Delegate that handles if any folder paths changed as a result of a move, rename, etc. in the path view*/
  137. FOnFolderPathChanged OnFolderPathChanged;
  138. #endif
  139. protected:
  140. /** Expands all parents of the specified item */
  141. void RecursiveExpandParents(const TSharedPtr<FTreeItem>& Item);
  142. /** Sort the root items into the correct order */
  143. void SortRootItems();
  144. /** Handles updating the content browser when an asset path is added to the asset registry */
  145. virtual void OnAssetRegistryPathAdded(const FString& Path);
  146. /** Handles updating the content browser when an asset path is removed from the asset registry */
  147. virtual void OnAssetRegistryPathRemoved(const FString& Path);
  148. /** Handles updating the content browser when a root content path is added to the asset registry */
  149. virtual void OnAssetRegistryRootPathAdded(const FString& Path);
  150. /** Handles updating the content browser when a root content path is removed from the asset registry */
  151. virtual void OnAssetRegistryRootPathRemoved(const FString& Path);
  152. /** Handles updating the content browser when root content path list been updated in the asset registry */
  153. virtual void OnAssetRegistryRootPathUpdated();
  154. /** Handles updating the content browser when folders is start rescanning from the asset registry */
  155. virtual void OnAssetRegistryFolderStartGathering(const TArray<FString>& Paths);
  156. /** Handles updating the content browser when folders is finishing rescanning from the asset registry */
  157. virtual void OnAssetRegistryFolderFinishGathering(const FString& InPath, const FString& InRootPath);
  158. /** Creates a list item for the tree view */
  159. virtual TSharedRef<ITableRow> GenerateTreeRow(TSharedPtr<FTreeItem> TreeItem, const TSharedRef<STableViewBase>& OwnerTable);
  160. /** Handles focusing a folder widget after it has been created with the intent to rename */
  161. void TreeItemScrolledIntoView(TSharedPtr<FTreeItem> TreeItem, const TSharedPtr<ITableRow>& Widget);
  162. /** Handler for tree view selection changes */
  163. void TreeSelectionChanged(TSharedPtr< FTreeItem > TreeItem, ESelectInfo::Type SelectInfo);
  164. /** Gets the content for a context menu */
  165. TSharedPtr<SWidget> MakePathViewContextMenu();
  166. /** Handler for returning a list of children associated with a particular tree node */
  167. void GetChildrenForTree(TSharedPtr< FTreeItem > TreeItem, TArray< TSharedPtr<FTreeItem> >& OutChildren);
  168. /** Gets the string to highlight in tree items (used in folder searching) */
  169. FText GetHighlightText() const;
  170. /** True if the specified item is selected in the asset tree */
  171. bool IsTreeItemSelected(TSharedPtr<FTreeItem> TreeItem) const;
  172. /** Handler for tree view folders are dragged */
  173. FReply OnFolderDragDetected(const FGeometry& Geometry, const FPointerEvent& MouseEvent);
  174. /** Handler for when assets or asset paths are dropped on a tree item */
  175. virtual void TreeAssetsOrPathsDropped(const TArray<FAssetData>& AssetList, const TArray<FString>& AssetPaths, const TSharedPtr<FTreeItem>& TreeItem);
  176. /** Handler for when asset paths are dropped on a tree item */
  177. void TreeFilesDropped(const TArray<FString>& FileNames, const TSharedPtr<FTreeItem>& TreeItem);
  178. /** Handler for the user selecting to move assets or asset paths to the specified folder */
  179. virtual void ExecuteTreeDropMove(TArray<FAssetData> AssetList, TArray<FString> AssetPaths, FString DestinationPath);
  180. /** Get relative path to one of the root paths, assume root paths are sorted */
  181. void GetPathItemList(const FString& InPath, const TArray<FString>& InRootPaths, TArray<FString>& OutPathItemList, bool bIncludeRootPath) const;
  182. private:
  183. /** Internal sync implementation, syncs to the tree to the given array of items */
  184. void SyncToInternal( const TArray<FExtAssetData>& AssetDataList, const TArray<FString>& FolderPaths, const bool bAllowImplicitSync );
  185. /** Called when "new folder" is selected in the context menu */
  186. void OnCreateNewFolder(const FString& FolderName, const FString& FolderPath);
  187. /** Selects the given path only if it exists. Returns true if selected. */
  188. bool ExplicitlyAddPathToSelection(const FString& Path);
  189. /** Returns true if the selection changed delegate should be allowed */
  190. bool ShouldAllowTreeItemChangedDelegate() const;
  191. /** Adds a new root folder */
  192. TSharedPtr<FTreeItem> AddRootItem( const FString& InFolderName );
  193. /** Handler for recursively expanding/collapsing items in the tree view */
  194. void SetTreeItemExpansionRecursive( TSharedPtr< FTreeItem > TreeItem, bool bInExpansionState );
  195. /** Handler for tree view expansion changes */
  196. void TreeExpansionChanged( TSharedPtr< FTreeItem > TreeItem, bool bIsExpanded );
  197. /** Handler for when the search box filter has changed */
  198. void FilterUpdated();
  199. /** Populates OutSearchStrings with the strings that should be used in searching */
  200. void PopulateFolderSearchStrings( const FString& FolderName, OUT TArray< FString >& OutSearchStrings ) const;
  201. /** Returns true if the supplied folder item already exists in the tree. If so, ExistingItem will be set to the found item. */
  202. bool FolderAlreadyExists(const TSharedPtr< FTreeItem >& TreeItem, TSharedPtr< FTreeItem >& ExistingItem);
  203. /** Removes the supplied folder from the tree. */
  204. void RemoveFolderItem(const TSharedPtr< FTreeItem >& TreeItem);
  205. /** True if the specified item is expanded in the asset tree */
  206. bool IsTreeItemExpanded(TSharedPtr<FTreeItem> TreeItem) const;
  207. /** Gets all the UObjects represented by assets in the AssetList */
  208. void GetDroppedObjects(const TArray<FAssetData>& AssetList, TArray<UObject*>& OutDroppedObjects);
  209. /** Handler for the user selecting to copy assets or asset paths to the specified folder */
  210. void ExecuteTreeDropCopy(TArray<FAssetData> AssetList, TArray<FString> AssetPaths, FString DestinationPath);
  211. /** Handler for the user selecting to copy assets or asset paths - and dependencies - to the specified folder */
  212. void ExecuteTreeDropAdvancedCopy(TArray<FAssetData> AssetList, TArray<FString> AssetPaths, FString DestinationPath);
  213. /** Notification for when the Asset Registry has completed it's initial search */
  214. void OnAssetRegistrySearchCompleted();
  215. /** Handles updating the content browser when a path is populated with an asset for the first time */
  216. void OnFolderPopulated(const FString& Path);
  217. /** Called from an engine core event when a new content path has been added or removed, so that we can refresh our root set of paths */
  218. void OnContentPathMountedOrDismounted( const FString& AssetPath, const FString& FileSystemPath );
  219. /** Called when the class hierarchy is updated due to the available modules changing */
  220. void OnClassHierarchyUpdated();
  221. /** Delegate called when an editor setting is changed */
  222. void HandleSettingChanged(FName PropertyName);
  223. /** One-off active timer to focus the widget post-construct */
  224. EActiveTimerReturnType SetFocusPostConstruct(double InCurrentTime, float InDeltaTime);
  225. /** One-off active timer to repopulate the path view */
  226. EActiveTimerReturnType TriggerRepopulate(double InCurrentTime, float InDeltaTime);
  227. protected:
  228. /** A helper class to manage PreventTreeItemChangedDelegateCount by incrementing it when constructed (on the stack) and decrementing when destroyed */
  229. class FScopedPreventTreeItemChangedDelegate
  230. {
  231. public:
  232. FScopedPreventTreeItemChangedDelegate(const TSharedRef<SExtPathView>& InPathView)
  233. : PathView(InPathView)
  234. {
  235. PathView->PreventTreeItemChangedDelegateCount++;
  236. }
  237. ~FScopedPreventTreeItemChangedDelegate()
  238. {
  239. check(PathView->PreventTreeItemChangedDelegateCount > 0);
  240. PathView->PreventTreeItemChangedDelegateCount--;
  241. }
  242. private:
  243. TSharedRef<SExtPathView> PathView;
  244. };
  245. /** The tree view widget */
  246. TSharedPtr< STreeView< TSharedPtr<FTreeItem>> > TreeViewPtr;
  247. /** The asset tree search box */
  248. TSharedPtr< SSearchBox > SearchBoxPtr;
  249. /** The list of folders in the tree */
  250. TArray< TSharedPtr<FTreeItem> > TreeRootItems;
  251. /** The The TextFilter attached to the SearchBox widget */
  252. TSharedPtr< FolderTextFilter > SearchBoxFolderFilter;
  253. /** The paths that were last reported by OnPathSelected event. Used in preserving selection when filtering folders */
  254. TSet< FString > LastSelectedPaths;
  255. /** If not empty, this is the path of the folders to sync once they are available while assets are still being discovered */
  256. TArray<FString> PendingInitialPaths;
  257. TSharedPtr<SWidget> PathViewWidget;
  258. private:
  259. /** The paths that were last reported by OnPathExpanded event. Used in preserving expansion when filtering folders */
  260. TSet< FString > LastExpandedPaths;
  261. /** Delegate to invoke when selection changes. */
  262. FOnPathSelected OnPathSelected;
  263. /** Delegate to invoke when generating the context menu for a folder */
  264. FOnGetFolderContextMenu OnGetFolderContextMenu;
  265. /** Delegate to invoke when a context menu for a folder is opening. */
  266. FContentBrowserMenuExtender_SelectedPaths OnGetPathContextMenuExtender;
  267. /** If > 0, the selection or expansion changed delegate will not be called. Used to update the tree from an external source or in certain bulk operations. */
  268. int32 PreventTreeItemChangedDelegateCount;
  269. /** If false, the context menu will not open when right clicking an item in the tree */
  270. bool bAllowContextMenu;
  271. /** If false, the classes folder will not be added to the tree automatically */
  272. bool bAllowClassesFolder;
  273. /** The title of this path view */
  274. FText TreeTitle;
  275. /** The plugin version text */
  276. FText PluginVersionText;
  277. };
  278. /**
  279. * The tree view of folders which contain favorited folders.
  280. */
  281. class SFavoritePathView : public SExtPathView
  282. {
  283. public:
  284. /** Constructs this widget with InArgs */
  285. virtual void Construct(const FArguments& InArgs) override;
  286. virtual void Populate() override;
  287. /** Saves any settings to config that should be persistent between editor sessions */
  288. virtual void SaveSettings(const FString& IniFilename, const FString& IniSection, const FString& SettingsString) const override;
  289. /** Loads any settings to config that should be persistent between editor sessions */
  290. virtual void LoadSettings(const FString& IniFilename, const FString& IniSection, const FString& SettingsString) override;
  291. /** Handler for when search terms change in the asset tree search box */
  292. virtual void OnAssetTreeSearchBoxChanged(const FText& InSearchText) override;
  293. /** Handler for when search term is committed in the asset tree search box */
  294. virtual void OnAssetTreeSearchBoxCommitted(const FText& InSearchText, ETextCommit::Type InCommitType) override;
  295. /** Selects the closest matches to the supplied paths in the tree. "/" delimited */
  296. virtual void SetSelectedPaths(const TArray<FString>& Paths) override;
  297. FOnAssetTreeSearchBoxChanged OnFavoriteSearchChanged;
  298. FOnAssetTreeSearchBoxCommitted OnFavoriteSearchCommitted;
  299. /** Adds nodes to the tree in order to construct the specified path. If bUserNamed is true, the user will name the folder and Path includes the default name. */
  300. virtual TSharedPtr<FTreeItem> AddPath(const FString& Path, const FString* RootPathPtr = nullptr, bool bUserNamed = false) override;
  301. private:
  302. virtual TSharedRef<ITableRow> GenerateTreeRow(TSharedPtr<FTreeItem> TreeItem, const TSharedRef<STableViewBase>& OwnerTable) override;
  303. /** Handles updating the content browser when an asset path is added to the asset registry */
  304. virtual void OnAssetRegistryPathAdded(const FString& Path) override;
  305. /** Handles updating the content browser when an asset path is removed from the asset registry */
  306. virtual void OnAssetRegistryPathRemoved(const FString& Path) override;
  307. virtual void ExecuteTreeDropMove(TArray<FAssetData> AssetList, TArray<FString> AssetPaths, FString DestinationPath) override;
  308. private:
  309. TArray<FString> RemovedByFolderMove;
  310. };