Add support for NotNullItems option in collections editors

#542
This commit is contained in:
Wojtek Figat
2021-06-09 10:58:54 +02:00
parent 0ba4a0cabc
commit 484bc409d4
11 changed files with 64 additions and 57 deletions

View File

@@ -789,8 +789,7 @@ namespace FlaxEditor.CustomEditors
/// <returns>True if allow to handle this event, otherwise false.</returns>
protected virtual bool OnDirty(CustomEditor editor, object value, object token = null)
{
ParentEditor.OnDirty(editor, value, token);
return true;
return ParentEditor.OnDirty(editor, value, token);
}
/// <summary>

View File

@@ -43,7 +43,7 @@ namespace FlaxEditor.CustomEditors.Editors
// Copy old values
Array.Copy(array, 0, newValues, 0, sharedCount);
if (elementType.IsValueType)
if (elementType.IsValueType || NotNullItems)
{
// Fill new entries with the last value
for (int i = oldSize; i < newSize; i++)
@@ -52,7 +52,7 @@ namespace FlaxEditor.CustomEditors.Editors
else
{
// Initialize new entries with default values
var defaultValue = TypeUtils.GetDefaultValue(new ScriptType(elementType), NotNullItems);
var defaultValue = TypeUtils.GetDefaultValue(new ScriptType(elementType));
for (int i = oldSize; i < newSize; i++)
newValues.SetValue(defaultValue, i);
}
@@ -60,7 +60,7 @@ namespace FlaxEditor.CustomEditors.Editors
else if (newSize > 0)
{
// Initialize new entries with default values
var defaultValue = TypeUtils.GetDefaultValue(new ScriptType(elementType), NotNullItems);
var defaultValue = TypeUtils.GetDefaultValue(new ScriptType(elementType));
for (int i = 0; i < newSize; i++)
newValues.SetValue(defaultValue, i);
}

View File

@@ -81,6 +81,7 @@ namespace FlaxEditor.CustomEditors.Editors
/// Determines if value of collection can be null.
/// </summary>
protected bool NotNullItems;
private IntegerValueElement _size;
private Color _background;
private int _elementsCount;
@@ -107,40 +108,34 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
_readOnly = false;
_canReorderItems = true;
NotNullItems = false;
// No support for different collections for now
if (HasDifferentValues || HasDifferentTypes)
return;
var size = Count;
_readOnly = false;
_canReorderItems = true;
_background = FlaxEngine.GUI.Style.Current.CollectionBackgroundColor;
NotNullItems = false;
// Try get CollectionAttribute for collection editor meta
var attributes = Values.GetAttributes();
Type overrideEditorType = null;
float spacing = 10.0f;
var collection = (CollectionAttribute)attributes?.FirstOrDefault(x => x is CollectionAttribute);
if (collection is null)
if (collection != null)
{
_readOnly = false;
NotNullItems = false;
_background = FlaxEngine.GUI.Style.Current.CollectionBackgroundColor;
}
else
{
// TODO: handle NotNullItems by filtering child editors SetValue
_readOnly = collection.ReadOnly;
_canReorderItems = collection.CanReorderItems;
NotNullItems = collection.NotNullItems;
_background = collection.BackgroundColor;
if (collection.BackgroundColor.HasValue)
_background = collection.BackgroundColor.Value;
overrideEditorType = TypeUtils.GetType(collection.OverrideEditorTypeName).Type;
spacing = collection.Spacing;
}
// Size
if (_readOnly)
if (_readOnly || (NotNullItems && size == 0))
{
layout.Label("Size", size.ToString());
}
@@ -214,7 +209,8 @@ namespace FlaxEditor.CustomEditors.Editors
Text = "+",
TooltipText = "Add new item",
AnchorPreset = AnchorPresets.TopRight,
Parent = area.ContainerControl
Parent = area.ContainerControl,
Enabled = !NotNullItems || size > 0,
};
addButton.Clicked += () =>
{
@@ -229,7 +225,7 @@ namespace FlaxEditor.CustomEditors.Editors
TooltipText = "Remove last item",
AnchorPreset = AnchorPresets.TopRight,
Parent = area.ContainerControl,
Enabled = size > 0
Enabled = size > 0,
};
removeButton.Clicked += () =>
{
@@ -345,5 +341,24 @@ namespace FlaxEditor.CustomEditors.Editors
RebuildParentCollection();
}
}
/// <inheritdoc />
protected override bool OnDirty(CustomEditor editor, object value, object token = null)
{
if (NotNullItems)
{
if (value == null && editor.ParentEditor == this)
return false;
if (editor == this && value is IList list)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i] == null)
return false;
}
}
}
return base.OnDirty(editor, value, token);
}
}
}

View File

@@ -165,7 +165,6 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
// No support for different collections for now
if (HasDifferentValues || HasDifferentTypes)
return;
@@ -176,29 +175,23 @@ namespace FlaxEditor.CustomEditors.Editors
var keyType = argTypes[0];
var valueType = argTypes[1];
_canEditKeys = keyType == typeof(string) || keyType.IsPrimitive || keyType.IsEnum;
_background = FlaxEngine.GUI.Style.Current.CollectionBackgroundColor;
_readOnly = false;
_notNullItems = false;
// Try get CollectionAttribute for collection editor meta
var attributes = Values.GetAttributes();
Type overrideEditorType = null;
float spacing = 0.0f;
if (attributes != null)
var collection = (CollectionAttribute)attributes?.FirstOrDefault(x => x is CollectionAttribute);
if (collection != null)
{
var collection = (CollectionAttribute)attributes.FirstOrDefault(x => x is CollectionAttribute);
if (collection is null)
{
_readOnly = false;
_notNullItems = false;
_background = FlaxEngine.GUI.Style.Current.CollectionBackgroundColor;
}
else
{
// TODO: handle ReadOnly and NotNullItems by filtering child editors SetValue
_readOnly = collection.ReadOnly;
_notNullItems = collection.NotNullItems;
_background = collection.BackgroundColor;
overrideEditorType = TypeUtils.GetType(collection.OverrideEditorTypeName).Type;
spacing = collection.Spacing;
}
_readOnly = collection.ReadOnly;
_notNullItems = collection.NotNullItems;
if (collection.BackgroundColor.HasValue)
_background = collection.BackgroundColor.Value;
overrideEditorType = TypeUtils.GetType(collection.OverrideEditorTypeName).Type;
spacing = collection.Spacing;
}
// Size
@@ -210,7 +203,7 @@ namespace FlaxEditor.CustomEditors.Editors
{
_size = layout.IntegerValue("Size");
_size.IntValue.MinValue = 0;
_size.IntValue.MaxValue = ushort.MaxValue;
_size.IntValue.MaxValue = _notNullItems ? size : ushort.MaxValue;
_size.IntValue.Value = size;
_size.IntValue.ValueChanged += OnSizeChanged;
}
@@ -259,7 +252,8 @@ namespace FlaxEditor.CustomEditors.Editors
Text = "+",
TooltipText = "Add new item",
AnchorPreset = AnchorPresets.TopRight,
Parent = area.ContainerControl
Parent = area.ContainerControl,
Enabled = !_notNullItems,
};
addButton.Clicked += () =>
{
@@ -274,7 +268,7 @@ namespace FlaxEditor.CustomEditors.Editors
TooltipText = "Remove last item",
AnchorPreset = AnchorPresets.TopRight,
Parent = area.ContainerControl,
Enabled = size > 0
Enabled = size > 0,
};
removeButton.Clicked += () =>
{
@@ -414,7 +408,7 @@ namespace FlaxEditor.CustomEditors.Editors
}
} while (!isUnique);
newValues[Convert.ChangeType(uniqueKey, keyType)] = TypeUtils.GetDefaultValue(new ScriptType(valueType), _notNullItems);
newValues[Convert.ChangeType(uniqueKey, keyType)] = TypeUtils.GetDefaultValue(new ScriptType(valueType));
}
else if (keyType.IsEnum)
{
@@ -435,7 +429,7 @@ namespace FlaxEditor.CustomEditors.Editors
}
} while (!isUnique && uniqueKeyIndex < enumValues.Length);
newValues[enumValues.GetValue(uniqueKeyIndex)] = TypeUtils.GetDefaultValue(new ScriptType(valueType), _notNullItems);
newValues[enumValues.GetValue(uniqueKeyIndex)] = TypeUtils.GetDefaultValue(new ScriptType(valueType));
}
else if (keyType == typeof(string))
{
@@ -455,7 +449,7 @@ namespace FlaxEditor.CustomEditors.Editors
}
} while (!isUnique);
newValues[uniqueKey] = TypeUtils.GetDefaultValue(new ScriptType(valueType), _notNullItems);
newValues[uniqueKey] = TypeUtils.GetDefaultValue(new ScriptType(valueType));
}
else
{

View File

@@ -46,7 +46,7 @@ namespace FlaxEditor.CustomEditors.Editors
for (int i = 0; i < sharedCount; i++)
newValues.Add(list[i]);
if (elementType.IsValueType)
if (elementType.IsValueType || NotNullItems)
{
// Fill new entries with the last value
for (int i = oldSize; i < newSize; i++)
@@ -55,7 +55,7 @@ namespace FlaxEditor.CustomEditors.Editors
else
{
// Initialize new entries with default values
var defaultValue = Scripting.TypeUtils.GetDefaultValue(elementType, NotNullItems);
var defaultValue = Scripting.TypeUtils.GetDefaultValue(elementType);
for (int i = oldSize; i < newSize; i++)
newValues.Add(defaultValue);
}
@@ -63,7 +63,7 @@ namespace FlaxEditor.CustomEditors.Editors
else if (newSize > 0)
{
// Fill new entries with default value
var defaultValue = Scripting.TypeUtils.GetDefaultValue(elementType, NotNullItems);
var defaultValue = Scripting.TypeUtils.GetDefaultValue(elementType);
for (int i = oldSize; i < newSize; i++)
newValues.Add(defaultValue);
}

View File

@@ -112,9 +112,9 @@ namespace FlaxEditor.CustomEditors
EndUndoRecord();
_setValueToken = token;
// Mark as modified and don't pass event further
// Mark as modified and don't pass event further to the higher editors (don't call parent)
_isDirty = true;
return false;
return true;
}
/// <inheritdoc />

View File

@@ -232,7 +232,7 @@ namespace FlaxEditor.Options
BorderNormal = Color.FromBgra(0xFF54545C),
TextBoxBackground = Color.FromBgra(0xFF333337),
TextBoxBackgroundSelected = Color.FromBgra(0xFF3F3F46),
CollectionBackgroundColor = Color.FromBgra(0x16FFFFFF),
CollectionBackgroundColor = Color.FromBgra(0x14CCCCCC),
ProgressNormal = Color.FromBgra(0xFF0ad328),
// Fonts

View File

@@ -37,9 +37,8 @@ namespace FlaxEditor.Scripting
/// Gets the default value for the given type (can be value type or reference type).
/// </summary>
/// <param name="type">The type.</param>
/// <param name="notNull">Whether the value can be empty. If that's true, it can't.</param>
/// <returns>The created instance.</returns>
public static object GetDefaultValue(ScriptType type, bool notNull = false)
public static object GetDefaultValue(ScriptType type)
{
if (type.Type == typeof(string))
return string.Empty;
@@ -65,7 +64,7 @@ namespace FlaxEditor.Scripting
Utilities.Utils.InitDefaultValues(value);
return value;
}
if (!notNull && new ScriptType(typeof(object)).IsAssignableFrom(type))
if (new ScriptType(typeof(object)).IsAssignableFrom(type))
return null;
if (type.CanCreateInstance)
{

View File

@@ -1,7 +1,6 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using System;
using FlaxEngine.GUI;
namespace FlaxEngine
{
@@ -39,6 +38,6 @@ namespace FlaxEngine
/// <summary>
/// The collection background color.
/// </summary>
public Color BackgroundColor = Style.Current.CollectionBackgroundColor;
public Color? BackgroundColor;
}
}

View File

@@ -221,7 +221,7 @@ namespace FlaxEngine
TextBoxBackground = Color.FromBgra(0xFF333337),
ProgressNormal = Color.FromBgra(0xFF0ad328),
TextBoxBackgroundSelected = Color.FromBgra(0xFF3F3F46),
CollectionBackgroundColor = Color.FromBgra(0x16FFFFFF),
CollectionBackgroundColor = Color.FromBgra(0x14CCCCCC),
SharedTooltip = new Tooltip(),
};
style.DragWindow = style.BackgroundSelected * 0.7f;

View File

@@ -157,6 +157,7 @@ namespace FlaxEngine.GUI
/// </summary>
[EditorOrder(195)]
public Color CollectionBackgroundColor;
/// <summary>
/// The progress normal color.
/// </summary>