// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using Microsoft.MixedReality.Toolkit.Input; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using UnityEngine; namespace Microsoft.MixedReality.Toolkit { /// /// Extension methods for .Net Collection objects, e.g. Lists, Dictionaries, Arrays /// public static class CollectionsExtensions { /// /// Creates a read-only wrapper around an existing collection. /// /// The type of element in the collection. /// The collection to be wrapped. /// The new, read-only wrapper around . public static ReadOnlyCollection AsReadOnly(this IList elements) { return new ReadOnlyCollection(elements); } /// /// Creates a read-only copy of an existing collection. /// /// The type of element in the collection. /// The collection to be copied. /// The new, read-only copy of . public static ReadOnlyCollection ToReadOnlyCollection(this IEnumerable elements) { return elements.ToArray().AsReadOnly(); } /// /// Inserts an item in its sorted position into an already sorted collection. This is useful if you need to consume the /// collection in between insertions and need it to stay correctly sorted the whole time. If you just need to insert a /// bunch of items and then consume the sorted collection at the end, it's faster to add all the elements and then use /// at the end. /// /// The type of element in the collection. /// The collection of sorted elements to be inserted into. /// The element to insert. /// The comparer to use when sorting or null to use . public static int SortedInsert(this List elements, TElement toInsert, IComparer comparer = null) { var effectiveComparer = comparer ?? Comparer.Default; if (Application.isEditor) { for (int iElement = 0; iElement < elements.Count - 1; iElement++) { var element = elements[iElement]; var nextElement = elements[iElement + 1]; if (effectiveComparer.Compare(element, nextElement) > 0) { Debug.LogWarning("Elements must already be sorted to call this method."); break; } } } int searchResult = elements.BinarySearch(toInsert, effectiveComparer); int insertionIndex = searchResult >= 0 ? searchResult : ~searchResult; elements.Insert(insertionIndex, toInsert); return insertionIndex; } /// /// Disposes of all non-null elements in a collection. /// /// The type of element in the collection. /// The collection of elements to be disposed. public static void DisposeElements(this IEnumerable elements) where TElement : IDisposable { foreach (var element in elements) { if (element != null) { element.Dispose(); } } } /// /// Disposes of all non-null elements in a collection. /// /// The type of element in the collection. /// The collection of elements to be disposed. public static void DisposeElements(this IList elements) where TElement : IDisposable { for (int iElement = 0; iElement < elements.Count; iElement++) { var element = elements[iElement]; if (element != null) { element.Dispose(); } } } /// /// Exports the values of a uint indexed Dictionary as an Array /// /// Type of data stored in the values of the Dictionary /// Dictionary to be exported /// array in the type of data stored in the Dictionary public static T[] ExportDictionaryValuesAsArray(this Dictionary input) { T[] output = new T[input.Count]; input.Values.CopyTo(output, 0); return output; } /// /// Overload extension to enable getting of an InteractionDefinition of a specific type /// /// The InteractionDefinition array reference /// The specific DeviceInputType value to query public static MixedRealityInteractionMapping GetInteractionByType(this MixedRealityInteractionMapping[] input, DeviceInputType key) { for (int i = 0; i < input?.Length; i++) { if (input[i].InputType == key) { return input[i]; } } return default(MixedRealityInteractionMapping); } /// /// Overload extension to enable getting of an InteractionDefinition of a specific type /// /// The InteractionDefinition array reference /// The specific DeviceInputType value to query public static bool SupportsInputType(this MixedRealityInteractionMapping[] input, DeviceInputType key) { for (int i = 0; i < input.Length; i++) { if (input[i].InputType == key) { return true; } } return false; } } }