Exemple #1
0
    public void drawEntity(NodeMEntity entity)
    {
        string name = "Entity";

        if (entity.entityName != "")
        {
            name = entity.entityName;
        }

        if (entity.orientation == PortOrientation.In)
        {
            //SirenixEditorGUI.
            SirenixEditorGUI.BeginIndentedHorizontal();
            SirenixEditorGUI.BeginBox();
            Rect rect = EditorGUILayout.GetControlRect();
            //  rect = EditorGUI.PrefixLabel(rect, new GUIContent("   "));


            rect = EditorGUI.PrefixLabel(rect, new GUIContent(name));

            if (GUI.Button(rect.AlignRight(15), EditorIcons.ArrowDown.Raw))
            {
                entity.style.unfolded = !entity.style.unfolded;
            }
            ;
            SirenixEditorGUI.EndBox();
            SirenixEditorGUI.EndIndentedHorizontal();
            // NodeEditorGUILayout.AddPortField(entity.port);
        }
        else
        {
            SirenixEditorGUI.BeginBox();
            Rect rect = EditorGUILayout.GetControlRect();
            EditorGUI.LabelField(rect.AlignRight(80), name);
            if (GUI.Button(rect.AlignLeft(15), EditorIcons.ArrowDown.Raw))
            {
                entity.style.unfolded = !entity.style.unfolded;
            }
            ;

            SirenixEditorGUI.EndBox();
            //  NodeEditorGUILayout.AddPortField(entity.port);
        }
        //  entity.style.unfolded = SirenixEditorGUI.Foldout(entity.style.unfolded, "");


        if (entity.style.unfolded)
        {
            SirenixEditorGUI.BeginBox();
            for (int i = 0; i < entity.components.Count; i++)
            {
                drawComponent(entity.components[i]);
            }
            SirenixEditorGUI.EndBox();
        }
        else
        {
            NodeEditorGUILayout.AddPortField(entity.port);
        }
    }
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(GUIContent label)
        {
            var property = this.Property;

            SirenixEditorGUI.BeginIndentedHorizontal();

            PropertyContext <int> height;

            if (property.Context.Get(this, "ButtonHeight", out height))
            {
                height.Value = 0;

                for (int i = 0; i < property.Children.Count; i++)
                {
                    var button = property.Children[i].Info.GetAttribute <ButtonAttribute>();
                    if (button != null && button.ButtonHeight > 0)
                    {
                        height.Value = button.ButtonHeight;
                    }
                }
            }

            for (int i = 0; i < property.Children.Count; i++)
            {
                var style = (GUIStyle)null;

                if (property.Children.Count != 1)
                {
                    if (i == 0)
                    {
                        style = SirenixGUIStyles.ButtonLeft;
                    }
                    else if (i == property.Children.Count - 1)
                    {
                        style = SirenixGUIStyles.ButtonRight;
                    }
                    else
                    {
                        style = SirenixGUIStyles.ButtonMid;
                    }
                }

                var child = property.Children[i];

                child.Context.GetGlobal("ButtonHeight", height.Value).Value = height.Value;
                child.Context.GetGlobal("ButtonStyle", style).Value         = style;
                DefaultMethodDrawer.DontDrawMethodParamaters = true;
                child.Draw(child.Label);
                DefaultMethodDrawer.DontDrawMethodParamaters = false;
            }

            SirenixEditorGUI.EndIndentedHorizontal();
        }
Exemple #3
0
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyGroupLayout(InspectorProperty property, ButtonGroupAttribute attribute, GUIContent label)
        {
            SirenixEditorGUI.BeginIndentedHorizontal();

            PropertyContext <int> height;

            if (property.Context.Get(this, "ButtonHeight", out height))
            {
                //height = new PropertyContext<int>();
                height.Value = 0;

                for (int i = 0; i < property.Children.Count; i++)
                {
                    var button = property.Children[i].Info.GetAttribute <ButtonAttribute>();
                    if (button != null && button.ButtonHeight > 0)
                    {
                        height.Value = button.ButtonHeight;
                    }
                }
            }

            for (int i = 0; i < property.Children.Count; i++)
            {
                var style = (GUIStyle)null;

                if (property.Children.Count != 1)
                {
                    if (i == 0)
                    {
                        style = SirenixGUIStyles.ButtonLeft;
                    }
                    else if (i == property.Children.Count - 1)
                    {
                        style = SirenixGUIStyles.ButtonRight;
                    }
                    else
                    {
                        style = SirenixGUIStyles.ButtonMid;
                    }
                }

                property.Children[i].Context.GetGlobal("ButtonHeight", height.Value).Value = height.Value;
                property.Children[i].Context.GetGlobal("ButtonStyle", style).Value         = style;
                InspectorUtilities.DrawProperty(property.Children[i]);
            }

            SirenixEditorGUI.EndIndentedHorizontal();
        }
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(IPropertyValueEntry <Vector3Int> entry, GUIContent label)
        {
            if (label == null)
            {
                SirenixEditorGUI.BeginIndentedHorizontal(EditorGUI.indentLevel == 0 ? GUIStyle.none : SirenixGUIStyles.PropertyMargin);
            }
            else
            {
                GUILayout.BeginHorizontal();
            }

            if (label != null)
            {
                EditorGUI.BeginChangeCheck();
                var value = SirenixEditorFields.VectorPrefixLabel(label, (Vector3)entry.SmartValue);
                if (EditorGUI.EndChangeCheck())
                {
                    entry.SmartValue = new Vector3Int((int)value.x, (int)value.y, (int)value.z);
                }
            }

            var  r          = GUIHelper.GetCurrentLayoutRect();
            bool showLabels = !(SirenixEditorFields.ResponsiveVectorComponentFields && (label != null ? r.width - EditorGUIUtility.labelWidth : r.width) < 185);

            GUIHelper.PushLabelWidth(SirenixEditorFields.SingleLetterStructLabelWidth);
            GUIHelper.PushIndentLevel(0);
            entry.Property.Children[0].Draw(showLabels ? GUIHelper.TempContent("X") : null);
            entry.Property.Children[1].Draw(showLabels ? GUIHelper.TempContent("Y") : null);
            entry.Property.Children[2].Draw(showLabels ? GUIHelper.TempContent("Z") : null);
            GUIHelper.PopIndentLevel();
            GUIHelper.PopLabelWidth();

            if (label == null)
            {
                SirenixEditorGUI.EndIndentedHorizontal();
            }
            else
            {
                GUILayout.EndHorizontal();
            }
        }
Exemple #5
0
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(GUIContent label)
        {
            var property  = this.Property;
            var attribute = this.Attribute;

            var context = property.Context.Get(this, "Context", (Context)null);

            if (context.Value == null)
            {
                context.Value = new Context();
                if (attribute.Title != null)
                {
                    context.Value.TitleHelper = new StringMemberHelper(property, attribute.Title);
                }

                context.Value.Widths      = new float[property.Children.Count];
                context.Value.MinWidths   = new float[property.Children.Count];
                context.Value.MaxWidths   = new float[property.Children.Count];
                context.Value.LabelWidths = new float[property.Children.Count];
                context.Value.Margins     = new Vector2[property.Children.Count];
                context.Value.Paddings    = new Vector2[property.Children.Count];

                float percentageAllocated = 0;
                for (int i = 0; i < property.Children.Count; i++)
                {
                    var child = property.Children[i];
                    var attr  = child.Children.Recurse()
                                .AppendWith(child)
                                .SelectMany(a => a.GetAttributes <HorizontalGroupAttribute>())
                                .FirstOrDefault(x => x.GroupID == attribute.GroupID);

                    if (attr == null)
                    {
                        context.Value.Widths[i] = -1;
                    }
                    else
                    {
                        context.Value.Widths[i]      = attr.Width;
                        context.Value.MinWidths[i]   = attr.MinWidth;
                        context.Value.MaxWidths[i]   = attr.MaxWidth;
                        context.Value.LabelWidths[i] = attr.LabelWidth;

                        if (attr.Width > 0 && attr.Width < 1)
                        {
                            context.Value.ContainsPercentageWidth++;
                            percentageAllocated += attr.Width;

                            // If we allocate 100% there is no way to resize the window down.
                            // In those cases, we convert the attribute to adjust itself automatically and Unity will ensure that
                            // that it reaches the 100% for us.
                            if (percentageAllocated >= 0.97)
                            {
                                percentageAllocated    -= attr.Width;
                                context.Value.Widths[i] = 0;
                                attr.Width = 0;
                            }
                        }

                        if (attr.MinWidth > 0 && attr.MinWidth <= 1)
                        {
                            context.Value.ContainsPercentageWidth++;

                            percentageAllocated += attr.MinWidth;
                            // Same thing for MinWidth.
                            if (percentageAllocated >= 0.97)
                            {
                                percentageAllocated       -= attr.MinWidth;
                                context.Value.MinWidths[i] = 0;
                                attr.MinWidth = 0;
                            }
                        }

                        context.Value.Margins[i]  = new Vector2(attr.MarginLeft, attr.MarginRight);
                        context.Value.Paddings[i] = new Vector2(attr.PaddingLeft, attr.PaddingRight);
                    }
                }
            }

            if (context.Value.TitleHelper != null)
            {
                if (context.Value.TitleHelper.ErrorMessage != null)
                {
                    SirenixEditorGUI.ErrorMessageBox(context.Value.TitleHelper.ErrorMessage);
                }
                else
                {
                    SirenixEditorGUI.Title(context.Value.TitleHelper.GetString(property), null, TextAlignment.Left, false);
                }
            }

            SirenixEditorGUI.BeginIndentedHorizontal();
            // GUILayout.BeginHorizontal();
            {
                if (attribute.LabelWidth > 0)
                {
                    GUIHelper.PushLabelWidth(attribute.LabelWidth);
                }

                var prevFieldWidth = EditorGUIUtility.fieldWidth;
                EditorGUIUtility.fieldWidth = 40;

                for (int i = 0; i < property.Children.Count; i++)
                {
                    float   width, minWidth, maxWidth;
                    Vector2 padding, margin;

                    if (context.Value.ContainsPercentageWidth > 1 && context.Value.TotalWidth == 0)
                    {
                        width    = 20; // Start small and expand next frame. Instead of starting to big and slowly getting smaller.
                        minWidth = 0;
                        maxWidth = 0;
                        padding  = new Vector2();
                        margin   = new Vector2();
                    }
                    else
                    {
                        width    = context.Value.Widths[i];
                        minWidth = context.Value.MinWidths[i];
                        maxWidth = context.Value.MaxWidths[i];
                        margin   = context.Value.Margins[i];
                        padding  = context.Value.Paddings[i];

                        if (padding.x > 0 && padding.x <= 1)
                        {
                            padding.x = padding.x * context.Value.TotalWidth;
                        }
                        if (padding.y > 0 && padding.y <= 1)
                        {
                            padding.y = padding.y * context.Value.TotalWidth;
                        }
                        if (margin.x > 0 && margin.x <= 1)
                        {
                            margin.x = margin.x * context.Value.TotalWidth;
                        }
                        if (margin.y > 0 && margin.y <= 1)
                        {
                            margin.y = margin.y * context.Value.TotalWidth;
                        }

                        if (width <= 1)
                        {
                            width = width * context.Value.TotalWidth;
                        }

                        width -= padding.x + padding.y;

                        if (minWidth > 0)
                        {
                            if (minWidth <= 1)
                            {
                                minWidth = minWidth * context.Value.TotalWidth;
                            }
                            minWidth -= padding.x + padding.y;
                        }

                        if (maxWidth > 0)
                        {
                            if (maxWidth <= 1)
                            {
                                maxWidth = maxWidth * context.Value.TotalWidth;
                            }
                            maxWidth -= padding.x + padding.y;
                        }
                    }

                    GUILayoutOptions.GUILayoutOptionsInstance options = null;

                    if (minWidth > 0)
                    {
                        options = GUILayoutOptions.MinWidth(minWidth);
                    }
                    if (maxWidth > 0)
                    {
                        options = options == null?GUILayoutOptions.MaxWidth(maxWidth) : options.MaxWidth(maxWidth);
                    }
                    if (options == null)
                    {
                        options = GUILayoutOptions.Width(width < 0 ? 0 : width);
                    }

                    if ((margin.x + padding.x) != 0)
                    {
                        GUILayout.Space(margin.x + padding.x);
                    }

                    GUILayout.BeginVertical(options);
                    property.Children[i].Draw(property.Children[i].Label);
                    GUILayout.Space(-3);
                    GUILayout.EndVertical();

                    if ((margin.y + padding.y) != 0)
                    {
                        GUILayout.Space(margin.y + padding.y);
                    }
                }

                if (Event.current.type == EventType.Repaint)
                {
                    var newWidth = GUIHelper.GetCurrentLayoutRect().width;

                    if (context.Value.TotalWidth != newWidth)
                    {
                        GUIHelper.RequestRepaint();
                    }

                    context.Value.TotalWidth = newWidth;
                }

                EditorGUIUtility.fieldWidth = prevFieldWidth;
                if (attribute.LabelWidth > 0)
                {
                    GUIHelper.PopLabelWidth();
                }
            }
            // GUILayout.EndHorizontal();
            SirenixEditorGUI.EndIndentedHorizontal();
        }
Exemple #6
0
        /// <summary>
        /// Not yet documented.
        /// </summary>
        protected override void DrawPropertyLayout(GUIContent label)
        {
            var entry     = this.ValueEntry;
            var attribute = this.Attribute;

            SirenixEditorGUI.BeginIndentedHorizontal();
            {
                var hideLabel = label == null;
                if (hideLabel == false)
                {
                    GUILayout.Label(label, GUILayoutOptions.Width(GUIHelper.BetterLabelWidth - 4).ExpandWidth(false));
                }
                else
                {
                    GUILayout.Space(5);
                }

                //var colorPaletDropDown = entry.Context.Get(this, "colorPalette", 0);
                //var currentName = entry.Context.Get(this, "currentName", attribute.PaletteName);
                //var showAlpha = entry.Context.Get(this, "showAlpha", attribute.ShowAlpha);
                //var names = ColorPaletteManager.Instance.GetColorPaletteNames();

                ColorPalette colorPalette;
                var          rect = EditorGUILayout.BeginHorizontal();
                {
                    rect.x    -= 3;
                    rect.width = 25;

                    entry.SmartValue = SirenixEditorGUI.DrawColorField(rect, entry.SmartValue, false, this.ShowAlpha);
                    bool openInEditorShown = false;
                    GUILayout.Space(28);
                    SirenixEditorGUI.BeginInlineBox();
                    {
                        if (attribute.PaletteName == null || ColorPaletteManager.Instance.ShowPaletteName)
                        {
                            SirenixEditorGUI.BeginToolbarBoxHeader();
                            {
                                if (attribute.PaletteName == null)
                                {
                                    var newValue = EditorGUILayout.Popup(this.PaletteIndex, this.Names, GUILayoutOptions.ExpandWidth(true));
                                    if (this.PaletteIndex != newValue)
                                    {
                                        this.PaletteIndex         = newValue;
                                        this.CurrentName          = this.Names[newValue];
                                        this.PersistentName.Value = this.CurrentName;
                                        GUIHelper.RemoveFocusControl();
                                    }
                                }
                                else
                                {
                                    GUILayout.Label(this.CurrentName);
                                    GUILayout.FlexibleSpace();
                                }
                                openInEditorShown = true;
                                if (SirenixEditorGUI.IconButton(EditorIcons.SettingsCog))
                                {
                                    ColorPaletteManager.Instance.OpenInEditor();
                                }
                            }
                            SirenixEditorGUI.EndToolbarBoxHeader();
                        }

                        if (attribute.PaletteName == null)
                        {
                            colorPalette = ColorPaletteManager.Instance.ColorPalettes.FirstOrDefault(x => x.Name == this.Names[this.PaletteIndex]);
                        }
                        else
                        {
                            colorPalette = ColorPaletteManager.Instance.ColorPalettes.FirstOrDefault(x => x.Name == this.NameGetter.GetString(entry));
                        }

                        if (colorPalette == null)
                        {
                            GUILayout.BeginHorizontal();
                            {
                                if (attribute.PaletteName != null)
                                {
                                    if (GUILayout.Button("Create color palette: " + this.NameGetter.GetString(entry)))
                                    {
                                        ColorPaletteManager.Instance.ColorPalettes.Add(new ColorPalette()
                                        {
                                            Name = this.NameGetter.GetString(entry)
                                        });
                                        ColorPaletteManager.Instance.OpenInEditor();
                                    }
                                }
                            }
                            GUILayout.EndHorizontal();
                        }
                        else
                        {
                            this.CurrentName = colorPalette.Name;
                            this.ShowAlpha   = attribute.ShowAlpha && colorPalette.ShowAlpha;
                            if (openInEditorShown == false)
                            {
                                GUILayout.BeginHorizontal();
                            }
                            var color   = entry.SmartValue;
                            var stretch = ColorPaletteManager.Instance.StretchPalette;
                            var size    = ColorPaletteManager.Instance.SwatchSize;
                            var margin  = ColorPaletteManager.Instance.SwatchSpacing;
                            if (DrawColorPaletteColorPicker(entry, colorPalette, ref color, colorPalette.ShowAlpha, stretch, size, 20, margin))
                            {
                                entry.SmartValue = color;
                                //entry.ApplyChanges();
                            }
                            if (openInEditorShown == false)
                            {
                                GUILayout.Space(4);
                                if (SirenixEditorGUI.IconButton(EditorIcons.SettingsCog))
                                {
                                    ColorPaletteManager.Instance.OpenInEditor();
                                }
                                GUILayout.EndHorizontal();
                            }
                        }
                    }
                    SirenixEditorGUI.EndInlineBox();
                }
                EditorGUILayout.EndHorizontal();
            }

            SirenixEditorGUI.EndIndentedHorizontal();
        }
Exemple #7
0
        private void DrawType(TypeGroup.TypePair typeToDraw, IPropertyValueEntry <InspectorTypeDrawingConfig> entry)
        {
            Type currentEditorType = typeToDraw.PreExistingEditorType;
            bool conflict          = false;

            if (currentEditorType == null)
            {
                for (int i = 0; i < entry.Values.Count; i++)
                {
                    var type = entry.Values[i].GetEditorType(typeToDraw.DrawnType);

                    if (i == 0)
                    {
                        currentEditorType = type;
                    }
                    else if (type != currentEditorType)
                    {
                        currentEditorType = null;
                        conflict          = true;
                        break;
                    }
                }
            }

            bool useToggle = true;

            SirenixEditorGUI.BeginListItem();
            {
                SirenixEditorGUI.BeginIndentedHorizontal();
                SirenixEditorGUI.IconButton(EditorIcons.Transparent, IconStyle, 16);

                if (typeToDraw.PreExistingEditorType != null)
                {
                    SirenixEditorGUI.IconButton(EditorIcons.Transparent, IconStyle, 16);
                    GUILayout.Label(typeToDraw.DrawnType.GetNiceName());
                    GUILayout.Label("Drawn by '" + typeToDraw.PreExistingEditorType + "'", SirenixGUIStyles.RightAlignedGreyMiniLabel);

                    for (int i = 0; i < entry.Values.Count; i++)
                    {
                        if (entry.Values[i].HasEntryForType(typeToDraw.DrawnType))
                        {
                            entry.Values[i].ClearEditorEntryForDrawnType(typeToDraw.DrawnType);
                        }
                    }
                }
                else
                {
                    EditorGUI.showMixedValue = conflict;

                    if (useToggle)
                    {
                        bool isToggled = currentEditorType == typeof(OdinEditor);

                        GUI.changed = false;
                        isToggled   = EditorGUI.Toggle(GUILayoutUtility.GetRect(16, 16, EditorStyles.toggle, GUILayoutOptions.ExpandWidth(false).Width(16)), isToggled);

                        if (GUI.changed)
                        {
                            for (int i = 0; i < entry.Values.Count; i++)
                            {
                                entry.Values[i].SetEditorType(typeToDraw.DrawnType, isToggled ? typeof(OdinEditor) : null);
                            }

                            UpdateRootGroupConflicts();
                            InspectorConfig.Instance.UpdateOdinEditors();
                        }

                        GUILayout.Label(typeToDraw.DrawnType.GetNiceName());
                    }
                    else
                    {
                        GUILayout.Label("TODO: DROPDOWN!");
                    }
                }

                SirenixEditorGUI.EndIndentedHorizontal();
                EditorGUI.showMixedValue = false;
            }
            SirenixEditorGUI.EndListItem();
        }
Exemple #8
0
        private void DrawTypeGroup(TypeGroup typeGroup, IPropertyValueEntry <InspectorTypeDrawingConfig> entry, string searchText)
        {
            if (!typeGroup.IsSearchVisible)
            {
                return;
            }

            bool useToggle = true;

            var rect = SirenixEditorGUI.BeginListItem();

            {
                bool toggleExpansion = false;

                SirenixEditorGUI.BeginIndentedHorizontal();
                {
                    EditorIcon icon = (typeGroup.IsExpanded || !searchText.IsNullOrWhitespace()) ? EditorIcons.TriangleDown : EditorIcons.TriangleRight;

                    toggleExpansion = SirenixEditorGUI.IconButton(icon, IconStyle, 16);

                    if (!typeGroup.HasEligibleTypes)
                    {
                        toggleExpansion |= SirenixEditorGUI.IconButton(EditorIcons.Transparent, 20);
                    }
                    else
                    {
                        if (useToggle)
                        {
                            EditorGUI.showMixedValue = typeGroup.HasConflict;

                            bool isToggled = typeGroup.HasConflict || typeGroup.GetSharedEditorType() == typeof(OdinEditor);

                            GUI.changed = false;
                            isToggled   = EditorGUI.Toggle(GUILayoutUtility.GetRect(16, 16, EditorStyles.toggle, GUILayoutOptions.ExpandWidth(false).Width(16)), isToggled);

                            if (GUI.changed)
                            {
                                typeGroup.SetSharedEditorType(isToggled ? typeof(OdinEditor) : null);
                                UpdateRootGroupConflicts();
                                InspectorConfig.Instance.UpdateOdinEditors();
                            }

                            EditorGUI.showMixedValue = false;
                        }
                        else
                        {
                            GUILayout.Label("TODO: DROPDOWN!");
                        }
                    }

                    GUILayout.Label(typeGroup.Name);
                }
                SirenixEditorGUI.EndIndentedHorizontal();

                if (toggleExpansion || (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)))
                {
                    typeGroup.IsExpanded = !typeGroup.IsExpanded;
                    Event.current.Use();
                }
            }
            SirenixEditorGUI.EndListItem();

            if (SirenixEditorGUI.BeginFadeGroup(typeGroup, typeGroup.IsExpanded || !searchText.IsNullOrWhitespace()))
            {
                EditorGUI.indentLevel++;

                foreach (var subType in typeGroup.SubTypes)
                {
                    if (typeGroup.IsTypeVisible(subType.DrawnType))
                    {
                        this.DrawType(subType, entry);
                    }
                }

                foreach (var subGroup in typeGroup.SubGroups)
                {
                    this.DrawTypeGroup(subGroup, entry, searchText);
                }

                EditorGUI.indentLevel--;
            }
            SirenixEditorGUI.EndFadeGroup();
        }
Exemple #9
0
        private void DrawRootTypeGroup(InspectorDefaultEditors editorCategory, IPropertyValueEntry <InspectorTypeDrawingConfig> entry, string searchText)
        {
            TypeGroup typeGroup;

            switch (editorCategory)
            {
            case InspectorDefaultEditors.UserTypes:
                typeGroup = UserTypesRootGroup;
                break;

            case InspectorDefaultEditors.PluginTypes:
                typeGroup = PluginTypesRootGroup;
                break;

            case InspectorDefaultEditors.UnityTypes:
                typeGroup = UnityTypesRootGroup;
                break;

            case InspectorDefaultEditors.OtherTypes:
            default:
                typeGroup = OtherTypesRootGroup;
                break;
            }

            if (typeGroup.SubTypes.Count == 0 && typeGroup.SubGroups.Count == 0)
            {
                SirenixEditorGUI.BeginListItem();
                {
                    SirenixEditorGUI.BeginIndentedHorizontal();
                    {
                        GUIHelper.PushGUIEnabled(false);
                        {
                            SirenixEditorGUI.IconButton(EditorIcons.TriangleRight, IconStyle, 16);
                            GUILayoutUtility.GetRect(16, 16, EditorStyles.toggle, GUILayoutOptions.ExpandWidth(false).Width(16));
                            GUILayout.Label(typeGroup.Name);
                        }
                        GUIHelper.PopGUIEnabled();
                    }
                    SirenixEditorGUI.EndIndentedHorizontal();
                }
                SirenixEditorGUI.EndListItem();
            }
            else
            {
                bool useToggle = true;

                var rect = SirenixEditorGUI.BeginListItem();
                {
                    bool toggleExpansion = false;

                    SirenixEditorGUI.BeginIndentedHorizontal();
                    {
                        EditorIcon icon = (typeGroup.IsExpanded || !searchText.IsNullOrWhitespace()) ? EditorIcons.TriangleDown : EditorIcons.TriangleRight;

                        toggleExpansion = SirenixEditorGUI.IconButton(icon, IconStyle, 16);

                        if (useToggle)
                        {
                            EditorGUI.showMixedValue = typeGroup.HasConflict;

                            bool isToggled = typeGroup.HasConflict || typeGroup.GetSharedEditorType() == typeof(OdinEditor);

                            GUI.changed = false;
                            isToggled   = EditorGUI.Toggle(GUILayoutUtility.GetRect(16, 16, EditorStyles.toggle, GUILayoutOptions.ExpandWidth(false).Width(16)), isToggled);

                            if (GUI.changed)
                            {
                                typeGroup.ClearEditorTypes();

                                if (isToggled)
                                {
                                    // Add rule flag
                                    InspectorConfig.Instance.DefaultEditorBehaviour |= editorCategory;
                                }
                                else
                                {
                                    // Remove rule flag
                                    InspectorConfig.Instance.DefaultEditorBehaviour = InspectorConfig.Instance.DefaultEditorBehaviour & ~editorCategory;
                                }

                                EditorUtility.SetDirty(InspectorConfig.Instance);
                                InspectorConfig.Instance.UpdateOdinEditors();
                            }

                            EditorGUI.showMixedValue = false;
                        }
                        else
                        {
                            GUILayout.Label("TODO: DROPDOWN!");
                        }

                        GUILayout.Label(typeGroup.Name);
                    }
                    SirenixEditorGUI.EndIndentedHorizontal();

                    if (toggleExpansion || (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)))
                    {
                        typeGroup.IsExpanded = !typeGroup.IsExpanded;
                        Event.current.Use();
                    }
                }
                SirenixEditorGUI.EndListItem();

                if (SirenixEditorGUI.BeginFadeGroup(typeGroup, typeGroup.IsExpanded || !searchText.IsNullOrWhitespace()))
                {
                    EditorGUI.indentLevel++;

                    foreach (var subType in typeGroup.SubTypes)
                    {
                        if (typeGroup.IsTypeVisible(subType.DrawnType))
                        {
                            this.DrawType(subType, entry);
                        }
                    }

                    foreach (var subGroup in typeGroup.SubGroups)
                    {
                        this.DrawTypeGroup(subGroup, entry, searchText);
                    }

                    EditorGUI.indentLevel--;
                }
                SirenixEditorGUI.EndFadeGroup();
            }
        }
        /// <summary>
        /// Not yet documented.
        /// </summary>
        protected override void DrawPropertyLayout(IPropertyValueEntry <Color> entry, ColorPaletteAttribute attribute, GUIContent label)
        {
            SirenixEditorGUI.BeginIndentedHorizontal();
            {
                var hideLabel = label == null;
                if (hideLabel == false)
                {
                    GUILayout.Label(label, GUILayoutOptions.Width(EditorGUIUtility.labelWidth - 4).ExpandWidth(false));
                }
                else
                {
                    GUILayout.Space(5);
                }

                PropertyContext <PaletteContext> contextBuffer;
                if (entry.Context.Get(this, "ColorPalette", out contextBuffer))
                {
                    contextBuffer.Value = new PaletteContext()
                    {
                        PaletteIndex = 0,
                        CurrentName  = attribute.PaletteName,
                        ShowAlpha    = attribute.ShowAlpha,
                        Names        = ColorPaletteManager.Instance.ColorPalettes.Select(x => x.Name).ToArray(),
                    };

                    // Get persistent context value
                    if (attribute.PaletteName == null)
                    {
                        contextBuffer.Value.PersistentName = entry.Context.GetPersistent <string>(this, "ColorPaletteName", null);
                        var list = contextBuffer.Value.Names.ToList();
                        contextBuffer.Value.CurrentName = contextBuffer.Value.PersistentName.Value;

                        if (contextBuffer.Value.CurrentName != null && list.Contains(contextBuffer.Value.CurrentName))
                        {
                            contextBuffer.Value.PaletteIndex = list.IndexOf(contextBuffer.Value.CurrentName);
                        }
                    }
                    else
                    {
                        contextBuffer.Value.NameGetter = new StringMemberHelper(entry.ParentType, attribute.PaletteName);
                    }
                }

                var context = contextBuffer.Value;

                //var colorPaletDropDown = entry.Context.Get(this, "colorPalette", 0);
                //var currentName = entry.Context.Get(this, "currentName", attribute.PaletteName);
                //var showAlpha = entry.Context.Get(this, "showAlpha", attribute.ShowAlpha);
                //var names = ColorPaletteManager.Instance.GetColorPaletteNames();

                ColorPalette colorPalette;
                var          rect = EditorGUILayout.BeginHorizontal();
                {
                    rect.x    -= 3;
                    rect.width = 25;

                    entry.SmartValue = SirenixEditorGUI.DrawColorField(rect, entry.SmartValue, false, context.ShowAlpha);
                    bool openInEditorShown = false;
                    GUILayout.Space(28);
                    SirenixEditorGUI.BeginInlineBox();
                    {
                        if (attribute.PaletteName == null || ColorPaletteManager.Instance.ShowPaletteName)
                        {
                            SirenixEditorGUI.BeginBoxHeader();
                            {
                                if (attribute.PaletteName == null)
                                {
                                    var newValue = EditorGUILayout.Popup(context.PaletteIndex, context.Names, GUILayoutOptions.ExpandWidth(true));
                                    if (context.PaletteIndex != newValue)
                                    {
                                        context.PaletteIndex         = newValue;
                                        context.CurrentName          = context.Names[newValue];
                                        context.PersistentName.Value = context.CurrentName;
                                        GUIHelper.RemoveFocusControl();
                                    }
                                }
                                else
                                {
                                    GUILayout.Label(context.CurrentName);
                                    GUILayout.FlexibleSpace();
                                }
                                openInEditorShown = true;
                                if (SirenixEditorGUI.IconButton(EditorIcons.SettingsCog))
                                {
                                    ColorPaletteManager.Instance.OpenInEditor();
                                }
                            }
                            SirenixEditorGUI.EndBoxHeader();
                        }

                        if (attribute.PaletteName == null)
                        {
                            colorPalette = ColorPaletteManager.Instance.ColorPalettes.FirstOrDefault(x => x.Name == context.Names[context.PaletteIndex]);
                        }
                        else
                        {
                            colorPalette = ColorPaletteManager.Instance.ColorPalettes.FirstOrDefault(x => x.Name == context.NameGetter.GetString(entry));
                        }

                        if (colorPalette == null)
                        {
                            GUILayout.BeginHorizontal();
                            {
                                if (attribute.PaletteName != null)
                                {
                                    if (GUILayout.Button("Create color palette: " + context.NameGetter.GetString(entry)))
                                    {
                                        ColorPaletteManager.Instance.ColorPalettes.Add(new ColorPalette()
                                        {
                                            Name = context.NameGetter.GetString(entry)
                                        });
                                        ColorPaletteManager.Instance.OpenInEditor();
                                    }
                                }
                            }
                            GUILayout.EndHorizontal();
                        }
                        else
                        {
                            context.CurrentName = colorPalette.Name;
                            context.ShowAlpha   = attribute.ShowAlpha && colorPalette.ShowAlpha;
                            if (openInEditorShown == false)
                            {
                                GUILayout.BeginHorizontal();
                            }
                            var color   = entry.SmartValue;
                            var stretch = ColorPaletteManager.Instance.StretchPalette;
                            var size    = ColorPaletteManager.Instance.SwatchSize;
                            var margin  = ColorPaletteManager.Instance.SwatchSpacing;
                            if (DrawColorPaletteColorPicker(entry, colorPalette, ref color, colorPalette.ShowAlpha, stretch, size, 20, margin))
                            {
                                entry.SmartValue = color;
                                //entry.ApplyChanges();
                            }
                            if (openInEditorShown == false)
                            {
                                GUILayout.Space(4);
                                if (SirenixEditorGUI.IconButton(EditorIcons.SettingsCog))
                                {
                                    ColorPaletteManager.Instance.OpenInEditor();
                                }
                                GUILayout.EndHorizontal();
                            }
                        }
                    }
                    SirenixEditorGUI.EndInlineBox();
                }
                EditorGUILayout.EndHorizontal();
            }

            SirenixEditorGUI.EndIndentedHorizontal();
        }
        private int DrawEntry(int index, ref bool collectionChanged)
        {
            SirenixEditorGUI.BeginIndentedHorizontal(new GUILayoutOption[] {});
            SirenixEditorGUI.BeginBox();
            SirenixEditorGUI.Title(this.Attribute.ListItemType.Name.Split('`')[0] + " " + index + "", "", TextAlignment.Center, true, false);
            SirenixEditorGUI.BeginIndentedVertical();

            EditorGUI.BeginChangeCheck();

            foreach (var child in this.Property.Children[index].Children)
            {
                child.Draw();
                if (true /*is node port?*/)
                {
                    NodeEditorGUILayout.PortField(/*port*/ null, new GUILayoutOption[] {});

                    /*
                     * To draw a port field here:
                     * - have a port to populate this field
                     * - the port should represent the set of properties for this item in
                     *  the list
                     * - I (hopefully) shouldn't have to add a port within the dynamic list
                     *  property's type
                     * To get the ports:
                     * - The list of ports is stored in the node at edit time. Somehow,
                     *  they need to end up here, and in the right order.
                     * - The NodeEditor does something similar already using attributes, so
                     *  it can't be *totally* impossible.
                     * Complications:
                     * - This property drawer isn't specific to the Node Editor Window.
                     *  This means ports shouldn't get drawn in every context.
                     * - There doesn't seem to be a way to get info about the node directly
                     *  into the property attribute as would be the simplest solution...
                     *  instead, online the suggestion is to use some kind of 3rd class to
                     *  look at class instances and pull information from point A to point
                     *  B. Sounds difficult to do elegantly in this scenario...but again,
                     *  the NodeEditor can accomplish drawing port handles over existing
                     *  property draws, so it must be possible.
                     * Observations:
                     *  - NodeEditor passes target.DynamicPorts into
                     *    NodeEditorGUILayout.PortField. That's the call we care about.
                     *  - target is almost certainly the Node that the NodeEditor is
                     *    tasked with rendering.
                     *  - target is defined in NodeEditorBase, as generic type K (which
                     *    for us is XNode.Node...)
                     *  - target seems to be handed to NodeEditorBase via GetEditor, which
                     *    seems like some weird roundabout constructor...
                     *    - is a static method that creates an instance of type T (NodeEditor in our case,
                     *      which again directly inherits from NodeEditorBase) using
                     *      reflection
                     *    - populates target (and other props)
                     *    - hands back the created instance
                     *  - NodeEditorBase.GetEditor() used by:
                     *    - NodeEditor: to add context menu stuff (not useful)
                     *    - NodeEditorAction: to handle mouse behavior (not useful)
                     *    - NodeEditorGUI: to draw all the nodes (sounds about right)
                     *      - Soon after GetEditor(), NodeEditorGUI calls OnBodyGUI() on
                     *        the instance, which in turn draws the port fields, so yes,
                     *        this is correct spot...
                     *      - NodeEditorGUI gets the node in question from a reference to
                     *        the graph.
                     *      - graph in this case is a property belonging to
                     *        NodeEditorGUI's outer class...yes, NodeEditorGUI is
                     *        enclosed within a partial class of NodeEditorWindow...wow,
                     *        the code smell is funky down here in XNode land.
                     *      - this, in turn, looks to be set in NodeEditorWindow.Open()
                     *    - NodeEditorWindow:
                     *      - Open() called by OnOpen(), which pulls in the graph via
                     *        Unity API (EditorUtility.InstanceIDToObject()), which is fed
                     *        an instanceID given to them by (you guessed it) the Unity
                     *        Engine...crap. That's gonna be way too much work.
                     *  - Where do I already have access to the graph?
                     *    - well, the graph has access to itself (obviously)
                     *    - each node has a reference to the graph.
                     *    - I can create a custom node editor script, and that would have
                     *      access to the graph.
                     *    - Right now, my assumption is that NodeEditors are specific to a
                     *      given type of node. I could supply a NodeEditor that's
                     *      specific to nodes of type AutoNode...but, well, much of the
                     *      drawing logic would be identical.
                     *      - NodeEditor walks through all visible properties and draws
                     *        them using NodeEditorGUILayout.PropertyField.
                     *      - Wait, the call we care about may actually be PropertyField,
                     *        which supposedly automatically displays ports if relevant. How
                     *        the heck does that work?
                     *      - It looks like that method grabs the Node directly from the
                     *        SerializedProperty. You don't need to explicitly pass it in!
                     *      - But how do I know if that'd even be set in
                     *        AutoTableAttributeDrawer? Am I even working with
                     *        SerializedProperties in my case? I don't think I am...
                     *      - Nope, I'm working with OdinInspector's InspectorProperty
                     *        class.
                     *      - Could the serialized property be buried somewhere in that
                     *        class's properties? Hold on...
                     *        - ValueEntry? BaseValueEntry? Oooh, SerializationRoot sounds
                     *          promising...trouble is, that's also an
                     *          InspectorProperty...dang it.
                     *      - Maybe the OdinAttributeDrawer base class has some hints!
                     *        - It has ValueEntry...which at least will get us the values
                     *          that we're trying to draw. That's a good start!
                     *        - Can you get the object ValueEntry belongs to, perhaps?
                     *          That'd be an odd, but doable way of getting the Ports.
                     *        - ValueEntry.SmartValue is the actual list of stuff, but not
                     *          the ports.
                     *          - oh, hold on...SmartValue may have the elements, but they
                     *            may be separated from the Node's property at this point.
                     *          - Wait wait, we have access to the instance values of the
                     *            Attribute
                     *          - Can I get the property an attribute belongs to in that
                     *            case?
                     *          - ...I think we're allllll the way back to square one. I'd
                     *            be able to do this if I had .NET 4.5 to work with, but
                     *            that seems to be from THIS YEAR (2021), and the latest
                     *            stable unity version is from last year, so there's no
                     *            way their dist of .NET would be 4.5.
                     *          - ...2012.
                     *          - .NET 4.5 was released in 2012.
                     *          - That's...GREAT in this case!
                     *          - I just tried it. It works (like, we ARE using 4.5), but the calling function
                     *            didn't turn out to be helpful at all.
                     *          - ASDLJHDFLKJHSJSLDFH
                     *          -
                     *          - ...
                     *          -
                     *          - *sad 4:00 AM programmer noises.*
                     *
                     *
                     *
                     */
                }
            }

            if (EditorGUI.EndChangeCheck())
            {
                collectionChanged = true;
            }


            SirenixEditorGUI.EndIndentedVertical();
            SirenixEditorGUI.EndBox();
            if (!SirenixEditorGUI.IconButton(EditorIcons.Minus))
            {
                index++;
            }
            else
            {
                this.ValueEntry.SmartValue.RemoveAt(index);
            }
            SirenixEditorGUI.EndIndentedHorizontal();

            return(index);
        }