Example #1
0
        /// <summary>
        /// Draws this property in the inspector with a given default label. This default label may be overridden by attributes on the drawn property.
        /// </summary>
        public void Draw(GUIContent defaultLabel)
        {
            this.Update();

            bool popGUIEnabled = false;

            try
            {
                this.PushDraw();

                if ((this.RecursiveDrawDepth + InlineEditorAttributeDrawer.CurrentInlineEditorDrawDepth) > GeneralDrawerConfig.Instance.MaxRecursiveDrawDepth)
                {
                    SirenixEditorGUI.ErrorMessageBox("The property '" + this.NiceName + "' has exceeded the maximum recursive draw depth limit of " + GeneralDrawerConfig.Instance.MaxRecursiveDrawDepth + ".");
                    return;
                }

                if (this.ValueEntry != null &&
                    this.ValueEntry.SerializationBackend == SerializationBackend.Odin &&
                    !this.SupportsPrefabModifications &&
                    this.Tree.PrefabModificationHandler.HasPrefabs &&
                    !GUIHelper.IsDrawingDictionaryKey &&
                    this.Info.PropertyType == PropertyType.Value)
                {
                    if ((this.ParentValueProperty == null || this.ParentValueProperty.SupportsPrefabModifications) && GeneralDrawerConfig.Instance.ShowPrefabModificationsDisabledMessage)
                    {
                        string objText = this.Tree.PrefabModificationHandler.HasNestedOdinPrefabData ? "this instance" : "prefab instances";
                        SirenixEditorGUI.InfoMessageBox("The property '" + this.NiceName + "' does not support being modified on " + objText + ". (You can disable this message in the general drawer config.)");
                    }

                    GUIHelper.PushGUIEnabled(false);
                    popGUIEnabled = true;
                }

                var chain = this.GetActiveDrawerChain();
                chain.Reset();

                var e             = Event.current.type;
                var currDrawCount = this.DrawCount;
                var measureBox    = e == EventType.Repaint || (e != EventType.Layout && this.LastDrawnValueRect.height == 0);

                if (measureBox)
                {
                    GUIHelper.BeginLayoutMeasuring();
                }

                {
                    try
                    {
                        if (chain.MoveNext())
                        {
                            bool setIsBoldState = this.ValueEntry != null && e == EventType.Repaint;
                            if (setIsBoldState)
                            {
                                var boldState = this.ValueEntry.ValueChangedFromPrefab;

                                if (GUIHelper.IsDrawingDictionaryKey)
                                {
                                    // Always propagate changed state down through dictionary keys
                                    boldState |= GUIHelper.IsBoldLabel;
                                }

                                GUIHelper.PushIsBoldLabel(boldState);
                            }

                            var popPushGUIEnabled = this.ValueEntry != null && !this.ValueEntry.IsEditable;
                            if (popPushGUIEnabled)
                            {
                                GUIHelper.PushGUIEnabled(false);
                            }

                            chain.Current.DrawProperty(defaultLabel);

                            if (popPushGUIEnabled)
                            {
                                GUIHelper.PopGUIEnabled();
                            }

                            if (setIsBoldState)
                            {
                                GUIHelper.PopIsBoldLabel();
                            }
                        }
                        else
                        {
                            if (this.Info.PropertyType == PropertyType.Method)
                            {
                                EditorGUILayout.LabelField(this.NiceName, "No drawers could be found for the method property '" + this.Name + "'.");
                            }
                            else if (this.Info.PropertyType == PropertyType.Group)
                            {
                                var attr = this.Info.GetAttribute <PropertyGroupAttribute>();

                                if (attr != null)
                                {
                                    EditorGUILayout.LabelField(this.NiceName, "No drawers could be found for the property group '" + this.Name + "' with property group attribute type '" + attr.GetType().GetNiceName() + "'.");
                                }
                                else
                                {
                                    EditorGUILayout.LabelField(this.NiceName, "No drawers could be found for the property group '" + this.Name + "'.");
                                }
                            }
                            //else if (property.Info.GetAttribute<HideInInspector>() == null)
                            //{
                            //    EditorGUILayout.LabelField(property.NiceName, "No drawers could be found for the value property '" + property.Name + "' of type '" + property.ValueEntry.TypeOfValue.GetNiceName() + "'.");
                            //}
                        }
                    }
                    catch (Exception ex)
                    {
                        if (ex is ExitGUIException || ex.InnerException is ExitGUIException)
                        {
                            throw ex;
                        }
                        else
                        {
                            var msg =
                                "This error occurred while being drawn by Odin. \n" +
                                "Odin Property Path: " + this.Path + "\n" +
                                "Odin Drawer Chain:\n" + string.Join("\n", chain.BakedDrawerArray.Select(n => " > " + n.GetType().GetNiceName()).ToArray()) + ".";

                            Debug.LogException(new OdinPropertyException(msg, ex));
                        }
                    }
                }

                if (measureBox)
                {
                    if (currDrawCount > this.lastDrawnValueRects.Count)
                    {
                        this.lastDrawnValueRects.SetLength(currDrawCount);
                    }

                    this.lastDrawnValueRects[currDrawCount - 1] = GUIHelper.EndLayoutMeasuring();
                }
            }
            finally
            {
                this.PopDraw();

                if (popGUIEnabled)
                {
                    GUIHelper.PopGUIEnabled();
                }
            }
        }
Example #2
0
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(GUIContent label)
        {
            var entry = this.ValueEntry;

            this.dictionaryResolver          = entry.Property.ChildResolver as StrongDictionaryPropertyResolver <TDictionary, TKey, TValue>;
            this.config                      = GeneralDrawerConfig.Instance;
            this.paging.NumberOfItemsPerPage = this.config.NumberOfItemsPrPage;
            listItemStyle.padding.right      = !entry.IsEditable || this.attrSettings.IsReadOnly ? 4 : 20;

            SirenixEditorGUI.BeginIndentedVertical(SirenixGUIStyles.PropertyPadding);
            {
                this.paging.Update(elementCount: entry.Property.Children.Count);
                this.DrawToolbar(entry);
                this.paging.Update(elementCount: entry.Property.Children.Count);

                if (!this.disableAddKey && this.attrSettings.IsReadOnly == false)
                {
                    this.DrawAddKey(entry);
                }

                float t;
                GUIHelper.BeginLayoutMeasuring();
                if (SirenixEditorGUI.BeginFadeGroup(UniqueDrawerKey.Create(entry.Property, this), this.toggled.Value, out t))
                {
                    var rect = SirenixEditorGUI.BeginVerticalList(false);
                    if (this.attrSettings.DisplayMode == DictionaryDisplayOptions.OneLine)
                    {
                        var maxWidth = rect.width - 90;
                        rect.xMin           = this.keyWidthOffset + 22;
                        rect.xMax           = rect.xMin + 10;
                        this.keyWidthOffset = this.keyWidthOffset + SirenixEditorGUI.SlideRect(rect).x;

                        if (Event.current.type == EventType.Repaint)
                        {
                            this.keyWidthOffset = Mathf.Clamp(this.keyWidthOffset, 90, maxWidth);
                        }

                        if (this.paging.ElementCount != 0)
                        {
                            var headerRect = SirenixEditorGUI.BeginListItem(false);
                            {
                                GUILayout.Space(14);
                                if (Event.current.type == EventType.Repaint)
                                {
                                    GUI.Label(headerRect.SetWidth(this.keyWidthOffset), this.keyLabel, SirenixGUIStyles.LabelCentered);
                                    GUI.Label(headerRect.AddXMin(this.keyWidthOffset), this.valueLabel, SirenixGUIStyles.LabelCentered);
                                    SirenixEditorGUI.DrawSolidRect(headerRect.AlignBottom(1), SirenixGUIStyles.BorderColor);
                                }
                            }
                            SirenixEditorGUI.EndListItem();
                        }
                    }

                    GUIHelper.PushHierarchyMode(false);
                    this.DrawElements(entry, label);
                    GUIHelper.PopHierarchyMode();
                    SirenixEditorGUI.EndVerticalList();
                }
                SirenixEditorGUI.EndFadeGroup();

                // Draw borders
                var outerRect = GUIHelper.EndLayoutMeasuring();
                if (t > 0.01f && Event.current.type == EventType.Repaint)
                {
                    Color col = SirenixGUIStyles.BorderColor;
                    outerRect.yMin -= 1;
                    SirenixEditorGUI.DrawBorders(outerRect, 1, col);
                    col.a *= t;
                    if (this.attrSettings.DisplayMode == DictionaryDisplayOptions.OneLine)
                    {
                        // Draw Slide Rect Border
                        outerRect.width = 1;
                        outerRect.x    += this.keyWidthOffset + 13;
                        SirenixEditorGUI.DrawSolidRect(outerRect, col);
                    }
                }
            }
            SirenixEditorGUI.EndIndentedVertical();
        }
Example #3
0
        /// <summary>
        /// Draws a property in the inspector using a given label.
        /// </summary>
        public static void DrawProperty(InspectorProperty property, GUIContent label)
        {
            if (property == null)
            {
                throw new ArgumentNullException("property");
            }

            bool popGUIEnabled = false;

            try
            {
                property.PushDraw();

                if ((property.RecursiveDrawDepth + InlineEditorAttributeDrawer.CurrentInlineEditorDrawDepth) > GeneralDrawerConfig.Instance.MaxRecursiveDrawDepth)
                {
                    AllEditorGUI.ErrorMessageBox("The property '" + property.NiceName + "' has exceeded the maximum recursive draw depth limit of " + GeneralDrawerConfig.Instance.MaxRecursiveDrawDepth + ".");
                    return;
                }

                if (property.ValueEntry != null && !property.SupportsPrefabModifications && property.Tree.HasPrefabs && !GUIHelper.IsDrawingDictionaryKey && (property.Info.PropertyType == PropertyType.ReferenceType || property.Info.PropertyType == PropertyType.ValueType))
                {
                    if ((property.Parent == null || property.Parent.SupportsPrefabModifications) && GeneralDrawerConfig.Instance.ShowPrefabModificationsDisabledMessage)
                    {
                        AllEditorGUI.InfoMessageBox("The property '" + property.NiceName + "' does not support being modified on prefab instances. (You can disable this message the general drawer config.)");
                    }

                    GUIHelper.PushGUIEnabled(false);
                    popGUIEnabled = true;
                }

                OdinDrawer[] drawers = DrawerLocator.GetDrawersForProperty(property);

                GUIHelper.BeginLayoutMeasuring();
                {
                    try
                    {
                        if (drawers.Length > 0)
                        {
                            bool setIsBoldState = property.ValueEntry != null && Event.current.type == EventType.Repaint;
                            if (setIsBoldState)
                            {
                                var boldState = property.ValueEntry.ValueChangedFromPrefab;

                                if (GUIHelper.IsDrawingDictionaryKey)
                                {
                                    // Always propagate changed state down through dictionary keys
                                    boldState |= GUIHelper.IsBoldLabel;
                                }

                                GUIHelper.PushIsBoldLabel(boldState);
                            }
                            drawers[0].DrawProperty(property, label);
                            if (setIsBoldState)
                            {
                                GUIHelper.PopIsBoldLabel();
                            }
                        }
                        else
                        {
                            if (property.Info.PropertyType == PropertyType.Method)
                            {
                                EditorGUILayout.LabelField(property.NiceName, "No drawers could be found for the method property '" + property.Name + "' with signature '" + property.Info.MemberInfo.GetNiceName() + "'.");
                            }
                            else if (property.Info.PropertyType == PropertyType.Group)
                            {
                                var attr = property.Info.GetAttribute <PropertyGroupAttribute>();

                                if (attr != null)
                                {
                                    EditorGUILayout.LabelField(property.NiceName, "No drawers could be found for the property group '" + property.Name + "' with property group attribute type '" + attr.GetType().GetNiceName() + "'.");
                                }
                                else
                                {
                                    EditorGUILayout.LabelField(property.NiceName, "No drawers could be found for the property group '" + property.Name + "'.");
                                }
                            }
                            //else if (property.Info.GetAttribute<HideInInspector>() == null)
                            //{
                            //    EditorGUILayout.LabelField(property.NiceName, "No drawers could be found for the value property '" + property.Name + "' of type '" + property.ValueEntry.TypeOfValue.GetNiceName() + "'.");
                            //}
                        }
                    }
                    catch (Exception ex)
                    {
                        if (ex is ExitGUIException || ex.InnerException is ExitGUIException)
                        {
                            throw ex;
                        }
                        else
                        {
                            var msg =
                                "This error occurred while being drawn by ODIN. \n" +
                                "ODIN Property Path: " + property.Path + "\n" +
                                "ODIN Drawer Chain: " + string.Join(", ", drawers.Select(n => n.GetType().GetNiceName()).ToArray()) + ".";

                            Debug.LogException(new OdinPropertyException(msg, ex));
                        }
                    }
                }
                if (Event.current.type != EventType.Layout)
                {
                    property.LastDrawnValueRect = GUIHelper.EndLayoutMeasuring();
                }
            }
            finally
            {
                property.PopDraw();

                if (popGUIEnabled)
                {
                    GUIHelper.PopGUIEnabled();
                }
            }
        }
        /// <summary>
        /// Draws the property.
        /// </summary>
        protected override void DrawPropertyLayout(IPropertyValueEntry <TDictionary> entry, GUIContent label)
        {
            var context = entry.Property.Context.Get(this, "context", (Context)null);

            if (context.Value == null)
            {
                context.Value                = new Context();
                context.Value.Toggled        = entry.Context.GetPersistent(this, "Toggled", GeneralDrawerConfig.Instance.OpenListsByDefault);
                context.Value.KeyWidthOffset = 130;
                context.Value.Label          = label ?? new GUIContent(typeof(TDictionary).GetNiceName());
                context.Value.AttrSettings   = entry.Property.Info.GetAttribute <DictionaryDrawerSettings>() ?? new DictionaryDrawerSettings();
                context.Value.DisableAddKey  = entry.Property.Tree.HasPrefabs && !entry.GetDictionaryHandler().SupportsPrefabModifications;

                if (!context.Value.DisableAddKey)
                {
                    context.Value.TempKeyValue = new TempKeyValue();

                    var tree = PropertyTree.Create(context.Value.TempKeyValue);
                    tree.UpdateTree();

                    context.Value.TempKeyEntry   = (IPropertyValueEntry <TKey>)tree.GetPropertyAtPath("Key").ValueEntry;
                    context.Value.TempValueEntry = (IPropertyValueEntry <TValue>)tree.GetPropertyAtPath("Value").ValueEntry;
                }
            }

            context.Value.DictionaryHandler           = (DictionaryHandler <TDictionary, TKey, TValue>)entry.GetDictionaryHandler();
            context.Value.Config                      = GeneralDrawerConfig.Instance;
            context.Value.Paging.NumberOfItemsPerPage = context.Value.Config.NumberOfItemsPrPage;
            context.Value.ListItemStyle.padding.right = !entry.IsEditable || context.Value.AttrSettings.IsReadOnly ? 4 : 20;

            //if (!IsSupportedKeyType)
            //{
            //    var message = entry.Property.Context.Get(this, "error_message", (string)null);
            //    var detailedMessage = entry.Property.Context.Get(this, "error_message_detailed", (string)null);
            //    var folded = entry.Property.Context.Get(this, "error_message_folded", true);

            //    if (message.Value == null)
            //    {
            //        string str = "";

            //        if (label != null)
            //        {
            //            str += label.text + "\n\n";
            //        }

            //        str += "The dictionary key type '" + typeof(TKey).GetNiceFullName() + "' is not supported in prefab instances. Expand this box to see which key types are supported.";

            //        message.Value = str;
            //    }

            //    if (detailedMessage.Value == null)
            //    {
            //        var sb = new StringBuilder("The following key types are supported:");

            //        sb.AppendLine()
            //          .AppendLine();

            //        foreach (var type in DictionaryKeyUtility.GetPersistentPathKeyTypes())
            //        {
            //            sb.AppendLine(type.GetNiceName());
            //        }

            //        sb.AppendLine("Enums of any type");

            //        detailedMessage.Value = sb.ToString();
            //    }

            //    folded.Value = SirenixEditorGUI.DetailedMessageBox(message.Value, detailedMessage.Value, MessageType.Error, folded.Value);

            //    return;
            //}

            SirenixEditorGUI.BeginIndentedVertical(SirenixGUIStyles.PropertyPadding);
            {
                context.Value.Paging.Update(elementCount: entry.Property.Children.Count);
                this.DrawToolbar(entry, context.Value);
                context.Value.Paging.Update(elementCount: entry.Property.Children.Count);

                if (!context.Value.DisableAddKey && context.Value.AttrSettings.IsReadOnly == false)
                {
                    this.DrawAddKey(entry, context.Value);
                }

                float t;
                GUIHelper.BeginLayoutMeasuring();
                if (SirenixEditorGUI.BeginFadeGroup(UniqueDrawerKey.Create(entry.Property, this), context.Value.Toggled.Value, out t))
                {
                    var rect = SirenixEditorGUI.BeginVerticalList(false);
                    if (context.Value.AttrSettings.DisplayMode == DictionaryDisplayOptions.OneLine)
                    {
                        var maxWidth = rect.width - 90;
                        rect.xMin = context.Value.KeyWidthOffset + 22;
                        rect.xMax = rect.xMin + 10;
                        context.Value.KeyWidthOffset = context.Value.KeyWidthOffset + SirenixEditorGUI.SlideRect(rect).x;

                        if (Event.current.type == EventType.Repaint)
                        {
                            context.Value.KeyWidthOffset = Mathf.Clamp(context.Value.KeyWidthOffset, 90, maxWidth);
                        }

                        if (context.Value.Paging.ElementCount != 0)
                        {
                            var headerRect = SirenixEditorGUI.BeginListItem(false);
                            {
                                GUILayout.Space(14);
                                if (Event.current.type == EventType.Repaint)
                                {
                                    GUI.Label(headerRect.SetWidth(context.Value.KeyWidthOffset), context.Value.AttrSettings.KeyLabel, SirenixGUIStyles.LabelCentered);
                                    GUI.Label(headerRect.AddXMin(context.Value.KeyWidthOffset), context.Value.AttrSettings.ValueLabel, SirenixGUIStyles.LabelCentered);
                                    SirenixEditorGUI.DrawSolidRect(headerRect.AlignBottom(1), SirenixGUIStyles.BorderColor);
                                }
                            }
                            SirenixEditorGUI.EndListItem();
                        }
                    }

                    this.DrawElements(entry, label, context.Value);
                    SirenixEditorGUI.EndVerticalList();
                }
                SirenixEditorGUI.EndFadeGroup();

                // Draw borders
                var outerRect = GUIHelper.EndLayoutMeasuring();
                if (t > 0.01f && Event.current.type == EventType.Repaint)
                {
                    Color col = SirenixGUIStyles.BorderColor;
                    outerRect.yMin -= 1;
                    SirenixEditorGUI.DrawBorders(outerRect, 1, col);
                    col.a *= t;
                    if (context.Value.AttrSettings.DisplayMode == DictionaryDisplayOptions.OneLine)
                    {
                        // Draw Slide Rect Border
                        outerRect.width = 1;
                        outerRect.x    += context.Value.KeyWidthOffset + 13;
                        SirenixEditorGUI.DrawSolidRect(outerRect, col);
                    }
                }
            }
            SirenixEditorGUI.EndIndentedVertical();
        }