// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Standard Library
using System;
using System.Collections.Generic;
// Unity
using UnityEditor;
// GameKit
using AWS.GameKit.Runtime.Utils;
namespace AWS.GameKit.Editor.Utils
{
///
/// A version of whose implements .
/// This class takes care of assigning and updating the reference whenever this dictionary is modified.
///
/// Make sure to call at the beginning of every OnGUI method, before running any code in the dictionary's elements.
///
///
[Serializable]
public class SerializablePropertyOrderedDictionary : SerializableOrderedDictionary
where TValue : IHasSerializedPropertyOfSelf
{
// Serialization
private SerializedProperty _valuesSerializedProperty;
private int _numNewElements = 0;
///
/// This method must be the first method called on a new instance of this class.
///
/// The of a class's instance variable holding this instance of .
public void Initialize(SerializedProperty serializedProperty)
{
_valuesSerializedProperty = serializedProperty.FindPropertyRelative($"{nameof(_values)}");
UpdateSerializedPropertyForElements(0);
}
///
/// This method should be called at the beginning of every OnGUI() frame, before running any code in this collection's elements.
///
///
/// New elements added to this collection by or will not
/// have their set until is called
/// at least one frame after the element was added.
///
/// The can't be set during the same frame the element was added to this collection because it doesn't
/// exist in Unity's serialization framework until one frame after the element was added to this class's internal list.
///
public void FrameDelayedInitializeNewElements()
{
UpdateSerializedPropertyForElements(_dict.Count - _numNewElements);
}
public override void Add(TKey key, TValue value)
{
base.Add(key, value);
++_numNewElements;
}
public override void Remove(TKey key)
{
int indexOfElement = _keys.IndexOf(key);
base.Remove(key);
if (indexOfElement >= 0)
{
// All elements after the removed element need to be updated because they have a new position in the _values list.
UpdateSerializedPropertyForElements(indexOfElement);
}
}
public override void Clear()
{
base.Clear();
_numNewElements = 0;
}
public override void Sort(Func>, IEnumerable>> sortFunction)
{
base.Sort(sortFunction);
// All elements need to be updated because they have a new position in the _values list.
// By changing the _numNewElements to dict length we will cause all the serialized elements to be updated by FrameDelayedInitializeNewElements() in the next GUI frame
_numNewElements = _dict.Count;
}
///
/// Update the serialized property of all elements in the _values list from the to the end of the list.
///
/// After calling this method, is reset to 0.
///
/// The first element to update. All elements coming before this index will not be updated.
private void UpdateSerializedPropertyForElements(int startingFromIndex)
{
for (int i = startingFromIndex; i < _dict.Count; ++i)
{
_values[i].SerializedPropertyOfSelf = _valuesSerializedProperty.GetArrayElementAtIndex(i);
}
_numNewElements = 0;
}
}
}