using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Jovian.Utilities;
using UnityEngine;
namespace Jovian.InspectorTools
{
///
/// Finds all objects in the project of 'objectType' then creates a dropdown showing all values matching 'memberName'
/// E.g. Find all 'ScriptableObject' and list their 'name' values in a list.
///
public class ObjectsPropertyAttribute : PropertyAttribute
{
public readonly Type objectType;
public readonly string memberName;
public ObjectsPropertyAttribute(Type objectType, string memberName)
{
this.objectType = objectType;
this.memberName = memberName;
}
}
}
#if UNITY_EDITOR
namespace Jovian.InspectorTools.Internal
{
using UnityEditor;
using System.Reflection;
[CustomPropertyDrawer(typeof(ObjectsPropertyAttribute))]
public class ObjectsPropertyAttributeDrawer : PropertyDrawer
{
private bool isInitialized;
private bool hasValidTarget;
private string[] values;
private int selectedIndex = -1;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType != SerializedPropertyType.String)
{
label.text = $"(!) {label.text}";
label.tooltip = $"ObjectPropertiesAttribute only works on strings.\n\n{label.tooltip}";
EditorGUI.PropertyField(position, property, label);
return;
}
if (!isInitialized)
{
Initialize(property.stringValue);
}
EditorGUI.BeginChangeCheck();
selectedIndex = Array.IndexOf(values, property.stringValue);
selectedIndex = EditorGUI.Popup(position, label.text, selectedIndex, values);
if (EditorGUI.EndChangeCheck())
{
property.stringValue = values[selectedIndex];
property.serializedObject.ApplyModifiedProperties();
}
}
private void Initialize(string currentValue)
{
ObjectsPropertyAttribute objectsPropertyAttribute = (ObjectsPropertyAttribute)attribute;
List objectsOfType =
AssetUtility.FindAllAssetsInProject(objectsPropertyAttribute.objectType);
const BindingFlags searchFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance;
FieldInfo field = objectsPropertyAttribute.objectType.GetFields(searchFlags)
.FirstOrDefault(memberInfo => memberInfo.Name == objectsPropertyAttribute.memberName);
PropertyInfo property = objectsPropertyAttribute.objectType.GetProperties(searchFlags)
.FirstOrDefault(memberInfo => memberInfo.Name == objectsPropertyAttribute.memberName);
if (field != null)
{
values = objectsOfType.Select(obj => field.GetValue(obj).ToString()).ToArray();
}
else if (property != null)
{
values = objectsOfType.Select(obj => property.GetValue(obj).ToString()).ToArray();
}
else
{
values = new string[] { };
Debug.LogError($"Cannot find member '{objectsPropertyAttribute.memberName}' for type '{objectsPropertyAttribute.objectType.Name}'");
}
isInitialized = true;
selectedIndex = Array.IndexOf(values, currentValue);
}
}
}
#endif