private void DrawFieldElement(UTField field, SerializedProperty prop) { var propPath = prop.propertyPath; var arrIndex = Convert.ToInt32(field.isArray ? propPath.Substring(propPath.LastIndexOf("[") + 1, propPath.LastIndexOf("]") - propPath.LastIndexOf("[") - 1) : null); var customLabel = field.attributes.Find(i => i is ShowLabelAttribute) as ShowLabelAttribute; var uiAttrs = field.uiAttrs; var uiOverride = uiAttrs.Where(i => i.GetType().GetMethod("OnGUI")?.DeclaringType == i.GetType()).ToArray(); EditorGUI.BeginChangeCheck(); switch (prop.type) { case "bool": if (uiOverride.Any()) { uiOverride.First().OnGUI(prop); break; } if (customLabel == null) { EditorGUILayout.PropertyField(prop, new GUIContent(), GUILayout.MaxWidth(30)); } else { EditorGUILayout.PropertyField(prop, new GUIContent(customLabel.label ?? prop.displayName)); } break; default: // for list views we handle the UI separately due to how popup targeting works if (uiOverride.Any() && !field.isInListView) { uiOverride.First().OnGUI(prop); break; } var popupAttr = field.attributes.Find(i => i is PopupAttribute) as PopupAttribute; if (popupAttr != null) { var sourceProp = UTUtils.GetPropThroughAttribute(serializedObject, popupAttr.methodName); // I do not like this handling // need a way to determine if target is a part of the list view or not without breaking the bank var source = sourceProp == null ? null : !field.isInListView ? sourceProp : sourceProp.isArray && sourceProp.arraySize > arrIndex ? sourceProp.GetArrayElementAtIndex(arrIndex) : null; var options = UTUtils.GetPopupOptions(prop, source, popupAttr, out var selectedIndex); selectedIndex = EditorGUILayout.Popup(selectedIndex, options); // we force reserialize for cases of default values if (prop.type == "int") { if (prop.intValue != selectedIndex) { shouldReserialize = true; } prop.intValue = selectedIndex; } else { if (prop.stringValue != options[selectedIndex]) { shouldReserialize = true; } prop.stringValue = options[selectedIndex]; } break; } // if there are no popup attributes - still allow gui override if (uiOverride.Any(i => !(i is PopupAttribute))) { uiOverride.First(i => !(i is PopupAttribute)).OnGUI(prop); break; } if (customLabel == null) { EditorGUILayout.PropertyField(prop, new GUIContent()); } else { EditorGUILayout.PropertyField(prop, new GUIContent(customLabel.label ?? prop.displayName)); } break; } if (EditorGUI.EndChangeCheck() && field.onValueChaged != null) { if (!field.isInListView) { field.onValueChaged.Invoke(t, new object[] { prop }); return; } HandleFieldChangeArray(field, prop, arrIndex); } }