# ObjectSelectorEngineAttribute

> Use this class attribute to register ObjectSelector search engines automatically. Search engines with this attribute must implement the IObjectSelectorEngine interface.

## Definition

* **Type:** Class
* **Namespace:** [UnityEditor.SearchService](/engine/6000.7/script-reference/unityeditor/searchservice.md)
* **Assembly:** UnityEditor.CoreModule
* **Inherits from:** [Attribute](https://learn.microsoft.com/dotnet/api/system.attribute)

```csharp
[AttributeUsage(AttributeTargets.Class)]
public class ObjectSelectorEngineAttribute : Attribute
```

## Remarks

The following example creates an ObjectSelector search engine:

```csharp
using System;
using UnityEditor.SearchService;
using Object = UnityEngine.Object;

[ObjectSelectorEngine]
class TestObjectSelectorSearchEngine : IObjectSelectorEngine
{
    public string name => "My Custom Engine";

    public void BeginSession(ISearchContext context)
    {
    }

    public void EndSession(ISearchContext context)
    {
        // EndSession can be called in two ways:
        // 1. Naturally when the onObjectSelectorClosed is called upon closing the window (which you should do in your window).
        // 2. Forcefully when a new session is started before the current one is finished.
        // In the second case, we need to close the window to avoid any issues since the ObjectSelector API does not support concurrent selectors.
        if ((((ObjectSelectorSearchContext)context).endSessionModes & ObjectSelectorSearchEndSessionModes.CloseSelector) != 0 && ObjectSelectorWindow.instance != null)
        {
            ObjectSelectorWindow.instance.Close();
        }
    }

    public void BeginSearch(ISearchContext context, string query)
    {
        // Not called.
    }

    public void EndSearch(ISearchContext context)
    {
        // Not called.
    }

    public bool SelectObject(ISearchContext context, Action<Object, bool> onObjectSelectorClosed, Action<Object> onObjectSelectedUpdated)
    {
        ObjectSelectorWindow.Show((ObjectSelectorSearchContext)context, onObjectSelectedUpdated, onObjectSelectorClosed);
        return true;
    }

    public void SetSearchFilter(ISearchContext context, string searchFilter)
    {
        ObjectSelectorWindow.instance.searchText = searchFilter;
    }
}
```

The following example creates an object selector window that displays returned items as a list of names and paths:

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.SearchService;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;

public class ObjectSelectorWindow : EditorWindow
{
    public class ItemInfo
    {
        public EntityId entityId;
        public string label;
        public bool isAsset;
        public GlobalObjectId globalObjectId;
    }

    static ObjectSelectorSearchContext s_Context;
    static Action<Object> s_OnSelectionChanged;
    static Action<Object, bool> s_OnSelectorClosed;
    public static ObjectSelectorWindow instance { get; private set; }

    List<ItemInfo> m_FilteredItems;
    ToolbarSearchField m_Searchbox;
    ListView m_ListView;
    string m_SearchText;
    ItemInfo m_CurrentItem;
    bool m_Canceled = true;

    public bool initialized { get; private set; } = false;

    public string searchText
    {
        get => m_SearchText;
        set
        {
            m_SearchText = value;
            FilterItems();
        }
    }

    public List<ItemInfo> allItems { get; private set; }

    public static void Show(ObjectSelectorSearchContext context, Action<Object> onSelectionChanged, Action<Object, bool> onSelectorClosed)
    {
        s_Context = context;
        s_OnSelectionChanged = onSelectionChanged;
        s_OnSelectorClosed = onSelectorClosed;

        // Create a window with CreateInstance, and show it.
        var window = CreateInstance<ObjectSelectorWindow>();
        instance = window;
        window.Show();
    }

    void Init()
    {
        m_SearchText = "";
        allItems = new List<ItemInfo>();
        m_FilteredItems = new List<ItemInfo>();

        if ((s_Context.visibleObjects & VisibleObjects.Assets) == VisibleObjects.Assets)
            allItems.AddRange(FetchAllAssets());
        if ((s_Context.visibleObjects & VisibleObjects.Scene) == VisibleObjects.Scene)
            allItems.AddRange(FetchAllGameObjects(s_Context));

        allItems.Sort((item, other) => item.label.CompareTo(other.label));
        m_FilteredItems.AddRange(allItems);
    }

    void OnEnable()
    {
        Init();

        m_Searchbox = new ToolbarSearchField();
        m_Searchbox.RegisterValueChangedCallback(SearchFilterChanged);
        m_Searchbox.style.flexGrow = 1;
        m_Searchbox.style.maxHeight = 16;
        m_Searchbox.style.width = Length.Percent(100f);
        m_Searchbox.style.marginRight = 4;
        rootVisualElement.Add(m_Searchbox);

        m_ListView = new ListView(m_FilteredItems, 16, MakeItem, BindItem);
        m_ListView.selectionChanged += ItemSelectionChanged;
        m_ListView.itemsChosen += ItemsChosen;
        m_ListView.style.flexGrow = 1;
        rootVisualElement.Add(m_ListView);

        // Initialize selection
        if (s_Context.currentObject != null)
        {
            var currentSelectedId = s_Context.currentObject.GetEntityId();
            var selectedIndex = m_FilteredItems.FindIndex(item => item.entityId == currentSelectedId);
            if (selectedIndex >= 0)
                m_ListView.selectedIndex = selectedIndex;
        }

        FinishInit();
    }

    void FinishInit()
    {
        EditorApplication.delayCall += () =>
        {
            m_ListView.Focus();
            initialized = true;
        };
    }

    void OnDisable()
    {
        // Call the onSelectorClosed callback when the window is closing.
        s_OnSelectorClosed?.Invoke(GetCurrentObject(), m_Canceled);
        instance = null;
    }

    void SearchFilterChanged(ChangeEvent<string> evt)
    {
        searchText = evt.newValue;
    }

    void FilterItems()
    {
        m_FilteredItems.Clear();
        m_FilteredItems.AddRange(allItems.Where(item => string.IsNullOrEmpty(searchText) || item.label.IndexOf(searchText, StringComparison.InvariantCultureIgnoreCase) >= 0));

        m_ListView.Rebuild();
    }

    void BindItem(VisualElement listItem, int index)
    {
        if (index < 0 || index >= m_FilteredItems.Count)
            return;

        var label = listItem as Label;
        if (label == null)
            return;
        label.text = m_FilteredItems[index].label;
    }

    static VisualElement MakeItem()
    {
        return new Label();
    }

    void ItemSelectionChanged(IEnumerable<object> selectedItems)
    {
        m_CurrentItem = selectedItems.FirstOrDefault() as ItemInfo;
        s_OnSelectionChanged?.Invoke(GetCurrentObject());
    }

    void ItemsChosen(IEnumerable<object> selectedItems)
    {
        m_CurrentItem = selectedItems.FirstOrDefault() as ItemInfo;
        m_Canceled = false;
        Close();
    }

    static IEnumerable<ItemInfo> FetchAllAssets()
    {
        var allPaths = AssetDatabase.GetAllAssetPaths();
        if (allPaths == null)
            yield break;

        var requiredTypes = s_Context.requiredTypeNames != null ? s_Context.requiredTypeNames.ToList() : new List<string>();
        foreach (var path in allPaths)
        {
            var type = AssetDatabase.GetMainAssetTypeAtPath(path);
            var typeName = type.FullName ?? "";
            if (requiredTypes.Any(requiredType => typeName.Contains(requiredType)))
            {
                var asset = AssetDatabase.LoadMainAssetAtPath(path);
                var globalObjectId = GlobalObjectId.GetGlobalObjectIdSlow(asset);
                var entityId = asset?.GetEntityId() ?? EntityId.None;
                yield return new ItemInfo { entityId = entityId, label = path, isAsset = true, globalObjectId = globalObjectId };
            }
        }
    }

    static IEnumerable<ItemInfo> FetchAllGameObjects(ObjectSelectorSearchContext context)
    {
        var property = new HierarchyIterator(HierarchyType.GameObjects, false);

        var requiredTypes = s_Context.requiredTypeNames != null ? s_Context.requiredTypeNames.ToList() : new List<string>();
        while (property.Next(null))
        {
            var objectReferenced = property.pptrValue;
            if (objectReferenced == null)
                continue;
            var globalObjectId = GlobalObjectId.GetGlobalObjectIdSlow(property.entityId);
            var typeName = objectReferenced.GetType().FullName ?? "";
            if (requiredTypes.Any(requiredType => typeName.Contains(requiredType)))
                yield return new ItemInfo { entityId = property.entityId, label = property.name, isAsset = false, globalObjectId = globalObjectId };
        }
    }

    Object GetCurrentObject()
    {
        if (m_CurrentItem == null)
            return null;
        var currentEntityId = m_CurrentItem.entityId;
        if (m_CurrentItem.isAsset)
        {
            var asset = AssetDatabase.LoadMainAssetAtPath(m_CurrentItem.label);
            currentEntityId = asset.GetEntityId();
        }
        return EditorUtility.EntityIdToObject(currentEntityId);
    }
}
```

## Inheritance

**Inherited Members:**

* [Attribute.GetCustomAttributes(MemberInfo, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-memberinfo-system-type\))
* [Attribute.GetCustomAttributes(MemberInfo, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-memberinfo-system-type-system-boolean\))
* [Attribute.GetCustomAttributes(MemberInfo)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-memberinfo\))
* [Attribute.GetCustomAttributes(MemberInfo, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-memberinfo-system-boolean\))
* [Attribute.IsDefined(MemberInfo, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined\(system-reflection-memberinfo-system-type\))
* [Attribute.IsDefined(MemberInfo, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined\(system-reflection-memberinfo-system-type-system-boolean\))
* [Attribute.GetCustomAttribute(MemberInfo, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute\(system-reflection-memberinfo-system-type\))
* [Attribute.GetCustomAttribute(MemberInfo, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute\(system-reflection-memberinfo-system-type-system-boolean\))
* [Attribute.GetCustomAttributes(ParameterInfo)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-parameterinfo\))
* [Attribute.GetCustomAttributes(ParameterInfo, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-parameterinfo-system-type\))
* [Attribute.GetCustomAttributes(ParameterInfo, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-parameterinfo-system-type-system-boolean\))
* [Attribute.GetCustomAttributes(ParameterInfo, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-parameterinfo-system-boolean\))
* [Attribute.IsDefined(ParameterInfo, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined\(system-reflection-parameterinfo-system-type\))
* [Attribute.IsDefined(ParameterInfo, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined\(system-reflection-parameterinfo-system-type-system-boolean\))
* [Attribute.GetCustomAttribute(ParameterInfo, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute\(system-reflection-parameterinfo-system-type\))
* [Attribute.GetCustomAttribute(ParameterInfo, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute\(system-reflection-parameterinfo-system-type-system-boolean\))
* [Attribute.GetCustomAttributes(Module, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-module-system-type\))
* [Attribute.GetCustomAttributes(Module)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-module\))
* [Attribute.GetCustomAttributes(Module, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-module-system-boolean\))
* [Attribute.GetCustomAttributes(Module, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-module-system-type-system-boolean\))
* [Attribute.IsDefined(Module, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined\(system-reflection-module-system-type\))
* [Attribute.IsDefined(Module, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined\(system-reflection-module-system-type-system-boolean\))
* [Attribute.GetCustomAttribute(Module, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute\(system-reflection-module-system-type\))
* [Attribute.GetCustomAttribute(Module, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute\(system-reflection-module-system-type-system-boolean\))
* [Attribute.GetCustomAttributes(Assembly, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-assembly-system-type\))
* [Attribute.GetCustomAttributes(Assembly, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-assembly-system-type-system-boolean\))
* [Attribute.GetCustomAttributes(Assembly)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-assembly\))
* [Attribute.GetCustomAttributes(Assembly, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattributes#system-attribute-getcustomattributes\(system-reflection-assembly-system-boolean\))
* [Attribute.IsDefined(Assembly, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined\(system-reflection-assembly-system-type\))
* [Attribute.IsDefined(Assembly, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.isdefined#system-attribute-isdefined\(system-reflection-assembly-system-type-system-boolean\))
* [Attribute.GetCustomAttribute(Assembly, Type)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute\(system-reflection-assembly-system-type\))
* [Attribute.GetCustomAttribute(Assembly, Type, bool)](https://learn.microsoft.com/dotnet/api/system.attribute.getcustomattribute#system-attribute-getcustomattribute\(system-reflection-assembly-system-type-system-boolean\))
* [Attribute.Equals(Object)](https://learn.microsoft.com/dotnet/api/system.attribute.equals)
* [Attribute.GetHashCode()](https://learn.microsoft.com/dotnet/api/system.attribute.gethashcode)
* [Attribute.Match(Object)](https://learn.microsoft.com/dotnet/api/system.attribute.match)
* [Attribute.IsDefaultAttribute()](https://learn.microsoft.com/dotnet/api/system.attribute.isdefaultattribute)
* [Attribute.TypeId()](https://learn.microsoft.com/dotnet/api/system.attribute.typeid)
