Instantly share code, notes, and snippets.
Created
September 15, 2018 23:22
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save GhatSmith/2da8a581bcc6750300d718562f31e63f to your computer and use it in GitHub Desktop.
This file contains 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
// Based on : http://baba-s.hatenablog.com/entry/2014/07/30/152826 | |
using System; | |
using System.Linq; | |
using System.Reflection; | |
using UnityEngine; | |
#if UNITY_EDITOR | |
using UnityEditor; | |
#endif | |
/// <summary> Example of use : [ButtonAttribute ("MethodName", "ButtonNameInInspector", "TooltipInInspector", true, true, "param1", 10, "param3")] </summary> | |
[AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = true)] | |
public sealed class ButtonAttribute : PropertyAttribute | |
{ | |
public string Function { get; private set; } | |
public string ButtonName { get; private set; } | |
public object[] Parameters { get; private set; } | |
public bool OnlyInPlayMode { get; private set; } | |
public string Tooltip { get; private set; } | |
public bool DisplayVariable { get; private set; } | |
/// <summary> WARNING : not working with overloaded functions </summary> | |
public ButtonAttribute(string function, string name, string tooltip, bool onlyInPlayMode, bool displayVariable, params object[] parameters) | |
{ | |
Function = function; | |
ButtonName = name; | |
OnlyInPlayMode = onlyInPlayMode; | |
Tooltip = tooltip; | |
DisplayVariable = displayVariable; | |
Parameters = parameters; | |
} | |
} | |
#if UNITY_EDITOR | |
[CustomPropertyDrawer(typeof(ButtonAttribute))] | |
public sealed class ButtonDrawer : PropertyDrawer | |
{ | |
private ButtonAttribute typedAttribute; | |
public ButtonAttribute TypedAttribute | |
{ | |
get | |
{ | |
if (typedAttribute == null) typedAttribute = attribute as ButtonAttribute; | |
return typedAttribute; | |
} | |
} | |
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |
{ | |
if (TypedAttribute.DisplayVariable) | |
{ | |
EditorGUI.PropertyField(position, property, label, true); | |
position.y += EditorGUI.GetPropertyHeight(property, label, true); | |
position.y += 2; // add little space above helpbox | |
} | |
string tooltip = TypedAttribute.Tooltip; | |
if (TypedAttribute.OnlyInPlayMode && !Application.isPlaying) | |
{ | |
EditorGUI.BeginDisabledGroup(true); | |
if (string.IsNullOrEmpty(tooltip)) tooltip = "Button only available in play mode"; | |
else tooltip = TypedAttribute.Tooltip + " (button only available in play mode)"; | |
} | |
position.height = EditorGUI.GetPropertyHeight(property, label, true); | |
if (GUI.Button(position, new GUIContent(TypedAttribute.ButtonName, tooltip))) | |
{ | |
var objectReferenceValue = property.serializedObject.targetObject; | |
var type = objectReferenceValue.GetType(); | |
var bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; | |
try | |
{ | |
var method = type.GetMethod(TypedAttribute.Function, bindingAttr); | |
method.Invoke(objectReferenceValue, TypedAttribute.Parameters); | |
} | |
catch (AmbiguousMatchException) | |
{ | |
var format = @"{0}.{1} : AmbiguousMatchException. Unable to determine which overloaded function is called for {0}.{1}. Please delete overloading function"; | |
var message = string.Format(format, type.Name, TypedAttribute.Function); | |
Debug.LogError(message, objectReferenceValue); | |
} | |
catch (ArgumentException) | |
{ | |
var parameters = string.Join(", ", TypedAttribute.Parameters.Select(c => c.ToString()).ToArray()); | |
var format = @"{0}.{1} : ArgumentException. You can't pass argument {2} to the function {0}.{1}. Please verify the types of the arguments"; | |
var message = string.Format(format, type.Name, TypedAttribute.Function, parameters); | |
Debug.LogError(message, objectReferenceValue); | |
} | |
catch (NullReferenceException) | |
{ | |
var format = @"{0}.{1} : NullReferenceException. Undefined function. Please verify if function is defined in {0}.{1}"; | |
var message = string.Format(format, type.Name, TypedAttribute.Function); | |
Debug.LogError(message, objectReferenceValue); | |
} | |
catch (TargetParameterCountException) | |
{ | |
var parameters = string.Join(", ", TypedAttribute.Parameters.Select(c => c.ToString()).ToArray()); | |
var format = @"{0}.{1} : TargetParameterCountException. You can't pass argument {2} to the function {0}.{1}. Please verify the number of the parameters given to the function "; | |
var message = string.Format(format, type.Name, TypedAttribute.Function, parameters); | |
Debug.LogError(message, objectReferenceValue); | |
} | |
} | |
if (TypedAttribute.OnlyInPlayMode && !Application.isPlaying) EditorGUI.EndDisabledGroup(); | |
} | |
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |
{ | |
if (TypedAttribute.DisplayVariable) return EditorGUI.GetPropertyHeight(property, label, true) + GetButtonHeight(); | |
else return GetButtonHeight(); | |
} | |
public float GetButtonHeight() | |
{ | |
GUIContent content = new GUIContent(TypedAttribute.ButtonName); | |
GUIStyle style = GUI.skin.box; | |
style.alignment = TextAnchor.MiddleCenter; | |
// Compute how large the button needs to be. | |
Vector2 size = style.CalcSize(content); | |
return size.y; | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment