33// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
44
55using System . IO ;
6- using System . Linq ;
76using System . Collections . Generic ;
87using UnityEditor . IMGUI . Controls ;
98using UnityEngine ;
@@ -199,9 +198,10 @@ override protected void RenameEnded()
199198 //------------------------------------------------
200199 // DataSource section
201200
202- internal class ProjectBrowserColumnOneTreeViewDataSource : TreeViewDataSource
201+ internal class ProjectBrowserColumnOneTreeViewDataSource : LazyTreeViewDataSource
203202 {
204203 static string kProjectBrowserString = "ProjectBrowser" ;
204+ static Texture2D s_FolderIcon = EditorGUIUtility . FindTexture ( EditorResources . folderIconName ) ;
205205
206206 public bool skipHiddenPackages { get ; set ; }
207207
@@ -213,25 +213,6 @@ public ProjectBrowserColumnOneTreeViewDataSource(TreeViewController treeView, bo
213213 SavedSearchFilters . AddChangeListener ( ReloadData ) ; // We reload on change
214214 }
215215
216- public override bool SetExpanded ( int id , bool expand )
217- {
218- if ( base . SetExpanded ( id , expand ) )
219- {
220- // Persist expanded state for ProjectBrowsers
221- InternalEditorUtility . expandedProjectWindowItems = expandedIDs . ToArray ( ) ;
222-
223- if ( m_RootItem . hasChildren )
224- {
225- // Set global expanded state of roots (Assets folder and Favorites root)
226- foreach ( TreeViewItem item in m_RootItem . children )
227- if ( item . id == id )
228- EditorPrefs . SetBool ( kProjectBrowserString + item . displayName , expand ) ;
229- }
230- return true ;
231- }
232- return false ;
233- }
234-
235216 public override bool IsExpandable ( TreeViewItem item )
236217 {
237218 return item . hasChildren && ( item != m_RootItem || rootIsCollapsable ) ;
@@ -272,88 +253,189 @@ public override bool IsRenamingItemAllowed(TreeViewItem item)
272253
273254 public override void FetchData ( )
274255 {
256+ bool firstInitialize = ! isInitialized ;
275257 m_RootItem = new TreeViewItem ( 0 , 0 , null , "Invisible Root Item" ) ;
276258 SetExpanded ( m_RootItem , true ) ; // ensure always visible
277259
278- Texture2D folderIcon = EditorGUIUtility . FindTexture ( EditorResources . folderIconName ) ;
279-
280- // We want three roots: Favorites, Assets, and Saved Filters
260+ // We want three roots: Favorites, Assets, and Packages
281261 List < TreeViewItem > visibleRoots = new List < TreeViewItem > ( ) ;
282262
283- // Fetch asset folders
263+ // Favorites root
264+ TreeViewItem savedFiltersRootItem = SavedSearchFilters . ConvertToTreeView ( ) ;
265+ visibleRoots . Add ( savedFiltersRootItem ) ;
266+
267+ // Assets root
284268 int assetsFolderInstanceID = AssetDatabase . GetMainAssetOrInProgressProxyInstanceID ( "Assets" ) ;
285269 int depth = 0 ;
286- string displayName = "Assets" ; //CreateDisplayName (assetsFolderInstanceID);
270+ string displayName = "Assets" ;
287271 AssetsTreeViewDataSource . RootTreeItem assetRootItem = new AssetsTreeViewDataSource . RootTreeItem ( assetsFolderInstanceID , depth , m_RootItem , displayName ) ;
288- assetRootItem . icon = folderIcon ;
289- ReadAssetDatabase ( "Assets" , assetRootItem , depth + 1 ) ;
272+ assetRootItem . icon = s_FolderIcon ;
273+ visibleRoots . Add ( assetRootItem ) ;
290274
291- // Fetch packages folder
275+ // Packages root
292276 displayName = PackageManager . Folders . GetPackagesPath ( ) ;
293277 AssetsTreeViewDataSource . RootTreeItem packagesRootItem = new AssetsTreeViewDataSource . RootTreeItem ( ProjectBrowser . kPackagesFolderInstanceId , depth , m_RootItem , displayName ) ;
294- depth ++ ;
278+ packagesRootItem . icon = s_FolderIcon ;
279+ visibleRoots . Add ( packagesRootItem ) ;
295280
296- packagesRootItem . icon = folderIcon ;
281+ m_RootItem . children = visibleRoots ;
297282
298- var packages = PackageManagerUtilityInternal . GetAllVisiblePackages ( skipHiddenPackages ) ;
299- foreach ( var package in packages )
283+ // Set global expanded state for roots from EditorPrefs (must be before building the rows)
284+ if ( firstInitialize )
300285 {
301- var packageFolderInstanceId = AssetDatabase . GetMainAssetOrInProgressProxyInstanceID ( package . assetPath ) ;
302-
303- displayName = ! string . IsNullOrEmpty ( package . displayName ) ? package . displayName : package . name ;
304- AssetsTreeViewDataSource . PackageTreeItem packageItem = new AssetsTreeViewDataSource . PackageTreeItem ( packageFolderInstanceId , depth , packagesRootItem , displayName ) ;
305- packageItem . icon = folderIcon ;
306- packagesRootItem . AddChild ( packageItem ) ;
307- ReadAssetDatabase ( package . assetPath , packageItem , depth + 1 ) ;
286+ foreach ( TreeViewItem item in m_RootItem . children )
287+ {
288+ // Do not expand Packages root item
289+ if ( item . id == ProjectBrowser . kPackagesFolderInstanceId )
290+ continue ;
291+ bool expanded = EditorPrefs . GetBool ( kProjectBrowserString + item . displayName , true ) ;
292+ SetExpanded ( item , expanded ) ;
293+ }
308294 }
309295
310- // Fetch saved filters
311- TreeViewItem savedFiltersRootItem = SavedSearchFilters . ConvertToTreeView ( ) ;
312- savedFiltersRootItem . parent = m_RootItem ;
296+ // Build rows
297+ //-----------
298+ m_Rows = new List < TreeViewItem > ( 100 ) ;
313299
314- // Order
315- visibleRoots . Add ( savedFiltersRootItem ) ;
316- visibleRoots . Add ( assetRootItem ) ;
317- visibleRoots . Add ( packagesRootItem ) ;
300+ // Favorites
301+ savedFiltersRootItem . parent = m_RootItem ;
302+ m_Rows . Add ( savedFiltersRootItem ) ;
303+ if ( IsExpanded ( savedFiltersRootItem ) )
304+ {
305+ foreach ( var f in savedFiltersRootItem . children )
306+ m_Rows . Add ( f ) ;
307+ }
308+ else
309+ {
310+ savedFiltersRootItem . children = CreateChildListForCollapsedParent ( ) ;
311+ }
318312
319- m_RootItem . children = visibleRoots ;
313+ // Asset folders
314+ m_Rows . Add ( assetRootItem ) ;
315+ ReadAssetDatabase ( "Assets" , assetRootItem , depth + 1 , m_Rows ) ;
320316
321- // Get global expanded state of roots
322- foreach ( TreeViewItem item in m_RootItem . children )
317+ // Individual Package folders (under the Packages root item)
318+ m_Rows . Add ( packagesRootItem ) ;
319+ var packages = PackageManagerUtilityInternal . GetAllVisiblePackages ( skipHiddenPackages ) ;
320+ if ( IsExpanded ( packagesRootItem ) )
321+ {
322+ depth ++ ;
323+ foreach ( var package in packages )
324+ {
325+ var packageFolderInstanceId = AssetDatabase . GetMainAssetOrInProgressProxyInstanceID ( package . assetPath ) ;
326+
327+ displayName = ! string . IsNullOrEmpty ( package . displayName ) ? package . displayName : package . name ;
328+ AssetsTreeViewDataSource . PackageTreeItem packageItem = new AssetsTreeViewDataSource . PackageTreeItem ( packageFolderInstanceId , depth , packagesRootItem , displayName ) ;
329+ packageItem . icon = s_FolderIcon ;
330+ packagesRootItem . AddChild ( packageItem ) ;
331+ m_Rows . Add ( packageItem ) ;
332+ ReadAssetDatabase ( package . assetPath , packageItem , depth + 1 , m_Rows ) ;
333+ }
334+ }
335+ else
323336 {
324- // Do not expand Packages root item
325- if ( item . id == ProjectBrowser . kPackagesFolderInstanceId )
326- continue ;
327- bool expanded = EditorPrefs . GetBool ( kProjectBrowserString + item . displayName , true ) ;
328- SetExpanded ( item , expanded ) ;
337+ if ( packages . Length > 0 )
338+ packagesRootItem . children = CreateChildListForCollapsedParent ( ) ;
329339 }
330340
331- m_NeedRefreshRows = true ;
341+ m_NeedRefreshRows = false ;
332342 }
333343
334- private void ReadAssetDatabase ( string assetFolderRootPath , TreeViewItem parent , int baseDepth )
344+ static bool HasSubFolders ( IHierarchyProperty property )
345+ {
346+ var path = AssetDatabase . GUIDToAssetPath ( property . guid ) ;
347+ var subFolders = AssetDatabase . GetSubFolders ( path ) ;
348+ return subFolders . Length > 0 ;
349+ }
350+
351+ private void ReadAssetDatabase ( string assetFolderRootPath , TreeViewItem parent , int baseDepth , IList < TreeViewItem > allRows )
335352 {
336353 // Read from Assets directory
337354 IHierarchyProperty property = new HierarchyProperty ( assetFolderRootPath ) ;
338355 property . Reset ( ) ;
339356
357+ if ( ! IsExpanded ( parent ) )
358+ {
359+ if ( HasSubFolders ( property ) )
360+ parent . children = CreateChildListForCollapsedParent ( ) ;
361+ return ;
362+ }
363+
340364 Texture2D folderIcon = EditorGUIUtility . FindTexture ( EditorResources . folderIconName ) ;
341365
342366 List < TreeViewItem > allFolders = new List < TreeViewItem > ( ) ;
343- while ( property . Next ( null ) )
367+ var expandedIDs = m_TreeView . state . expandedIDs . ToArray ( ) ;
368+ while ( property . Next ( expandedIDs ) )
344369 {
345370 if ( property . isFolder )
346371 {
347372 AssetsTreeViewDataSource . FolderTreeItem folderItem = new AssetsTreeViewDataSource . FolderTreeItem ( property . guid , property . instanceID , baseDepth + property . depth , null , property . name ) ;
348373 folderItem . icon = folderIcon ;
349374 allFolders . Add ( folderItem ) ;
375+ allRows . Add ( folderItem ) ;
376+ if ( ! IsExpanded ( folderItem ) )
377+ {
378+ if ( HasSubFolders ( property ) )
379+ folderItem . children = CreateChildListForCollapsedParent ( ) ;
380+ }
350381 }
351382 }
352383
353384 // Fix references
354385 TreeViewUtility . SetChildParentReferences ( allFolders , parent ) ;
355386 }
356387
388+ public override void SetExpandedWithChildren ( int id , bool expand )
389+ {
390+ base . SetExpandedWithChildren ( id , expand ) ;
391+ PersistExpandedState ( id , expand ) ;
392+ }
393+
394+ public override bool SetExpanded ( int id , bool expand )
395+ {
396+ if ( base . SetExpanded ( id , expand ) )
397+ {
398+ PersistExpandedState ( id , expand ) ;
399+ return true ;
400+ }
401+ return false ;
402+ }
403+
404+ void PersistExpandedState ( int id , bool expand )
405+ {
406+ // Persist expanded state for ProjectBrowsers
407+ InternalEditorUtility . expandedProjectWindowItems = expandedIDs . ToArray ( ) ;
408+
409+ if ( m_RootItem . hasChildren )
410+ {
411+ // Set global expanded state of roots (Assets folder and Favorites root)
412+ foreach ( TreeViewItem item in m_RootItem . children )
413+ if ( item . id == id )
414+ EditorPrefs . SetBool ( kProjectBrowserString + item . displayName , expand ) ;
415+ }
416+ }
417+
418+ protected override void GetParentsAbove ( int id , HashSet < int > parentsAbove )
419+ {
420+ if ( SavedSearchFilters . IsSavedFilter ( id ) )
421+ {
422+ parentsAbove . Add ( SavedSearchFilters . GetRootInstanceID ( ) ) ;
423+ }
424+ else
425+ {
426+ // AssetDatabase folders (in Assets or Packages)
427+ var path = AssetDatabase . GetAssetPath ( id ) ;
428+ if ( Directory . Exists ( path ) )
429+ parentsAbove . UnionWith ( ProjectWindowUtil . GetAncestors ( id ) ) ;
430+ }
431+ }
432+
433+ protected override void GetParentsBelow ( int id , HashSet < int > parentsBelow )
434+ {
435+ var extra = GetParentsBelow ( id ) ;
436+ parentsBelow . UnionWith ( extra ) ;
437+ }
438+
357439 private HashSet < int > GetParentsBelow ( int id )
358440 {
359441 // Add all children expanded ids to hashset
@@ -363,44 +445,30 @@ private HashSet<int> GetParentsBelow(int id)
363445 if ( id == ProjectBrowser . kPackagesFolderInstanceId )
364446 {
365447 parentsBelow . Add ( id ) ;
366- var item = m_TreeView . FindItem ( id ) ;
367- foreach ( var child in item . children )
448+ var packages = PackageManagerUtilityInternal . GetAllVisiblePackages ( skipHiddenPackages ) ;
449+ foreach ( var package in packages )
368450 {
369- if ( child . hasChildren )
370- parentsBelow . UnionWith ( GetParentsBelow ( child . id ) ) ;
451+ var packageFolderInstanceId = AssetDatabase . GetMainAssetOrInProgressProxyInstanceID ( package . assetPath ) ;
452+ parentsBelow . UnionWith ( GetParentsBelow ( packageFolderInstanceId ) ) ;
371453 }
372454 return parentsBelow ;
373455 }
374456
375457 var path = AssetDatabase . GetAssetPath ( id ) ;
376- var pathComponents = path . Split ( '/' ) ;
377- IHierarchyProperty search = new HierarchyProperty ( pathComponents [ 0 ] ) ;
458+ IHierarchyProperty search = new HierarchyProperty ( path ) ;
378459 if ( search . Find ( id , null ) )
379460 {
380461 parentsBelow . Add ( id ) ;
381462
382463 int depth = search . depth ;
383464 while ( search . Next ( null ) && search . depth > depth )
384465 {
385- if ( search . hasChildren )
466+ if ( search . isFolder && search . hasChildren )
386467 parentsBelow . Add ( search . instanceID ) ;
387468 }
388469 }
389470 return parentsBelow ;
390471 }
391-
392- override public void SetExpandedWithChildren ( int id , bool expand )
393- {
394- HashSet < int > oldExpandedSet = new HashSet < int > ( expandedIDs ) ;
395- HashSet < int > candidates = GetParentsBelow ( id ) ;
396-
397- if ( expand )
398- oldExpandedSet . UnionWith ( candidates ) ;
399- else
400- oldExpandedSet . ExceptWith ( candidates ) ;
401-
402- SetExpandedIDs ( oldExpandedSet . ToArray ( ) ) ;
403- }
404472 }
405473
406474 internal class ProjectBrowserColumnOneTreeViewDragging : AssetsTreeViewDragging
0 commit comments