//------------------------------------------------- // NGUI: Next-Gen UI kit // Copyright © 2011-2017 Tasharen Entertainment Inc //------------------------------------------------- #if !COMBAT_SERVER using UnityEngine; #endif using System; using System.Collections.Generic; using System.Diagnostics; using CombatLibrary.CombatLibrary.CombatCore; #if !COMBAT_SERVER using Debug = UnityEngine.Debug; #endif /// /// This improved version of the System.Collections.Generic.List that doesn't release the buffer on Clear(), /// resulting in better performance and less garbage collection. /// PRO: BetterList performs faster than List when you Add and Remove items (although slower if you remove from the beginning). /// CON: BetterList performs worse when sorting the list. If your operations involve sorting, use the standard List instead. /// public class BetterList : IDisposable { public int tranId; #if UNITY_FLASH List mList = new List(); /// /// Direct access to the buffer. Note that you should not use its 'Length' parameter, but instead use BetterList.size. /// public T this[int i] { get { return mList[i]; } set { mList[i] = value; } } /// /// Compatibility with the non-flash syntax. /// public List buffer { get { return mList; } } /// /// Direct access to the buffer's size. Note that it's only public for speed and efficiency. You shouldn't modify it. /// public int size { get { return mList.Count; } } /// /// For 'foreach' functionality. /// public IEnumerator GetEnumerator () { return mList.GetEnumerator(); } /// /// Clear the array by resetting its size to zero. Note that the memory is not actually released. /// public void Clear () { mList.Clear(); } /// /// Clear the array and release the used memory. /// public void Release () { mList.Clear(); } /// /// Add the specified item to the end of the list. /// public void Add (T item) { mList.Add(item); } /// /// Insert an item at the specified index, pushing the entries back. /// public void Insert (int index, T item) { if (index > -1 && index < mList.Count) mList.Insert(index, item); else mList.Add(item); } /// /// Returns 'true' if the specified item is within the list. /// public bool Contains (T item) { return mList.Contains(item); } /// /// Return the index of the specified item. /// public int IndexOf (T item) { return mList.IndexOf(item); } /// /// Remove the specified item from the list. Note that RemoveAt() is faster and is advisable if you already know the index. /// public bool Remove (T item) { return mList.Remove(item); } /// /// Remove an item at the specified index. /// public void RemoveAt (int index) { mList.RemoveAt(index); } /// /// Remove an item from the end. /// public T Pop () { if (buffer != null && size != 0) { T val = buffer[mList.Count - 1]; mList.RemoveAt(mList.Count - 1); return val; } return default(T); } /// /// Mimic List's ToArray() functionality, except that in this case the list is resized to match the current size. /// public T[] ToArray () { return mList.ToArray(); } /// /// List.Sort equivalent. /// public void Sort (System.Comparison comparer) { mList.Sort(comparer); } #else /// /// Direct access to the buffer. Note that you should not use its 'Length' parameter, but instead use BetterList.size. /// public T[] buffer; private int buffSize = 8; public int Count { get { return size; } } public bool isNotPool = true; /// /// Direct access to the buffer's size. Note that it's only public for speed and efficiency. You shouldn't modify it. /// public int size = 0; // /// // /// For 'foreach' functionality. // /// // [DebuggerHidden] // [DebuggerStepThrough] // public IEnumerator GetEnumerator() // { // if (buffer != null) // { // for (int i = 0; i < size; ++i) // { // yield return buffer[i]; // } // } // } public BetterList() { isNotPool = true; } // ~BetterList() // { // CombatListPool.Instance.Recycle(this); // } public BetterList(bool isNotPool) { this.isNotPool = isNotPool; } public BetterList(bool isNotPool, int size) { this.isNotPool = isNotPool; buffSize = size; } public BetterList(int size) { buffSize = size; } public BetterList(List allVe) { buffer = allVe.ToArray(); size = buffer.Length; } /// /// Convenience function. I recommend using .buffer instead. /// [DebuggerHidden] public T this[int i] { get { return buffer[i]; } set { buffer[i] = value; } } /// /// Helper function that expands the size of the array, maintaining the content. /// void AllocateMore() { T[] newList = (buffer != null) ? new T[System.Math.Max(buffer.Length << 1, buffSize)] : new T[buffSize]; if (buffer != null && size > 0) buffer.CopyTo(newList, 0); buffer = newList; } /// /// Trim the unnecessary memory, resizing the buffer to be of 'Length' size. /// Call this function only if you are sure that the buffer won't need to resize anytime soon. /// void Trim() { if (size > 0) { if (size < buffer.Length) { T[] newList = new T[size]; for (int i = 0; i < size; ++i) newList[i] = buffer[i]; buffer = newList; } } else buffer = null; } /// /// Clear the array by resetting its size to zero. Note that the memory is not actually released. /// public void Clear() { size = 0; } /// /// Clear the array and release the used memory. /// public void Release() { size = 0; buffer = null; } /// /// Add the specified item to the end of the list. /// public void Add(T item) { if (buffer == null || size == buffer.Length) AllocateMore(); buffer[size++] = item; } /// /// Insert an item at the specified index, pushing the entries back. /// public void Insert(int index, T item) { if (buffer == null || size == buffer.Length) AllocateMore(); if (index > -1 && index < size) { for (int i = size; i > index; --i) buffer[i] = buffer[i - 1]; buffer[index] = item; ++size; } else Add(item); } /// /// Returns 'true' if the specified item is within the list. /// public bool Contains(T item) { if (buffer == null) return false; for (int i = 0; i < size; ++i) if (buffer[i].Equals(item)) return true; return false; } /// /// Return the index of the specified item. /// public int IndexOf(T item) { if (buffer == null) return -1; for (int i = 0; i < size; ++i) if (buffer[i].Equals(item)) return i; return -1; } /// /// Remove the specified item from the list. Note that RemoveAt() is faster and is advisable if you already know the index. /// public bool Remove(T item) { if (buffer != null) { EqualityComparer comp = EqualityComparer.Default; for (int i = 0; i < size; ++i) { if (comp.Equals(buffer[i], item)) { --size; buffer[i] = default(T); for (int b = i; b < size; ++b) buffer[b] = buffer[b + 1]; buffer[size] = default(T); return true; } } } return false; } /// /// Remove an item at the specified index. /// public void RemoveAt(int index) { if (buffer != null && index > -1 && index < size) { --size; buffer[index] = default(T); for (int b = index; b < size; ++b) buffer[b] = buffer[b + 1]; buffer[size] = default(T); } } /// /// Remove an item from the end. /// public T Pop() { if (buffer != null && size != 0) { T val = buffer[--size]; buffer[size] = default(T); return val; } return default(T); } public void AddRange(List target) { for (int i = 0; i < target.Count; i++) { Add(target[i]); } } public void AddRange(T[] target) { if (target == null) { return; } for (int i = 0; i < target.Length; i++) { Add(target[i]); } } public void AddRange(BetterList target) { for (int i = 0; i < target.Count; i++) { Add(target[i]); } } private void Add(object item) { if (buffer == null || size == buffer.Length) AllocateMore(); buffer[size++] = (T)item; } public void AddRange(BetterList target) { // for (int i = 0; i < target.size; i++) // { // Add(target[i]); // } if (target == null || target.buffer == null) { return; } if (buffer == null) { buffer = new T[0]; } if (size + target.size > buffer.Length) { System.Array.Resize(ref buffer, size + target.size); } System.Array.Copy(target.buffer, 0, buffer, size, target.size); size += target.size; } /// /// Mimic List's ToArray() functionality, except that in this case the list is resized to match the current size. /// public T[] ToArray() { Trim(); return buffer; } //class Comparer : System.Collections.IComparer //{ // public System.Comparison func; // public int Compare (object x, object y) { return func((T)x, (T)y); } //} //Comparer mComp = new Comparer(); /// /// List.Sort equivalent. Doing Array.Sort causes GC allocations. /// //public void Sort (System.Comparison comparer) //{ // if (size > 0) // { // mComp.func = comparer; // System.Array.Sort(buffer, 0, size, mComp); // } //} /// /// List.Sort equivalent. Manual sorting causes no GC allocations. /// [DebuggerHidden] [DebuggerStepThrough] public void Sort(CompareFunc comparer) { int start = 0; int max = size - 1; bool changed = true; while (changed) { changed = false; for (int i = start; i < max; ++i) { // Compare the two values if (comparer(buffer[i], buffer[i + 1]) > 0) { // Swap the values T temp = buffer[i]; buffer[i] = buffer[i + 1]; buffer[i + 1] = temp; changed = true; } else if (!changed) { // Nothing has changed -- we can start here next time start = (i == 0) ? 0 : i - 1; } } } } /// /// Comparison function should return -1 if left is less than right, 1 if left is greater than right, and 0 if they match. /// public delegate int CompareFunc(T left, T right); #endif public void Dispose() { if (isNotPool) { return; } CombatListPool.Instance.Recycle(this); } }