TaiZhouCangChu_VRanime/Assets/HTC.UnityPlugin/Utility/Container/EnumArray.cs

960 lines
35 KiB
C#

//========= Copyright 2016-2023, HTC Corporation. All rights reserved. ===========
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using UnityEngine;
using UnityEngine.Serialization;
namespace HTC.UnityPlugin.Utility
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
public class InvalidEnumArrayIndexAttribute : Attribute { }
public abstract class EnumToIntResolver { }
/// <summary>
/// A base generic class that provide function that converts Enum value into int value.
///
/// </summary>
/// <remarks>
/// Resolver should provide faster function to convert from TEnum into int value
/// If not defined, EnumArrayBase<TEnum> static constructor can only provide slower convert function like "(int)(object)enumValue" or "EqualityComparer<TEnum>.Default.GetHashCode(enumValue)"
///
/// <example>
/// <code>
/// class MyEnumResolver : EnumToIntResolver<MyEnum>
/// {
/// public override int Resolve(MyEnum e) { return (int)e; }
/// }
/// </code>
/// </example>
///
/// Define custom resolver class for each enum type in your project, EnumToIntResolverCache will find it and instantiate/cache their instance
/// </remarks>
/// <seealso cref="EnumArray{TEnum, TValue}"/>
/// <seealso cref="EnumToIntResolverCache"/>
public abstract class EnumToIntResolver<TEnum> : EnumToIntResolver
#if CSHARP_7_OR_LATER
where TEnum : Enum
#endif
{
public abstract int Resolve(TEnum e);
}
public static class EnumToIntResolverCache
{
private static Dictionary<Type, Type> typeCache;
private static Dictionary<Type, EnumToIntResolver> instanceCache;
public static void ClearCache()
{
typeCache = null;
instanceCache = null;
}
public static bool TryGetCachedResolverType<TEnum>(out Type resolverType)
#if CSHARP_7_OR_LATER
where TEnum : Enum
#endif
{
if (typeCache == null)
{
typeCache = new Dictionary<Type, Type>();
FindAllResolverTypesInAllDomain(typeCache);
}
return typeCache.TryGetValue(typeof(TEnum), out resolverType);
}
public static bool TryGetCachedResolverInstance<TEnum>(out EnumToIntResolver<TEnum> resolver)
#if CSHARP_7_OR_LATER
where TEnum : Enum
#endif
{
var enumType = typeof(TEnum);
var resolverBase = default(EnumToIntResolver);
if (instanceCache != null && instanceCache.TryGetValue(enumType, out resolverBase))
{
resolver = resolverBase as EnumToIntResolver<TEnum>;
return true;
}
else
{
Type resolverType;
if (TryGetCachedResolverType<TEnum>(out resolverType))
{
resolver = (EnumToIntResolver<TEnum>)Activator.CreateInstance(resolverType);
if (instanceCache == null) { instanceCache = new Dictionary<Type, EnumToIntResolver>(); }
instanceCache[enumType] = resolver;
return true;
}
resolver = null;
return false;
}
}
public static int FindAllResolverTypesInAllDomain(IDictionary<Type, Type> outDict)
{
var count = 0;
var resolverTypeDef = typeof(EnumToIntResolver<>);
var resolverBaseType = typeof(EnumToIntResolver);
var currentAsm = resolverTypeDef.Assembly;
var currentAsmName = currentAsm.GetName().Name;
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
var referencingCurrentAsm = false;
if (asm == currentAsm)
{
referencingCurrentAsm = true;
}
else
{
foreach (var asmref in asm.GetReferencedAssemblies())
{
if (asmref.Name == currentAsmName)
{
referencingCurrentAsm = true;
break;
}
}
}
if (referencingCurrentAsm)
{
// try find valid role enum type in assembly
foreach (var type in asm.GetTypes())
{
if (type.IsAbstract) { continue; }
if (!type.IsSubclassOf(resolverBaseType)) { continue; }
if (!type.BaseType.IsGenericType) { continue; }
if (type.BaseType.GetGenericTypeDefinition() != resolverTypeDef) { continue; }
foreach (var typeParam in type.BaseType.GetGenericArguments())
{
#if !CSHARP_7_OR_LATER
if (!typeParam.IsEnum) { break; }
#endif
if (!outDict.ContainsKey(typeParam))
{
outDict[typeParam] = type;
++count;
//Debug.Log("Found reslover type (" + type.FullName + ") for " + typeParam.Name);
}
break;
}
}
}
}
return count;
}
}
[Serializable]
public abstract class EnumArrayBase
{
public const int DEFAULT_LENGTH_LIMIT = 1024;
protected delegate bool RangeCheckFunc(object e, out int ei);
public abstract Type EnumType { get; }
public abstract Type ElementType { get; }
public abstract int MinInt { get; }
public abstract int MaxInt { get; }
public abstract int Length { get; }
public abstract int Capacity { get; }
public abstract string EnumName(int enumInt);
public abstract string EnumNameWithAlias(int enumInt);
public abstract bool IsValidIndex(int enumInt);
public abstract void Clear();
public abstract void FillCapacityToLength();
public abstract void TrimCapacityToLength();
protected static bool WithoutInvalidIndexAttr(FieldInfo fi)
{
return fi.IsStatic && fi.GetCustomAttributes(typeof(InvalidEnumArrayIndexAttribute), true).Length == 0;
}
protected static int CompareMetadataToken(FieldInfo fi)
{
return fi.MetadataToken;
}
protected static bool RangeCheckFromUInt8(object e, out int ei) { ei = (byte)e; return true; }
protected static bool RangeCheckFromInt8(object e, out int ei) { ei = (sbyte)e; return true; }
protected static bool RangeCheckFromInt16(object e, out int ei) { ei = (short)e; return true; }
protected static bool RangeCheckFromUInt16(object e, out int ei) { ei = (ushort)e; return true; }
protected static bool RangeCheckFromInt32(object e, out int ei) { ei = (int)e; return true; }
protected static bool RangeCheckFromUInt32(object e, out int ei)
{
var l = (uint)e;
if (l <= int.MaxValue)
{
ei = (int)l;
return true;
}
else
{
ei = int.MaxValue;
return false;
}
}
protected static bool RangeCheckFromInt64(object e, out int ei)
{
var l = (long)e;
if (l < int.MinValue)
{
ei = int.MinValue;
return false;
}
else if (l <= int.MaxValue)
{
ei = (int)l;
return true;
}
else
{
ei = int.MaxValue;
return false;
}
}
protected static bool RangeCheckFromUInt64(object e, out int ei)
{
var l = (ulong)e;
if (l <= int.MaxValue)
{
ei = (int)l;
return true;
}
else
{
ei = int.MaxValue;
return false;
}
}
}
[Serializable]
public abstract class EnumArrayBase<TEnum> : EnumArrayBase
#if CSHARP_7_OR_LATER
where TEnum : Enum
#endif
{
public struct EnumEnumerator : IEnumerator<TEnum>, IEnumerable<TEnum>
{
private readonly int iStart;
private readonly int iEnd;
private int iCurrent;
object IEnumerator.Current { get { return Current; } }
public TEnum Current { get { return InternalI2E(iCurrent); } }
public static EnumEnumerator All
{
get
{
return new EnumEnumerator(0, StaticLength - 1);
}
}
public static EnumEnumerator From(TEnum from)
{
var ifrom = E2I(from) - StaticMinInt; return new EnumEnumerator(ifrom, Mathf.Max(ifrom, StaticLength - 1));
}
public static EnumEnumerator FromTo(TEnum from, TEnum to)
{
return new EnumEnumerator(E2I(from) - StaticMinInt, E2I(to) - StaticMinInt);
}
private EnumEnumerator(int from, int to)
{
if (StaticLength == 0)
{
iStart = iEnd = iCurrent = -1;
}
else
{
from = Mathf.Clamp(from, 0, StaticLength - 1);
to = Mathf.Clamp(to, 0, StaticLength - 1);
if (from <= to)
{
iStart = iCurrent = from - 1;
iEnd = to;
}
else
{
iStart = iCurrent = from + 1;
iEnd = to;
}
}
}
void IDisposable.Dispose() { }
public void Reset() { iCurrent = iStart; }
public EnumEnumerator GetEnumerator() { return this; }
IEnumerator<TEnum> IEnumerable<TEnum>.GetEnumerator() { return this; }
IEnumerator IEnumerable.GetEnumerator() { return this; }
public bool MoveNext()
{
while (iCurrent != iEnd)
{
iCurrent = iCurrent > iEnd ? (iCurrent - 1) : (iCurrent + 1);
if (InternalStaticIsValidIndex(iCurrent))
{
return true;
}
}
return false;
}
}
private static readonly TEnum[] enums;
private static readonly string[] enumNames;
private static readonly string[] enumNameWithAliases;
private static Func<TEnum, int> funcE2I;
public static readonly int StaticMinInt;
public static readonly TEnum StaticMin;
public static readonly int StaticMaxInt;
public static readonly TEnum StaticMax;
public static readonly int StaticLength;
public static readonly Type StaticEnumType = typeof(TEnum);
static EnumArrayBase()
{
#if !CSHARP_7_OR_LATER
if (!StaticEnumType.IsEnum) { throw new Exception(StaticEnumType.Name + " is not enum type!"); }
#endif
var underlyingType = Enum.GetUnderlyingType(StaticEnumType);
var rangeCheckFunc = default(RangeCheckFunc);
if (underlyingType == typeof(int))
{
rangeCheckFunc = RangeCheckFromInt32;
}
else if (underlyingType == typeof(uint))
{
rangeCheckFunc = RangeCheckFromUInt32;
}
else if (underlyingType == typeof(long))
{
rangeCheckFunc = RangeCheckFromInt64;
}
else if (underlyingType == typeof(ulong))
{
rangeCheckFunc = RangeCheckFromUInt64;
}
else if (underlyingType == typeof(byte))
{
rangeCheckFunc = RangeCheckFromUInt8;
}
else if (underlyingType == typeof(sbyte))
{
rangeCheckFunc = RangeCheckFromInt8;
}
else if (underlyingType == typeof(short))
{
rangeCheckFunc = RangeCheckFromInt16;
}
else if (underlyingType == typeof(ushort))
{
rangeCheckFunc = RangeCheckFromUInt16;
}
// find out min/max/length value in defined enum values
var fields = StaticEnumType.GetFields().Where(WithoutInvalidIndexAttr).OrderBy((Func<FieldInfo, int>)CompareMetadataToken).ToArray();
var fieldEnums = new TEnum[fields.Length];
var fieldValues = new int[fields.Length];
var fieldNames = new string[fields.Length];
var validIndexFound = false;
for (int i = 0, imax = fields.Length; i < imax; ++i)
{
var field = fields[i];
var vo = field.GetValue(null);
var ve = (TEnum)vo;
int vi;
if (rangeCheckFunc(vo, out vi))
{
if (!validIndexFound)
{
validIndexFound = true;
StaticMinInt = StaticMaxInt = vi;
StaticMin = StaticMax = ve;
}
else
{
if (vi < StaticMinInt)
{
if (StaticMaxInt >= int.MinValue + DEFAULT_LENGTH_LIMIT && vi <= StaticMaxInt - DEFAULT_LENGTH_LIMIT)
{
Debug.Log("[EnumArray] too small. vi=" + vi + " min=" + StaticMinInt + " max=" + StaticMaxInt);
continue; // length out of range
}
StaticMinInt = vi;
StaticMin = ve;
}
else if (vi > StaticMaxInt)
{
if (StaticMinInt <= int.MaxValue - DEFAULT_LENGTH_LIMIT && vi >= StaticMinInt + DEFAULT_LENGTH_LIMIT)
{
Debug.Log("[EnumArray] too large. vi=" + vi + " min=" + StaticMinInt + " max=" + StaticMaxInt);
continue; // length out of range
}
StaticMaxInt = vi;
StaticMax = ve;
}
}
fieldValues[i] = vi;
fieldEnums[i] = ve;
fieldNames[i] = field.Name;
}
}
if (!validIndexFound)
{
Debug.LogWarning("Valid index for EnumArray not found. type:" + StaticEnumType.Name);
StaticMinInt = 0;
StaticMin = default(TEnum);
StaticMaxInt = 0;
StaticMax = default(TEnum);
StaticLength = 0;
}
StaticLength = StaticMaxInt - StaticMinInt + 1;
// create an int array with invalid enum values
enums = new TEnum[StaticLength];
enumNames = new string[StaticLength];
enumNameWithAliases = new string[StaticLength];
for (int fi = 0, imax = fields.Length; fi < imax; ++fi)
{
if (fieldNames[fi] == null) { continue; }
var i = fieldValues[fi] - StaticMinInt;
if (enumNames[i] == null)
{
enums[i] = fieldEnums[fi];
enumNames[i] = fieldNames[fi];
}
else if (enumNameWithAliases[i] == null)
{
enumNameWithAliases[i] = fieldNames[fi];
}
else
{
enumNameWithAliases[i] += ", " + fieldNames[fi];
}
}
for (int i = 0, imax = StaticLength; i < imax; ++i)
{
if (enumNames[i] != null)
{
if (enumNameWithAliases[i] != null)
{
enumNameWithAliases[i] = enumNames[i] + " (" + enumNameWithAliases[i] + ")";
}
else
{
enumNameWithAliases[i] = enumNames[i];
}
}
}
}
public override Type EnumType { get { return StaticEnumType; } }
public override string EnumName(int enumInt)
{
return StaticEnumName(enumInt);
}
public override string EnumNameWithAlias(int enumInt)
{
return StaticEnumNameWithAlias(enumInt);
}
public static string StaticEnumName(TEnum e)
{
return StaticEnumName(E2I(e));
}
public static string StaticEnumName(int enumInt)
{
return enumNames[enumInt - StaticMinInt];
}
public static string StaticEnumNameWithAlias(int enumInt)
{
return enumNameWithAliases[enumInt - StaticMinInt];
}
public override bool IsValidIndex(int enumInt)
{
return StaticIsValidIndex(enumInt);
}
public static bool StaticIsValidIndex(TEnum e)
{
return StaticIsValidIndex(E2I(e));
}
public static bool StaticIsValidIndex(int enumInt)
{
var i = enumInt - StaticMinInt;
return i >= 0 && i < StaticLength && InternalStaticIsValidIndex(i);
}
protected static bool InternalStaticIsValidIndex(int index)
{
return enumNames[index] != null;
}
public static EnumEnumerator StaticEnums { get { return EnumEnumerator.All; } }
public static EnumEnumerator StaticEnumsFrom(TEnum from) { return EnumEnumerator.From(from); }
public static EnumEnumerator StaticEnumsFrom(TEnum from, TEnum to) { return EnumEnumerator.FromTo(from, to); }
public static void InitializeFuncE2I()
{
if (funcE2I != null) { return; }
// Find first found custom resolver
// resolver should provide faster function to convert TEnum to int value
// most common & fasteast converting is to directly cast in the script like "return (int)enumValue;"
// In this generic constructor, we can only use slower converting function like "(int)(object)enumValue" or "EqualityComparer<TEnum>.Default.GetHashCode(enumValue)"
EnumToIntResolver<TEnum> resolver;
if (EnumToIntResolverCache.TryGetCachedResolverInstance(out resolver))
{
funcE2I = resolver.Resolve;
return;
}
WarnBoxingResolver();
var underlyingType = Enum.GetUnderlyingType(StaticEnumType);
if (underlyingType == typeof(int))
{
funcE2I = EqualityComparer<TEnum>.Default.GetHashCode;
}
else if (underlyingType == typeof(uint))
{
funcE2I = e => (int)(uint)(object)e;
}
else if (underlyingType == typeof(long))
{
funcE2I = e => (int)(long)(object)e;
}
else if (underlyingType == typeof(ulong))
{
funcE2I = e => (int)(ulong)(object)e;
}
else if (underlyingType == typeof(byte))
{
funcE2I = e => (byte)(object)e;
}
else if (underlyingType == typeof(sbyte))
{
funcE2I = e => (sbyte)(object)e;
}
else if (underlyingType == typeof(short))
{
funcE2I = e => (short)(object)e;
}
else if (underlyingType == typeof(ushort))
{
funcE2I = e => (ushort)(object)e;
}
}
public static int E2I(TEnum e)
{
InitializeFuncE2I();
return funcE2I(e);
}
public static TEnum I2E(int ei)
{
return InternalI2E(ei - StaticMinInt);
}
protected static TEnum InternalI2E(int index)
{
return enums[index];
}
private static void WarnBoxingResolver()
{
Debug.LogWarning("Boxing Resolver for enum " + StaticEnumType.Name + " is used. Define subclass of class EnumToIntResolver<" + StaticEnumType.Name + "> to provide faster resolver instead.");
}
}
[Serializable]
public class EnumArray<TEnum, TValue> : EnumArrayBase<TEnum>, IEnumerable<TValue>
#if CSHARP_7_OR_LATER
where TEnum : Enum
#endif
{
public interface IReadOnly : IEnumerable<TValue>
{
Type EnumType { get; }
Type ElementType { get; }
TEnum Min { get; }
TEnum Max { get; }
int MinInt { get; }
int MaxInt { get; }
TValue this[TEnum e] { get; }
TValue this[int ev] { get; }
new ValueEnumerator GetEnumerator();
ValueEnumerator Values { get; }
ValueEnumerator ValuesFrom(TEnum from);
ValueEnumerator ValuesFrom(TEnum from, TEnum to);
EnumEnumerator Enums { get; }
EnumEnumerator EnumsFrom(TEnum from);
EnumEnumerator EnumsFrom(TEnum from, TEnum to);
EnumValueEnumerator EnumValues { get; }
EnumValueEnumerator EnumValuesFrom(TEnum from);
EnumValueEnumerator EnumValuesFrom(TEnum from, TEnum to);
/// <summary>
/// Length between min and max TEnum value
/// </summary>
int Length { get; }
/// <summary>
/// Real length for the underlying array
/// (underlying array could be overridden with unexpected length by Unity's serialization)
/// </summary>
int Capacity { get; }
}
[Serializable]
private class ReadOnlyEnumArray : IReadOnly
{
public readonly EnumArray<TEnum, TValue> source;
public ReadOnlyEnumArray(EnumArray<TEnum, TValue> source) { this.source = source; }
public Type EnumType { get { return source.EnumType; } }
public Type ElementType { get { return source.ElementType; } }
public TEnum Min { get { return source.Min; } }
public TEnum Max { get { return source.Max; } }
public int MinInt { get { return source.MinInt; } }
public int MaxInt { get { return source.MaxInt; } }
public int Length { get { return source.Length; } }
public int Capacity { get { return source.Capacity; } }
public TValue this[TEnum e] { get { return source[e]; } }
public TValue this[int ev] { get { return source[ev]; } }
public ValueEnumerator GetEnumerator() { return source.GetEnumerator(); }
IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() { return source.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return source.GetEnumerator(); }
public ValueEnumerator Values { get { return source.Values; } }
public ValueEnumerator ValuesFrom(TEnum from) { return source.ValuesFrom(from); }
public ValueEnumerator ValuesFrom(TEnum from, TEnum to) { return source.ValuesFrom(from, to); }
public EnumEnumerator Enums { get { return source.Enums; } }
public EnumEnumerator EnumsFrom(TEnum from) { return source.EnumsFrom(from); }
public EnumEnumerator EnumsFrom(TEnum from, TEnum to) { return source.EnumsFrom(from, to); }
public EnumValueEnumerator EnumValues { get { return source.EnumValues; } }
public EnumValueEnumerator EnumValuesFrom(TEnum from) { return source.EnumValuesFrom(from); }
public EnumValueEnumerator EnumValuesFrom(TEnum from, TEnum to) { return source.EnumValuesFrom(from, to); }
}
public struct ValueEnumerator : IEnumerator<TValue>, IEnumerable<TValue>
{
private readonly TValue[] elements;
private readonly int iStart;
private readonly int iEnd;
private int iCurrent;
object IEnumerator.Current { get { return Current; } }
public TValue Current { get { return elements[iCurrent]; } }
public static ValueEnumerator All(EnumArray<TEnum, TValue> array)
{
return new ValueEnumerator(array, 0, StaticLength - 1);
}
public static ValueEnumerator From(EnumArray<TEnum, TValue> array, TEnum from)
{
var ifrom = E2I(from) - StaticMinInt;
return new ValueEnumerator(array, ifrom, Mathf.Max(ifrom, StaticLength - 1));
}
public static ValueEnumerator FromTo(EnumArray<TEnum, TValue> array, TEnum from, TEnum to)
{
return new ValueEnumerator(array, E2I(from) - StaticMinInt, E2I(to) - StaticMinInt);
}
private ValueEnumerator(EnumArray<TEnum, TValue> array, int from, int to)
{
if (StaticLength == 0)
{
elements = null;
iStart = iEnd = iCurrent = -1;
}
else
{
from = Mathf.Clamp(from, 0, StaticLength - 1);
to = Mathf.Clamp(to, 0, StaticLength - 1);
if (from <= to)
{
iStart = iCurrent = from - 1;
iEnd = to;
}
else
{
iStart = iCurrent = from + 1;
iEnd = to;
}
array.FillCapacityToLength();
elements = array.elements;
}
}
void IDisposable.Dispose() { }
public void Reset() { iCurrent = iStart; }
public ValueEnumerator GetEnumerator() { return this; }
IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() { return this; }
IEnumerator IEnumerable.GetEnumerator() { return this; }
public bool MoveNext()
{
if (elements != null)
{
while (iCurrent != iEnd)
{
iCurrent = iCurrent > iEnd ? (iCurrent - 1) : (iCurrent + 1);
if (InternalStaticIsValidIndex(iCurrent))
{
return true;
}
}
}
return false;
}
}
public struct EnumValueEnumerator : IEnumerator<KeyValuePair<TEnum, TValue>>, IEnumerable<KeyValuePair<TEnum, TValue>>
{
private readonly TValue[] elements;
private readonly int iStart;
private readonly int iEnd;
private int iCurrent;
object IEnumerator.Current { get { return Current; } }
public KeyValuePair<TEnum, TValue> Current { get { return new KeyValuePair<TEnum, TValue>(InternalI2E(iCurrent), elements[iCurrent]); } }
public static EnumValueEnumerator All(EnumArray<TEnum, TValue> array)
{
return new EnumValueEnumerator(array, 0, StaticLength - 1);
}
public static EnumValueEnumerator From(EnumArray<TEnum, TValue> array, TEnum from)
{
var ifrom = E2I(from) - StaticMinInt;
return new EnumValueEnumerator(array, ifrom, Mathf.Max(ifrom, StaticLength - 1));
}
public static EnumValueEnumerator FromTo(EnumArray<TEnum, TValue> array, TEnum from, TEnum to)
{
return new EnumValueEnumerator(array, E2I(from) - StaticMinInt, E2I(to) - StaticMinInt);
}
private EnumValueEnumerator(EnumArray<TEnum, TValue> array, int from, int to)
{
if (StaticLength == 0)
{
elements = null;
iStart = iEnd = iCurrent = -1;
}
else
{
from = Mathf.Clamp(from, 0, StaticLength - 1);
to = Mathf.Clamp(to, 0, StaticLength - 1);
if (from <= to)
{
iStart = iCurrent = from - 1;
iEnd = to;
}
else
{
iStart = iCurrent = from + 1;
iEnd = to;
}
array.FillCapacityToLength();
elements = array.elements;
}
}
void IDisposable.Dispose() { }
public void Reset() { iCurrent = iStart; }
public EnumValueEnumerator GetEnumerator() { return this; }
IEnumerator<KeyValuePair<TEnum, TValue>> IEnumerable<KeyValuePair<TEnum, TValue>>.GetEnumerator() { return this; }
IEnumerator IEnumerable.GetEnumerator() { return this; }
public bool MoveNext()
{
if (elements != null)
{
while (iCurrent != iEnd)
{
iCurrent = iCurrent > iEnd ? (iCurrent - 1) : (iCurrent + 1);
if (InternalStaticIsValidIndex(iCurrent))
{
return true;
}
}
}
return false;
}
}
[SerializeField]
[FormerlySerializedAs("m_array")]
private TValue[] elements;
private ReadOnlyEnumArray readOnly;
public readonly static Type StaticElementType = typeof(TValue);
public EnumArray() { elements = new TValue[StaticLength]; }
public EnumArray(TValue initValue) : this() { Clear(initValue); }
public override Type ElementType { get { return StaticElementType; } }
public override int MinInt { get { return StaticMinInt; } }
public override int MaxInt { get { return StaticMaxInt; } }
public TEnum Min { get { return StaticMin; } }
public TEnum Max { get { return StaticMax; } }
/// <summary>
/// Length between min and max TEnum value
/// </summary>
public override int Length { get { return StaticLength; } }
/// <summary>
/// Real length for the underlying array
/// (underlying array could be overridden with unexpected length by Unity's serialization)
/// </summary>
public override int Capacity { get { return elements == null ? 0 : elements.Length; } }
public IReadOnly ReadOnly { get { return readOnly != null ? readOnly : (readOnly = new ReadOnlyEnumArray(this)); } }
public ValueEnumerator GetEnumerator() { return Values; }
IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() { return GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public ValueEnumerator Values { get { return ValueEnumerator.All(this); } }
public ValueEnumerator ValuesFrom(TEnum from) { return ValueEnumerator.From(this, from); }
public ValueEnumerator ValuesFrom(TEnum from, TEnum to) { return ValueEnumerator.FromTo(this, from, to); }
public EnumEnumerator Enums { get { return StaticEnums; } }
public EnumEnumerator EnumsFrom(TEnum from) { return StaticEnumsFrom(from); }
public EnumEnumerator EnumsFrom(TEnum from, TEnum to) { return StaticEnumsFrom(from, to); }
public EnumValueEnumerator EnumValues { get { return EnumValueEnumerator.All(this); } }
public EnumValueEnumerator EnumValuesFrom(TEnum from) { return EnumValueEnumerator.From(this, from); }
public EnumValueEnumerator EnumValuesFrom(TEnum from, TEnum to) { return EnumValueEnumerator.FromTo(this, from, to); }
public TValue this[TEnum e]
{
get { return this[E2I(e)]; }
set { this[E2I(e)] = value; }
}
public TValue this[int ei]
{
get { FillCapacityToLength(); return elements[ei - StaticMinInt]; }
set { FillCapacityToLength(); elements[ei - StaticMinInt] = value; }
}
public override void Clear()
{
if (elements != null && elements.Length > 0)
{
Array.Clear(elements, 0, elements.Length);
}
}
public void Clear(TValue clearWith)
{
FillCapacityToLength();
for (int i = elements.Length - 1; i >= 0; --i) { elements[i] = clearWith; }
}
public void CopyFrom(EnumArray<TEnum, TValue> source)
{
if (ReferenceEquals(this, source)) { return; }
FillCapacityToLength();
source.FillCapacityToLength();
Array.Copy(source.elements, 0, elements, 0, StaticLength);
}
public static void Copy(EnumArray<TEnum, TValue> srcArray, TEnum srcEnumIndex, EnumArray<TEnum, TValue> dstArray, TEnum dstEnumIndex, int length)
{
Copy(srcArray, E2I(srcEnumIndex), dstArray, E2I(dstEnumIndex), length);
}
public static void Copy(EnumArray<TEnum, TValue> srcArray, int srcEnumValueIndex, EnumArray<TEnum, TValue> dstArray, int dstEnumValueIndex, int length)
{
srcArray.FillCapacityToLength();
dstArray.FillCapacityToLength();
Array.Copy(srcArray.elements, srcEnumValueIndex - StaticMinInt, dstArray.elements, dstEnumValueIndex - StaticMinInt, length);
}
public override void FillCapacityToLength()
{
if (elements == null)
{
elements = new TValue[StaticLength];
return;
}
var len = StaticLength;
if (elements.Length < len)
{
Array.Resize(ref elements, len);
}
}
public override void TrimCapacityToLength()
{
if (elements == null)
{
return;
}
var len = StaticLength;
if (elements.Length > len)
{
Array.Resize(ref elements, len);
}
}
}
}