/// <summary> /// Convert the specified list of delegate entries into a string array. /// </summary> static public string[] GetNames(List <PropertyReferenceDrawer.Entry> list, string choice, out int index) { index = 0; string[] names = new string[list.Count + 1]; names[0] = "<GameObject>"; for (int i = 0; i < list.Count;) { PropertyReferenceDrawer.Entry ent = list[i]; string del = NGUITools.GetFuncName(ent.target, ent.name); names[++i] = del; if (index == 0 && string.Equals(del, choice)) { index = i; } } return(names); }
/// <summary> /// Draw an editor field for the Unity Delegate. /// </summary> static public bool Field(Object undoObject, EventDelegate del, bool removeButton, bool minimalistic) { if (del == null) { return(false); } bool prev = GUI.changed; GUI.changed = false; bool retVal = false; MonoBehaviour target = del.target; bool remove = false; if (removeButton && (del.target != null || del.isValid)) { if (!minimalistic) { NGUIEditorTools.SetLabelWidth(82f); } if (del.target == null && del.isValid) { EditorGUILayout.LabelField("Notify", del.ToString()); } else { target = EditorGUILayout.ObjectField("Notify", del.target, typeof(MonoBehaviour), true) as MonoBehaviour; } GUILayout.Space(-18f); GUILayout.BeginHorizontal(); GUILayout.Space(70f); if (GUILayout.Button("", "ToggleMixed", GUILayout.Width(20f), GUILayout.Height(16f))) { target = null; remove = true; } GUILayout.EndHorizontal(); } else { target = EditorGUILayout.ObjectField("Notify", del.target, typeof(MonoBehaviour), true) as MonoBehaviour; } if (remove) { NGUIEditorTools.RegisterUndo("Delegate Selection", undoObject); del.Clear(); EditorUtility.SetDirty(undoObject); } else if (del.target != target) { NGUIEditorTools.RegisterUndo("Delegate Selection", undoObject); del.target = target; EditorUtility.SetDirty(undoObject); } if (del.target != null && del.target.gameObject != null) { GameObject go = del.target.gameObject; List <PropertyReferenceDrawer.Entry> list = GetMethods(go); int index = 0; string[] names = PropertyReferenceDrawer.GetNames(list, del.ToString(), out index); int choice = 0; GUILayout.BeginHorizontal(); choice = EditorGUILayout.Popup("Method", index, names); NGUIEditorTools.DrawPadding(); GUILayout.EndHorizontal(); if (choice > 0 && choice != index) { PropertyReferenceDrawer.Entry entry = list[choice - 1]; NGUIEditorTools.RegisterUndo("Delegate Selection", undoObject); del.target = entry.target as MonoBehaviour; del.methodName = entry.name; EditorUtility.SetDirty(undoObject); retVal = true; } GUI.changed = false; EventDelegate.Parameter[] ps = del.parameters; if (ps != null) { for (int i = 0; i < ps.Length; ++i) { EventDelegate.Parameter param = ps[i]; Object obj = EditorGUILayout.ObjectField(" Arg " + i, param.obj, typeof(Object), true); if (GUI.changed) { GUI.changed = false; param.obj = obj; EditorUtility.SetDirty(undoObject); } if (obj == null) { continue; } GameObject selGO = null; System.Type type = obj.GetType(); if (type == typeof(GameObject)) { selGO = obj as GameObject; } else if (type.IsSubclassOf(typeof(Component))) { selGO = (obj as Component).gameObject; } if (selGO != null) { // Parameters must be exact -- they can't be converted like property bindings PropertyReferenceDrawer.filter = param.expectedType; PropertyReferenceDrawer.canConvert = false; List <PropertyReferenceDrawer.Entry> ents = PropertyReferenceDrawer.GetProperties(selGO, true, false); int selection; string[] props = GetNames(ents, NGUITools.GetFuncName(param.obj, param.field), out selection); GUILayout.BeginHorizontal(); int newSel = EditorGUILayout.Popup(" ", selection, props); NGUIEditorTools.DrawPadding(); GUILayout.EndHorizontal(); if (GUI.changed) { GUI.changed = false; if (newSel == 0) { param.obj = selGO; param.field = null; } else { param.obj = ents[newSel - 1].target; param.field = ents[newSel - 1].name; } EditorUtility.SetDirty(undoObject); } } else if (!string.IsNullOrEmpty(param.field)) { param.field = null; EditorUtility.SetDirty(undoObject); } PropertyReferenceDrawer.filter = typeof(void); PropertyReferenceDrawer.canConvert = true; } } } else { retVal = GUI.changed; } GUI.changed = prev; return(retVal); }
/// <summary> /// Collect a list of usable delegates from the specified target game object. /// </summary> static public List <PropertyReferenceDrawer.Entry> GetMethods(GameObject target) { MonoBehaviour[] comps = target.GetComponents <MonoBehaviour>(); List <PropertyReferenceDrawer.Entry> list = new List <PropertyReferenceDrawer.Entry>(); for (int i = 0, imax = comps.Length; i < imax; ++i) { MonoBehaviour mb = comps[i]; if (mb == null) { continue; } MethodInfo[] methods = mb.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public); for (int b = 0; b < methods.Length; ++b) { MethodInfo mi = methods[b]; if (mi.ReturnType == typeof(void)) { string name = mi.Name; if (name == "Invoke") { continue; } if (name == "InvokeRepeating") { continue; } if (name == "CancelInvoke") { continue; } if (name == "StopCoroutine") { continue; } if (name == "StopAllCoroutines") { continue; } if (name == "BroadcastMessage") { continue; } if (name.StartsWith("SendMessage")) { continue; } if (name.StartsWith("set_")) { continue; } PropertyReferenceDrawer.Entry ent = new PropertyReferenceDrawer.Entry(); ent.target = mb; ent.name = mi.Name; list.Add(ent); } } } return(list); }
public override void OnGUI(Rect rect, SerializedProperty prop, GUIContent label) { Undo.RecordObject(prop.serializedObject.targetObject, "Delegate Selection"); SerializedProperty targetProp = prop.FindPropertyRelative("mTarget"); SerializedProperty methodProp = prop.FindPropertyRelative("mMethodName"); MonoBehaviour target = targetProp.objectReferenceValue as MonoBehaviour; string methodName = methodProp.stringValue; EditorGUI.indentLevel = prop.depth; EditorGUI.LabelField(rect, label); Rect lineRect = rect; lineRect.yMin = rect.yMin + lineHeight; lineRect.yMax = lineRect.yMin + lineHeight; EditorGUI.indentLevel = targetProp.depth; target = EditorGUI.ObjectField(lineRect, "Notify", target, typeof(MonoBehaviour), true) as MonoBehaviour; targetProp.objectReferenceValue = target; if (target != null && target.gameObject != null) { GameObject go = target.gameObject; List <PropertyReferenceDrawer.Entry> list = EventDelegateEditor.GetMethods(go); int index = 0; int choice = 0; EventDelegate del = new EventDelegate(); del.target = target; del.methodName = methodName; string[] names = PropertyReferenceDrawer.GetNames(list, del.ToString(), out index); lineRect.yMin += lineHeight; lineRect.yMax += lineHeight; choice = EditorGUI.Popup(lineRect, "Method", index, names); if (choice > 0 && choice != index) { PropertyReferenceDrawer.Entry entry = list[choice - 1]; target = entry.target as MonoBehaviour; methodName = entry.name; targetProp.objectReferenceValue = target; methodProp.stringValue = methodName; } SerializedProperty paramArrayProp = prop.FindPropertyRelative("mParameters"); EventDelegate.Parameter[] ps = del.parameters; if (ps != null) { paramArrayProp.arraySize = ps.Length; for (int i = 0; i < ps.Length; i++) { EventDelegate.Parameter param = ps[i]; SerializedProperty paramProp = paramArrayProp.GetArrayElementAtIndex(i); SerializedProperty objProp = paramProp.FindPropertyRelative("obj"); SerializedProperty fieldProp = paramProp.FindPropertyRelative("field"); param.obj = objProp.objectReferenceValue; param.field = fieldProp.stringValue; Object obj = param.obj; lineRect.yMin += lineHeight; lineRect.yMax += lineHeight; obj = EditorGUI.ObjectField(lineRect, " Arg " + i, obj, typeof(Object), true); objProp.objectReferenceValue = obj; del.parameters[i].obj = obj; param.obj = obj; if (obj == null) { continue; } GameObject selGO = null; System.Type type = param.obj.GetType(); if (type == typeof(GameObject)) { selGO = param.obj as GameObject; } else if (type.IsSubclassOf(typeof(Component))) { selGO = (param.obj as Component).gameObject; } if (selGO != null) { // Parameters must be exact -- they can't be converted like property bindings PropertyReferenceDrawer.filter = param.expectedType; PropertyReferenceDrawer.canConvert = false; List <PropertyReferenceDrawer.Entry> ents = PropertyReferenceDrawer.GetProperties(selGO, true, false); int selection; string[] props = EventDelegateEditor.GetNames(ents, NGUITools.GetFuncName(param.obj, param.field), out selection); lineRect.yMin += lineHeight; lineRect.yMax += lineHeight; int newSel = EditorGUI.Popup(lineRect, " ", selection, props); if (newSel != selection) { if (newSel == 0) { param.obj = selGO; param.field = null; objProp.objectReferenceValue = selGO; fieldProp.stringValue = null; } else { param.obj = ents[newSel - 1].target; param.field = ents[newSel - 1].name; objProp.objectReferenceValue = param.obj; fieldProp.stringValue = param.field; } } } else if (!string.IsNullOrEmpty(param.field)) { param.field = null; } PropertyReferenceDrawer.filter = typeof(void); PropertyReferenceDrawer.canConvert = true; } } } }