diff --git a/Alchemy/Assets/Alchemy/Editor/AlchemyEditor.cs b/Alchemy/Assets/Alchemy/Editor/AlchemyEditor.cs index 715f430..1ecd053 100644 --- a/Alchemy/Assets/Alchemy/Editor/AlchemyEditor.cs +++ b/Alchemy/Assets/Alchemy/Editor/AlchemyEditor.cs @@ -23,6 +23,8 @@ public abstract class AlchemyEditor : Editor #if ALCHEMY_SUPPORT_SERIALIZATION const string AlchemySerializationWarning = "In the current version, fields with the [AlchemySerializedField] attribute do not support editing multiple objects."; #endif + + void OnEnable() { @@ -96,6 +98,7 @@ public override VisualElement CreateInspectorGUI() return root; } + } #if !ALCHEMY_DISABLE_DEFAULT_EDITOR diff --git a/Alchemy/Assets/Alchemy/Editor/Elements/AlchemyPropertyField.cs b/Alchemy/Assets/Alchemy/Editor/Elements/AlchemyPropertyField.cs index 5305bce..be1b031 100644 --- a/Alchemy/Assets/Alchemy/Editor/Elements/AlchemyPropertyField.cs +++ b/Alchemy/Assets/Alchemy/Editor/Elements/AlchemyPropertyField.cs @@ -46,7 +46,7 @@ public AlchemyPropertyField(SerializedProperty property, Type type, bool isArray var drawer = AlchemyEditorUtility.CreateGroupDrawer(groupAttribute, targetType); var root = drawer.CreateRootElement(labelText); - InspectorHelper.BuildElements(property.serializedObject, root, property.GetValue(), name => property.FindPropertyRelative(name)); + InspectorHelper.BuildElements(property.serializedObject, root, IObjectAccessor.Create(property), name => property.FindPropertyRelative(name)); if (root is BindableElement bindableElement) bindableElement.BindProperty(property); element = root; } @@ -56,7 +56,7 @@ public AlchemyPropertyField(SerializedProperty property, Type type, bool isArray var clickable = InternalAPIHelper.GetClickable(foldout.Q()); InternalAPIHelper.SetAcceptClicksIfDisabled(clickable, true); - InspectorHelper.BuildElements(property.serializedObject, foldout, property.GetValue(), name => property.FindPropertyRelative(name)); + InspectorHelper.BuildElements(property.serializedObject, foldout, IObjectAccessor.Create(property), name => property.FindPropertyRelative(name)); foldout.BindProperty(property); element = foldout; } diff --git a/Alchemy/Assets/Alchemy/Editor/Elements/ClassField.cs b/Alchemy/Assets/Alchemy/Editor/Elements/ClassField.cs index 91334cc..6e51409 100644 --- a/Alchemy/Assets/Alchemy/Editor/Elements/ClassField.cs +++ b/Alchemy/Assets/Alchemy/Editor/Elements/ClassField.cs @@ -7,8 +7,8 @@ namespace Alchemy.Editor.Elements { public sealed class ClassField : VisualElement { - public ClassField(Type type, string label) : this(TypeHelper.CreateDefaultInstance(type), type, label) { } - public ClassField(object obj, Type type, string label) + // public ClassField(Type type, string label) : this(TypeHelper.CreateDefaultInstance(type), type, label) { } + public ClassField(IObjectAccessor accessor, Type type, string label) { var foldout = new Foldout { @@ -44,14 +44,14 @@ public ClassField(object obj, Type type, string label) // Add member elements foreach (var member in node.Members.OrderByAttributeThenByMemberType()) { - var element = new ReflectionField(obj, member); + var element = new ReflectionField(accessor, member); element.style.width = Length.Percent(100f); - element.OnValueChanged += x => OnValueChanged?.Invoke(obj); + element.OnValueChanged += x => OnValueChanged?.Invoke(accessor.Target); var e = node.Drawer?.GetGroupElement(member.GetCustomAttribute()); if (e == null) node.VisualElement.Add(element); else e.Add(element); - AlchemyAttributeDrawer.ExecutePropertyDrawers(null, null, obj, member, element); + AlchemyAttributeDrawer.ExecutePropertyDrawers(null, null, accessor.Target, member, element); } } diff --git a/Alchemy/Assets/Alchemy/Editor/Elements/DictionaryField.cs b/Alchemy/Assets/Alchemy/Editor/Elements/DictionaryField.cs index 400ee26..66035d6 100644 --- a/Alchemy/Assets/Alchemy/Editor/Elements/DictionaryField.cs +++ b/Alchemy/Assets/Alchemy/Editor/Elements/DictionaryField.cs @@ -97,14 +97,14 @@ public Item(object collection, object keyValuePair) }; box.Add(keyValueElement); - keyField = new GenericField(key, keyType, KeyName) + keyField = new GenericField(new IdentityAccessor(key), keyType, KeyName) { style = { flexGrow = 1f } }; keyField.OnValueChanged += SetKey; keyValueElement.Add(keyField); - - valueField = new GenericField(value, valueType, ValueName) + + valueField = new GenericField(new DelegateAccessor(()=>value,null), valueType, ValueName) { style = { flexGrow = 1f } }; diff --git a/Alchemy/Assets/Alchemy/Editor/Elements/GenericField.cs b/Alchemy/Assets/Alchemy/Editor/Elements/GenericField.cs index 828fd98..0c5660e 100644 --- a/Alchemy/Assets/Alchemy/Editor/Elements/GenericField.cs +++ b/Alchemy/Assets/Alchemy/Editor/Elements/GenericField.cs @@ -14,17 +14,17 @@ namespace Alchemy.Editor.Elements public sealed class GenericField : VisualElement { const string CreateButtonText = "Create..."; - - public GenericField(object obj, Type type, string label,bool isDelayed = false) + + public GenericField(IObjectAccessor accessor, Type type, string label,bool isDelayed = false) { - Build(obj, type, label, isDelayed); + Build(accessor, type, label, isDelayed); GUIHelper.ScheduleAdjustLabelWidth(this); } - void Build(object obj, Type type, string label, bool isDelayed) + void Build(IObjectAccessor accessor, Type type, string label, bool isDelayed) { Clear(); - + var obj = accessor.Target; // Add [Create...] button if (obj == null && !typeof(UnityEngine.Object).IsAssignableFrom(type)) { @@ -52,7 +52,7 @@ void Build(object obj, Type type, string label, bool isDelayed) nullLabelElement.Add(new Button(() => { var instance = ""; - Build(instance, type, label, isDelayed); + Build(new IdentityAccessor(instance), type, label, isDelayed); OnValueChanged?.Invoke(instance); }) { @@ -64,7 +64,7 @@ void Build(object obj, Type type, string label, bool isDelayed) nullLabelElement.Add(new Button(() => { var instance = Activator.CreateInstance(type, Activator.CreateInstance(type.GenericTypeArguments[0])); - Build(instance, type, label, isDelayed); + Build(new IdentityAccessor(instance), type, label, isDelayed); OnValueChanged?.Invoke(instance); }) { @@ -76,7 +76,7 @@ void Build(object obj, Type type, string label, bool isDelayed) nullLabelElement.Add(new Button(() => { var instance = TypeHelper.CreateDefaultInstance(type); - Build(instance, type, label, isDelayed); + Build(new IdentityAccessor(instance), type, label, isDelayed); OnValueChanged?.Invoke(instance); }) { @@ -89,7 +89,6 @@ void Build(object obj, Type type, string label, bool isDelayed) return; } - this.isDelayed = isDelayed; if (type == typeof(bool)) { @@ -246,36 +245,46 @@ void Build(object obj, Type type, string label, bool isDelayed) } else { - var field = new ClassField(obj, type, label); + var field = new ClassField(accessor, type, label); field.OnValueChanged += x => OnValueChanged?.Invoke(x); Add(field); } - } - - public event Action OnValueChanged; - bool isDelayed; - bool changed; - - void AddField(BaseField control, T value) - { - control.value = value; - if (isDelayed && control is not ObjectField) // ignore ObjectField + void AddField(BaseField control, T value) { - control.RegisterValueChangedCallback(x => changed = true); - control.RegisterCallback(x => + control.value = value; + + if (isDelayed && control is not ObjectField) // ignore ObjectField { - if (changed) + var changed = false; + control.RegisterValueChangedCallback(_ => changed = true); + control.RegisterCallback(_ => { - OnValueChanged?.Invoke(control.value); - changed = false; - } - }); - } - else - { - control.RegisterValueChangedCallback(x => OnValueChanged?.Invoke(x.newValue)); + if (changed) + { + OnValueChanged?.Invoke(control.value); + changed = false; + } + }); + } + else + { + control.RegisterValueChangedCallback(x => + { + OnValueChanged?.Invoke(x.newValue); + + }); + } + Add(control); + if (type.IsValueType&&accessor is not IdentityAccessor) + { + control.schedule.Execute(() => + { + control.value = (T)accessor.Target; + }).Until(()=>control.parent==null); + } } - Add(control); } + + public event Action OnValueChanged; } } \ No newline at end of file diff --git a/Alchemy/Assets/Alchemy/Editor/Elements/HashSetField.cs b/Alchemy/Assets/Alchemy/Editor/Elements/HashSetField.cs index 0682cb0..3019ae4 100644 --- a/Alchemy/Assets/Alchemy/Editor/Elements/HashSetField.cs +++ b/Alchemy/Assets/Alchemy/Editor/Elements/HashSetField.cs @@ -42,7 +42,7 @@ public override HashMapItemBase CreateItem(object collection, object elementObj, public sealed class Item : HashMapItemBase { - public Item(object collection, object elementObj, string label) + public Item(object collection, object elementObj, string label) { var box = new Box() { @@ -54,13 +54,14 @@ public Item(object collection, object elementObj, string label) }; var valueType = elementObj == null ? collection.GetType().GenericTypeArguments[0] : elementObj.GetType(); - - inputField = new GenericField(elementObj, valueType, label); + var accessor = new IdentityAccessor(elementObj); + inputField = new GenericField(accessor, valueType, label); inputField.style.flexGrow = 1f; inputField.OnValueChanged += x => { value = x; OnValueChanged?.Invoke(x); + accessor.Target = x; }; box.Add(inputField); diff --git a/Alchemy/Assets/Alchemy/Editor/Elements/ListField.cs b/Alchemy/Assets/Alchemy/Editor/Elements/ListField.cs index 6a76b6a..46d6fb0 100644 --- a/Alchemy/Assets/Alchemy/Editor/Elements/ListField.cs +++ b/Alchemy/Assets/Alchemy/Editor/Elements/ListField.cs @@ -32,7 +32,7 @@ public ListField(IList target, string label) var value = list[index]; var listType = list.GetType(); var valueType = value != null ? value.GetType() : listType.IsGenericType ? listType.GenericTypeArguments[0] : typeof(object); - var fieldElement = new GenericField(value, valueType, label); + var fieldElement = new GenericField(new DelegateAccessor(()=>list[((Item)element).index] ,newValue=>list[((Item)element).index]=newValue), valueType, label); element.Add(fieldElement); var labelElement = fieldElement.Q