public override void OnGUI(Rect rect, SerializedProperty prop, GUIContent label) { Undo.RecordObject(prop.serializedObject.targetObject, "Delegate Selection"); EditorGUI.BeginProperty(rect, label, prop); int indent = EditorGUI.indentLevel; SerializedProperty showGroup = prop.FindPropertyRelative("mShowGroup"); SerializedProperty nameProp = prop.FindPropertyRelative("mEventName"); SerializedProperty targetProp = prop.FindPropertyRelative("mTarget"); SerializedProperty methodProp = prop.FindPropertyRelative("mMethodName"); SerializedProperty updateMethodsProp = prop.FindPropertyRelative("mUpdateEntryList"); if (EditorApplication.isCompiling) { updateMethodsProp.boolValue = true; } string eventName = nameProp.stringValue; UnityEngine.Object target = targetProp.objectReferenceValue; //controls Rect groupPos = new Rect(rect.x + 5, rect.y + 2, rect.width, ThunderEventDrawerTools.lineHeight); showGroup.boolValue = EditorGUI.Foldout(groupPos, showGroup.boolValue, label); if (showGroup.boolValue) { EditorGUI.indentLevel++; lineRect = rect; lineRect.yMin = rect.yMin + ThunderEventDrawerTools.lineHeight; lineRect.yMax = lineRect.yMin + ThunderEventDrawerTools.lineHeight; eventName = EditorGUI.TextField(lineRect, eventName); nameProp.stringValue = eventName; lineRect.yMin += ThunderEventDrawerTools.lineHeight; lineRect.yMax += ThunderEventDrawerTools.lineHeight; target = EditorGUI.ObjectField(lineRect, "Notify", target, typeof(UnityEngine.Object), true); //update method list if target component was modified if (targetProp.objectReferenceValue != target) { updateMethodsProp.boolValue = true; } targetProp.objectReferenceValue = target; if (target != null) { List <Entry> listWithParams = null; SerializedProperty entryArrayProp = prop.FindPropertyRelative("mEntryList"); if (updateMethodsProp.boolValue && EditorApplication.isCompiling == false) { GameObject go = target as GameObject; if (go == null) { Component component = target as Component; if (target) { UpdateMethods(listWithParams, entryArrayProp, updateMethodsProp, component.gameObject); } } else { UpdateMethods(listWithParams, entryArrayProp, updateMethodsProp, go); } } else { //get list from array listWithParams = new List <Entry>(); SerializedProperty entryItem; int arraySize = entryArrayProp.arraySize; for (int i = 0; i < arraySize; i++, entryItem = null) { entryItem = entryArrayProp.GetArrayElementAtIndex(i); if (entryItem == null) { continue; } UnityEngine.Object targetComp = entryItem.FindPropertyRelative("target").objectReferenceValue; string name = entryItem.FindPropertyRelative("name").stringValue; listWithParams.Add(new Entry(targetComp, name)); } } int index = 0; int choice = 0; string methodName = methodProp.stringValue; //check and trim missing method message here if (methodName.StartsWith("<Missing - ") == true) { methodName = methodName.Replace("<Missing - ", ""); methodName = methodName.Replace(">", ""); } string[] names = GetNames(listWithParams, ThunderEvent.GetClassName(target), methodName, true, out index, methodProp); lineRect.yMin += ThunderEventDrawerTools.lineHeight; lineRect.yMax += ThunderEventDrawerTools.lineHeight; choice = EditorGUI.Popup(lineRect, "Event", index, names); //saving selected method or field if (choice > 0 && choice != index) { Entry entry = listWithParams [choice - 1]; if (target != entry.target) { target = entry.target; targetProp.objectReferenceValue = target; SerializedProperty cacheProp = prop.FindPropertyRelative("mCached"); cacheProp.boolValue = false; } //Debug.Log(entry.target.name + "-" + entry.name); methodName = entry.name; //remove params if (string.IsNullOrEmpty(methodName) == false && methodName.Contains(" (")) { methodName = methodName.Remove(methodName.IndexOf(" (")); } if (methodName != methodProp.stringValue) { methodProp.stringValue = methodName; entry.name = methodName; SerializedProperty cacheProp = prop.FindPropertyRelative("mCached"); cacheProp.boolValue = false; } } eventDelegate.target = target; eventDelegate.methodName = methodName; //showing if method or field is missing if (eventDelegate.isValid == false) { if (methodName.StartsWith("<Missing - ") == false) { methodName = "<Missing - " + methodName + ">"; } methodProp.stringValue = methodName; EditorGUI.indentLevel = indent; EditorGUI.EndProperty(); return; } //showing parameters SerializedProperty paramArrayProp = prop.FindPropertyRelative("mParameters"); ThunderEvent.Parameter[] ps = eventDelegate.parameters; if (ps != null) { bool showGameObject = false; //EditorGUI.indentLevel++; float paramTypeWidth = 80; float lineOriginalMax = lineRect.xMax; lineRect.xMax -= 68; int imax = ps.Length; paramArrayProp.arraySize = imax; for (int i = 0; i < imax; i++) { ThunderEvent.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; lineRect.yMin += ThunderEventDrawerTools.lineHeight; lineRect.yMax += ThunderEventDrawerTools.lineHeight; //showing param info string paramDesc = GetSimpleName(param.expectedType); paramDesc += " " + param.name; if (IsPrimitiveType(param.expectedType)) { if (lineOriginalMax == lineRect.xMax) { lineRect.xMax -= 68; } //only do this if parameter is a primitive type Rect paramTypeRect = new Rect(lineRect.x + lineRect.width - 12, lineRect.y, paramTypeWidth, ThunderEventDrawerTools.lineHeight); SerializedProperty paramTypeProp = paramProp.FindPropertyRelative("paramRefType"); //draw param type option EditorGUI.PropertyField(paramTypeRect, paramTypeProp, GUIContent.none); param.paramRefType = (ParameterType)paramTypeProp.enumValueIndex; } else { lineRect.xMax = lineOriginalMax; } bool useManualValue = paramProp.FindPropertyRelative("paramRefType").enumValueIndex == (int)ParameterType.Value; if (useManualValue) { if (param.expectedType == typeof(string)) { SerializedProperty valueProp = paramProp.FindPropertyRelative("argStringValue"); EditorGUI.PropertyField(lineRect, valueProp, new GUIContent(paramDesc)); param.value = valueProp.stringValue; } else if (param.expectedType == typeof(int)) { SerializedProperty valueProp = paramProp.FindPropertyRelative("argIntValue"); EditorGUI.PropertyField(lineRect, valueProp, new GUIContent(paramDesc)); param.value = valueProp.intValue; } else if (param.expectedType == typeof(float)) { SerializedProperty valueProp = paramProp.FindPropertyRelative("argFloatValue"); EditorGUI.PropertyField(lineRect, valueProp, new GUIContent(paramDesc)); param.value = valueProp.floatValue; } else if (param.expectedType == typeof(double)) { SerializedProperty valueProp = paramProp.FindPropertyRelative("argDoubleValue"); EditorGUI.PropertyField(lineRect, valueProp, new GUIContent(paramDesc)); param.value = valueProp.doubleValue; } else if (param.expectedType == typeof(bool)) { SerializedProperty valueProp = paramProp.FindPropertyRelative("argBoolValue"); EditorGUI.PropertyField(lineRect, valueProp, new GUIContent(paramDesc)); param.value = valueProp.boolValue; } else if (param.expectedType == typeof(Color)) { SerializedProperty valueProp = paramProp.FindPropertyRelative("argColor"); EditorGUI.PropertyField(lineRect, valueProp, new GUIContent(paramDesc)); param.value = valueProp.colorValue; } else if (param.expectedType == typeof(Vector2)) { SerializedProperty valueProp = paramProp.FindPropertyRelative("argVector2"); lineRect.y += 2; EditorGUI.PropertyField(lineRect, valueProp, new GUIContent(paramDesc)); param.value = valueProp.vector2Value; } else if (param.expectedType == typeof(Vector3)) { SerializedProperty valueProp = paramProp.FindPropertyRelative("argVector3"); lineRect.y += 2; EditorGUI.PropertyField(lineRect, valueProp, new GUIContent(paramDesc)); param.value = valueProp.vector3Value; } else if (param.expectedType == typeof(Quaternion)) { SerializedProperty valueProp = paramProp.FindPropertyRelative("argVector4"); Vector4 vec4 = valueProp.vector4Value; lineRect.y += 2; //workaround for vector 4, it uses an extra line. //valueProp.vector4Value = EditorGUI.Vector4Field(lineRect, paramDesc, valueProp.vector4Value); //create all this values just once if (vec4Values == null) { vec4Values = new float[4]; } vec4Values[0] = vec4.x; vec4Values[1] = vec4.y; vec4Values[2] = vec4.z; vec4Values[3] = vec4.w; if (vec4GUIContent == null) { vec4GUIContent = new GUIContent[4]; } vec4GUIContent[0] = new GUIContent("X"); vec4GUIContent[1] = new GUIContent("Y"); vec4GUIContent[2] = new GUIContent("Z"); vec4GUIContent[3] = new GUIContent("W"); EditorGUI.LabelField(lineRect, paramDesc); Rect vector4Line = new Rect(lineRect); vector4Line.xMin += (EditorGUI.indentLevel * ThunderEventDrawerTools.lineHeight) + 150; EditorGUI.MultiFloatField(vector4Line, vec4GUIContent, vec4Values); valueProp.vector4Value = new Vector4(vec4Values[0], vec4Values[1], vec4Values[2], vec4Values[3]); param.value = valueProp.vector4Value; } else if (param.expectedType.IsEnum) { SerializedProperty valueProp = paramProp.FindPropertyRelative("argIntValue"); if (param.expectedType.GetAttribute <System.FlagsAttribute>() != null) { param.value = EditorGUI.MaskField(lineRect, new GUIContent(paramDesc), valueProp.intValue, Enum.GetNames(param.expectedType)); valueProp.intValue = (int)param.value; } else { Enum selectedOpt = (Enum)Enum.ToObject(param.expectedType, valueProp.intValue); param.value = EditorGUI.EnumPopup(lineRect, new GUIContent(paramDesc), selectedOpt); valueProp.intValue = (int)param.value; } } else { showGameObject = true; } } if (showGameObject || !useManualValue) { UnityEngine.Object obj = param.obj; obj = EditorGUI.ObjectField(lineRect, paramDesc, obj, typeof(UnityEngine.Object), true); param.obj = obj; objProp.objectReferenceValue = obj; if (obj == null) { continue; } //show gameobject 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 filter = param.expectedType; canConvert = false; List <Entry> ents = GetProperties(selGO, true, false); int selection = 0; string[] props = GetNames(ents, ThunderEvent.GetClassName(param.obj), ThunderEvent.GetFuncName(param.obj, param.field), false, out selection); lineRect.yMin += ThunderEventDrawerTools.lineHeight; lineRect.yMax += ThunderEventDrawerTools.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; } filter = typeof(void); canConvert = true; } showGameObject = false; } } } } EditorGUI.indentLevel = indent; EditorGUI.EndProperty(); }
/// <summary> /// Width value to start using minimalistic method. /// </summary> //int minimalistWidth = 0; //TODO: implement minimalistic method, unity activates it at 257 public override float GetPropertyHeight(SerializedProperty prop, GUIContent label) { SerializedProperty showGroup = prop.FindPropertyRelative("mShowGroup"); if (!showGroup.boolValue) { return(ThunderEventDrawerTools.lineHeight); } float lines = (3 * ThunderEventDrawerTools.lineHeight); SerializedProperty targetProp = prop.FindPropertyRelative("mTarget"); if (targetProp.objectReferenceValue == null) { return(lines); } lines += ThunderEventDrawerTools.lineHeight; SerializedProperty methodProp = prop.FindPropertyRelative("mMethodName"); if (methodProp.stringValue == "<Choose>" || methodProp.stringValue.StartsWith("<Missing - ")) { return(lines); } eventDelegate.target = targetProp.objectReferenceValue; eventDelegate.methodName = methodProp.stringValue; if (eventDelegate.isValid == false) { return(lines); } SerializedProperty paramArrayProp = prop.FindPropertyRelative("mParameters"); ThunderEvent.Parameter[] ps = eventDelegate.parameters; if (ps != null) { ThunderEvent.Parameter param = null; int imax = ps.Length; paramArrayProp.arraySize = imax; for (int i = 0; i < imax; i++, param = null) { param = ps [i]; lines += ThunderEventDrawerTools.lineHeight; SerializedProperty paramProp = paramArrayProp.GetArrayElementAtIndex(i); SerializedProperty objProp = paramProp.FindPropertyRelative("obj"); bool useManualValue = paramProp.FindPropertyRelative("paramRefType").enumValueIndex == (int)ParameterType.Value; if (useManualValue) { if (param.expectedType == typeof(string) || param.expectedType == typeof(int) || param.expectedType == typeof(float) || param.expectedType == typeof(double) || param.expectedType == typeof(bool) || param.expectedType.IsEnum || param.expectedType == typeof(Color)) { continue; } else if (param.expectedType == typeof(Vector2) || param.expectedType == typeof(Vector3) || param.expectedType == typeof(Vector4)) { //if (lineRect.width < minimalistWidth) //use minimalist method //{ // if (param.expectedType == typeof(Vector2) || param.expectedType == typeof(Vector3)) // { // lines += lineHeight; // } //} lines += 4; continue; } } UnityEngine.Object obj = objProp.objectReferenceValue; if (obj == null) { continue; } System.Type type = obj.GetType(); GameObject selGO = null; if (type == typeof(GameObject)) { selGO = obj as GameObject; } else if (type.IsSubclassOf(typeof(Component))) { selGO = (obj as Component).gameObject; } if (selGO != null) { lines += ThunderEventDrawerTools.lineHeight; } } } return(lines); }
/// <summary> /// The standard height size for each property line. /// </summary> private UnityEditorInternal.ReorderableList getList(SerializedProperty property) { if (list == null) { list = new ReorderableList(property.serializedObject, property, true, true, true, true); list.drawElementCallback = (UnityEngine.Rect rect, int index, bool isActive, bool isFocused) => { rect.width -= 10; rect.x += 8; SerializedProperty elemtProp = property.GetArrayElementAtIndex(index); if (EditorApplication.isCompiling) { SerializedProperty updateMethodsProp = elemtProp.FindPropertyRelative("mUpdateEntryList"); if (updateMethodsProp != null) { updateMethodsProp.boolValue = true; } } EditorGUI.PropertyField(rect, elemtProp, true); }; list.elementHeightCallback = (index) => { var element = property.GetArrayElementAtIndex(index); float yOffset = 12; SerializedProperty showGroup = element.FindPropertyRelative("mShowGroup"); if (!showGroup.boolValue) { return(ThunderEventDrawerTools.lineHeight + 1); } float lines = (3 * ThunderEventDrawerTools.lineHeight) + yOffset; SerializedProperty targetProp = element.FindPropertyRelative("mTarget"); if (targetProp.objectReferenceValue == null) { return(lines); } lines += ThunderEventDrawerTools.lineHeight; SerializedProperty methodProp = element.FindPropertyRelative("mMethodName"); if (methodProp.stringValue == "<Choose>" || methodProp.stringValue.StartsWith("<Missing - ")) { return(lines); } eventDelegate.target = targetProp.objectReferenceValue; eventDelegate.methodName = methodProp.stringValue; if (eventDelegate.isValid == false) { return(lines); } SerializedProperty paramArrayProp = element.FindPropertyRelative("mParameters"); ThunderEvent.Parameter[] ps = eventDelegate.parameters; if (ps != null) { int imax = ps.Length; paramArrayProp.arraySize = imax; for (int i = 0; i < imax; i++) { ThunderEvent.Parameter param = ps[i]; lines += ThunderEventDrawerTools.lineHeight; SerializedProperty paramProp = paramArrayProp.GetArrayElementAtIndex(i); SerializedProperty objProp = paramProp.FindPropertyRelative("obj"); bool useManualValue = paramProp.FindPropertyRelative("paramRefType").enumValueIndex == (int)ParameterType.Value; if (useManualValue) { if (param.expectedType == typeof(string) || param.expectedType == typeof(int) || param.expectedType == typeof(float) || param.expectedType == typeof(double) || param.expectedType == typeof(bool) || param.expectedType.IsEnum || param.expectedType == typeof(Color)) { continue; } else if (param.expectedType == typeof(Vector2) || param.expectedType == typeof(Vector3) || param.expectedType == typeof(Vector4)) { //TODO: use minimalist method lines += 2f; continue; } } UnityEngine.Object obj = objProp.objectReferenceValue; if (obj == null) { continue; } Type type = obj.GetType(); GameObject selGO = null; if (type == typeof(GameObject)) { selGO = obj as GameObject; } else if (type.IsSubclassOf(typeof(Component))) { selGO = (obj as Component).gameObject; } if (selGO != null) { lines += ThunderEventDrawerTools.lineHeight; } } } return(lines - ThunderEventDrawerTools.lineHeight / 2); }; } return(list); }