示例#1
0
        private void HandleListView(List <UTField> listViewFields, KeyValuePair <string, UTFieldType> fieldEntry)
        {
            List <SerializedProperty> propsList = new List <SerializedProperty>();

            foreach (var field in listViewFields)
            {
                propsList.Add(serializedObject.FindProperty(field.name));
            }

            // draw header
            var parentProp = serializedObject.FindProperty(listViewFields[0].name);
            var uiAttrs    = listViewFields[0].uiAttrs;

            var isVisible = true;

            foreach (var uiAttr in uiAttrs)
            {
                if (!uiAttr.GetVisible(parentProp))
                {
                    isVisible = false;
                    break;
                }
            }

            if (!isVisible)
            {
                return;
            }

            foreach (var uiAttr in uiAttrs)
            {
                uiAttr.BeforeGUI(propsList[0]);
            }

            var propDisabled = listViewFields.Exists(i => i.isDisabled);
            var page         = listPaginations[fieldEntry.Key];
            var pageCount    = Mathf.CeilToInt(parentProp.arraySize / 30f);

            if (pageCount > 1 && page > pageCount - 1)
            {
                page = pageCount - 1;
                listPaginations[fieldEntry.Key] = page;
            }


            var utilsShownVal = utilsShown[fieldEntry.Key];

            parentProp.isExpanded =
                UTStyles.FoldoutHeader(
                    GetListViewHeaderText(fieldEntry.Key, propDisabled, parentProp.isExpanded, page, pageCount,
                                          parentProp.arraySize),
                    parentProp.isExpanded, ref utilsShownVal);
            utilsShown[fieldEntry.Key] = utilsShownVal;
            var foldoutRect = GUILayoutUtility.GetLastRect();

            if (!propDisabled && UTEditorArray.HandleDragAndDrop(foldoutRect, serializedObject, propsList))
            {
                droppedObjects = true;
                if (listViewFields[0].onValueChaged == null)
                {
                    return;
                }

                HandleFieldChangeArray(listViewFields[0], parentProp, parentProp.arraySize - 1);
                return;
            }

            if (droppedObjects)
            {
                return;
            }
            if (!parentProp.isExpanded)
            {
                return;
            }
            EditorGUI.BeginDisabledGroup(propDisabled);
            // List View Utils
            if (utilsShownVal)
            {
                CreateListViewUtils(propsList, fieldEntry);
            }

            for (int i = 30 * page; i < Mathf.Min(parentProp.arraySize, 30 * (page + 1)); i++)
            {
                Rect   headerRect = default;
                Rect[] fieldRects = new Rect[listViewFields.Count];
                // get a react to draw a header later
                if (listViewFields.Count > 1 && i == 30 * page)
                {
                    headerRect = EditorGUILayout.GetControlRect();
                }

                EditorGUILayout.BeginHorizontal();

                // position controls
                if (UTEditorArray.RenderPositionControls(i, propsList, out var newIndex))
                {
                    HandleFieldChangeArray(listViewFields[0], parentProp.GetArrayElementAtIndex(newIndex), newIndex);
                    break;
                }

                var fieldIndex = 0;
                foreach (var field in listViewFields)
                {
                    var prop = serializedObject.FindProperty(field.name);

                    if (prop.arraySize != parentProp.arraySize)
                    {
                        prop.arraySize = parentProp.arraySize;
                    }

                    DrawFieldElement(field, prop.GetArrayElementAtIndex(i));
                    // saved the field width to reuse in the header later
                    if (listViewFields.Count > 1 && i == 30 * page)
                    {
                        fieldRects[fieldIndex] = GUILayoutUtility.GetLastRect();
                    }

                    fieldIndex++;
                }

                // removal controls
                if (UTEditorArray.RenderRemoveControls(i, propsList))
                {
                    if (listViewFields[0].onValueChaged != null)
                    {
                        HandleFieldChangeArray(listViewFields[0], null, i);
                    }

                    break;
                }

                EditorGUILayout.EndHorizontal();
                // draw a header with saved field widths
                // we only draw a header for cases where there are multiple elements
                if (listViewFields.Count > 1 && i == 30 * page)
                {
                    GUI.Box(headerRect, "", new GUIStyle("helpBox"));
                    for (int j = 0; j < listViewFields.Count; j++)
                    {
                        var adjustedRect = fieldRects[j];
                        if (j == 0)
                        {
                            adjustedRect.xMin = headerRect.xMin + 2;
                        }

                        adjustedRect.yMin = headerRect.yMin;
                        adjustedRect.yMax = headerRect.yMax;
                        EditorGUI.LabelField(adjustedRect,
                                             listViewFields[j].listViewColumnName ??
                                             serializedObject.FindProperty(listViewFields[j].name).displayName);
                    }
                }
            }

            EditorGUI.EndDisabledGroup();

            if (pageCount > 1)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUI.BeginDisabledGroup(page != pageCount - 1);
            }

            if (GUILayout.Button(listViewFields[0].listViewAddTitle ?? "Add Element"))
            {
                var insertAt = parentProp.arraySize;
                if (listViewFields[0].listViewAddMethod != null)
                {
                    listViewFields[0].listViewAddMethod.Invoke(t, new object[] { serializedObject });
                }
                else
                {
                    foreach (var field in listViewFields)
                    {
                        var prop = serializedObject.FindProperty(field.name);
                        prop.InsertArrayElementAtIndex(insertAt);
                    }
                }

                if (listViewFields[0].onValueChaged != null)
                {
                    HandleFieldChangeArray(listViewFields[0], parentProp.GetArrayElementAtIndex(insertAt), insertAt);
                }
            }

            if (pageCount > 1)
            {
                EditorGUI.EndDisabledGroup();
                EditorGUI.BeginDisabledGroup(page <= 0);
                if (GUILayout.Button(UTStyles.ArrowL, UTStyles.MiniArrowLeft))
                {
                    listPaginations[fieldEntry.Key]--;
                }
                EditorGUI.EndDisabledGroup();

                EditorGUI.BeginDisabledGroup(page >= pageCount - 1);
                if (GUILayout.Button(UTStyles.ArrowR, UTStyles.MiniArrowRight))
                {
                    listPaginations[fieldEntry.Key]++;
                }
                EditorGUI.EndDisabledGroup();
                EditorGUILayout.EndHorizontal();
            }

            foreach (var uiAttr in uiAttrs)
            {
                uiAttr.AfterGUI(parentProp);
            }
        }
示例#2
0
        private void RenderStackedArray(string name, SerializedProperty prop, SerializedProperty otherProp, PopupAttribute leftPopup,
                                        PopupAttribute rightPopup,
                                        string addMethod, string addText, string changedCallback)
        {
            var disabledString = propDisabled ? "[Read Only]" : "";

            prop.isExpanded = UTStyles.FoldoutHeader($"{name} [{prop.arraySize}] {disabledString}", prop.isExpanded);
            var foldoutRect = GUILayoutUtility.GetLastRect();

            if (!propDisabled)
            {
                HandleDragAndDrop(foldoutRect, prop, otherProp);
                if (droppedObjects)
                {
                    return;
                }
            }
            if (!prop.isExpanded)
            {
                return;
            }
            EditorGUI.BeginDisabledGroup(propDisabled);
            for (int i = 0; i < prop.arraySize; i++)
            {
                EditorGUILayout.BeginHorizontal();
                if (RenderPositionControls(i, new[] { prop, otherProp }))
                {
                    break;
                }

                // this code is very similar to PopupAttribute itself
                // but we have to handle it here directly because we are connecting two different props together
                // should probably refactor at some point
                EditorGUI.BeginChangeCheck();
                // handle arrays of different lengths
                var lLength = prop.arraySize;
                var rLength = otherProp.arraySize;
                if (lLength != rLength)
                {
                    prop.arraySize      = Math.Max(lLength, rLength);
                    otherProp.arraySize = Math.Max(lLength, rLength);
                }
                // Left Field
                if (leftPopup == null)
                {
                    EditorGUILayout.PropertyField(prop.GetArrayElementAtIndex(i), new GUIContent());
                }
                else
                {
                    var source  = otherProp.GetArrayElementAtIndex(i);
                    var options = UTUtils.GetPopupOptions(prop.GetArrayElementAtIndex(i), source, leftPopup, out var selectedIndex);

                    selectedIndex = EditorGUILayout.Popup(selectedIndex, options);
                    prop.GetArrayElementAtIndex(i).stringValue = options[selectedIndex];
                }

                if (rightPopup == null)
                {
                    EditorGUILayout.PropertyField(otherProp.GetArrayElementAtIndex(i), new GUIContent());
                }
                else
                {
                    var source  = prop.GetArrayElementAtIndex(i);
                    var options = UTUtils.GetPopupOptions(otherProp.GetArrayElementAtIndex(i), source, rightPopup, out var selectedIndex);

                    selectedIndex = EditorGUILayout.Popup(selectedIndex, options);
                    otherProp.GetArrayElementAtIndex(i).stringValue = options[selectedIndex];
                }

                if (EditorGUI.EndChangeCheck())
                {
                    HandleChangeCallback(t, changedCallback, prop, otherProp, new object[] { prop.GetArrayElementAtIndex(i), otherProp.GetArrayElementAtIndex(i), i });
                }

                if (RenderRemoveControls(i, new[] { prop, otherProp }))
                {
                    HandleChangeCallback(t, changedCallback, prop, otherProp, new object[] { null, null, i });
                    break;
                }

                EditorGUILayout.EndHorizontal();
            }

            if (!propDisabled)
            {
                EditorGUILayout.BeginHorizontal();
                if (RenderAddControls(new[] { prop, otherProp }, addText, addMethod))
                {
                    HandleChangeCallback(t, changedCallback, prop, otherProp, new object[] { prop.GetArrayElementAtIndex(prop.arraySize - 1), otherProp.GetArrayElementAtIndex(otherProp.arraySize - 1), prop.arraySize - 1 });
                }
                if (GUILayout.Button("Clear", GUILayout.MaxWidth(60)))
                {
                    prop.arraySize      = 0;
                    otherProp.arraySize = 0;
                    HandleChangeCallback(t, changedCallback, prop, otherProp, new object[] { null, null, 0 });
                }
                EditorGUILayout.EndHorizontal();
            }
            EditorGUI.EndDisabledGroup();
        }
示例#3
0
        private void RenderStackedArray(string name, SerializedProperty prop, SerializedProperty otherProp,
                                        string addMethod, string addText, string changedCallback)
        {
            var disabledString = propDisabled ? "[Read Only]" : "";

            prop.isExpanded = UTStyles.FoldoutHeader($"{name} [{prop.arraySize}] {disabledString}", prop.isExpanded);
            var foldoutRect = GUILayoutUtility.GetLastRect();

            if (!propDisabled)
            {
                HandleDragAndDrop(foldoutRect, prop, otherProp);
                if (droppedObjects)
                {
                    return;
                }
            }
            if (!prop.isExpanded)
            {
                return;
            }
            EditorGUI.BeginDisabledGroup(propDisabled);
            for (int i = 0; i < prop.arraySize; i++)
            {
                EditorGUILayout.BeginHorizontal();
                if (RenderPositionControls(i, new[] { prop, otherProp }))
                {
                    break;
                }

                EditorGUI.BeginChangeCheck();
                // handle arrays of different lengths
                var lLength = prop.arraySize;
                var rLength = otherProp.arraySize;
                if (lLength != rLength)
                {
                    prop.arraySize      = Math.Max(lLength, rLength);
                    otherProp.arraySize = Math.Max(lLength, rLength);
                }
                EditorGUILayout.PropertyField(prop.GetArrayElementAtIndex(i), new GUIContent());
                EditorGUILayout.PropertyField(otherProp.GetArrayElementAtIndex(i), new GUIContent());
                if (EditorGUI.EndChangeCheck())
                {
                    HandleChangeCallback(t, changedCallback, prop, otherProp, new object[] { prop.GetArrayElementAtIndex(i), otherProp.GetArrayElementAtIndex(i), i });
                }

                if (RenderRemoveControls(i, new[] { prop, otherProp }))
                {
                    HandleChangeCallback(t, changedCallback, prop, otherProp, new object[] { null, null, i });
                    break;
                }

                EditorGUILayout.EndHorizontal();
            }

            if (!propDisabled)
            {
                EditorGUILayout.BeginHorizontal();
                if (RenderAddControls(new[] { prop, otherProp }, addText, addMethod))
                {
                    HandleChangeCallback(t, changedCallback, prop, otherProp, new object[] { prop.GetArrayElementAtIndex(prop.arraySize - 1), otherProp.GetArrayElementAtIndex(otherProp.arraySize - 1), prop.arraySize - 1 });
                }
                if (GUILayout.Button("Clear", GUILayout.MaxWidth(40)))
                {
                    prop.arraySize      = 0;
                    otherProp.arraySize = 0;
                    HandleChangeCallback(t, changedCallback, prop, otherProp, new object[] { null, null, 0 });
                }
                EditorGUILayout.EndHorizontal();
            }
            EditorGUI.EndDisabledGroup();
        }
示例#4
0
        private void RenderArray(SerializedProperty prop, string changedCallback)
        {
            var formatted = Regex.Split(prop.name, @"(?<!^)(?=[A-Z])");

            formatted[0] = formatted[0].Substring(0, 1).ToUpper() + formatted[0].Substring(1);
            var disabledString = propDisabled ? "[Read Only]" : "";

            prop.isExpanded = UTStyles.FoldoutHeader($"{String.Join(" ", formatted)} [{prop.arraySize}] {disabledString}", prop.isExpanded);
            var foldoutRect = GUILayoutUtility.GetLastRect();

            if (!propDisabled)
            {
                HandleDragAndDrop(foldoutRect, prop);
                if (droppedObjects)
                {
                    return;
                }
            }
            if (!prop.isExpanded)
            {
                return;
            }
            EditorGUI.BeginDisabledGroup(propDisabled);
            var popup = UTUtils.GetPropertyAttribute <PopupAttribute>(prop);

            for (int i = 0; i < prop.arraySize; i++)
            {
                EditorGUILayout.BeginHorizontal();
                if (RenderPositionControls(i, new[] { prop }))
                {
                    break;
                }
                EditorGUI.BeginChangeCheck();
                if (popup == null)
                {
                    EditorGUILayout.PropertyField(prop.GetArrayElementAtIndex(i), new GUIContent());
                }
                else
                {
                    var options = UTUtils.GetPopupOptions(prop.GetArrayElementAtIndex(i), null, popup, out var selectedIndex);
                    selectedIndex = EditorGUILayout.Popup(selectedIndex, options);
                    prop.GetArrayElementAtIndex(i).stringValue = options[selectedIndex];
                }
                if (EditorGUI.EndChangeCheck())
                {
                    HandleChangeCallback(t, changedCallback, prop, null, new object[] { prop.GetArrayElementAtIndex(i), i });
                }

                if (RenderRemoveControls(i, new[] { prop }))
                {
                    HandleChangeCallback(t, changedCallback, prop, null, new object[] { null, i });
                    break;
                }
                EditorGUILayout.EndHorizontal();
            }

            if (!propDisabled)
            {
                EditorGUILayout.BeginHorizontal();
                if (RenderAddControls(new[] { prop }, "Add Element", null))
                {
                    HandleChangeCallback(t, changedCallback, prop, null, new object[] { prop.GetArrayElementAtIndex(prop.arraySize - 1), prop.arraySize - 1 });
                }
                if (GUILayout.Button("Clear", GUILayout.MaxWidth(60)))
                {
                    prop.arraySize = 0;
                    HandleChangeCallback(t, changedCallback, prop, null, new object[] { null, 0 });
                }
                EditorGUILayout.EndHorizontal();
            }
            EditorGUI.EndDisabledGroup();
        }
示例#5
0
        public override void OnInspectorGUI()
        {
            t = (UdonSharpBehaviour)target;

            showUdonSettings = (bool)(UTUtils.GetUTSetting("showUdonSettings", UTUtils.UTSettingType.Bool) ?? false);

            // we force-disable collision transfer for toolkit driven behaviours as it is not applicable
            if (!nonUBChecked)
            {
                nonUBMode    = t.gameObject.GetComponent <UdonBehaviour>() == null;
                nonUBChecked = true;
            }

            if (!nonUBMode)
            {
                if (UdonSharpEditorUtility.GetBackingUdonBehaviour(t).AllowCollisionOwnershipTransfer)
                {
                    UdonSharpEditorUtility.GetBackingUdonBehaviour(t).AllowCollisionOwnershipTransfer = false;
                }
            }

            var headerExited = false;

            EditorGUI.BeginChangeCheck();
            showUdonSettings = GUILayout.Toggle(showUdonSettings, "Udon Settings", UTStyles.smallButton);
            if (EditorGUI.EndChangeCheck())
            {
                UTUtils.SetUTSetting("showUdonSettings", UTUtils.UTSettingType.Bool, showUdonSettings);
            }

            if (showUdonSettings)
            {
                headerExited = UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(t, true);
            }

            if (headerExited)
            {
                return;
            }

            #region Caching

            if (!cacheBuilt)
            {
                tT           = t.GetType();
                programAsset = UdonSharpEditorUtility.GetUdonSharpProgramAsset(t);
                behInfo      = new UTBehaviourInfo(t);

                var prop = serializedObject.GetIterator();
                var next = prop.NextVisible(true);

                if (next)
                {
                    do
                    {
                        if (prop.name == "m_Script")
                        {
                            continue;
                        }

                        if (!fieldCache.ContainsKey(prop.name))
                        {
                            var newField = new UTField(prop);
                            fieldCache.Add(prop.name, newField);
                            if (newField.isInTabGroup)
                            {
                                if (!tabs.ContainsKey(newField.tabGroupName))
                                {
                                    tabs.Add(newField.tabGroupName, new Dictionary <string, UTFieldType>());
                                    // we only support one tab group per behaviour right now
                                    if (!tabsExist)
                                    {
                                        fieldOrder.Add(newField.tabGroupName, UTFieldType.Tab);
                                        tabsExist = true;
                                    }
                                }

                                // since tabs can host foldouts - we need to explicitly retarget them
                                // this logic could be generalized if i ever want to make all of this recursive
                                if (newField.isInFoldout)
                                {
                                    if (!foldouts.ContainsKey(newField.foldoutName))
                                    {
                                        foldouts.Add(newField.foldoutName, new Dictionary <string, UTFieldType>());
                                        tabs[newField.tabGroupName].Add(newField.foldoutName, UTFieldType.Foldout);
                                    }

                                    AddToFieldOrder(newField, prop, true);
                                    continue;
                                }

                                AddToFieldOrder(newField, prop, addToTabGroup: true);
                                continue;
                            }

                            if (newField.isInFoldout)
                            {
                                if (!foldouts.ContainsKey(newField.foldoutName))
                                {
                                    foldouts.Add(newField.foldoutName, new Dictionary <string, UTFieldType>());
                                    fieldOrder.Add(newField.foldoutName, UTFieldType.Foldout);
                                }

                                AddToFieldOrder(newField, prop, true);
                                continue;
                            }

                            AddToFieldOrder(newField, prop);
                        }
                    } while (prop.NextVisible(false));
                }

                cacheBuilt = true;
                return;
            }

            var e = Event.current;
            if (e.type == EventType.Repaint)
            {
                if (firstRepaint)
                {
                    firstRepaint = false;
                    return;
                }
            }

            #endregion

            if (behInfo.customName != null || behInfo.helpUrl != null)
            {
                EditorGUILayout.BeginHorizontal();
                UTStyles.RenderHeader(behInfo.customName != null ? behInfo.customName : behInfo.name);
                if (behInfo.helpUrl != null)
                {
                    if (GUILayout.Button("?", GUILayout.Height(26), GUILayout.Width(26)))
                    {
                        Application.OpenURL(behInfo.helpUrl);
                    }
                }
                EditorGUILayout.EndHorizontal();
            }

            if (behInfo.helpMsg != null)
            {
                UTStyles.RenderNote(behInfo.helpMsg);
            }

            if (behInfo.onBeforeEditor != null)
            {
                behInfo.onBeforeEditor.Invoke(t, new object[] { serializedObject });
            }

            // handle jagged arrays
            Undo.RecordObject(t, "Change Properties");

            EditorGUI.BeginChangeCheck();
            droppedObjects = false;

            // this method is overrideable by custom code
            DrawGUI();

            if (EditorGUI.EndChangeCheck() || droppedObjects || shouldReserialize)
            {
                if (behInfo.onValuesChanged != null)
                {
                    behInfo.onValuesChanged.Invoke(t, new object[] { serializedObject });
                }
                serializedObject.ApplyModifiedProperties();
            }

            if (droppedObjects)
            {
                return;
            }

            if (behInfo.onAfterEditor != null)
            {
                behInfo.onAfterEditor.Invoke(t, new object[] { serializedObject });
            }

            #region Buttons
            if (behInfo.buttons != null && !Application.isPlaying && behInfo.buttons.Length > 0)
            {
                buttonsExpanded = UTStyles.FoldoutHeader("Editor Methods", buttonsExpanded);
                if (buttonsExpanded)
                {
                    EditorGUILayout.BeginVertical(new GUIStyle("helpBox"));
                    foreach (var button in behInfo.buttons)
                    {
                        if (GUILayout.Button(button.Name))
                        {
                            button.Invoke(t, new object[] {});
                        }
                    }
                    EditorGUILayout.EndVertical();
                }
            }
            if (Application.isPlaying && behInfo.udonCustomEvents.Length > 0 && !nonUBMode)
            {
                methodsExpanded = UTStyles.FoldoutHeader("Udon Events", methodsExpanded);
                if (methodsExpanded)
                {
                    EditorGUILayout.BeginVertical(new GUIStyle("helpBox"));
                    var rowBreak = Mathf.Max(1, Mathf.Min(3, behInfo.udonCustomEvents.Length - 1));
                    var rowEndI  = -100;
                    foreach (var(button, i) in behInfo.udonCustomEvents.WithIndex())
                    {
                        if (i == rowEndI && i != behInfo.udonCustomEvents.Length - 1)
                        {
                            EditorGUILayout.EndHorizontal();
                        }
                        if (i % rowBreak == 0 && i != behInfo.udonCustomEvents.Length - 1)
                        {
                            EditorGUILayout.BeginHorizontal();
                            rowEndI = Math.Min(i + rowBreak, behInfo.udonCustomEvents.Length - 1);
                        }
                        if (GUILayout.Button(button))
                        {
                            UdonSharpEditorUtility.GetBackingUdonBehaviour(t).SendCustomEvent(button);
                            UdonSharpEditorUtility.CopyUdonToProxy(t);
                        }
                        if (i == behInfo.udonCustomEvents.Length - 1 && rowEndI != -100)
                        {
                            EditorGUILayout.EndHorizontal();
                        }
                    }
                    EditorGUILayout.EndVertical();
                }
            }
            #endregion
        }
        private void HandleFields(Dictionary <string, UTFieldType> fields)
        {
            foreach (var fieldEntry in fields)
            {
                if (droppedObjects)
                {
                    break;
                }
                switch (fieldEntry.Value)
                {
                case UTFieldType.Regular: {
                    var prop = serializedObject.FindProperty(fieldEntry.Key);
                    DrawField(fieldCache[fieldEntry.Key], prop);
                    break;
                }

                case UTFieldType.Tab: {
                    var tabNames      = tabs.Select(i => i.Key).ToArray();
                    var tabSaveTarget = fieldCache[tabs[tabNames[0]].Keys.ToArray()[0]].tabSaveTarget;
                    if (!String.IsNullOrEmpty(tabSaveTarget))
                    {
                        var targetProp = serializedObject.FindProperty(tabSaveTarget);
                        tabOpen = targetProp.intValue;
                        EditorGUI.BeginChangeCheck();
                        tabOpen = GUILayout.Toolbar(tabOpen, tabNames);
                        if (EditorGUI.EndChangeCheck())
                        {
                            targetProp.intValue = tabOpen;
                            if (fieldCache.ContainsKey(tabSaveTarget))
                            {
                                var fieldChange = fieldCache?[tabSaveTarget].onValueChaged;
                                if (fieldChange != null)
                                {
                                    fieldChange.Invoke(t, new object[] { targetProp });
                                }
                            }
                        }
                    }
                    else
                    {
                        tabOpen = GUILayout.Toolbar(tabOpen, tabNames);
                    }
                    HandleFields(tabs[tabNames[tabOpen]]);
                    break;
                }

                case UTFieldType.Foldout: {
                    var     foldout = foldouts[fieldEntry.Key].First();
                    UTField field;
                    switch (foldout.Value)
                    {
                    case UTFieldType.Horizontal: {
                        field = horizontalViews[foldout.Key].First();
                        break;
                    }

                    case UTFieldType.ListView: {
                        field = listViews[foldout.Key].First();
                        break;
                    }

                    default: {
                        field = fieldCache[foldout.Key];
                        break;
                    }
                    }
                    var parentProp  = serializedObject.FindProperty(field.name);
                    var foldoutName = field.foldoutName;
                    parentProp.isExpanded = UTStyles.FoldoutHeader(foldoutName, parentProp.isExpanded);
                    if (!parentProp.isExpanded)
                    {
                        break;
                    }
                    EditorGUILayout.BeginVertical(new GUIStyle("helpBox"));
                    HandleFields(foldouts[fieldEntry.Key]);
                    EditorGUILayout.EndVertical();
                    break;
                }

                case UTFieldType.ListView: {
                    var listViewFields = listViews[fieldEntry.Key];
                    HandleListView(listViewFields, fieldEntry);
                    break;
                }

                case UTFieldType.Horizontal: {
                    if (droppedObjects)
                    {
                        break;
                    }
                    var horizontalFields = horizontalViews[fieldEntry.Key];
                    List <SerializedProperty> propsList = new List <SerializedProperty>();
                    foreach (var field in horizontalFields)
                    {
                        propsList.Add(serializedObject.FindProperty(field.name));
                    }

                    var uiAttrs = horizontalFields[0].uiAttrs;

                    var isVisible = true;
                    foreach (var uiAttr in uiAttrs)
                    {
                        if (!uiAttr.GetVisible(propsList[0]))
                        {
                            isVisible = false;
                            break;
                        }
                    }

                    if (!isVisible)
                    {
                        break;
                    }

                    foreach (var uiAttr in uiAttrs)
                    {
                        uiAttr.BeforeGUI(propsList[0]);
                    }

                    var horizontalAttr =
                        horizontalFields[0].attributes.Find(i => i is HorizontalAttribute) as HorizontalAttribute;
                    if (horizontalAttr.showHeader)
                    {
                        // header frame and label for the group
                        var oldColor   = GUI.backgroundColor;
                        var headerRect = EditorGUILayout.GetControlRect();
                        GUI.backgroundColor = new Color(oldColor.r, oldColor.g, oldColor.b, 0.5f);
                        GUI.Box(headerRect, "", new GUIStyle("helpBox"));
                        GUI.backgroundColor = oldColor;
                        EditorGUI.LabelField(headerRect, fieldEntry.Key);
                    }

                    EditorGUILayout.BeginHorizontal();
                    for (int i = 0; i < propsList.Count; i++)
                    {
                        DrawFieldElement(horizontalFields[i], propsList[i]);
                    }

                    EditorGUILayout.EndHorizontal();

                    foreach (var uiAttr in uiAttrs)
                    {
                        uiAttr.AfterGUI(propsList[0]);
                    }

                    break;
                }
                }
            }
        }