Skip to content

Instantly share code, notes, and snippets.

@pacoelayudante
Last active October 15, 2023 01:35
Show Gist options
  • Save pacoelayudante/04645f4c30666f45f1352bb06bc6137e to your computer and use it in GitHub Desktop.
Save pacoelayudante/04645f4c30666f45f1352bb06bc6137e to your computer and use it in GitHub Desktop.
despues la actualizao
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
#endif
///<summary>
/// Es así la cosa, se lo pones a un object reference e indicas que metodo de busqueda usar
/// de ahi se muestra drop down al costado que encuentra las opciones viables
/// tambien hay un flag para indicar si queres que te alerte si el valor esta null
///</summary>
public class AutoBuscarObjetoAttribute : PropertyAttribute
{
public enum Metodo
{
GetComponent, // solo valido para comps (scriptable objet no tiene sus propios componentes)
GetComponentInChildren, // idem
FindObjectOfType // ver temita de los prefab stage y supongo de escenas diferentes y eso
}
private Metodo _metodo;
public AutoBuscarObjetoAttribute(Metodo metodo)
{
_metodo = metodo;
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(AutoBuscarObjetoAttribute))]
public class ObjectFieldAutoFinderAttributeEditor : PropertyDrawer
{
private const string LIMPIAR = "> Limpiar_";
private static readonly string[] LISTA_VACIA = new string[0];
private static readonly string[] MULTI_INVALIDO = new string[] { LIMPIAR, "GetComponent invalido para seleccion multiple :(" };
private static readonly string[] NADA_ENCONTRADO = new string[] { LIMPIAR, "Ninguna opcion encontrada :(" };
private static readonly string[] MULTI_STAGE = new string[] { LIMPIAR, "Objetos de diferentes Stages seleccionados :(" };
private static List<Object> objetosEncontrados = new(16);
private const float ANCHO = 20f;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType != SerializedPropertyType.ObjectReference)
{
// icono o algo avisando que no se puede
EditorGUI.PropertyField(position, property, label);
return;
}
position.width -= ANCHO;
EditorGUI.PropertyField(position, property, label);
position.x = position.xMax;
position.width = ANCHO;
var metodoDeBusqueda = ((AutoBuscarObjetoAttribute)attribute)._metodo;
var serializedObject = property.serializedObject;
bool multiValorInvalido = metodoDeBusqueda != Metodo.FindObjectOfType
&& serializedObject.isEditingMultipleObjects;
using (var change = new EditorGUI.ChangeCheckScope())
{
string[] opciones = null;
if (Event.current.type == EventType.MouseDown && position.Contains(Event.current.mousePosition))
{
if (multiValorInvalido)
opciones = MULTI_INVALIDO;
else
opciones = GenerarOpciones(metodoDeBusqueda, property, serializedObject);
}
else
{
opciones = LISTA_VACIA;
}
var indiceMasUno = EditorGUI.Popup(position, -1, opciones);
if (change.changed && !multiValorInvalido && objetosEncontrados.Count > 0)
{
if (indiceMasUno == 0)
property.objectReferenceValue = null;
else if (!multiValorInvalido && objetosEncontrados.Count > 0)
{
var objetoElegido = objetosEncontrados[indiceMasUno - 1];
property.objectReferenceValue = objetoElegido;
if (objetoElegido != null)
EditorGUIUtility.PingObject(property.objectReferenceValue);
}
}
}
}
public string[] GenerarOpciones(Metodo metodo, SerializedProperty property, SerializedObject serializedObject)
{
// get type
var targetObject = serializedObject.targetObject;
var targetObjectType = targetObject.GetType();
var fieldInfo = targetObjectType.GetField( property.propertyPath, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance);
var tipo = fieldInfo.FieldType;
objetosEncontrados.Clear();
if (metodo == Metodo.GetComponent)
{
}
else if (metodo == Metodo.GetComponentInChildren)
{
if (targetObject is Component comp)
{
// me suena que en realidad la unica parte que tengo que branchear
// es la de Get o Find lo demas esta bien que sea todo igual
var encontrados = comp.GetComponentsInChildren(tipo, includeInactive: true);
if (encontrados.Length == 0)
return NADA_ENCONTRADO;
else
{
var listaDeNombres = new string[encontrados.Length + 1];
listaDeNombres[0] = LIMPIAR;
for (int i = 0; i < encontrados.Length; i++)
{
var encontrado = encontrados[i];
objetosEncontrados.Add(encontrado);
// deberia mostrar el hierarchy name (al menos el parent/root?)
listaDeNombres[i + 1] = encontrado.name;
}
return listaDeNombres;
}
}
}
if (metodo == Metodo.FindObjectOfType)
{
// falta resolver temita del stage - prefab stage
var encontrados = Object.FindObjectsOfType(tipo, includeInactive: true);
if (encontrados.Length == 0)
return NADA_ENCONTRADO;
else
{
var listaDeNombres = new string[encontrados.Length + 1];
listaDeNombres[0] = LIMPIAR;
for (int i = 0; i < encontrados.Length; i++)
{
var encontrado = encontrados[i];
objetosEncontrados.Add(encontrado);
// deberia mostrar el hierarchy name (al menos el parent/root?)
listaDeNombres[i + 1] = encontrado.name;
}
return listaDeNombres;
}
}
else
{
// get comp local <- este es mas facil podria estar primero
// get comp in child <- este no deberia necesitar el tema de staging creo
return new string[0];
}
}
}
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment