Переключение вкладок в imgui

При создании сложных интерфейсов в инспекторе Unity иногда возникает необходиость создания чего-то вроде вкладок. Вкладки имеют одинаковую структуру, но разное содержание.

Для пример рассмотрим следующий класс:

using System.Linq;
using UnityEditor;
using UnityEngine;

public class User
{
    public string Name;
    public int Age;
}

class ListEditor : EditorWindow
{
    [MenuItem("Test/ListEditor")]
    static void Display()
    {
        var window = EditorWindow.CreateWindow<ListEditor>();
        window.Show();
    }

    public int _selected;
    public User[] _users = new[] { new User(), new User(), new User() };

    private void OnGUI()
    {
        var user = _users[_selected];

        user.Name = EditorGUILayout.TextField(user.Name);
        user.Age = EditorGUILayout.IntField(user.Age);

        _selected = GUILayout.Toolbar(_selected, _users.Select(x => x.Name).ToArray());
    }
}

Если поставить в таком окне фокус на текстовое поле и переключать вкладки то текстовое поле будет оставаться в фокусе, и будет показывать неправильное значение

Проблема

Это происходит из–за того, что Unity использует индексы элементов и с ее точки зрения ни какого переключения вкладок не произошло.

Решение

Для решения нужно “сообщить” юнити о том что содержимое изменилось. Для этого предназначена функция GUIUtility.GetControlID с помощью нее можно обозначить уникальность страницы. Для этого нужно передать уникальное число. Для этого подойдет хешкод объекта user.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private void OnGUI()
{
        var user = _users[_selected];

        var id = GUIUtility.GetControlID(user.GetHashCode(), FocusType.Passive);

        user.Name = EditorGUILayout.TextField(user.Name);
        user.Age = EditorGUILayout.IntField(user.Age);

        _selected = GUILayout.Toolbar(_selected, _users.Select(x => x.Name).ToArray());
}

Решение