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