From fe1a65565420cd9b3b6e88fea00e044b1b0fe8a1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 14 Dec 2023 13:57:16 +0100 Subject: [PATCH] Add support for displaying and reverting array values to prefab value in properties panel #1548 --- Source/Editor/CustomEditors/CustomEditor.cs | 77 +++++++++---------- .../CustomEditors/Editors/CollectionEditor.cs | 31 +++++++- 2 files changed, 63 insertions(+), 45 deletions(-) diff --git a/Source/Editor/CustomEditors/CustomEditor.cs b/Source/Editor/CustomEditors/CustomEditor.cs index 9de330213..a519b1da1 100644 --- a/Source/Editor/CustomEditors/CustomEditor.cs +++ b/Source/Editor/CustomEditors/CustomEditor.cs @@ -7,9 +7,8 @@ using FlaxEditor.CustomEditors.GUI; using FlaxEditor.Scripting; using FlaxEngine; using FlaxEngine.GUI; +using FlaxEngine.Json; using FlaxEngine.Utilities; -using Newtonsoft.Json; -using JsonSerializer = FlaxEngine.Json.JsonSerializer; namespace FlaxEditor.CustomEditors { @@ -386,22 +385,22 @@ namespace FlaxEditor.CustomEditors LinkedLabel = label; } - private void RevertDiffToDefault(CustomEditor editor) - { - if (editor.ChildrenEditors.Count == 0) - { - // Skip if no change detected - if (!editor.Values.IsDefaultValueModified) - return; + /// + /// If true, the value reverting to default/reference will be handled via iteration over children editors, instead of for a whole object at once. + /// + public virtual bool RevertValueWithChildren => ChildrenEditors.Count != 0; - editor.SetValueToDefault(); + private void RevertDiffToDefault() + { + if (RevertValueWithChildren) + { + foreach (var child in ChildrenEditors) + child.RevertDiffToDefault(); } else { - for (int i = 0; i < editor.ChildrenEditors.Count; i++) - { - RevertDiffToDefault(editor.ChildrenEditors[i]); - } + if (Values.IsDefaultValueModified) + SetValueToDefault(); } } @@ -414,11 +413,6 @@ namespace FlaxEditor.CustomEditors { if (!Values.IsDefaultValueModified) return false; - - // Skip array items (show diff only on a bottom level properties and fields) - if (ParentEditor is Editors.ArrayEditor) - return false; - return true; } } @@ -430,7 +424,7 @@ namespace FlaxEditor.CustomEditors { if (!Values.HasDefaultValue) return; - RevertDiffToDefault(this); + RevertDiffToDefault(); } /// @@ -468,22 +462,17 @@ namespace FlaxEditor.CustomEditors } } - private void RevertDiffToReference(CustomEditor editor) + private void RevertDiffToReference() { - if (editor.ChildrenEditors.Count == 0) + if (RevertValueWithChildren) { - // Skip if no change detected - if (!editor.Values.IsReferenceValueModified) - return; - - editor.SetValueToReference(); + foreach (var child in ChildrenEditors) + child.RevertDiffToReference(); } else { - for (int i = 0; i < editor.ChildrenEditors.Count; i++) - { - RevertDiffToReference(editor.ChildrenEditors[i]); - } + if (Values.IsReferenceValueModified) + SetValueToReference(); } } @@ -496,11 +485,6 @@ namespace FlaxEditor.CustomEditors { if (!Values.IsReferenceValueModified) return false; - - // Skip array items (show diff only on a bottom level properties and fields) - if (ParentEditor is Editors.ArrayEditor) - return false; - return true; } } @@ -512,7 +496,7 @@ namespace FlaxEditor.CustomEditors { if (!Values.HasReferenceValue) return; - RevertDiffToReference(this); + RevertDiffToReference(); } /// @@ -657,7 +641,7 @@ namespace FlaxEditor.CustomEditors // Default try { - obj = JsonConvert.DeserializeObject(text, TypeUtils.GetType(Values.Type), JsonSerializer.Settings); + obj = Newtonsoft.Json.JsonConvert.DeserializeObject(text, TypeUtils.GetType(Values.Type), JsonSerializer.Settings); } catch { @@ -762,7 +746,7 @@ namespace FlaxEditor.CustomEditors /// public void SetValueToDefault() { - SetValue(Values.DefaultValue); + SetValueCloned(Values.DefaultValue); } /// @@ -799,7 +783,19 @@ namespace FlaxEditor.CustomEditors return; } - SetValue(Values.ReferenceValue); + SetValueCloned(Values.ReferenceValue); + } + + private void SetValueCloned(object value) + { + // For objects (eg. arrays) we need to clone them to prevent editing default/reference value within editor + if (value != null && !value.GetType().IsValueType) + { + var json = JsonSerializer.Serialize(value); + value = JsonSerializer.Deserialize(json, value.GetType()); + } + + SetValue(value); } /// @@ -811,7 +807,6 @@ namespace FlaxEditor.CustomEditors { if (_isSetBlocked) return; - if (OnDirty(this, value, token)) { _hasValueDirty = true; diff --git a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs index 6f623fb23..919da4301 100644 --- a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs +++ b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs @@ -87,6 +87,7 @@ namespace FlaxEditor.CustomEditors.Editors protected bool NotNullItems; private IntegerValueElement _size; + private PropertyNameLabel _sizeLabel; private Color _background; private int _elementsCount; private bool _readOnly; @@ -109,6 +110,9 @@ namespace FlaxEditor.CustomEditors.Editors } } + /// + public override bool RevertValueWithChildren => false; // Always revert value for a whole collection + /// public override void Initialize(LayoutElementsContainer layout) { @@ -174,7 +178,9 @@ namespace FlaxEditor.CustomEditors.Editors } else { - _size = dragArea.IntegerValue("Size"); + var sizeProperty = dragArea.AddPropertyItem("Size"); + _sizeLabel = sizeProperty.Labels.Last(); + _size = sizeProperty.IntegerValue(); _size.IntValue.MinValue = 0; _size.IntValue.MaxValue = ushort.MaxValue; _size.IntValue.Value = size; @@ -274,6 +280,15 @@ namespace FlaxEditor.CustomEditors.Editors } } + /// + protected override void Deinitialize() + { + _size = null; + _sizeLabel = null; + + base.Deinitialize(); + } + /// /// Rebuilds the parent layout if its collection. /// @@ -296,7 +311,6 @@ namespace FlaxEditor.CustomEditors.Editors { if (IsSetBlocked) return; - Resize(_size.IntValue.Value); } @@ -311,11 +325,9 @@ namespace FlaxEditor.CustomEditors.Editors return; var cloned = CloneValues(); - var tmp = cloned[dstIndex]; cloned[dstIndex] = cloned[srcIndex]; cloned[srcIndex] = tmp; - SetValue(cloned); } @@ -371,6 +383,17 @@ namespace FlaxEditor.CustomEditors.Editors if (HasDifferentValues || HasDifferentTypes) return; + // Update reference/default value indicator + if (_sizeLabel != null) + { + var color = Color.Transparent; + if (Values.HasReferenceValue && Values.ReferenceValue is IList referenceValue && referenceValue.Count != Count) + color = FlaxEngine.GUI.Style.Current.BackgroundSelected; + else if (Values.HasDefaultValue && Values.DefaultValue is IList defaultValue && defaultValue.Count != Count) + color = Color.Yellow * 0.8f; + _sizeLabel.HighlightStripColor = color; + } + // Check if collection has been resized (by UI or from external source) if (Count != _elementsCount) {