123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- using UnityEngine.UIElements;
- using UnityEditor.ShaderGraph.Drawing;
- using UnityEditor.Searcher;
-
- namespace UnityEditor.ShaderGraph
- {
- public class SearchWindowAdapter : SearcherAdapter
- {
- readonly VisualTreeAsset m_DefaultItemTemplate;
- public override bool HasDetailsPanel => false;
-
- public SearchWindowAdapter(string title) : base(title)
- {
- m_DefaultItemTemplate = Resources.Load<VisualTreeAsset>("SearcherItem");
- }
-
- private SearcherItem GetFirstChildItem(SearcherItem item)
- {
- if (item.Children.Count != 0)
- {
- SearcherItem childIterator = null;
- // Discard searcher item for selection if it is a category, get next best child item from it instead
- // There is no utility in selecting category headers/titles, only the leaf entries
- childIterator = item.Children[0];
- while (childIterator != null && childIterator.Children.Count != 0)
- {
- childIterator = childIterator.Children[0];
- }
-
- item = childIterator;
- }
-
- return item;
- }
-
- private int ComputeScoreForMatch(string[] queryTerms, SearcherItem matchItem)
- {
- // Scoring Criteria:
- // - Exact name match is most preferred.
- // - Partial name match is next.
- // - Exact synonym match is next.
- // - Partial synonym match is next.
- // - No match is last.
- int score = 0;
-
- // Split the entry name so that we can remove suffix that looks like "Clamp: In(4)"
- var nameSansSuffix = matchItem.Name.Split(':').First();
-
- int nameCharactersMatched = 0;
-
- foreach (var queryWord in queryTerms)
- {
- if (nameSansSuffix.Contains(queryWord, StringComparison.OrdinalIgnoreCase))
- {
- score += 100000;
- nameCharactersMatched += queryWord.Length;
- }
-
- // Check for synonym matches -- give a bonus to each
- if (matchItem.Synonyms != null)
- {
- foreach (var syn in matchItem.Synonyms)
- {
- if (syn.Equals(queryWord, StringComparison.OrdinalIgnoreCase))
- {
- score += 10000;
- }
- else if (syn.Contains(queryWord, StringComparison.OrdinalIgnoreCase))
- {
- score += 1000;
- score -= (syn.Length - queryWord.Length);
- }
- }
- }
- }
-
- if (nameCharactersMatched > 0)
- {
- int unmatchedCharacters = (nameSansSuffix.Length - nameCharactersMatched);
- score -= unmatchedCharacters;
- }
-
- return score;
- }
-
- public override SearcherItem OnSearchResultsFilter(IEnumerable<SearcherItem> searchResults, string searchQuery)
- {
- if (searchQuery.Length == 0)
- return GetFirstChildItem(searchResults.FirstOrDefault());
-
- // Sort results by length so that shorter length results are prioritized
- // prevents entries with short names getting stuck at end of list after entries with longer names when both contain the same word
- searchResults = searchResults.OrderBy(x => x.Name.Length).ToList();
-
- var bestMatch = GetFirstChildItem(searchResults.FirstOrDefault());
- int bestScore = 0;
- List<int> visitedItems = new List<int>();
- var queryTerms = searchQuery.Split(' ');
- foreach (var result in searchResults)
- {
- var currentItem = GetFirstChildItem(result);
-
- if (currentItem.Parent != null)
- {
- SearcherItem parentItem = currentItem.Parent;
- foreach (var matchItem in parentItem.Children)
- {
- if (visitedItems.Contains(matchItem.Id))
- continue;
-
- int currentScore = ComputeScoreForMatch(queryTerms, matchItem);
- if (currentScore > bestScore)
- {
- bestScore = currentScore;
- bestMatch = matchItem;
- }
-
- visitedItems.Add(matchItem.Id);
- }
- }
- }
-
- return bestMatch;
- }
- }
-
- internal class SearchNodeItem : SearcherItem
- {
- public NodeEntry NodeGUID;
-
- public SearchNodeItem(string name, NodeEntry nodeGUID, string[] synonyms,
- string help = " ", List<SearchNodeItem> children = null) : base(name)
- {
- NodeGUID = nodeGUID;
- Synonyms = synonyms;
- }
- }
- }
|