Created
July 28, 2019 16:31
-
-
Save CustomPhase/5adf565b92cf247d1d658ffc7abcf995 to your computer and use it in GitHub Desktop.
Custom reorderable UnityActions
This file contains hidden or 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
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
[System.Serializable] | |
public class CustomUnityAction { | |
[SerializeField] | |
public List<SerializableAction> actions; | |
public void Invoke() | |
{ | |
if (actions != null) | |
{ | |
for (int i = 0; i < actions.Count; i++) | |
{ | |
actions[i].Invoke(); | |
} | |
} | |
} | |
} |
This file contains hidden or 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
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEditor; | |
[CustomPropertyDrawer(typeof(CustomUnityAction))] | |
public class CustomUnityActionDrawer : PropertyDrawer { | |
public override float GetPropertyHeight(SerializedProperty property, UnityEngine.GUIContent label) | |
{ | |
return getList(property.FindPropertyRelative("actions")).GetHeight()+8; | |
} | |
private UnityEditorInternal.ReorderableList list; | |
private string propName; | |
private UnityEditorInternal.ReorderableList getList(SerializedProperty property) | |
{ | |
if (list == null) | |
{ | |
list = new UnityEditorInternal.ReorderableList(property.serializedObject, property, true, true, true, true); | |
list.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => | |
{ | |
rect.width -= 5; | |
rect.x += 5; | |
EditorGUI.PropertyField(rect, property.GetArrayElementAtIndex(index), true); | |
}; | |
list.drawHeaderCallback += DrawHeader; | |
} | |
return list; | |
} | |
private void DrawHeader(Rect rect) | |
{ | |
GUI.Label(rect, propName, EditorStyles.boldLabel); | |
} | |
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |
{ | |
// Using BeginProperty / EndProperty on the parent property means that | |
// prefab override logic works on the entire property. | |
EditorGUI.BeginProperty(position, label, property); | |
propName = ObjectNames.NicifyVariableName(property.name); | |
var listProperty = property.FindPropertyRelative("actions"); | |
var list = getList(listProperty); | |
var height = 0f; | |
for (var i = 0; i < listProperty.arraySize; i++) | |
{ | |
height = Mathf.Max(height, EditorGUI.GetPropertyHeight(listProperty.GetArrayElementAtIndex(i))); | |
} | |
list.elementHeight = height; | |
position.x += 4; | |
list.DoList(position); | |
EditorGUI.EndProperty(); | |
} | |
} |
This file contains hidden or 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
using System; | |
using System.IO; | |
using System.Runtime.Serialization.Formatters.Binary; | |
using UnityEngine; | |
[Serializable] | |
public class SerializableAction | |
{ | |
[SerializeField] | |
private UnityEngine.Object _target; | |
[SerializeField] | |
private string _methodName = ""; | |
[SerializeField] | |
private byte[] _serialData = { }; | |
[SerializeField] | |
private GameObject go; | |
Action _action; | |
public void Invoke() | |
{ | |
if (_action == null) | |
{ | |
_action = CreateDelegate(); | |
} | |
_action.Invoke(); | |
} | |
public void SetDelegate(Action action) | |
{ | |
if (action == null) | |
{ | |
_target = null; | |
_methodName = ""; | |
_serialData = new byte[] { }; | |
return; | |
} | |
var delAction = action as Delegate; | |
if (delAction == null) | |
{ | |
throw new InvalidOperationException(typeof(Action).Name + " is not a delegate type."); | |
} | |
_target = delAction.Target as UnityEngine.Object; | |
if (_target != null) | |
{ | |
_methodName = delAction.Method.Name; | |
_serialData = null; | |
} | |
else | |
{ | |
//Serialize the data to a binary stream | |
using (var stream = new MemoryStream()) | |
{ | |
(new BinaryFormatter()).Serialize(stream, action); | |
stream.Flush(); | |
_serialData = stream.ToArray(); | |
} | |
_methodName = null; | |
} | |
} | |
public Action CreateDelegate() | |
{ | |
if (_serialData.Length == 0 && _methodName == "") | |
{ | |
return null; | |
} | |
if (_target != null) | |
{ | |
return Delegate.CreateDelegate(typeof(Action), _target, _methodName) as Action; | |
} | |
using (var stream = new MemoryStream(_serialData)) | |
{ | |
return (new BinaryFormatter()).Deserialize(stream) as Action; | |
} | |
} | |
} |
This file contains hidden or 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
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEditor; | |
using System.Reflection; | |
using System.Linq; | |
[CustomPropertyDrawer(typeof(SerializableAction))] | |
public class SerializableActionDrawer : PropertyDrawer { | |
int selection; | |
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |
{ | |
return 26; | |
} | |
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |
{ | |
// Using BeginProperty / EndProperty on the parent property means that | |
// prefab override logic works on the entire property. | |
EditorGUI.BeginProperty(position, label, property); | |
// Draw label | |
//position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); | |
// Don't make child fields be indented | |
var indent = EditorGUI.indentLevel; | |
EditorGUI.indentLevel = 0; | |
// Calculate rects | |
Rect objectRect = new Rect(position.x, position.y+5, 90, position.height-10); | |
var selectRect = new Rect(position.x + 96, position.y+5, position.width - 96, position.height-10); | |
bool changedObject = false; | |
EditorGUI.BeginChangeCheck(); | |
EditorGUI.ObjectField(objectRect, property.FindPropertyRelative("go"), typeof(GameObject), GUIContent.none); | |
changedObject = EditorGUI.EndChangeCheck(); | |
//EditorGUI.PropertyField(objectRect, property.FindPropertyRelative("go"), GUIContent.none); | |
if (property.FindPropertyRelative("go").objectReferenceValue != null) | |
{ | |
selection = 0; | |
int count = 0; | |
GameObject go = property.FindPropertyRelative("go").objectReferenceValue as GameObject; | |
Component[] components = go.GetComponents<Component>(); | |
List<string> methods = new List<string>(); | |
Dictionary<int, KeyValuePair<Object, string>> data = new Dictionary<int, KeyValuePair<Object, string>>(); | |
for (int i = 0; i<components.Length; i++) | |
{ | |
if (components[i].GetType() != typeof(Transform)) { | |
MethodInfo[] _meth = components[i].GetType().GetMethods(); | |
for (int m = 0; m < _meth.Length; m++) | |
{ | |
if (_meth[m].IsPublic && !_meth[m].IsSpecialName) | |
{ | |
methods.Add(components[i].GetType().Name + "/" + _meth[m].Name); | |
if (components[i]==property.FindPropertyRelative("_target").objectReferenceValue && | |
_meth[m].Name==property.FindPropertyRelative("_methodName").stringValue ) | |
{ | |
selection = count; | |
} | |
data.Add(count, new KeyValuePair<Object, string>(components[i], _meth[m].Name)); | |
count++; | |
} | |
} | |
} | |
} | |
EditorGUI.BeginChangeCheck(); | |
selection = EditorGUI.Popup(selectRect, selection, methods.ToArray()); | |
if (EditorGUI.EndChangeCheck() || changedObject) | |
{ | |
property.FindPropertyRelative("_target").objectReferenceValue = data[selection].Key; | |
property.FindPropertyRelative("_methodName").stringValue = data[selection].Value; | |
} | |
} else | |
{ | |
GUI.enabled = false; | |
EditorGUI.Popup(selectRect, selection, new string[] { "Select object first" }); | |
GUI.enabled = true; | |
} | |
// Draw fields - passs GUIContent.none to each so they are drawn without labels | |
//EditorGUI.PropertyField(amountRect, property.FindPropertyRelative("amount"), GUIContent.none); | |
//EditorGUI.PropertyField(unitRect, property.FindPropertyRelative("unit"), GUIContent.none); | |
//EditorGUI.PropertyField(nameRect, property.FindPropertyRelative("name"), GUIContent.none); | |
// Set indent back to what it was | |
EditorGUI.indentLevel = indent; | |
EditorGUI.EndProperty(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment