/// <summary> /// Initiate a search and return all search items matching the search context. Other items can be found later using the asynchronous searches. /// </summary> /// <param name="context">The current search context</param> /// <returns>A list of search items matching the search query.</returns> public static List <SearchItem> GetItems(SearchContext context, SearchFlags options = SearchFlags.Default) { // Stop all search sessions every time there is a new search. context.sessions.StopAllAsyncSearchSessions(); var allItems = new List <SearchItem>(3); #if QUICKSEARCH_DEBUG var debugProviderList = context.providers.ToList(); using (new DebugTimer($"Search get items {String.Join(", ", debugProviderList.Select(p=>p.name.id))} -> {context.searchQuery}")); #endif foreach (var provider in context.providers) { using (var fetchTimer = new DebugTimer(null)) { try { var iterator = provider.fetchItems(context, allItems, provider); if (iterator != null) { if (options.HasFlag(SearchFlags.Synchronous)) { var stackedEnumerator = new StackedEnumerator <SearchItem>(iterator); while (stackedEnumerator.MoveNext()) { if (stackedEnumerator.Current != null) { allItems.Add(stackedEnumerator.Current); } } } else { var session = context.sessions.GetProviderSession(provider.name.id); session.Reset(iterator, k_MaxFetchTimeMs); session.Start(); if (!session.FetchSome(allItems, k_MaxFetchTimeMs)) { session.Stop(); } } } provider.RecordFetchTime(fetchTimer.timeMs); } catch (Exception ex) { UnityEngine.Debug.LogException(new Exception($"Failed to get fetch {provider.name.displayName} provider items.", ex)); } } } if (!options.HasFlag(SearchFlags.Sorted)) { return(allItems); } allItems.Sort(SortItemComparer); return(allItems.GroupBy(i => i.id).Select(i => i.First()).ToList()); }
/// <summary> /// Hard reset an async search session. /// </summary> /// <param name="itemEnumerator">The enumerator that will yield new search results. This object can be an IEnumerator or IEnumerable</param> /// <param name="maxFetchTimePerProviderMs">The amount of time allowed to yield new results.</param> /// <remarks>Normally async search sessions are re-used per search provider.</remarks> public void Reset(object itemEnumerator, long maxFetchTimePerProviderMs = k_MaxTimePerUpdate) { // Remove and add the event handler in case it was already removed. Stop(); searchInProgress = true; m_MaxFetchTimePerProviderMs = maxFetchTimePerProviderMs; m_ItemsEnumerator = new StackedEnumerator <SearchItem>(itemEnumerator); EditorApplication.update += OnUpdate; }
/// <summary> /// Initiate a search and return all search items matching the search context. Other items can be found later using the asynchronous searches. /// </summary> /// <param name="context">The current search context</param> /// <param name="options">Options defining how the query will be performed</param> /// <returns>A list of search items matching the search query.</returns> public static List <SearchItem> GetItems(SearchContext context, SearchFlags options = SearchFlags.Default) { DebugInfo.gcFetch = GC.GetTotalMemory(false); // Stop all search sessions every time there is a new search. context.sessions.StopAllAsyncSearchSessions(); context.searchFinishTime = context.searchStartTime = EditorApplication.timeSinceStartup; context.sessionEnded -= OnSearchEnded; context.sessionEnded += OnSearchEnded; #if SHOW_SEARCH_PROGRESS if (Progress.Exists(context.progressId)) { Progress.Finish(context.progressId, Progress.Status.Succeeded); } context.progressId = Progress.Start($"Searching...", options: Progress.Options.Indefinite); #endif if (options.HasFlag(SearchFlags.WantsMore)) { context.wantsMore = true; } if (options.HasFlag(SearchFlags.Synchronous)) { context.options |= SearchFlags.Synchronous; } int fetchProviderCount = 0; var allItems = new List <SearchItem>(3); #if QUICKSEARCH_DEBUG var debugProviderList = context.providers.ToList(); using (new DebugTimer($"Search get items {String.Join(", ", debugProviderList.Select(p=>p.name.id))} -> {context.searchQuery}")); #endif foreach (var provider in context.providers) { try { var watch = new System.Diagnostics.Stopwatch(); watch.Start(); fetchProviderCount++; var iterator = provider.fetchItems(context, allItems, provider); if (iterator != null && options.HasFlag(SearchFlags.Synchronous)) { var stackedEnumerator = new StackedEnumerator <SearchItem>(iterator); while (stackedEnumerator.MoveNext()) { if (stackedEnumerator.Current != null) { allItems.Add(stackedEnumerator.Current); } } } else { var session = context.sessions.GetProviderSession(context, provider.name.id); session.Reset(context, iterator, k_MaxFetchTimeMs); session.Start(); var sessionEnded = !session.FetchSome(allItems, k_MaxFetchTimeMs); if (options.HasFlag(SearchFlags.FirstBatchAsync)) { session.SendItems(allItems); } if (sessionEnded) { session.Stop(); } } provider.RecordFetchTime(watch.Elapsed.TotalMilliseconds); } catch (Exception ex) { UnityEngine.Debug.LogException(new Exception($"Failed to get fetch {provider.name.displayName} provider items.", ex)); } } if (fetchProviderCount == 0) { OnSearchEnded(context); context.sessions.StopAllAsyncSearchSessions(); } DebugInfo.gcFetch = GC.GetTotalMemory(false) - DebugInfo.gcFetch; if (!options.HasFlag(SearchFlags.Sorted)) { return(allItems); } allItems.Sort(SortItemComparer); return(allItems.GroupBy(i => i.id).Select(i => i.First()).ToList()); }