From 20faf1bef51f7e0120787ef42f26f54afb408e0a Mon Sep 17 00:00:00 2001 From: VladV Date: Wed, 21 Jun 2023 21:48:08 +0400 Subject: [PATCH] Add drawer for Button with parameters --- Editor.Extras/Drawers/ButtonDrawer.cs | 99 +++++++++++++++---- .../Buttons/Buttons_ButtonSample.cs | 6 ++ Editor/TriPropertyDefinition.cs | 16 ++- README.md | 9 +- Runtime/Attributes/ButtonAttribute.cs | 3 +- 5 files changed, 105 insertions(+), 28 deletions(-) diff --git a/Editor.Extras/Drawers/ButtonDrawer.cs b/Editor.Extras/Drawers/ButtonDrawer.cs index 434a5e5..ef9b418 100644 --- a/Editor.Extras/Drawers/ButtonDrawer.cs +++ b/Editor.Extras/Drawers/ButtonDrawer.cs @@ -2,7 +2,9 @@ using System.Reflection; using TriInspector; using TriInspector.Drawers; +using TriInspector.Elements; using TriInspector.Resolvers; +using TriInspector.Utilities; using UnityEditor; using UnityEngine; @@ -16,12 +18,10 @@ public class ButtonDrawer : TriAttributeDrawer public override TriExtensionInitializationResult Initialize(TriPropertyDefinition propertyDefinition) { - var isValidMethod = propertyDefinition.TryGetMemberInfo(out var memberInfo) && - memberInfo is MethodInfo mi && - mi.GetParameters().Length == 0; + var isValidMethod = propertyDefinition.TryGetMemberInfo(out var memberInfo) && memberInfo is MethodInfo; if (!isValidMethod) { - return "[Button] valid only on methods without parameters"; + return "[Button] valid only on methods"; } _nameResolver = ValueResolver.ResolveString(propertyDefinition, Attribute.Name); @@ -33,33 +33,94 @@ memberInfo is MethodInfo mi && return TriExtensionInitializationResult.Ok; } - public override float GetHeight(float width, TriProperty property, TriElement next) + public override TriElement CreateElement(TriProperty property, TriElement next) { - if (Attribute.ButtonSize != 0) - { - return Attribute.ButtonSize; - } - - return EditorGUIUtility.singleLineHeight; + return new TriButtonElement(property, Attribute, _nameResolver); } - public override void OnGUI(Rect position, TriProperty property, TriElement next) + private class TriButtonElement : TriHeaderGroupBaseElement { - var name = _nameResolver.GetValue(property); + private readonly TriProperty _property; + private readonly ButtonAttribute _attribute; + private readonly ValueResolver _nameResolver; + private readonly object[] _invocationArgs; - if (string.IsNullOrEmpty(name)) + public TriButtonElement(TriProperty property, ButtonAttribute attribute, + ValueResolver nameResolver) { - name = property.DisplayName; + _property = property; + _attribute = attribute; + _nameResolver = nameResolver; + + var mi = property.TryGetMemberInfo(out var memberInfo) + ? (MethodInfo) memberInfo + : throw new Exception("TriButtonElement requires MethodInfo"); + + var parameters = mi.GetParameters(); + + _invocationArgs = new object[parameters.Length]; + + for (var i = 0; i < parameters.Length; i++) + { + var pIndex = i; + var pInfo = parameters[pIndex]; + + if (pInfo.HasDefaultValue) + { + _invocationArgs[pIndex] = pInfo.DefaultValue; + } + + var pTriDefinition = TriPropertyDefinition.CreateForGetterSetter( + pIndex, pInfo.Name, pInfo.ParameterType, + ((self, targetIndex) => _invocationArgs[pIndex]), + ((self, targetIndex, value) => _invocationArgs[pIndex] = value)); + + var pTriProperty = new TriProperty(_property.PropertyTree, _property, pTriDefinition, null); + + AddChild(new TriPropertyElement(pTriProperty)); + } } - if (string.IsNullOrEmpty(name)) + protected override float GetHeaderHeight(float width) { - name = property.RawName; + return GetButtonHeight(); + } + + protected override void DrawHeader(Rect position) + { + if (_invocationArgs.Length > 0) + { + TriEditorGUI.DrawBox(position, TriEditorStyles.TabOnlyOne); + } + + var name = _nameResolver.GetValue(_property); + + if (string.IsNullOrEmpty(name)) + { + name = _property.DisplayName; + } + + if (string.IsNullOrEmpty(name)) + { + name = _property.RawName; + } + + var buttonRect = new Rect(position) + { + height = GetButtonHeight(), + }; + + if (GUI.Button(buttonRect, name)) + { + InvokeButton(_property, _invocationArgs); + } } - if (GUI.Button(position, name)) + private float GetButtonHeight() { - InvokeButton(property, Array.Empty()); + return _attribute.ButtonSize != 0 + ? _attribute.ButtonSize + : EditorGUIUtility.singleLineHeight; } } diff --git a/Editor.Samples/Buttons/Buttons_ButtonSample.cs b/Editor.Samples/Buttons/Buttons_ButtonSample.cs index 21999dd..968bfed 100644 --- a/Editor.Samples/Buttons/Buttons_ButtonSample.cs +++ b/Editor.Samples/Buttons/Buttons_ButtonSample.cs @@ -8,4 +8,10 @@ private void DoButton() { Debug.Log("Button clicked!"); } + + [Button(ButtonSizes.Large)] + private void DoButtonWithParameters(Vector3 vec, string str = "default value") + { + Debug.Log($"Button with parameters: {vec} {str}"); + } } \ No newline at end of file diff --git a/Editor/TriPropertyDefinition.cs b/Editor/TriPropertyDefinition.cs index a35fe2a..75cdcb0 100644 --- a/Editor/TriPropertyDefinition.cs +++ b/Editor/TriPropertyDefinition.cs @@ -18,7 +18,7 @@ public class TriPropertyDefinition private readonly List _extensionErrors = new List(); private readonly MemberInfo _memberInfo; private readonly List _attributes; - private readonly bool _isNonPolymorphicSerializedByUnity; + private readonly bool _skipNullValuesFix; private TriPropertyDefinition _arrayElementDefinitionBackingField; @@ -53,6 +53,14 @@ private static TriPropertyDefinition CreateForMemberInfo( memberInfo, ownerType, order, propertyName, propertyType, valueGetter, valueSetter, attributes, false); } + internal static TriPropertyDefinition CreateForGetterSetter( + int order, string name, Type fieldType, + ValueGetterDelegate valueGetter, ValueSetterDelegate valueSetter) + { + return new TriPropertyDefinition( + null, null, order, name, fieldType, valueGetter, valueSetter, null, false); + } + internal TriPropertyDefinition( MemberInfo memberInfo, Type ownerType, @@ -74,9 +82,7 @@ internal TriPropertyDefinition( _valueGetter = valueGetter; _valueSetter = valueSetter; - _isNonPolymorphicSerializedByUnity = memberInfo is FieldInfo fi && - TriUnitySerializationUtilities.IsSerializableByUnity(fi) && - fi.GetCustomAttribute() == null; + _skipNullValuesFix = memberInfo != null && memberInfo.GetCustomAttribute() != null; Order = order; IsReadOnly = _valueSetter == null || Attributes.TryGet(out ReadOnlyAttribute _); @@ -150,7 +156,7 @@ public object GetValue(TriProperty property, int targetIndex) { var value = _valueGetter(property, targetIndex); - if (value == null && _isNonPolymorphicSerializedByUnity) + if (value == null && !_skipNullValuesFix) { value = TriUnitySerializationUtilities.PopulateUnityDefaultValueForType(FieldType); diff --git a/README.md b/README.md index 297a479..762770f 100644 --- a/README.md +++ b/README.md @@ -544,13 +544,16 @@ public float val; #### Button -![Button](https://user-images.githubusercontent.com/26966368/168235907-2b5ed6d4-d00b-4cd6-999c-432abd0a2230.png) +![Button](https://github.com/codewriter-packages/Tri-Inspector/assets/26966368/76f4a3a4-4bf9-4f58-8615-17adb986ab81) ```csharp [Button("Click me!")] -private void DoButton() +private void Button() => Debug.Log("Button clicked!"); + +[Button(ButtonSizes.Large)] +private void ButtonWithParameters(Vector3 vec, string str = "default value") { - Debug.Log("Button clicked!"); + Debug.Log($"Button with parameters: {vec} {str}"); } ``` diff --git a/Runtime/Attributes/ButtonAttribute.cs b/Runtime/Attributes/ButtonAttribute.cs index a7657b5..e86a26e 100644 --- a/Runtime/Attributes/ButtonAttribute.cs +++ b/Runtime/Attributes/ButtonAttribute.cs @@ -16,9 +16,10 @@ public ButtonAttribute(string name) Name = name; } - public ButtonAttribute(ButtonSizes buttonSize) + public ButtonAttribute(ButtonSizes buttonSize, string name = null) { ButtonSize = (int) buttonSize; + Name = name; } public string Name { get; set; }