From 3cf3f58db17352fa4118b7e617f50787c4d5045e Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 12 Aug 2021 11:47:38 +0200 Subject: [PATCH] Fix UI with list of null items when layout gets rebuilt at item level --- Source/Editor/CustomEditors/CustomEditor.cs | 16 +++++++--------- .../CustomEditors/Editors/CollectionEditor.cs | 12 ++++++++++-- .../CustomEditors/Editors/DictionaryEditor.cs | 9 ++++++++- .../CustomEditors/Editors/GenericEditor.cs | 19 ++++++++++++------- .../CustomEditors/LayoutElementsContainer.cs | 7 +++++++ .../CustomEditors/Values/ValueContainer.cs | 16 ++++++++++++++++ 6 files changed, 60 insertions(+), 19 deletions(-) diff --git a/Source/Editor/CustomEditors/CustomEditor.cs b/Source/Editor/CustomEditors/CustomEditor.cs index 07cc1c08d..e681127fd 100644 --- a/Source/Editor/CustomEditors/CustomEditor.cs +++ b/Source/Editor/CustomEditors/CustomEditor.cs @@ -101,11 +101,6 @@ namespace FlaxEditor.CustomEditors /// protected bool IsSetBlocked => _isSetBlocked; - /// - /// Gets a value indicating whether this editor needs value propagation up (value synchronization when one of the child editors changes value, used by the struct types). - /// - protected virtual bool NeedsValuePropagationUp => Values.HasValueType; - /// /// The linked label used to show this custom editor. Can be null if not used (eg. editor is inlined or is using a very customized UI layout). /// @@ -281,7 +276,7 @@ namespace FlaxEditor.CustomEditors // Propagate values up (eg. when member of structure gets modified, also structure should be updated as a part of the other object) var obj = _parent; - while (obj._parent != null && !(obj._parent is SyncPointEditor)) // && obj.NeedsValuePropagationUp) + while (obj._parent != null && !(obj._parent is SyncPointEditor)) { obj.Values.Set(obj._parent.Values, obj.Values); obj = obj._parent; @@ -301,12 +296,15 @@ namespace FlaxEditor.CustomEditors _isSetBlocked = false; // Update children + if (_skipChildrenRefresh) + { + _skipChildrenRefresh = false; + return; + } try { - var childrenCount = _skipChildrenRefresh ? 0 : _children.Count; - for (int i = 0; i < childrenCount; i++) + for (int i = 0; i < _children.Count; i++) _children[i].RefreshInternal(); - _skipChildrenRefresh = false; } catch (TargetException ex) { diff --git a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs index 6c3dda04e..9f660c328 100644 --- a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs +++ b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs @@ -154,6 +154,10 @@ namespace FlaxEditor.CustomEditors.Editors var panel = layout.VerticalPanel(); panel.Panel.BackgroundColor = _background; var elementType = ElementType; + + // Use separate layout cells for each collection items to improve layout updates for them in separation + var useSharedLayout = elementType.IsPrimitive || elementType.IsEnum; + if (_canReorderItems) { for (int i = 0; i < size; i++) @@ -178,7 +182,9 @@ namespace FlaxEditor.CustomEditors.Editors } var overrideEditor = overrideEditorType != null ? (CustomEditor)Activator.CreateInstance(overrideEditorType) : null; - panel.Object(new CollectionItemLabel(this, i), new ListValueContainer(elementType, i, Values), overrideEditor); + var property = panel.AddPropertyItem(new CollectionItemLabel(this, i)); + var itemLayout = useSharedLayout ? (LayoutElementsContainer)property : property.VerticalPanel(); + itemLayout.Object(new ListValueContainer(elementType, i, Values), overrideEditor); } } else @@ -194,7 +200,9 @@ namespace FlaxEditor.CustomEditors.Editors } var overrideEditor = overrideEditorType != null ? (CustomEditor)Activator.CreateInstance(overrideEditorType) : null; - panel.Object("Element " + i, new ListValueContainer(elementType, i, Values), overrideEditor); + var property = panel.AddPropertyItem("Element " + i); + var itemLayout = useSharedLayout ? (LayoutElementsContainer)property : property.VerticalPanel(); + itemLayout.Object(new ListValueContainer(elementType, i, Values), overrideEditor); } } } diff --git a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs index 51309a2fa..53e539234 100644 --- a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs +++ b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs @@ -216,6 +216,11 @@ namespace FlaxEditor.CustomEditors.Editors panel.Panel.BackgroundColor = _background; var keysEnumerable = ((IDictionary)Values[0]).Keys.OfType(); var keys = keysEnumerable as object[] ?? keysEnumerable.ToArray(); + var valuesType = new ScriptType(valueType); + + // Use separate layout cells for each collection items to improve layout updates for them in separation + var useSharedLayout = valueType.IsPrimitive || valueType.IsEnum; + for (int i = 0; i < size; i++) { if (i != 0 && spacing > 0f) @@ -239,7 +244,9 @@ namespace FlaxEditor.CustomEditors.Editors var key = keys.ElementAt(i); var overrideEditor = overrideEditorType != null ? (CustomEditor)Activator.CreateInstance(overrideEditorType) : null; - panel.Object(new DictionaryItemLabel(this, key), new DictionaryValueContainer(new ScriptType(valueType), key, Values), overrideEditor); + var property = panel.AddPropertyItem(new DictionaryItemLabel(this, key)); + var itemLayout = useSharedLayout ? (LayoutElementsContainer)property : property.VerticalPanel(); + itemLayout.Object(new DictionaryValueContainer(valuesType, key, Values), overrideEditor); } } _elementsCount = size; diff --git a/Source/Editor/CustomEditors/Editors/GenericEditor.cs b/Source/Editor/CustomEditors/Editors/GenericEditor.cs index fc1b3b047..8510fa9ff 100644 --- a/Source/Editor/CustomEditors/Editors/GenericEditor.cs +++ b/Source/Editor/CustomEditors/Editors/GenericEditor.cs @@ -228,6 +228,7 @@ namespace FlaxEditor.CustomEditors.Editors } private VisibleIfCache[] _visibleIfCaches; + private bool _isNull; /// /// Gets the items for the type @@ -264,7 +265,7 @@ namespace FlaxEditor.CustomEditors.Editors // Skip properties without getter or setter if (!p.HasGet || (!p.HasSet && !showInEditor)) continue; - + // Skip hidden fields, handle special attributes if ((!p.IsPublic && !showInEditor) || attributes.Any(x => x is HideInEditorAttribute)) continue; @@ -421,7 +422,9 @@ namespace FlaxEditor.CustomEditors.Editors /// public override void Initialize(LayoutElementsContainer layout) { + var values = Values; _visibleIfCaches = null; + _isNull = values != null && values.IsNull; // Collect items to edit List items; @@ -446,12 +449,7 @@ namespace FlaxEditor.CustomEditors.Editors Parent = layout.ContainerControl, Location = new Vector2(layout.ContainerControl.Width - ButtonSize - 4, (layout.ContainerControl.Height - ButtonSize) * 0.5f), }; - button.Clicked += () => - { - var newType = Values.Type; - SetValue(newType.CreateInstance()); - RebuildLayoutOnRefresh(); - }; + button.Clicked += () => SetValue(Values.Type.CreateInstance()); } layout.Label(""); @@ -558,6 +556,13 @@ namespace FlaxEditor.CustomEditors.Editors /// public override void Refresh() { + // Automatic refresh when value nullability changed + if (_isNull != Values.IsNull) + { + RebuildLayout(); + return; + } + if (_visibleIfCaches != null) { try diff --git a/Source/Editor/CustomEditors/LayoutElementsContainer.cs b/Source/Editor/CustomEditors/LayoutElementsContainer.cs index d7df2fbb1..b63d9f6b9 100644 --- a/Source/Editor/CustomEditors/LayoutElementsContainer.cs +++ b/Source/Editor/CustomEditors/LayoutElementsContainer.cs @@ -30,6 +30,11 @@ namespace FlaxEditor.CustomEditors /// public readonly List Children = new List(); + /// + /// The child custom editors. + /// + public readonly List Editors = new List(); + /// /// Gets the control represented by this element. /// @@ -722,6 +727,7 @@ namespace FlaxEditor.CustomEditors var customEditor = CustomEditor.CurrentCustomEditor; Assert.IsNotNull(customEditor); customEditor.OnChildCreated(editor); + Editors.Add(editor); } /// @@ -730,6 +736,7 @@ namespace FlaxEditor.CustomEditors public virtual void ClearLayout() { Children.Clear(); + Editors.Clear(); } /// diff --git a/Source/Editor/CustomEditors/Values/ValueContainer.cs b/Source/Editor/CustomEditors/Values/ValueContainer.cs index 9bdbc4bcf..1252c9179 100644 --- a/Source/Editor/CustomEditors/Values/ValueContainer.cs +++ b/Source/Editor/CustomEditors/Values/ValueContainer.cs @@ -101,6 +101,22 @@ namespace FlaxEditor.CustomEditors } } + /// + /// Gets a value indicating whether all values in the collection are null. Returns true if collection is empty. + /// + public bool IsNull + { + get + { + for (int i = 0; i < Count; i++) + { + if (this[i] != null) + return false; + } + return true; + } + } + /// /// Gets a value indicating whether this any value in the collection is of value type (eg. a structure, not a class type). Returns false if collection is empty. ///