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 } }