109 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			109 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | ||
|  | using System.Collections.Generic; | ||
|  | using System.Linq; | ||
|  | using JetBrains.Annotations; | ||
|  | 
 | ||
|  | namespace UnityEditor.Searcher | ||
|  | { | ||
|  |     [PublicAPI] | ||
|  |     public class Searcher | ||
|  |     { | ||
|  |         public ISearcherAdapter Adapter { get; } | ||
|  |         public Comparison<SearcherItem> SortComparison { get; set; } | ||
|  | 
 | ||
|  |         readonly List<SearcherDatabaseBase> m_Databases; | ||
|  | 
 | ||
|  |         public Searcher(SearcherDatabaseBase database, string title) | ||
|  |             : this(new List<SearcherDatabaseBase> { database }, title, null) | ||
|  |         { } | ||
|  | 
 | ||
|  |         public Searcher(IEnumerable<SearcherDatabaseBase> databases, string title) | ||
|  |             : this(databases, title, null) | ||
|  |         { } | ||
|  | 
 | ||
|  |         public Searcher(SearcherDatabaseBase database, ISearcherAdapter adapter = null) | ||
|  |             : this(new List<SearcherDatabaseBase> { database }, adapter) | ||
|  |         { } | ||
|  | 
 | ||
|  |         public Searcher(IEnumerable<SearcherDatabaseBase> databases, ISearcherAdapter adapter = null) | ||
|  |             : this(databases, string.Empty, adapter) | ||
|  |         { } | ||
|  | 
 | ||
|  |         Searcher(IEnumerable<SearcherDatabaseBase> databases, string title, ISearcherAdapter adapter) | ||
|  |         { | ||
|  |             m_Databases = new List<SearcherDatabaseBase>(); | ||
|  |             var databaseId = 0; | ||
|  |             foreach (var database in databases) | ||
|  |             { | ||
|  |                 // This is needed for sorting items between databases. | ||
|  |                 database.OverwriteId(databaseId); | ||
|  |                 databaseId++; | ||
|  | 
 | ||
|  |                 m_Databases.Add(database); | ||
|  |             } | ||
|  | 
 | ||
|  |             Adapter = adapter ?? new SearcherAdapter(title); | ||
|  |         } | ||
|  | 
 | ||
|  |         public void BuildIndices() | ||
|  |         { | ||
|  |             foreach (var database in m_Databases) | ||
|  |             { | ||
|  |                 database.BuildIndex(); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         public IEnumerable<SearcherItem> Search(string query) | ||
|  |         { | ||
|  |             query = query.ToLower(); | ||
|  | 
 | ||
|  |             var results = new List<SearcherItem>(); | ||
|  |             float maxScore = 0; | ||
|  |             foreach (var database in m_Databases) | ||
|  |             { | ||
|  |                 var localResults = database.Search(query, out var localMaxScore); | ||
|  |                 if (localMaxScore > maxScore) | ||
|  |                 { | ||
|  |                     // skip the highest scored item in the local results and | ||
|  |                     // insert it back as the first item. The first item should always be | ||
|  |                     // the highest scored item. The order of the other items does not matter | ||
|  |                     // because they will be reordered to recreate the tree properly. | ||
|  |                     if (results.Count > 0) | ||
|  |                     { | ||
|  |                         // backup previous best result | ||
|  |                         results.Add(results[0]); | ||
|  |                         // replace it with the new best result | ||
|  |                         results[0] = localResults[0]; | ||
|  |                         // add remaining results at the end | ||
|  |                         results.AddRange(localResults.Skip(1)); | ||
|  |                     } | ||
|  |                     else // best result will be the first item | ||
|  |                         results.AddRange(localResults); | ||
|  | 
 | ||
|  |                     maxScore = localMaxScore; | ||
|  |                 } | ||
|  |                 else // no new best result just append everything | ||
|  |                 { | ||
|  |                     results.AddRange(localResults); | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             return results; | ||
|  |         } | ||
|  | 
 | ||
|  |         [PublicAPI] | ||
|  |         public class AnalyticsEvent | ||
|  |         { | ||
|  |             [PublicAPI] | ||
|  |             public enum EventType{ Pending, Picked, Cancelled } | ||
|  |             public readonly EventType eventType; | ||
|  |             public readonly string currentSearchFieldText; | ||
|  |             public AnalyticsEvent(EventType eventType, string currentSearchFieldText) | ||
|  |             { | ||
|  |                 this.eventType = eventType; | ||
|  |                 this.currentSearchFieldText = currentSearchFieldText; | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } |