Exemplo n.º 1
0
 /// <summary>
 /// Initializes the <see cref="ObjectX"/> class.
 /// </summary>
 static ObjectX()
 {
     System.Text.RegularExpressions.Regex matchCandlelightClass =
         new System.Text.RegularExpressions.Regex(@"^Candlelight\b");
     using (var types = new HashPool <System.Type> .Scope())
     {
         GetAllTypes(types.HashSet);
         foreach (var type in types.HashSet)
         {
             if (
                 !type.IsSubclassOf(typeof(UnityEngine.ScriptableObject)) ||
                 !matchCandlelightClass.IsMatch(type.Namespace ?? "")
                 )
             {
                 continue;
             }
             System.Reflection.ConstructorInfo constructor = type.GetConstructor(
                 System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static |
                 System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic,
                 null,
                 System.Type.EmptyTypes,
                 null
                 );
             if (constructor == null || constructor.IsPublic)
             {
                 UnityEngine.Debug.LogError(
                     string.Format("<b>{0}</b> has no protected, parameterless constructor.", type)
                     );
             }
         }
     }
 }
Exemplo n.º 2
0
 /// <summary>
 /// Gets an auto-incremented version of the specified base name that does not already exist in the specified
 /// collection.
 /// </summary>
 /// <returns>An auto-incremented version of the specified base name that does not already exist in the specified
 /// collection.</returns>
 /// <param name="baseName">Base name.</param>
 /// <param name="existingNames">Existing names.</param>
 public static string GetUniqueName(this string baseName, IList <string> existingNames)
 {
     using (var allNames = new HashPool <string> .Scope())
     {
         if (existingNames != null)
         {
             for (int i = 0; i < existingNames.Count; ++i)
             {
                 allNames.HashSet.Add(existingNames[i]);
             }
         }
         return(GetUniqueName(baseName, allNames.HashSet));
     }
 }
Exemplo n.º 3
0
#pragma warning restore 414

        /// <summary>
        /// Gets an auto-incremented version of the specified base name that does not already exist in the specified
        /// collection.
        /// </summary>
        /// <returns>An auto-incremented version of the specified base name that does not already exist in the specified
        /// collection.</returns>
        /// <param name="baseName">Base name.</param>
        /// <param name="existingNames">Existing names.</param>
        public static string GetUniqueName(this string baseName, IEnumerable <string> existingNames)
        {
            using (HashPool <string> .Scope allNames = new HashPool <string> .Scope())
            {
                if (existingNames != null)
                {
                    foreach (string existing in existingNames)
                    {
                        allNames.HashSet.Add(existing);
                    }
                }
                return(GetUniqueName(baseName, allNames.HashSet));
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Sets a backing field for a list of identifiable objects that should have unique keys. Use this method when
        /// you need to serialize something that may be deserialized as a dictionary.
        /// </summary>
        /// <returns>
        /// <see langword="true"/> if the new value differs from the old one; otherwise, <see langword="false"/>.
        /// </returns>
        /// <param name="backingField">Backing field of identifiable objects.</param>
        /// <param name="value">Value.</param>
        /// <param name="mutateIdentifier">A method to mutate the identifier on an object if it is not unique.</param>
        /// <param name="ignoreCase">
        /// If set to <see langword="true"/>, then all string-based keys will be made lowercase.
        /// </param>
        /// <param name="intKeyMode">Mode for handling duplicate <see cref="System.Int32"/> keys.</param>
        /// <typeparam name="T">
        /// A type with a <see cref="System.Int32"/>, <see cref="System.String"/>, or <see cref="UnityEngine.Object"/>
        /// identifier.
        /// </typeparam>
        /// <typeparam name="TId">
        /// The identifier type (either <see cref="UnityEngine.Object"/>-derived, <see cref="System.Int32"/>, or
        /// <see cref="System.String"/>).
        /// </typeparam>
        private static bool SetKeyedListBackingFieldFromArray <T, TId>(
            List <T> backingField,
            IList <T> value,
            System.Func <TId, T, T> mutateIdentifier,
            bool ignoreCase,
            IntKeyMode intKeyMode = IntKeyMode.Increment
            ) where T : IIdentifiable <TId>
        {
            if (value == null || value.Count == 0)
            {
                int oldCount = backingField.Count;
                backingField.Clear();
                return(oldCount != 0);
            }
            using (ListPool <T> .Scope oldValue = new ListPool <T> .Scope())
            {
                oldValue.List.AddRange(backingField);
                backingField.Clear();
                bool isString = typeof(TId) == typeof(string);
                bool isInt    = !isString && typeof(TId) == typeof(int);
                if (!isInt && !isString)                 // NOTE: WinRT cannot use Type.IsAssignableFrom()
                {
                    int nullHash  = 0;
                    int nullIndex = backingField.FindIndex(item => item.Identifier.GetHashCode() == nullHash);
                    foreach (T newValue in value)
                    {
                        if (newValue == null)
                        {
                            if (nullIndex < 0)
                            {
                                backingField.Add(newValue);
                                nullIndex = backingField.Count - 1;
                            }
                        }
                        else if (
                            !object.ReferenceEquals(newValue.Identifier, default(TId)) &&
                            backingField.FindIndex(
                                item => item.Identifier.GetHashCode() == newValue.Identifier.GetHashCode()
                                ) < 0
                            )
                        {
                            backingField.Add(newValue);
                            if (newValue.Identifier.GetHashCode() == nullHash)
                            {
                                nullIndex = backingField.Count - 1;
                            }
                        }
                        else if (nullIndex < 0)
                        {
                            backingField.Add(mutateIdentifier(default(TId), newValue));
                            nullIndex = backingField.Count - 1;
                        }
                    }
                }
                else
                {
                    using (var keyedValues = new DictPool <TId, T> .Scope())
                    {
                        using (var stringKeys = new HashPool <string> .Scope())
                        {
                            TId id;
                            for (int i = 0; i < value.Count; ++i)
                            {
                                id = value[i] == null ? default(TId) : value[i].Identifier;
                                if (isString)
                                {
                                    string key = (string)(object)id ?? string.Empty;
                                    if (ignoreCase && key.ContainsUppercase())
                                    {
                                        key = key.ToLower();
                                    }
                                    key = key.GetUniqueName(stringKeys.HashSet);
                                    stringKeys.HashSet.Add(key);
                                    id = (TId)(object)key;
                                }
                                else if (isInt)
                                {
                                    switch (intKeyMode)
                                    {
                                    case IntKeyMode.Increment:
                                        while (keyedValues.Dict.ContainsKey(id))
                                        {
                                            id = (TId)(object)((int)(object)id + 1);
                                        }
                                        break;

                                    case IntKeyMode.SetToZero:
                                        if (keyedValues.Dict.ContainsKey(id))
                                        {
                                            id = (TId)(object)0;
                                            if (keyedValues.Dict.ContainsKey(id))
                                            {
                                                continue;
                                            }
                                        }
                                        break;
                                    }
                                }
                                keyedValues.Dict[id] = value[i];
                            }
                            foreach (KeyValuePair <TId, T> kv in keyedValues.Dict)
                            {
                                backingField.Add(mutateIdentifier(kv.Key, kv.Value));
                            }
                        }
                    }
                }
                return(!oldValue.List.SequenceEqual(backingField));
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Sets a backing field for a set of objects.
        /// </summary>
        /// <returns>
        /// <see langword="true"/> if the new value differs from the old one; otherwise, <see langword="false"/>.
        /// </returns>
        /// <param name="backingField">Backing field.</param>
        /// <param name="value">Value.</param>
        /// <param name="ignoreCase">
        /// If set to <see langword="true"/>, then all string elements keys will be made lowercase.
        /// </param>
        /// <param name="intKeyMode">Mode for handling duplicate <see cref="System.Int32"/> keys.</param>
        /// <typeparam name="T">
        /// The element type (either <see cref="UnityEngine.Object"/>-derived, <see cref="System.Int32"/>, or
        /// <see cref="System.String"/>).
        /// </typeparam>
        private static bool SetHashedListBackingFieldFromArray <T>(
            List <T> backingField, IList <T> value, bool ignoreCase, IntKeyMode intKeyMode = IntKeyMode.Increment
            )
        {
            if (value == null || value.Count == 0)
            {
                int oldCount = backingField.Count;
                backingField.Clear();
                return(oldCount != 0);
            }
            T[] oldValue = backingField.ToArray();
            backingField.Clear();
            bool isString = typeof(T) == typeof(string);
            bool isInt    = !isString && typeof(T) == typeof(int);

            if (!isInt && !isString)             // NOTE: WinRT cannot use Type.IsAssignableFrom()
            {
                int nullHash  = 0;
                int nullIndex = backingField.FindIndex(item => item.GetHashCode() == nullHash);
                foreach (T newValue in value)
                {
                    if (
                        !object.ReferenceEquals(newValue, default(T)) &&
                        backingField.FindIndex(item => item.GetHashCode() == newValue.GetHashCode()) < 0
                        )
                    {
                        backingField.Add(newValue);
                        if (newValue.GetHashCode() == nullHash)
                        {
                            nullIndex = backingField.Count - 1;
                        }
                    }
                    else if (nullIndex < 0)
                    {
                        backingField.Add(default(T));
                        nullIndex = backingField.Count - 1;
                    }
                }
            }
            else
            {
                using (var hashedValues = new HashPool <T> .Scope())
                {
                    using (var stringKeys = new HashPool <string> .Scope())
                    {
                        for (int i = 0; i < value.Count; ++i)
                        {
                            T id = value[i];
                            if (isString)
                            {
                                string key = (string)(object)id ?? string.Empty;
                                if (ignoreCase && key.ContainsUppercase())
                                {
                                    key = key.ToLower();
                                }
                                key = key.GetUniqueName(stringKeys.HashSet);
                                stringKeys.HashSet.Add(key);
                                id = (T)(object)key;
                            }
                            else if (isInt)
                            {
                                switch (intKeyMode)
                                {
                                case IntKeyMode.Increment:
                                    while (hashedValues.HashSet.Contains(id))
                                    {
                                        id = (T)(object)((int)(object)id + 1);
                                    }
                                    break;

                                case IntKeyMode.SetToZero:
                                    if (hashedValues.HashSet.Contains(id))
                                    {
                                        id = (T)(object)0;
                                        if (hashedValues.HashSet.Contains(id))
                                        {
                                            continue;
                                        }
                                    }
                                    break;
                                }
                            }
                            hashedValues.HashSet.Add(id);
                        }
                        foreach (T hashedValue in hashedValues.HashSet)
                        {
                            backingField.Add(hashedValue);
                        }
                    }
                }
            }
            return(!oldValue.SequenceEqual(backingField));
        }