Unity3D - PropertyAttribute - OnChanged Call a method (more options(arguments, playmodeOnly/editorOnly/Both & basic error checking)
using System.Linq; | |
using UnityEngine; | |
using UnityEditor; | |
using System; | |
public class OnChangedCallAttribute : PropertyAttribute | |
{ | |
public enum RunTimeCriteriaEnum | |
{ | |
EditorOnly, | |
PlayModeOnly, | |
Both | |
} | |
public string methodName; | |
public object[] arguments; | |
public RunTimeCriteriaEnum Criteria = RunTimeCriteriaEnum.Both; | |
public OnChangedCallAttribute(string methodNameNoArguments, RunTimeCriteriaEnum runTimeCriteria = RunTimeCriteriaEnum.Both) | |
{ | |
methodName = methodNameNoArguments; | |
arguments = new object[0]; | |
Criteria = runTimeCriteria; | |
} | |
public OnChangedCallAttribute(string methodNameNoArguments, object[] arguments, RunTimeCriteriaEnum runTimeCriteria = RunTimeCriteriaEnum.Both) | |
{ | |
methodName = methodNameNoArguments; | |
this.arguments = arguments; | |
Criteria = runTimeCriteria; | |
} | |
} | |
#if UNITY_EDITOR | |
[CustomPropertyDrawer(typeof(OnChangedCallAttribute))] | |
public class OnChangedCallAttributePropertyDrawer : PropertyDrawer | |
{ | |
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |
{ | |
EditorGUI.BeginChangeCheck(); | |
EditorGUI.PropertyField(position, property); | |
if (EditorGUI.EndChangeCheck()) | |
{ | |
OnChangedCallAttribute at = attribute as OnChangedCallAttribute; | |
//Exit if it is not in the right play mode | |
if (at.Criteria != OnChangedCallAttribute.RunTimeCriteriaEnum.Both | |
&& ((!EditorApplication.isPlaying && at.Criteria == OnChangedCallAttribute.RunTimeCriteriaEnum.PlayModeOnly) | |
|| (EditorApplication.isPlaying && at.Criteria == OnChangedCallAttribute.RunTimeCriteriaEnum.EditorOnly))) | |
return; | |
Type parentType = property.serializedObject.targetObject.GetType(); | |
var findMethod = parentType.GetMethods().Where(m => m.Name == at.methodName).ToList(); | |
if(findMethod.Count() == 0) // Found? | |
{ | |
Debug.LogError(string.Format("Error: [OnChangedCall(\"{0}\")] Method Name in ({1}) not found. Did you perhaps typo?", at.methodName, parentType.ToString())); | |
return; | |
} | |
var method = findMethod.First(); | |
if(method.GetParameters().Length != at.arguments.Length) // All arguments supplied? | |
{ | |
Debug.LogError(string.Format("Error: [OnChangedCall] {0} in ({1}) Requires {2} arguments {3} supplied.", at.methodName, parentType.ToString(), method.GetParameters().Length, at.arguments.Length)); | |
return; | |
} | |
method.Invoke(property.serializedObject.targetObject, at.arguments); | |
} | |
} | |
} | |
#endif |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class OnChangedCallTester : MonoBehaviour | |
{ | |
public bool UpdateProp = true; | |
[SerializeField] | |
[OnChangedCall("ImChanged")] | |
private int myPropVar; | |
[SerializeField] | |
[OnChangedCall("TYPO")] | |
private int TypoInt; | |
[SerializeField] | |
[OnChangedCall("ArgumentTest",new object[]{"INSERTARG"})] | |
private int testArgument; | |
[SerializeField] | |
[OnChangedCall("ArgumentTest")] | |
private int OopsForgotArg; | |
[OnChangedCall("EditorModeOnly", OnChangedCallAttribute.RunTimeCriteriaEnum.EditorOnly)] | |
public int EditorOnly = 0; | |
[OnChangedCall("PlayModeOnly", OnChangedCallAttribute.RunTimeCriteriaEnum.PlayModeOnly)] | |
public int PlayOnly = 0; | |
public int MyProperty | |
{ | |
get { return myPropVar; } | |
set { myPropVar = value; ImChanged(); } | |
} | |
public void ArgumentTest(string test) | |
{ | |
Debug.Log(test); | |
} | |
public void PlayModeOnly() | |
{ | |
Debug.Log("PlayMode"); | |
} | |
public void EditorModeOnly() | |
{ | |
Debug.Log("Editor"); | |
} | |
public void ImChanged() | |
{ | |
Debug.Log("I have changed to " + myPropVar); | |
} | |
private void Update() | |
{ | |
if(UpdateProp) | |
MyProperty++; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment