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