using System;
#if UNITY_EDITOR
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
#endif
namespace Golems.Attributes
{
///
/// Show the EditorInspectableLevel property on the field.
///
[AttributeUsage(AttributeTargets.Field)]
public class ShowLevelAttribute : Attribute
{
public bool ShowWhenNotPlaying
{
get;
private set;
}
public ShowLevelAttribute()
{
ShowWhenNotPlaying = false;
}
public ShowLevelAttribute(bool showWhenNotPlaying)
{
ShowWhenNotPlaying = showWhenNotPlaying;
}
#if UNITY_EDITOR
private const BindingFlags k_ShowLevelBindingFlags = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.DeclaredOnly;
private static readonly List s_Fields = new List();
private static GUIStyle s_LabelStyle = null;
private const string k_EditorLevelProperty = "EditorInspectableLevel";
public static void EditorShowLevelInfo(UnityEngine.Object target, string label)
{
s_Fields.Clear();
GetShowLevelAttributeFields(target, s_Fields, EditorApplication.isPlaying);
if (s_Fields.Count <= 0)
{
return;
}
if (!string.IsNullOrEmpty(label))
{
if (s_LabelStyle == null)
{
s_LabelStyle = EditorStyles.boldLabel;
s_LabelStyle.richText = true;
}
EditorGUILayout.LabelField(label, s_LabelStyle);
}
var origIndent = EditorGUI.indentLevel;
EditorGUI.indentLevel += 1;
for (int i = 0; i < s_Fields.Count; i++)
{
var field = s_Fields[i];
var niceName = ObjectNames.NicifyVariableName(field.Name);
var fieldValue = field.GetValue(target);
if (fieldValue != null)
{
var levelProperty = GetLevelNoSideEffectsProperty(fieldValue);
if (levelProperty != null)
{
var levelValue = levelProperty.GetValue(fieldValue);
var level = levelValue;
EditorGUI.BeginDisabledGroup(true);
EditorGUI.EndDisabledGroup();
}
else
{
EditorGUILayout.LabelField($"{niceName} does not implement LevelNoSideEffects");
}
}
else
{
EditorGUILayout.LabelField($"{niceName} is null");
}
}
EditorGUI.indentLevel = origIndent;
}
private static void GetShowLevelAttributeFields(object target, List resList, bool appPlaying)
{
int count = 0;
for (var currentType = target.GetType(); currentType != null; currentType = currentType.BaseType)
{
if (count == 100)
{
return;
}
var fields = currentType.GetFields(k_ShowLevelBindingFlags);
//
// Search for ShowLevelAttribute within each field on this Object
//
for (int i = 0, counti = fields.Length; i < counti; ++i)
{
var field = fields[i];
var showLevelAttribute = field.GetCustomAttribute(true);
if (showLevelAttribute == null)
continue;
if (!appPlaying && !showLevelAttribute.ShowWhenNotPlaying)
{
continue;
}
resList.Add(field);
}
count += 1;
}
}
private static PropertyInfo GetLevelNoSideEffectsProperty(object fieldValue)
{
var properties = fieldValue.GetType().GetProperties(BindingFlags.GetProperty |
BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < properties.Length; i++)
{
var property = properties[i];
if (k_EditorLevelProperty.CompareTo(property.Name) == 0)
{
return property;
}
}
return null;
}
#endif
}
}