Last active
May 19, 2025 17:07
-
-
Save Arc-huangjingtong/ddf510af71aea8dbce74a3c41b6ba5d6 to your computer and use it in GitHub Desktop.
UnityShowDictionaryInspectors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if UNITY_EDITOR | |
using UnityEditor; | |
#endif | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Reflection; | |
using UnityEngine; | |
public class DictionaryDrawerAttribute : PropertyAttribute | |
{ | |
public readonly string TargetDictName; | |
public DictionaryDrawerAttribute(string targetDictionaryName) => TargetDictName = targetDictionaryName; | |
} | |
#if UNITY_EDITOR | |
[CustomPropertyDrawer(typeof(DictionaryDrawerAttribute))] | |
public class ProxyDictionaryDrawer : PropertyDrawer | |
{ | |
private static readonly Dictionary<string, bool> FoldoutStates = new(); | |
private const float LineHeight = 20f; | |
private const float FoldoutWidth = 15f; | |
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |
{ | |
if (attribute is not DictionaryDrawerAttribute attr) return; | |
var targetObject = property.serializedObject.targetObject; | |
var dictField = targetObject.GetType().GetField(attr.TargetDictName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); | |
if (dictField == null || !typeof(IDictionary).IsAssignableFrom(dictField.FieldType)) | |
{ | |
EditorGUI.HelpBox(position, $"Dictionary '{attr.TargetDictName}' not found", MessageType.Error); | |
return; | |
} | |
label.text = attr.TargetDictName; | |
var dict = dictField.GetValue(targetObject) as IDictionary; | |
DrawDictionaryProxy(position, property, dict, label); | |
} | |
private void DrawDictionaryProxy(Rect position, SerializedProperty property, IDictionary dict, GUIContent label) | |
{ | |
var stateKey = $"{property.propertyPath}_{property.serializedObject.GetHashCode()}"; | |
FoldoutStates.TryAdd(stateKey, false); | |
var headerRect = new Rect(position.x, position.y, position.width, LineHeight); | |
FoldoutStates[stateKey] = EditorGUI.Foldout(headerRect, FoldoutStates[stateKey], label, true); | |
if (!FoldoutStates[stateKey]) return; | |
var y = position.y + LineHeight; | |
var index = 0; | |
try | |
{ | |
foreach (DictionaryEntry entry in dict) | |
{ | |
var lineRect = new Rect(position.x + FoldoutWidth, y, position.width - FoldoutWidth, LineHeight); | |
DrawDictionaryLine(lineRect, entry); | |
y += LineHeight; | |
} | |
} | |
catch (InvalidOperationException) | |
{ | |
// 处理迭代过程中字典被修改的情况 | |
} | |
} | |
private void DrawDictionaryLine(Rect rect, DictionaryEntry entry) | |
{ | |
GUI.enabled = false; | |
var keyContent = entry.Key != null ? entry.Key.ToString() : "null"; | |
var valueContent = entry.Value != null ? entry.Value.ToString() : "null"; | |
EditorGUI.TextField(new Rect(rect.x, rect.y, rect.width / 2 - 5, LineHeight), | |
$"{keyContent}"); | |
EditorGUI.TextField(new Rect(rect.x + rect.width / 2 + 5, rect.y, rect.width / 2 - 5, LineHeight), | |
$"{valueContent}"); | |
GUI.enabled = true; | |
} | |
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |
{ | |
var attr = attribute as DictionaryDrawerAttribute; | |
if (attr == null) return LineHeight; | |
var targetObject = property.serializedObject.targetObject; | |
var dictField = targetObject.GetType().GetField(attr.TargetDictName, | |
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); | |
if (dictField?.GetValue(targetObject) is not IDictionary dict) return LineHeight; | |
var stateKey = $"{property.propertyPath}_{property.serializedObject.GetHashCode()}"; | |
return FoldoutStates.TryGetValue(stateKey, out var expanded) && expanded | |
? LineHeight * (dict.Count + 1) | |
: LineHeight; | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment