/// <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(); } } }
/// <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(); }
/// <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(); }