private IEnumerable <SearchItem> FetchItems(SearchContext context, SearchProvider provider)
        {
            if (m_GodBuilderEnumerator == null)
            {
                m_GodBuilderEnumerator = BuildGODS(context, provider);
            }

            while (m_GodBuilderEnumerator.MoveNext())
            {
                yield return(m_GodBuilderEnumerator.Current);
            }

            if (indexer == null)
            {
                indexer = new SceneSearchIndexer(SceneManager.GetActiveScene().name, gods)
                {
                    patternMatchCount = patternMatchCount
                };
                indexer.Build();
                yield return(null);
            }

            foreach (var item in SearchGODs(context, provider))
            {
                yield return(item);
            }

            while (!indexer.IsReady())
            {
                yield return(null);
            }

            foreach (var r in indexer.Search(context.searchQuery))
            {
                if (r.index < 0 || r.index >= gods.Length)
                {
                    continue;
                }

                var god            = gods[r.index];
                var gameObjectId   = god.id;
                var gameObjectName = god.gameObject.name;
                var itemScore      = r.score - 1000;
                if (gameObjectName.Equals(context.searchQuery, StringComparison.InvariantCultureIgnoreCase))
                {
                    itemScore *= 2;
                }
                var item = provider.CreateItem(gameObjectId, itemScore, null,
                                               null,
                                               //$"Index:{itemScore} -> {String.Join(";", SceneSearchIndexer.SplitComponents(god.rawname))}",
                                               null, r.index);
                item.descriptionFormat = SearchItemDescriptionFormat.Ellipsis |
                                         SearchItemDescriptionFormat.RightToLeft |
                                         SearchItemDescriptionFormat.Highlight;
                yield return(item);
            }
        }
Exemple #2
0
        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);
        }