No desenvolvimento com Unity, é possível personalizar a exibição de arrays no Inspector utilizando scripts do editor. A seguir, apresenta-se um exemplo prático.
Definição de Classe Personalizada
[System.Serializable]
public class Pessoa
{
public string nome;
public int idade;
}
Classe de Dados com ScriptableObject
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu]
public class DadosPessoa : ScriptableObject
{
public List<Pessoa> listaPessoas;
}
Exibição em Uma Única Linha por Elemento
Para exibir o conteúdo de cada elemanto em uma linha, é necessário criar um PropertyDrawer. Note que a API de layout automático não deve ser usada neste caso.
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(Pessoa))]
public class PessoaDrawer : PropertyDrawer
{
public override void OnGUI(Rect posicao, SerializedProperty propriedade, GUIContent etiqueta)
{
var spNome = propriedade.FindPropertyRelative("nome");
var spIdade = propriedade.FindPropertyRelative("idade");
var retangulo1 = new Rect(posicao.x, posicao.y, posicao.width * 0.5f, EditorGUIUtility.singleLineHeight);
var retangulo2 = new Rect(posicao.x + posicao.width * 0.5f + 40, posicao.y, posicao.width * 0.5f, EditorGUIUtility.singleLineHeight);
int nivelIndentacao = EditorGUI.indentLevel;
float larguraEtiqueta = EditorGUIUtility.labelWidth;
EditorGUI.indentLevel = 2;
EditorGUIUtility.labelWidth = 60;
EditorGUI.PropertyField(retangulo1, spNome, new GUIContent("Nome"));
EditorGUI.PropertyField(retangulo2, spIdade, new GUIContent("Idade"));
EditorGUI.indentLevel = nivelIndentacao;
EditorGUIUtility.labelWidth = larguraEtiqueta;
}
public override float GetPropertyHeight(SerializedProperty propriedade, GUIContent etiqueta)
{
return base.GetPropertyHeight(propriedade, etiqueta);
}
}
Personalização do Nome da Lista e dos Elementos
Para alterar o nome exibido da lista e dos elementos, pode-se implementar um editor personalizado utilizando ReorderableList.
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(DadosPessoa))]
public class DadosPessoaEditor : Editor
{
private SerializedProperty propriedadeLista;
private ReorderableList listaReordenavel;
private void OnEnable()
{
propriedadeLista = serializedObject.FindProperty("listaPessoas");
if (listaReordenavel == null)
{
listaReordenavel = new ReorderableList(serializedObject, propriedadeLista, true, true, true, true);
listaReordenavel.drawHeaderCallback += DesenharCabecalho;
listaReordenavel.drawElementCallback += DesenharElemento;
listaReordenavel.elementHeightCallback += ObterAlturaElemento;
}
}
private void DesenharCabecalho(Rect retangulo)
{
EditorGUI.LabelField(retangulo, "Lista de Pessoas");
}
private void DesenharElemento(Rect retangulo, int indice, bool ativo, bool focado)
{
var elemento = propriedadeLista.GetArrayElementAtIndex(indice);
var retanguloDobra = new Rect(retangulo.x, retangulo.y, retangulo.width, EditorGUIUtility.singleLineHeight);
int nivelIndentacao = EditorGUI.indentLevel;
EditorGUI.indentLevel = 1;
elemento.isExpanded = EditorGUI.Foldout(retanguloDobra, elemento.isExpanded, new GUIContent("Pessoa " + indice));
EditorGUI.indentLevel = nivelIndentacao;
if (elemento.isExpanded)
{
var retanguloConteudo = new Rect(retangulo.x, retangulo.y + retanguloDobra.height, retangulo.width, EditorGUI.GetPropertyHeight(elemento));
EditorGUI.PropertyField(retanguloConteudo, elemento);
}
}
private float ObterAlturaElemento(int indice)
{
var elemento = propriedadeLista.GetArrayElementAtIndex(indice);
float altura = EditorGUIUtility.singleLineHeight;
if (elemento.isExpanded)
altura += EditorGUI.GetPropertyHeight(elemento);
return altura;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
listaReordenavel.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
}