using System; using System.Reflection; using Alchemy.Inspector; using UnityEditor; using UnityEngine; using UnityEngine.UIElements; namespace Alchemy.Editor.Elements { public sealed class ReflectionField : VisualElement { public ReflectionField(object target, MemberInfo memberInfo) { Rebuild(target, memberInfo); } public void Rebuild(object target, MemberInfo memberInfo) { Clear(); if (memberInfo is MethodInfo methodInfo) { if (methodInfo.HasCustomAttribute()) { var button = new MethodButton(target, methodInfo); if (methodInfo.TryGetCustomAttribute(out LabelTextAttribute labelText)) { button.SetLableText(labelText.Text); } Add(button); } return; } object value; GenericField element; switch (memberInfo) { default: return; case FieldInfo fieldInfo: value = fieldInfo.IsStatic ? fieldInfo.GetValue(null) : target == null ? TypeHelper.GetDefaultValue(fieldInfo.FieldType) : fieldInfo.GetValue(target); var fieldType = target == null ? fieldInfo.FieldType : fieldInfo.GetValue(target)?.GetType() ?? fieldInfo.FieldType; element = new GenericField(value, fieldType, ObjectNames.NicifyVariableName(memberInfo.Name), true); element.OnValueChanged += x => { OnBeforeValueChange?.Invoke(target); fieldInfo.SetValue(target, x); // Force serialization if (target is ISerializationCallbackReceiver receiver) { receiver.OnBeforeSerialize(); } OnValueChanged?.Invoke(target); }; break; case PropertyInfo propertyInfo: if (!propertyInfo.HasCustomAttribute()) return; if (!propertyInfo.CanRead) return; value = propertyInfo.GetMethod.IsStatic ? propertyInfo.GetValue(null) : target == null ? TypeHelper.GetDefaultValue(propertyInfo.PropertyType) : propertyInfo.GetValue(target); var propertyType = target == null ? propertyInfo.PropertyType : propertyInfo.GetValue(target)?.GetType() ?? propertyInfo.PropertyType; element = new GenericField(value, propertyType, ObjectNames.NicifyVariableName(memberInfo.Name), true); element.OnValueChanged += x => { OnBeforeValueChange?.Invoke(target); if (propertyInfo.CanWrite) propertyInfo.SetValue(target, x); // Force serialization if (target is ISerializationCallbackReceiver receiver) { receiver.OnBeforeSerialize(); } OnValueChanged?.Invoke(target); }; element.SetEnabled(propertyInfo.CanWrite); break; } Add(element); } public event Action OnBeforeValueChange; public event Action OnValueChanged; } }