/// <summary> /// Create a new SceneProvider. /// </summary> /// <param name="providerId">Unique Id for the scene provider.</param> /// <param name="filterId">Filter token id use to search only with this provider.</param> /// <param name="displayName">Provider display name used in UI.</param> public SceneProvider(string providerId, string filterId, string displayName) : base(providerId, displayName) { priority = 50; this.filterId = filterId; showDetails = true; showDetailsOptions = ShowDetailsOptions.Inspector | ShowDetailsOptions.Actions; isEnabledForContextualSearch = () => Utils.IsFocusedWindowTypeName("SceneView") || Utils.IsFocusedWindowTypeName("SceneHierarchyWindow"); EditorApplication.hierarchyChanged += () => m_HierarchyChanged = true; toObject = (item, type) => ObjectFromItem(item, type); fetchItems = (context, items, provider) => SearchItems(context, provider); fetchLabel = (item, context) => { if (item.label != null) { return(item.label); } var go = ObjectFromItem(item); if (!go) { return(item.id); } if (context == null || context.searchView == null || context.searchView.displayMode == DisplayMode.List) { var transformPath = SearchUtils.GetTransformPath(go.transform); var components = go.GetComponents <Component>(); if (components.Length > 2 && components[1] && components[components.Length - 1]) { item.label = $"{transformPath} ({components[1].GetType().Name}..{components[components.Length - 1].GetType().Name})"; } else if (components.Length > 1 && components[1]) { item.label = $"{transformPath} ({components[1].GetType().Name})"; } else { item.label = $"{transformPath} ({item.id})"; } if (context != null) { long score = 1; List <int> matches = new List <int>(); var sq = Utils.CleanString(context.searchQuery); if (FuzzySearch.FuzzyMatch(sq, Utils.CleanString(item.label), ref score, matches)) { item.label = RichTextFormatter.FormatSuggestionTitle(item.label, matches); } } } else { item.label = go.name; } return(item.label); }; fetchDescription = (item, context) => { var go = ObjectFromItem(item); return(item.description = SearchUtils.GetHierarchyPath(go)); }; fetchThumbnail = (item, context) => { var obj = ObjectFromItem(item); if (obj == null) { return(null); } return(item.thumbnail = Utils.GetThumbnailForGameObject(obj)); }; fetchPreview = (item, context, size, options) => { var obj = ObjectFromItem(item); if (obj == null) { return(item.thumbnail); } return(Utils.GetSceneObjectPreview(obj, options, item.thumbnail)); }; startDrag = (item, context) => { if (context.selection.Count > 1) { Utils.StartDrag(context.selection.Select(i => ObjectFromItem(i)).ToArray(), item.GetLabel(context, true)); } else { Utils.StartDrag(new [] { ObjectFromItem(item) }, item.GetLabel(context, true)); } }; trackSelection = (item, context) => PingItem(item); fetchGameObjects = SearchUtils.FetchGameObjects; buildKeywordComponents = SceneQueryEngine.BuildKeywordComponents; }
public SceneProvider(string providerId, string filterId, string displayName) : base(providerId, displayName) { priority = 50; this.filterId = filterId; showDetails = true; showDetailsOptions = ShowDetailsOptions.Inspector | ShowDetailsOptions.Actions | ShowDetailsOptions.Preview | ShowDetailsOptions.DefaultGroup; isEnabledForContextualSearch = () => Utils.IsFocusedWindowTypeName("SceneView") || Utils.IsFocusedWindowTypeName("SceneHierarchyWindow"); SearchMonitor.sceneChanged += InvalidateScene; SearchMonitor.documentsInvalidated += Refresh; SearchMonitor.objectChanged += OnObjectChanged; supportsSyncViewSearch = true; toObject = (item, type) => ObjectFromItem(item, type); toKey = (item) => ToKey(item); fetchItems = (context, items, provider) => SearchItems(context, provider); fetchLabel = (item, context) => { if (item.label != null) { return(item.label); } var go = ObjectFromItem(item); if (!go) { return(item.id); } if (context == null || context.searchView == null || context.searchView.displayMode == DisplayMode.List) { var transformPath = SearchUtils.GetTransformPath(go.transform); if (item.options.HasAny(SearchItemOptions.Compacted)) { item.label = transformPath; } else { var components = go.GetComponents <Component>(); if (components.Length > 2 && components[1] && components[components.Length - 1]) { item.label = $"{transformPath} ({components[1].GetType().Name}..{components[components.Length - 1].GetType().Name})"; } else if (components.Length > 1 && components[1]) { item.label = $"{transformPath} ({components[1].GetType().Name})"; } else { item.label = $"{transformPath} ({item.id})"; } } if (context != null) { long score = 1; List <int> matches = new List <int>(); var sq = Utils.CleanString(context.searchQuery); if (FuzzySearch.FuzzyMatch(sq, Utils.CleanString(item.label), ref score, matches)) { item.label = RichTextFormatter.FormatSuggestionTitle(item.label, matches); } } } else { item.label = go.name; } return(item.label); }; fetchDescription = (item, context) => { var go = ObjectFromItem(item); return(item.description = SearchUtils.GetHierarchyPath(go)); }; fetchThumbnail = (item, context) => { var obj = ObjectFromItem(item); if (obj == null) { return(null); } return(item.thumbnail = Utils.GetThumbnailForGameObject(obj)); }; fetchPreview = (item, context, size, options) => { var obj = ObjectFromItem(item); if (obj == null) { return(item.thumbnail); } return(Utils.GetSceneObjectPreview(obj, size, options, item.thumbnail)); }; startDrag = (item, context) => { if (context.selection.Count > 1) { Utils.StartDrag(context.selection.Select(i => ObjectFromItem(i)).ToArray(), item.GetLabel(context, true)); } else { Utils.StartDrag(new[] { ObjectFromItem(item) }, item.GetLabel(context, true)); } }; fetchPropositions = (context, options) => { if (options.HasAny(SearchPropositionFlags.QueryBuilder)) { return(FetchQueryBuilderPropositions(context)); } return(m_SceneQueryEngine == null ? new SearchProposition[0] : m_SceneQueryEngine.FindPropositions(context, options)); }; trackSelection = (item, context) => PingItem(item); fetchColumns = (context, items) => SceneSelectors.Enumerate(items); }
public SceneProvider(string providerId, string filterId, string displayName) : base(providerId, displayName) { priority = 50; this.filterId = filterId; this.showDetails = true; subCategories = new List <NameEntry> { new NameEntry("fuzzy", "fuzzy"), new NameEntry("components", "components (c:)") }; isEnabledForContextualSearch = () => QuickSearch.IsFocusedWindowTypeName("SceneView") || QuickSearch.IsFocusedWindowTypeName("SceneHierarchyWindow"); EditorApplication.hierarchyChanged += () => m_HierarchyChanged = true; onEnable = () => { if (m_HierarchyChanged) { m_BuildIndexEnumerator = null; m_HierarchyChanged = false; } }; onDisable = () => { // Only track changes that occurs when Quick Search is not active. m_HierarchyChanged = false; }; fetchItems = (context, items, provider) => SearchItems(context, provider); fetchLabel = (item, context) => { if (item.label != null) { return(item.label); } var go = ObjectFromItem(item); if (!go) { return(item.id); } var transformPath = GetTransformPath(go.transform); var components = go.GetComponents <Component>(); if (components.Length > 2 && components[1] && components[components.Length - 1]) { item.label = $"{transformPath} ({components[1].GetType().Name}..{components[components.Length-1].GetType().Name})"; } else if (components.Length > 1 && components[1]) { item.label = $"{transformPath} ({components[1].GetType().Name})"; } else { item.label = $"{transformPath} ({item.id})"; } long score = 1; List <int> matches = new List <int>(); var sq = CleanString(context.searchQuery); if (FuzzySearch.FuzzyMatch(sq, CleanString(item.label), ref score, matches)) { item.label = RichTextFormatter.FormatSuggestionTitle(item.label, matches); } return(item.label); }; fetchDescription = (item, context) => { var go = ObjectFromItem(item); return(item.description = GetHierarchyPath(go)); }; fetchThumbnail = (item, context) => { var obj = ObjectFromItem(item); if (obj == null) { return(null); } return(item.thumbnail = Utils.GetThumbnailForGameObject(obj)); }; fetchPreview = (item, context, size, options) => { var obj = ObjectFromItem(item); if (obj == null) { return(item.thumbnail); } var assetPath = GetHierarchyAssetPath(obj, true); if (String.IsNullOrEmpty(assetPath)) { return(item.thumbnail); } return(AssetPreview.GetAssetPreview(obj) ?? Utils.GetAssetPreviewFromPath(assetPath, size, options)); }; startDrag = (item, context) => { var obj = ObjectFromItem(item); if (obj != null) { DragAndDrop.PrepareStartDrag(); DragAndDrop.objectReferences = new[] { obj }; DragAndDrop.StartDrag("Drag scene object"); } }; fetchGameObjects = FetchGameObjects; buildKeywordComponents = o => null; trackSelection = (item, context) => PingItem(item); }
public SceneObjectsProvider(string providerId, string displayName = null) : base(providerId, displayName) { priority = 50; filterId = "h:"; subCategories = new List <NameId> { new NameId("fuzzy", "fuzzy"), }; isEnabledForContextualSearch = () => QuickSearchTool.IsFocusedWindowTypeName("SceneView") || QuickSearchTool.IsFocusedWindowTypeName("SceneHierarchyWindow"); EditorApplication.hierarchyChanged += () => m_HierarchyChanged = true; onEnable = () => { if (m_HierarchyChanged) { componentsById.Clear(); indexer = null; gods = null; m_GodBuilderEnumerator = null; m_HierarchyChanged = false; } }; onDisable = () => {}; fetchItems = (context, items, provider) => FetchItems(context, provider); fetchLabel = (item, context) => { if (item.label != null) { return(item.label); } var go = ObjectFromItem(item); if (!go) { return(item.id); } var transformPath = GetTransformPath(go.transform); var components = go.GetComponents <Component>(); if (components.Length > 2 && components[1] && components[components.Length - 1]) { item.label = $"{transformPath} ({components[1].GetType().Name}..{components[components.Length-1].GetType().Name})"; } else if (components.Length > 1 && components[1]) { item.label = $"{transformPath} ({components[1].GetType().Name})"; } else { item.label = $"{transformPath} ({item.id})"; } long score = 1; List <int> matches = new List <int>(); var sq = CleanString(context.searchQuery); if (FuzzySearch.FuzzyMatch(sq, CleanString(item.label), ref score, matches)) { item.label = RichTextFormatter.FormatSuggestionTitle(item.label, matches); } return(item.label); }; fetchDescription = (item, context) => { #if QUICKSEARCH_DEBUG item.description = gods[(int)item.data].name + " * " + item.score; #else var go = ObjectFromItem(item); item.description = GetHierarchyPath(go); #endif return(item.description); }; fetchThumbnail = (item, context) => { var obj = ObjectFromItem(item); if (obj == null) { return(null); } item.thumbnail = PrefabUtility.GetIconForGameObject(obj); if (item.thumbnail) { return(item.thumbnail); } return(EditorGUIUtility.ObjectContent(obj, obj.GetType()).image as Texture2D); }; fetchPreview = (item, context, size, options) => { var obj = ObjectFromItem(item); if (obj == null) { return(item.thumbnail); } var assetPath = GetHierarchyAssetPath(obj, true); if (String.IsNullOrEmpty(assetPath)) { return(item.thumbnail); } return(AssetPreview.GetAssetPreview(obj) ?? Utils.GetAssetPreviewFromPath(assetPath)); }; startDrag = (item, context) => { var obj = ObjectFromItem(item); if (obj != null) { DragAndDrop.PrepareStartDrag(); DragAndDrop.objectReferences = new[] { obj }; DragAndDrop.StartDrag("Drag scene object"); } }; trackSelection = (item, context) => PingItem(item); }
public static IEnumerable <FindResult> Search(string searchQuery, string[] words, IEnumerable <string> roots, FindOptions options) { #if DEBUG_FIND_PROVIDER using (new DebugTimer($"Searching {s_FileCount} files with <i>{searchQuery}</i> ({options})")) #endif { var results = new ConcurrentBag <FindResult>(); var searchTask = Task.Run(() => { Regex globRx = null, rxm = null; var validRx = options.HasFlag(FindOptions.Regex) && ParseRx(searchQuery, out rxm); var validGlob = options.HasFlag(FindOptions.Glob) && ParseGlob(searchQuery, out globRx); var validWords = options.HasFlag(FindOptions.Words); var validFuzzy = options.HasFlag(FindOptions.Fuzzy); Parallel.ForEach(roots, r => { var isPackage = options.HasFlag(FindOptions.Packages) && r.StartsWith("Packages/", StringComparison.Ordinal); if (!options.HasFlag(FindOptions.Packages) && isPackage) { return; } if (!s_RootFilePaths.TryGetValue(r, out var files)) { files = new ConcurrentDictionary <string, byte>(Directory.EnumerateFiles(r, "*", SearchOption.AllDirectories) .Where(p => !p.EndsWith(".meta", StringComparison.Ordinal)) .Select(p => p.Replace("\\", "/")).ToDictionary(p => p, p => (byte)0)); s_RootFilePaths.TryAdd(r, files); #if DEBUG_FIND_PROVIDER s_FileCount += files.Length; #endif } Parallel.ForEach(files, kvp => { try { var f = kvp.Key; long fuzzyScore = 0; int score = isPackage ? (int)FindOptions.Packages : 0; if (validWords && SearchUtils.MatchSearchGroups(words, f, out _, out _, StringComparison.OrdinalIgnoreCase)) { results.Add(new FindResult(f, score | (int)FindOptions.Words)); } else if (validRx && rxm.IsMatch(f)) { results.Add(new FindResult(f, score | (int)FindOptions.Regex)); } else if (validGlob && globRx.IsMatch(f)) { results.Add(new FindResult(f, score | (int)FindOptions.Glob)); } else if (validFuzzy && FuzzySearch.FuzzyMatch(searchQuery, f, ref fuzzyScore)) { results.Add(new FindResult(f, ComputeFuzzyScore(score, fuzzyScore))); } } catch { // ignore } }); }); }); while (results.Count > 0 || !searchTask.Wait(1) || results.Count > 0) { if (results.TryTake(out var e)) { yield return(e); } } } }
public SceneProvider(string providerId, string filterId, string displayName) : base(providerId, displayName) { priority = 50; this.filterId = filterId; isEnabledForContextualSearch = () => Utils.IsFocusedWindowTypeName("SceneView") || Utils.IsFocusedWindowTypeName("SceneHierarchyWindow"); EditorApplication.hierarchyChanged += () => m_HierarchyChanged = true; onEnable = () => { if (m_HierarchyChanged) { m_GameObjects = fetchGameObjects(); m_SceneQueryEngine = new SceneQueryEngine(m_GameObjects); m_HierarchyChanged = false; } }; onDisable = () => { // Only track changes that occurs when Quick Search is not active. m_HierarchyChanged = false; }; toObject = (item, type) => ObjectFromItem(item); fetchItems = (context, items, provider) => SearchItems(context, provider); fetchLabel = (item, context) => { if (item.label != null) { return(item.label); } var go = ObjectFromItem(item); if (!go) { return(item.id); } if (context.searchView == null || context.searchView.displayMode == DisplayMode.List) { var transformPath = SearchUtils.GetTransformPath(go.transform); var components = go.GetComponents <Component>(); if (components.Length > 2 && components[1] && components[components.Length - 1]) { item.label = $"{transformPath} ({components[1].GetType().Name}..{components[components.Length - 1].GetType().Name})"; } else if (components.Length > 1 && components[1]) { item.label = $"{transformPath} ({components[1].GetType().Name})"; } else { item.label = $"{transformPath} ({item.id})"; } long score = 1; List <int> matches = new List <int>(); var sq = Utils.CleanString(context.searchQuery); if (FuzzySearch.FuzzyMatch(sq, Utils.CleanString(item.label), ref score, matches)) { item.label = RichTextFormatter.FormatSuggestionTitle(item.label, matches); } } else { item.label = go.name; } return(item.label); }; fetchDescription = (item, context) => { var go = ObjectFromItem(item); return(item.description = SearchUtils.GetHierarchyPath(go)); }; fetchThumbnail = (item, context) => { var obj = ObjectFromItem(item); if (obj == null) { return(null); } return(item.thumbnail = Utils.GetThumbnailForGameObject(obj)); }; fetchPreview = (item, context, size, options) => { var obj = ObjectFromItem(item); if (obj == null) { return(item.thumbnail); } var sr = obj.GetComponent <SpriteRenderer>(); if (sr && sr.sprite && sr.sprite.texture) { return(sr.sprite.texture); } #if PACKAGE_UGUI var uii = obj.GetComponent <UnityEngine.UI.Image>(); if (uii && uii.mainTexture is Texture2D uiit) { return(uiit); } #endif var preview = AssetPreview.GetAssetPreview(obj); if (preview) { return(preview); } var assetPath = SearchUtils.GetHierarchyAssetPath(obj, true); if (String.IsNullOrEmpty(assetPath)) { return(item.thumbnail); } return(Utils.GetAssetPreviewFromPath(assetPath, size, options)); }; startDrag = (item, context) => { var obj = ObjectFromItem(item); if (obj != null) { Utils.StartDrag(obj, item.label); } }; trackSelection = (item, context) => PingItem(item); fetchGameObjects = SceneQueryEngine.FetchGameObjects; buildKeywordComponents = SceneQueryEngine.BuildKeywordComponents; }
public SceneObjectsProvider(string providerId, string displayName = null) : base(providerId, displayName) { priority = 50; filterId = "h:"; subCategories = new List <NameId> { new NameId("fuzzy", "fuzzy"), new NameId("limit", $"limit to {k_LimitMatches} matches") }; isEnabledForContextualSearch = () => QuickSearchTool.IsFocusedWindowTypeName("SceneView") || QuickSearchTool.IsFocusedWindowTypeName("SceneHierarchyWindow"); EditorApplication.hierarchyChanged += () => componentsById.Clear(); onEnable = () => { //using (new DebugTimer("Building Scene Object Description")) { var objects = new GameObject[0]; var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { objects = SceneModeUtility.GetObjects(new[] { prefabStage.prefabContentsRoot }, true); } else { var goRoots = new List <UnityEngine.Object>(); for (int i = 0; i < UnityEngine.SceneManagement.SceneManager.sceneCount; ++i) { goRoots.AddRange(UnityEngine.SceneManagement.SceneManager.GetSceneAt(i).GetRootGameObjects()); } objects = SceneModeUtility.GetObjects(goRoots.ToArray(), true); } //using (new DebugTimer($"Fetching {gods.Length} Scene Objects Components")) { gods = new GOD[objects.Length]; for (int i = 0; i < objects.Length; ++i) { gods[i].gameObject = objects[i]; var id = gods[i].gameObject.GetInstanceID(); if (!componentsById.TryGetValue(id, out gods[i].name)) { if (gods.Length > k_LODDetail2) { gods[i].name = CleanString(gods[i].gameObject.name); } else if (gods.Length > k_LODDetail1) { gods[i].name = CleanString(GetTransformPath(gods[i].gameObject.transform)); } else { gods[i].name = BuildComponents(gods[i].gameObject); } componentsById[id] = gods[i].name; } } indexer = new SceneSearchIndexer(SceneManager.GetActiveScene().name, gods); indexer.Build(); } } }; onDisable = () => { indexer = null; gods = new GOD[0]; }; fetchItems = (context, items, provider) => { if (gods == null) { return; } if (indexer != null && indexer.IsReady()) { var results = indexer.Search(context.searchQuery).Take(201); items.AddRange(results.Select(r => { if (r.index < 0 || r.index >= gods.Length) { return(provider.CreateItem("invalid")); } var gameObjectId = gods[r.index].gameObject.GetInstanceID().ToString(); var gameObjectName = gods[r.index].gameObject.name; var itemScore = r.score - 1000; if (gameObjectName.Equals(context.searchQuery, StringComparison.InvariantCultureIgnoreCase)) { itemScore *= 2; } var item = provider.CreateItem(gameObjectId, itemScore, null, null, null, r.index); item.descriptionFormat = SearchItemDescriptionFormat.Ellipsis | SearchItemDescriptionFormat.RightToLeft | SearchItemDescriptionFormat.Highlight; return(item); })); } SearchGODs(context, provider, items); }; fetchLabel = (item, context) => { if (item.label != null) { return(item.label); } var go = ObjectFromItem(item); if (!go) { return(item.id); } var transformPath = GetTransformPath(go.transform); var components = go.GetComponents <Component>(); if (components.Length > 2 && components[1] && components[components.Length - 1]) { item.label = $"{transformPath} ({components[1].GetType().Name}..{components[components.Length-1].GetType().Name})"; } else if (components.Length > 1 && components[1]) { item.label = $"{transformPath} ({components[1].GetType().Name})"; } else { item.label = $"{transformPath} ({item.id})"; } long score = 1; List <int> matches = new List <int>(); var sq = CleanString(context.searchQuery); if (FuzzySearch.FuzzyMatch(sq, CleanString(item.label), ref score, matches)) { item.label = RichTextFormatter.FormatSuggestionTitle(item.label, matches); } return(item.label); }; fetchDescription = (item, context) => { #if QUICKSEARCH_DEBUG item.description = gods[(int)item.data].name + " * " + item.score; #else var go = ObjectFromItem(item); item.description = GetHierarchyPath(go); #endif return(item.description); }; fetchThumbnail = (item, context) => { if (item.thumbnail) { return(item.thumbnail); } var obj = ObjectFromItem(item); if (obj != null) { if (SearchSettings.fetchPreview) { var assetPath = GetHierarchyAssetPath(obj, true); if (!String.IsNullOrEmpty(assetPath)) { item.thumbnail = AssetPreview.GetAssetPreview(obj); if (item.thumbnail) { return(item.thumbnail); } item.thumbnail = Utils.GetAssetThumbnailFromPath(assetPath, true); if (item.thumbnail) { return(item.thumbnail); } } } item.thumbnail = PrefabUtility.GetIconForGameObject(obj); if (item.thumbnail) { return(item.thumbnail); } item.thumbnail = EditorGUIUtility.ObjectContent(obj, obj.GetType()).image as Texture2D; } return(item.thumbnail); }; startDrag = (item, context) => { var obj = ObjectFromItem(item); if (obj != null) { DragAndDrop.PrepareStartDrag(); DragAndDrop.objectReferences = new[] { obj }; DragAndDrop.StartDrag("Drag scene object"); } }; trackSelection = (item, context) => PingItem(item); }
private void SearchGODs(SearchContext context, SearchProvider provider, List <SearchItem> items) { int addedCount = 0; List <int> matches = new List <int>(); var sq = CleanString(context.searchQuery); var limitSearch = context.categories.Any(c => c.name.id == "limit" && c.isEnabled); var useFuzzySearch = gods.Length < k_LODDetail2 && context.categories.Any(c => c.name.id == "fuzzy" && c.isEnabled); long bestScore = 1; for (int i = 0, end = gods.Length; i != end; ++i) { var go = gods[i].gameObject; if (!go) { continue; } long score = 1; if (useFuzzySearch) { if (!FuzzySearch.FuzzyMatch(sq, gods[i].name, ref score, matches)) { continue; } if (score > bestScore) { bestScore = score; } if (limitSearch && addedCount > (k_LimitMatches / 2)) { useFuzzySearch = addedCount < ((k_LimitMatches * 7) / 8); } } else { if (!MatchSearchGroups(context, gods[i].name, true)) { continue; } score = bestScore + 1; } var gameObjectId = go.GetInstanceID().ToString(); var item = provider.CreateItem(gameObjectId, ~(int)score, null, null, null, i); item.descriptionFormat = SearchItemDescriptionFormat.Ellipsis | SearchItemDescriptionFormat.RightToLeft; if (useFuzzySearch) { item.descriptionFormat |= SearchItemDescriptionFormat.FuzzyHighlight; } else { item.descriptionFormat |= SearchItemDescriptionFormat.Highlight; } items.Add(item); if (limitSearch && ++addedCount > k_LimitMatches) { break; } } }