diff --git a/.gitignore b/.gitignore index ac529bb..f9c83e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/EntitySystem/note.txt -/EntitySystem/note.txt.meta -/*.meta *.meta +/obj +/bin/Release/netstandard2.0 +/bin/Debug/netstandard2.0 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..532d6f0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Svelto.Common"] + path = Svelto.Common + url = https://github.com/sebas77/Svelto.Common.git diff --git a/DataStructures/CircularBufferIndexer.cs b/DataStructures/CircularBufferIndexer.cs deleted file mode 100644 index 6d86441..0000000 --- a/DataStructures/CircularBufferIndexer.cs +++ /dev/null @@ -1,183 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace Svelto.DataStructures -{ - // Serves as simple circular buffer dictionary, first in, first out - // Main drawback: it is the oldest in the list that is removed and the fact that we might re access a key - // isn't taken into account (we would have to do a shift in both arrays) - // Could be added as an option? - - public class CircularBufferIndexer : IDictionary - { - public ICollection Keys - { - get { return _keys; } - } - - public ICollection Values - { - get { return _values; } - } - - public int Count - { - get { throw new NotImplementedException(); } - } - - public bool IsReadOnly - { - get { throw new NotImplementedException(); } - } - - public CircularBufferIndexer(int size) - { - _keys = new TKey[size]; - _values = new TVal[size]; - _length = _startIndex = _nextIndex = 0; - } - - public TVal this[TKey key] - { - get - { - int index = _startIndex; - for (int i = 0; i < _length; ++i) - { - if (_keys[index].Equals(key)) - { - return _values[index]; - } - - index = NextPosition(index); - } - throw new KeyNotFoundException(); - } - set - { - int index = _startIndex; - for (int i = 0; i < _length; ++i) - { - if (_keys[index].Equals(key)) - { - _values[index] = value; - return; - } - - index = NextPosition(index); - } - throw new KeyNotFoundException(); - } - } - - public void Add(TKey key, TVal value) - { - if (ContainsKey(key)) - { - this[key] = value; - return; - } - - _keys[_nextIndex] = key; - _values[_nextIndex] = value; - _nextIndex = NextPosition(_nextIndex); - if (IsFull()) - { - _startIndex = NextPosition(_startIndex); - } - else - { - ++_length; - } - } - - public bool ContainsKey(TKey key) - { - int index = _startIndex; - for (int i = 0; i < _length; ++i) - { - if (_keys[index].Equals(key)) - { - return true; - } - - index = NextPosition(index); - } - return false; - } - - public bool Remove(TKey key) - { - throw new NotImplementedException(); - } - - public bool TryGetValue(TKey key, out TVal value) - { - value = default(TVal); - int index = _startIndex; - for (int i = 0; i < _length; ++i) - { - if (_keys[index].Equals(key)) - { - value = _values[index]; - return true; - } - - index = NextPosition(index); - } - return false; - } - - public IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - - public void Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(KeyValuePair item) - { - throw new NotImplementedException(); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public bool Remove(KeyValuePair item) - { - throw new NotImplementedException(); - } - - IEnumerator> IEnumerable>.GetEnumerator() - { - throw new NotImplementedException(); - } - - int NextPosition(int position) - { - return (position + 1) % _keys.Length; - } - - bool IsFull() - { - return _length == _values.Length; - } - - TKey[] _keys; - TVal[] _values; - int _startIndex; - int _nextIndex; - int _length; - } -} diff --git a/DataStructures/FasterList.cs b/DataStructures/FasterList.cs deleted file mode 100644 index d87c13b..0000000 --- a/DataStructures/FasterList.cs +++ /dev/null @@ -1,807 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; - -namespace Svelto.DataStructures -{ - public struct FasterListEnumerator : IEnumerator - { - public T Current - { - get { return _current; } - } - - public FasterListEnumerator(T[] buffer, int size) - { - _size = size; - _counter = 0; - _buffer = buffer; - _current = default(T); - } - - object IEnumerator.Current - { - get { return _current; } - } - - T IEnumerator.Current - { - get { return _current; } - } - - public void Dispose() - { - _buffer = null; - } - - public bool MoveNext() - { - if (_counter < _size) - { - _current = _buffer[_counter++]; - - return true; - } - - _current = default(T); - - return false; - } - - public void Reset() - { - _counter = 0; - } - - bool IEnumerator.MoveNext() - { - return MoveNext(); - } - - void IEnumerator.Reset() - { - Reset(); - } - - T[] _buffer; - int _counter; - int _size; - T _current; - } - - public struct FasterListEnumeratorCast : IEnumerator where T:U - { - public T Current - { - get { return (T)_buffer.Current; } - } - - public FasterListEnumeratorCast(FasterListEnumerator buffer) - { - _buffer = buffer; - } - - object IEnumerator.Current - { - get { return (T)_buffer.Current; } - } - - T IEnumerator.Current - { - get { return (T)_buffer.Current; } - } - - public void Dispose() - {} - - public bool MoveNext() - { - return _buffer.MoveNext(); - } - - public void Reset() - { - _buffer.Reset(); - } - - bool IEnumerator.MoveNext() - { - return MoveNext(); - } - - void IEnumerator.Reset() - { - Reset(); - } - - FasterListEnumerator _buffer; - } - - public struct FasterReadOnlyList : IList - { - public static FasterReadOnlyList DefaultList = new FasterReadOnlyList(new FasterList()); - - public int Count { get { return _list.Count; } } - public bool IsReadOnly { get { return true; } } - - public FasterReadOnlyList(FasterList list) - { - _list = list; - } - - public T this[int index] { get { return _list[index]; } set { throw new NotImplementedException(); } } - - public FasterListEnumerator GetEnumerator() - { - return _list.GetEnumerator(); - } - - public void Add(T item) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(T item) - { - return _list.Contains(item); - } - - public void CopyTo(T[] array, int arrayIndex) - { - _list.CopyTo(array, arrayIndex); - } - - public bool Remove(T item) - { - throw new NotImplementedException(); - } - - public int IndexOf(T item) - { - return _list.IndexOf(item); - } - - public void Insert(int index, T item) - { - throw new NotImplementedException(); - } - - public void RemoveAt(int index) - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - readonly FasterList _list; - } - - public struct FasterListThreadSafe : IList - { - public FasterListThreadSafe(FasterList list) - { - if (list == null) throw new ArgumentException("invalid list"); - _list = list; - _lockQ = new ReaderWriterLockSlim(); - } - - public int Count - { - get - { - _lockQ.EnterReadLock(); - try - { - return _list.Count; - } - finally - { - _lockQ.ExitReadLock(); - } - } - } - public bool IsReadOnly { get { return false; } } - - public T this[int index] - { - get - { - _lockQ.EnterReadLock(); - try - { - return _list[index]; - } - finally - { - _lockQ.ExitReadLock(); - } - } - set - { - _lockQ.EnterWriteLock(); - try - { - _list[index] = value; - } - finally - { - _lockQ.ExitWriteLock(); - } - } - } - - public FasterListEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - - public void Add(T item) - { - _lockQ.EnterWriteLock(); - try - { - _list.Add(item); - } - finally - { - _lockQ.ExitWriteLock(); - } - } - - public void Clear() - { - _lockQ.EnterWriteLock(); - try - { - _list.Clear(); - } - finally - { - _lockQ.ExitWriteLock(); - } - } - - public void FastClear() - { - _lockQ.EnterWriteLock(); - try - { - _list.FastClear(); - } - finally - { - _lockQ.ExitWriteLock(); - } - } - - public bool Contains(T item) - { - _lockQ.EnterReadLock(); - try - { - return _list.Contains(item); - } - finally - { - _lockQ.ExitReadLock(); - } - } - - public void CopyTo(T[] array, int arrayIndex) - { - _lockQ.EnterReadLock(); - try - { - _list.CopyTo(array, arrayIndex); - } - finally - { - _lockQ.ExitReadLock(); - } - } - - public bool Remove(T item) - { - _lockQ.EnterWriteLock(); - try - { - return _list.Remove(item); - } - finally - { - _lockQ.ExitWriteLock(); - } - } - - public int IndexOf(T item) - { - _lockQ.EnterReadLock(); - try - { - return _list.IndexOf(item); - } - finally - { - _lockQ.ExitReadLock(); - } - } - - public void Insert(int index, T item) - { - _lockQ.EnterWriteLock(); - try - { - _list.Insert(index, item); - } - finally - { - _lockQ.ExitWriteLock(); - } - } - - public void RemoveAt(int index) - { - _lockQ.EnterWriteLock(); - try - { - _list.RemoveAt(index); - } - finally - { - _lockQ.ExitWriteLock(); - } - } - - public void UnorderedRemoveAt(int index) - { - _lockQ.EnterWriteLock(); - try - { - _list.UnorderedRemoveAt(index); - } - finally - { - _lockQ.ExitWriteLock(); - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - - readonly FasterList _list; - - readonly ReaderWriterLockSlim _lockQ; - } - - public struct FasterReadOnlyListCast : IList where U:T - { - public static FasterReadOnlyListCast DefaultList = new FasterReadOnlyListCast(new FasterList()); - - public int Count { get { return _list.Count; } } - public bool IsReadOnly { get { return true; } } - - public FasterReadOnlyListCast(FasterList list) - { - _list = list; - } - - public U this[int index] { get { return (U)_list[index]; } set { throw new NotImplementedException(); } } - - public FasterListEnumeratorCast GetEnumerator() - { - return new FasterListEnumeratorCast(_list.GetEnumerator()); - } - - public void Add(U item) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(U item) - { - return _list.Contains(item); - } - - public void CopyTo(U[] array, int arrayIndex) - { - Array.Copy(_list.ToArrayFast(), 0, array, arrayIndex, _list.Count); - } - - public bool Remove(U item) - { - throw new NotImplementedException(); - } - - public int IndexOf(U item) - { - return _list.IndexOf(item); - } - - public void Insert(int index, U item) - { - throw new NotImplementedException(); - } - - public void RemoveAt(int index) - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - readonly FasterList _list; - } - - public interface IFasterList - {} - - public class FasterList : IList, IFasterList - { - const int MIN_SIZE = 4; - - public int Count - { - get { return _count; } - } - - public bool IsReadOnly - { - get { return false; } - } - - public FasterList() - { - _count = 0; - - _buffer = new T[MIN_SIZE]; - } - - public FasterList(int initialSize) - { - _count = 0; - - _buffer = new T[initialSize]; - } - - public FasterList(ICollection collection) - { - _buffer = new T[collection.Count]; - - collection.CopyTo(_buffer, 0); - - _count = _buffer.Length; - } - - public FasterList(FasterList listCopy) - { - _buffer = new T[listCopy.Count]; - - listCopy.CopyTo(_buffer, 0); - - _count = listCopy.Count; - } - - public T this[int i] - { - get { DesignByContract.Check.Require(i < _count, "out of bound index"); return _buffer[i]; } - set { DesignByContract.Check.Require(i < _count, "out of bound index"); _buffer[i] = value; } - } - - public void Add(T item) - { - if (_count == _buffer.Length) - AllocateMore(); - - _buffer[_count++] = item; - } - - - /// - /// this is a dirtish trick to be able to use the index operastor - /// before adding the elements through the Add functions - /// - /// - /// - /// - public static FasterList PreFill(int initialSize) where U:T, new() - { - var list = new FasterList(initialSize); - - for (int i = 0; i < initialSize; i++) - list.Add(new U()); - - list._count = 0; - - return list; - } - - public void AddRange(IEnumerable items, int count) - { - AddRange(items.GetEnumerator(), count); - } - - public void AddRange(IEnumerator items, int count) - { - if (_count + count >= _buffer.Length) - AllocateMore(_count + count); - - while (items.MoveNext()) - _buffer[_count++] = items.Current; - } - - public void AddRange(ICollection items) - { - AddRange(items.GetEnumerator(), items.Count); - } - - public void AddRange(FasterList items) - { - AddRange(items.ToArrayFast(), items.Count); - } - - public void AddRange(T[] items, int count) - { - if (count == 0) return; - - if (_count + count >= _buffer.Length) - AllocateMore(_count + count); - - Array.Copy(items, 0, _buffer, _count, count); - _count += count; - } - - public void AddRange(T[] items) - { - AddRange(items, items.Length); - } - - public FasterReadOnlyList AsReadOnly() - { - return new FasterReadOnlyList(this); - } - - /// - /// Careful, you could keep on holding references you don't want to hold to anymore - /// Use DeepClear in case. - /// - public void FastClear() - { - _count = 0; - } - - public void Clear() - { - Array.Clear(_buffer, 0, _buffer.Length); - - _count = 0; - } - - public bool Contains(T item) - { - var index = IndexOf(item); - - return index != -1; - } - - public void CopyTo(T[] array, int arrayIndex) - { - Array.Copy(_buffer, 0, array, arrayIndex, Count); - } - - public FasterListEnumerator GetEnumerator() - { - return new FasterListEnumerator(_buffer, Count); - } - - public int IndexOf(T item) - { - var comp = EqualityComparer.Default; - - for (var index = _count - 1; index >= 0; --index) - if (comp.Equals(_buffer[index], item)) - return index; - - return -1; - } - - public void Insert(int index, T item) - { - DesignByContract.Check.Require(index < _count, "out of bound index"); - - if (_count == _buffer.Length) AllocateMore(); - - Array.Copy(_buffer, index, _buffer, index + 1, _count - index); - - _buffer[index] = item; - ++_count; - } - - public void Release() - { - _count = 0; - _buffer = null; - } - - public bool Remove(T item) - { - var index = IndexOf(item); - - if (index == -1) - return false; - - RemoveAt(index); - - return true; - } - - public void RemoveAt(int index) - { - DesignByContract.Check.Require(index < _count, "out of bound index"); - - if (index == --_count) - return; - - Array.Copy(_buffer, index + 1, _buffer, index, _count - index); - - _buffer[_count] = default(T); - } - - public void Resize(int newSize) - { - if (newSize < MIN_SIZE) - newSize = MIN_SIZE; - - Array.Resize(ref _buffer, newSize); - - _count = newSize; - } - - public void SetAt(int index, T value) - { - if (index >= _buffer.Length) - AllocateMore(index + 1); - - if (_count <= index) - _count = index + 1; - - this[index] = value; - } - - public void Sort(IComparer comparer) - { - Array.Sort(_buffer, 0, _count, comparer); - } - - public T[] ToArray() - { - T[] destinationArray = new T[_count]; - - Array.Copy(_buffer, 0, destinationArray, 0, _count); - - return destinationArray; - } - - /// - /// This function exists to allow fast iterations. The size of the array returned cannot be - /// used. The list count must be used instead. - /// - /// - public T[] ToArrayFast() - { - return _buffer; - } - - public bool UnorderedRemove(T item) - { - var index = IndexOf(item); - - if (index == -1) - return false; - - UnorderedRemoveAt(index); - - return true; - } - - public bool UnorderedRemoveAt(int index) - { - DesignByContract.Check.Require(index < _count && _count > 0, "out of bound index"); - - if (index == --_count) - { - _buffer[_count] = default(T); - return false; - } - - _buffer[index] = _buffer[_count]; - _buffer[_count] = default(T); - - return true; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - void AllocateMore() - { - var newList = new T[Math.Max(_buffer.Length << 1, MIN_SIZE)]; - if (_count > 0) _buffer.CopyTo(newList, 0); - _buffer = newList; - } - - void AllocateMore(int newSize) - { - var oldLength = Math.Max(_buffer.Length, MIN_SIZE); - - while (oldLength < newSize) - oldLength <<= 1; - - var newList = new T[oldLength]; - if (_count > 0) Array.Copy(_buffer, newList, _count); - _buffer = newList; - } - - public void Trim() - { - if (_count < _buffer.Length) - Resize(_count); - } - - public bool Reuse(int index, out U result) - where U:class, T - { - result = default(U); - - if (index >= _buffer.Length) - return false; - - result = (U)_buffer[index]; - - return result != null; - } - - T[] _buffer; - int _count; - } -} diff --git a/DataStructures/HashableWeakReference.cs b/DataStructures/HashableWeakReference.cs deleted file mode 100644 index 62edfa6..0000000 --- a/DataStructures/HashableWeakReference.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; - -namespace Svelto.DataStructures -{ - class HashableWeakRef : IEquatable> where T : class - { - public bool isAlive { get { return _weakRef.IsAlive; } } - public T Target { get { return (T)_weakRef.Target; } } - - public HashableWeakRef(T target) - { - _weakRef = new WeakReference(target); - _hash = target.GetHashCode(); - } - - public static bool operator !=(HashableWeakRef a, HashableWeakRef b) - { - return !(a == b); - } - - public static bool operator ==(HashableWeakRef a, HashableWeakRef b) - { - if (a._hash != b._hash) - return false; - - var tmpTargetA = (T) a._weakRef.Target; - var tmpTargetB = (T) b._weakRef.Target; - - if (tmpTargetA == null || tmpTargetB == null) - return false; - - return tmpTargetA == tmpTargetB; - } - - public override bool Equals(object other) - { - if (other is HashableWeakRef) - return this.Equals((HashableWeakRef)other); - - return false; - } - - public bool Equals(HashableWeakRef other) - { - return (this == other); - } - - public override int GetHashCode() - { - return _hash; - } - - int _hash; - WeakReference _weakRef; - } -} diff --git a/DataStructures/LockFreeQueue.cs b/DataStructures/LockFreeQueue.cs deleted file mode 100644 index 4c55f39..0000000 --- a/DataStructures/LockFreeQueue.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System.Collections.Generic; -using System.Threading; - -//from unify wiki -namespace Svelto.DataStructures -{ - public class SingleLinkNode - { - // Note; the Next member cannot be a property since - // it participates in many CAS operations - public SingleLinkNode Next; - public T Item; - } - - public static class SyncMethods - { - public static bool CAS(ref T location, T comparand, T newValue) where T : class - { - return - (object)comparand == - (object)Interlocked.CompareExchange(ref location, newValue, comparand); - } - } - - public class LockFreeLinkPool - { - private SingleLinkNode head; - - public LockFreeLinkPool() - { - head = new SingleLinkNode(); - } - - public void Push(SingleLinkNode newNode) - { - newNode.Item = default(T); - do - { - newNode.Next = head.Next; - } while (!SyncMethods.CAS>(ref head.Next, newNode.Next, newNode)); - return; - } - - public bool Pop(out SingleLinkNode node) - { - do - { - node = head.Next; - if (node == null) - { - return false; - } - } while (!SyncMethods.CAS>(ref head.Next, node, node.Next)); - return true; - } - } - - public class LockFreeQueue - { - - SingleLinkNode head; - SingleLinkNode tail; - LockFreeLinkPool trash; - - public LockFreeQueue() - { - head = new SingleLinkNode(); - tail = head; - trash = new LockFreeLinkPool(); - } - - public void Enqueue(T item) - { - SingleLinkNode oldTail = null; - SingleLinkNode oldTailNext; - - SingleLinkNode newNode; - if (!trash.Pop(out newNode)) - { - newNode = new SingleLinkNode(); - } - else - { - newNode.Next = null; - } - newNode.Item = item; - - bool newNodeWasAdded = false; - while (!newNodeWasAdded) - { - oldTail = tail; - oldTailNext = oldTail.Next; - - if (tail == oldTail) - { - if (oldTailNext == null) - newNodeWasAdded = SyncMethods.CAS>(ref tail.Next, null, newNode); - else - SyncMethods.CAS>(ref tail, oldTail, oldTailNext); - } - } - SyncMethods.CAS>(ref tail, oldTail, newNode); - } - - public bool Dequeue(out T item) - { - item = default(T); - SingleLinkNode oldHead = null; - - bool haveAdvancedHead = false; - while (!haveAdvancedHead) - { - - oldHead = head; - SingleLinkNode oldTail = tail; - SingleLinkNode oldHeadNext = oldHead.Next; - - if (oldHead == head) - { - if (oldHead == oldTail) - { - if (oldHeadNext == null) - { - return false; - } - SyncMethods.CAS>(ref tail, oldTail, oldHeadNext); - } - else - { - item = oldHeadNext.Item; - haveAdvancedHead = SyncMethods.CAS>(ref head, oldHead, oldHeadNext); - if (haveAdvancedHead) - { - trash.Push(oldHead); - } - } - } - } - return true; - } - } -} \ No newline at end of file diff --git a/DataStructures/PriorityQueue/HeapPriorityQueue.cs b/DataStructures/PriorityQueue/HeapPriorityQueue.cs deleted file mode 100644 index 606acd5..0000000 --- a/DataStructures/PriorityQueue/HeapPriorityQueue.cs +++ /dev/null @@ -1,327 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using Svelto.DataStructures; - -namespace Svelto.DataStructures -{ - /// - /// An implementation of a min-Priority Queue using a heap. Has O(1) .Contains()! - /// See https://bitbucket.org/BlueRaja/high-speed-priority-queue-for-c/wiki/Getting%20Started for more information - /// - /// The values in the queue. Must implement the PriorityQueueNode interface - public sealed class HeapPriorityQueue : IPriorityQueue - where T : PriorityQueueNode - { - private int _numNodes; - private readonly FasterList _nodes; - private long _numNodesEverEnqueued; - - /// - /// Instantiate a new Priority Queue - /// - /// The max nodes ever allowed to be enqueued (going over this will cause an exception) - public HeapPriorityQueue() - { - _numNodes = 0; - _nodes = new FasterList(); - _numNodesEverEnqueued = 0; - } - - public HeapPriorityQueue(int initialSize) - { - _numNodes = 0; - _nodes = new FasterList(initialSize); - _numNodesEverEnqueued = 0; - } - - /// - /// Returns the number of nodes in the queue. O(1) - /// - public int Count - { - get - { - return _numNodes; - } - } - - /// - /// Returns the maximum number of items that can be enqueued at once in this queue. Once you hit this number (ie. once Count == MaxSize), - /// attempting to enqueue another item will throw an exception. O(1) - /// - public int MaxSize - { - get - { - return _nodes.Count - 1; - } - } - - /// - /// Removes every node from the queue. O(n) (So, don't do this often!) - /// - #if NET_VERSION_4_5 - [MethodImpl(MethodImplOptions.AggressiveInlining)] - #endif - public void Clear() - { - _nodes.FastClear(); - - _numNodes = 0; - } - - /// - /// Returns (in O(1)!) whether the given node is in the queue. O(1) - /// - #if NET_VERSION_4_5 - [MethodImpl(MethodImplOptions.AggressiveInlining)] - #endif - public bool Contains(T node) - { - return (_nodes[node.QueueIndex] == node); - } - - /// - /// Enqueue a node - .Priority must be set beforehand! O(log n) - /// - #if NET_VERSION_4_5 - [MethodImpl(MethodImplOptions.AggressiveInlining)] - #endif - public void Enqueue(T node, double priority) - { - node.Priority = priority; - _numNodes++; - if (_nodes.Count < _numNodes) - _nodes.Resize(_numNodes + 1); - - _nodes[_numNodes] = node; - node.QueueIndex = _numNodes; - node.InsertionIndex = _numNodesEverEnqueued++; - CascadeUp(_nodes[_numNodes]); - } - - #if NET_VERSION_4_5 - [MethodImpl(MethodImplOptions.AggressiveInlining)] - #endif - private void Swap(T node1, T node2) - { - //Swap the nodes - _nodes[node1.QueueIndex] = node2; - _nodes[node2.QueueIndex] = node1; - - //Swap their indicies - int temp = node1.QueueIndex; - node1.QueueIndex = node2.QueueIndex; - node2.QueueIndex = temp; - } - - //Performance appears to be slightly better when this is NOT inlined o_O - private void CascadeUp(T node) - { - //aka Heapify-up - int parent = node.QueueIndex / 2; - while(parent >= 1) - { - T parentNode = _nodes[parent]; - if(HasHigherPriority(parentNode, node)) - break; - - //Node has lower priority value, so move it up the heap - Swap(node, parentNode); //For some reason, this is faster with Swap() rather than (less..?) individual operations, like in CascadeDown() - - parent = node.QueueIndex / 2; - } - } - - #if NET_VERSION_4_5 - [MethodImpl(MethodImplOptions.AggressiveInlining)] - #endif - private void CascadeDown(T node) - { - //aka Heapify-down - T newParent; - int finalQueueIndex = node.QueueIndex; - while(true) - { - newParent = node; - int childLeftIndex = 2 * finalQueueIndex; - - //Check if the left-child is higher-priority than the current node - if(childLeftIndex > _numNodes) - { - //This could be placed outside the loop, but then we'd have to check newParent != node twice - node.QueueIndex = finalQueueIndex; - _nodes[finalQueueIndex] = node; - break; - } - - T childLeft = _nodes[childLeftIndex]; - if(HasHigherPriority(childLeft, newParent)) - { - newParent = childLeft; - } - - //Check if the right-child is higher-priority than either the current node or the left child - int childRightIndex = childLeftIndex + 1; - if(childRightIndex <= _numNodes) - { - T childRight = _nodes[childRightIndex]; - if(HasHigherPriority(childRight, newParent)) - { - newParent = childRight; - } - } - - //If either of the children has higher (smaller) priority, swap and continue cascading - if(newParent != node) - { - //Move new parent to its new index. node will be moved once, at the end - //Doing it this way is one less assignment operation than calling Swap() - _nodes[finalQueueIndex] = newParent; - - int temp = newParent.QueueIndex; - newParent.QueueIndex = finalQueueIndex; - finalQueueIndex = temp; - } - else - { - //See note above - node.QueueIndex = finalQueueIndex; - _nodes[finalQueueIndex] = node; - break; - } - } - } - - /// - /// Returns true if 'higher' has higher priority than 'lower', false otherwise. - /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false - /// - #if NET_VERSION_4_5 - [MethodImpl(MethodImplOptions.AggressiveInlining)] - #endif - private bool HasHigherPriority(T higher, T lower) - { - return (higher.Priority < lower.Priority || - (higher.Priority == lower.Priority && higher.InsertionIndex < lower.InsertionIndex)); - } - - /// - /// Removes the head of the queue (node with highest priority; ties are broken by order of insertion), and returns it. O(log n) - /// - public T Dequeue() - { - T returnMe = _nodes[1]; - Remove(returnMe); - return returnMe; - } - - /// - /// Returns the head of the queue, without removing it (use Dequeue() for that). O(1) - /// - public T First - { - get - { - return _nodes[1]; - } - } - - /// - /// This method must be called on a node every time its priority changes while it is in the queue. - /// Forgetting to call this method will result in a corrupted queue! - /// O(log n) - /// - #if NET_VERSION_4_5 - [MethodImpl(MethodImplOptions.AggressiveInlining)] - #endif - public void UpdatePriority(T node, double priority) - { - node.Priority = priority; - OnNodeUpdated(node); - } - - private void OnNodeUpdated(T node) - { - //Bubble the updated node up or down as appropriate - int parentIndex = node.QueueIndex / 2; - T parentNode = _nodes[parentIndex]; - - if(parentIndex > 0 && HasHigherPriority(node, parentNode)) - { - CascadeUp(node); - } - else - { - //Note that CascadeDown will be called if parentNode == node (that is, node is the root) - CascadeDown(node); - } - } - - /// - /// Removes a node from the queue. Note that the node does not need to be the head of the queue. O(log n) - /// - public void Remove(T node) - { - if(_numNodes <= 1) - { - _nodes[1] = null; - _numNodes = 0; - return; - } - - //Make sure the node is the last node in the queue - bool wasSwapped = false; - T formerLastNode = _nodes[_numNodes]; - if(node.QueueIndex != _numNodes) - { - //Swap the node with the last node - Swap(node, formerLastNode); - wasSwapped = true; - } - - _numNodes--; - _nodes[node.QueueIndex] = null; - - if(wasSwapped) - { - //Now bubble formerLastNode (which is no longer the last node) up or down as appropriate - OnNodeUpdated(formerLastNode); - } - } - - public IEnumerator GetEnumerator() - { - for(int i = 1; i <= _numNodes; i++) - yield return _nodes[i]; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - /// Should not be called in production code. - /// Checks to make sure the queue is still in a valid state. Used for testing/debugging the queue. - /// - public bool IsValidQueue() - { - for(int i = 1; i < _nodes.Count; i++) - { - if(_nodes[i] != null) - { - int childLeftIndex = 2 * i; - if(childLeftIndex < _nodes.Count && _nodes[childLeftIndex] != null && HasHigherPriority(_nodes[childLeftIndex], _nodes[i])) - return false; - - int childRightIndex = childLeftIndex + 1; - if(childRightIndex < _nodes.Count && _nodes[childRightIndex] != null && HasHigherPriority(_nodes[childRightIndex], _nodes[i])) - return false; - } - } - return true; - } - } -} \ No newline at end of file diff --git a/DataStructures/PriorityQueue/IPriorityQueue.cs b/DataStructures/PriorityQueue/IPriorityQueue.cs deleted file mode 100644 index 632820e..0000000 --- a/DataStructures/PriorityQueue/IPriorityQueue.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Generic; - -namespace Svelto.DataStructures -{ - /// - /// The IPriorityQueue interface. This is mainly here for purists, and in case I decide to add more implementations later. - /// For speed purposes, it is actually recommended that you *don't* access the priority queue through this interface, since the JIT can - /// (theoretically?) optimize method calls from concrete-types slightly better. - /// - public interface IPriorityQueue : IEnumerable - where T : PriorityQueueNode - { - void Remove(T node); - void UpdatePriority(T node, double priority); - void Enqueue(T node, double priority); - T Dequeue(); - T First { get; } - int Count { get; } - int MaxSize { get; } - void Clear(); - bool Contains(T node); - } -} diff --git a/DataStructures/PriorityQueue/PriorityQueueNode.cs b/DataStructures/PriorityQueue/PriorityQueueNode.cs deleted file mode 100644 index b09f3a4..0000000 --- a/DataStructures/PriorityQueue/PriorityQueueNode.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Svelto.DataStructures -{ - public class PriorityQueueNode - { - /// - /// The Priority to insert this node at. Must be set BEFORE adding a node to the queue - /// - public double Priority { get; - set; - } - - /// - /// Used by the priority queue - do not edit this value. - /// Represents the order the node was inserted in - /// - public long InsertionIndex { get; set; } - - /// - /// Used by the priority queue - do not edit this value. - /// Represents the current position in the queue - /// - public int QueueIndex { get; set; } - } -} diff --git a/DataStructures/ReadOnlyDictionary.cs b/DataStructures/ReadOnlyDictionary.cs deleted file mode 100644 index 8b09f3a..0000000 --- a/DataStructures/ReadOnlyDictionary.cs +++ /dev/null @@ -1,544 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace Svelto.DataStructures -{ - public struct ReadOnlyDictionary : IDictionary - { - public bool isInitialized { get { return _dictionary != null; } } - - /// - /// Gets the element that has the specified key. - /// - /// The key of the element to get. - /// The element that has the specified key. - /// If is . - /// If property is retrieved and is not found. - public TValue this[TKey key] - { - get - { - return _dictionary[key]; - } - } - - /// - /// Gets the number of items in the dictionary. - /// - /// - /// The number of items in the dictionary. - /// - public int Count - { - get - { - return _dictionary.Count; - } - } - - /// - /// Gets a key collection that contains the keys of the dictionary. - /// - /// - /// A key collection that contains the keys of the dictionary. - /// - public KeyCollection Keys - { - get - { - return new KeyCollection(_dictionary.Keys); - } - } - - /// - /// Gets a collection that contains the values in the dictionary. - /// - /// - /// A collection that contains the values in the object that implements . - /// - public ValueCollection Values - { - get - { - return new ValueCollection(_dictionary.Values); - } - } - - /// - /// Initializes a new instance of the class - /// that is a wrapper around the specified dictionary. - /// - /// The dictionary to wrap. - public ReadOnlyDictionary(Dictionary dictionary) - { - if (dictionary == null) - throw new ArgumentNullException("dictionary"); - - _dictionary = dictionary; - } - - /// - /// - /// Gets the element that has the specified key. - /// - /// If the property is set. - TValue IDictionary.this[TKey key] - { - get - { - return this[key]; - } - - set - { - throw new NotSupportedException(); - } - } - - /// - ICollection IDictionary.Keys - { - get - { - return Keys; - } - } - - /// - ICollection IDictionary.Values - { - get - { - return Values; - } - } - - /// - bool ICollection>.IsReadOnly - { - get - { - return true; - } - } - - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - void IDictionary.Add(TKey key, TValue value) - { - throw new NotSupportedException(); - } - - /// - bool IDictionary.Remove(TKey key) - { - throw new NotSupportedException(); - } - - /// - void ICollection>.Add(KeyValuePair item) - { - throw new NotSupportedException(); - } - - /// - void ICollection>.Clear() - { - throw new NotSupportedException(); - } - - /// - bool ICollection>.Contains(KeyValuePair item) - { - throw new NotImplementedException(); - } - - /// - void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - /// - bool ICollection>.Remove(KeyValuePair item) - { - throw new NotSupportedException(); - } - - bool IDictionary.ContainsKey(TKey key) - { - return _dictionary.ContainsKey(key); - } - - bool IDictionary.TryGetValue(TKey key, out TValue value) - { - return _dictionary.TryGetValue(key, out value); - } - - int ICollection>.Count - { - get { return _dictionary.Count; } - } - - IEnumerator> IEnumerable>.GetEnumerator() - { - return _dictionary.GetEnumerator(); - } - - /// - /// Determines whether the dictionary contains an element that has the specified key. - /// - /// The key to locate in the dictionary. - /// if the dictionary contains an element that has the specified key; otherwise, . - public bool ContainsKey(TKey key) - { - return _dictionary.ContainsKey(key); - } - - public DictionaryEnumerator GetEnumerator() - { - return new DictionaryEnumerator(_dictionary); - } - - /// - /// Retrieves the value that is associated with the specified key. - /// - /// The key whose value will be retrieved. - /// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the parameter. This parameter is passed uninitialized. - /// if the object that implements contains an element with the specified key; otherwise, . - public bool TryGetValue(TKey key, out TValue value) - { - return _dictionary.TryGetValue(key, out value); - } - - readonly Dictionary _dictionary; - - /// - /// Represents a read-only collection of the keys of a object. - /// - public struct KeyCollection : ICollection, ICollection - { - /// - /// Initializes a new instance of the class - /// as a wrapper around the specified collection of keys. - /// - /// The collection of keys to wrap. - /// If is . - internal KeyCollection(ICollection keys) - { - if (keys == null) - throw new ArgumentNullException("keys"); - - _keys = keys; - } - - /// - bool ICollection.IsSynchronized - { - get - { - return false; - } - } - - /// - object ICollection.SyncRoot - { - get - { - throw new NotImplementedException(); - } - } - - /// - void ICollection.CopyTo(Array array, int index) - { - throw new NotImplementedException(); - } - - /// - /// Gets the number of elements in the collection. - /// - /// - /// The number of elements in the collection. - /// - public int Count - { - get - { - return _keys.Count; - } - } - - /// - bool ICollection.IsReadOnly - { - get - { - return true; - } - } - - /// - /// Copies the elements of the collection to an array, starting at a specific array index. - /// - /// The one-dimensional array that is the destination of the elements copied from the collection. The array must have zero-based indexing. - /// The zero-based index in at which copying begins. - /// If is . - /// If is less than 0. - /// - /// If is multidimensional. - /// -or- - /// If the number of elements in the source collection is greater than the available space from to the end of the destination . - /// -or- - /// If the type cannot be cast automatically to the type of the destination . - /// - public void CopyTo(TKey[] array, int arrayIndex) - { - _keys.CopyTo(array, arrayIndex); - } - - /// - /// Returns an enumerator that iterates through the collection. - /// - /// An enumerator that can be used to iterate through the collection. - public IEnumerator GetEnumerator() - { - return _keys.GetEnumerator(); - } - - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - bool ICollection.Contains(TKey item) - { - return _keys.Contains(item); - } - - /// - void ICollection.Add(TKey item) - { - throw new NotSupportedException(); - } - - /// - bool ICollection.Remove(TKey item) - { - throw new NotSupportedException(); - } - - /// - void ICollection.Clear() - { - throw new NotSupportedException(); - } - - /// - /// The wrapped collection of keys. - /// - readonly ICollection _keys; - } - - /// - /// Represents a read-only collection of the values of a object. - /// - public struct ValueCollection : ICollection, ICollection - { - /// - /// Initializes a new instance of the class - /// as a wrapper around the specified collection of values. - /// - /// The collection of values to wrap. - /// If is . - internal ValueCollection(ICollection values) - { - if (values == null) - throw new ArgumentNullException("values"); - - _values = values; - } - - /// - bool ICollection.IsSynchronized - { - get - { - return false; - } - } - - /// - object ICollection.SyncRoot - { - get - { - throw new NotImplementedException(); - } - } - - /// - void ICollection.CopyTo(Array array, int index) - { - throw new NotImplementedException(); - } - - /// - /// Gets the number of elements in the collection. - /// - /// - /// The number of elements in the collection. - /// - public int Count - { - get - { - return _values.Count; - } - } - - /// - bool ICollection.IsReadOnly - { - get - { - return true; - } - } - - /// - /// Copies the elements of the collection to an array, starting at a specific array index. - /// - /// The one-dimensional array that is the destination of the elements copied from the collection. The array must have zero-based indexing. - /// The zero-based index in at which copying begins. - /// If is . - /// If is less than 0. - /// - /// If is multidimensional. - /// -or- - /// If the number of elements in the source collection is greater than the available space from to the end of the destination . - /// -or- - /// If the type cannot be cast automatically to the type of the destination . - /// - public void CopyTo(TValue[] array, int arrayIndex) - { - _values.CopyTo(array, arrayIndex); - } - - /// - /// Returns an enumerator that iterates through the collection. - /// - /// An enumerator that can be used to iterate through the collection. - public IEnumerator GetEnumerator() - { - return _values.GetEnumerator(); - } - - /// - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - bool ICollection.Contains(TValue item) - { - return _values.Contains(item); - } - - /// - void ICollection.Add(TValue item) - { - throw new NotSupportedException(); - } - - /// - bool ICollection.Remove(TValue item) - { - throw new NotSupportedException(); - } - - /// - void ICollection.Clear() - { - throw new NotSupportedException(); - } - - /// - /// The wrapped collection of values. - /// - readonly ICollection _values; - } - - public struct DictionaryEnumerator:IEnumerator> - { - /// - public TKey Key - { - get - { - return _enumerator.Current.Key; - } - } - - /// - public TValue Value - { - get - { - return _enumerator.Current.Value; - } - } - - public DictionaryEnumerator(IDictionary dictionary) - { - if (dictionary == null) - throw new ArgumentNullException("dictionary"); - - _enumerator = dictionary.GetEnumerator(); - } - - /// - public KeyValuePair Current - { - get - { - return _enumerator.Current; - } - } - - /// - public bool MoveNext() - { - return _enumerator.MoveNext(); - } - - /// - public void Reset() - { - _enumerator.Reset(); - } - - object IEnumerator.Current - { - get { return _enumerator.Current; } - } - - public void Dispose() - { - _enumerator.Dispose(); - } - - readonly IEnumerator> _enumerator; - } - } -} diff --git a/DataStructures/ThreadSafeDictionary.cs b/DataStructures/ThreadSafeDictionary.cs deleted file mode 100644 index 4a4a71f..0000000 --- a/DataStructures/ThreadSafeDictionary.cs +++ /dev/null @@ -1,290 +0,0 @@ - -using System.Collections.Generic; -using System.Threading; - -namespace Svelto.DataStructures -{ - /// - /// original code: http://devplanet.com/blogs/brianr/archive/2008/09/29/thread-safe-dictionary-update.aspx - /// simplified (not an IDictionary) and apdated (uses FasterList) - /// - /// - /// - - public class ThreadSafeDictionary - { - public ThreadSafeDictionary(int v) - { - dict = new Dictionary(v); - } - - public ThreadSafeDictionary() - { - dict = new Dictionary(); - } - - // setup the lock; - public virtual int Count - { - get - { - LockQ.EnterReadLock(); - try - { - return dict.Count; - } - finally - { - LockQ.ExitReadLock(); - } - } - } - - public virtual bool IsReadOnly - { - get - { - LockQ.EnterReadLock(); - try - { - return dict.IsReadOnly; - } - finally - { - LockQ.ExitReadLock(); - } - } - } - - public virtual FasterList Keys - { - get - { - LockQ.EnterReadLock(); - try - { - return new FasterList(dict.Keys); - } - finally - { - LockQ.ExitReadLock(); - } - } - } - - public virtual FasterList Values - { - get - { - LockQ.EnterReadLock(); - try - { - return new FasterList(dict.Values); - } - finally - { - LockQ.ExitReadLock(); - } - } - } - - public virtual TValue this[TKey key] - { - get - { - LockQ.EnterReadLock(); - try - { - return dict[key]; - } - finally - { - LockQ.ExitReadLock(); - } - } - - set - { - LockQ.EnterWriteLock(); - try - { - dict[key] = value; - } - finally - { - LockQ.ExitWriteLock(); - } - } - } - - public virtual void Add(KeyValuePair item) - { - LockQ.EnterWriteLock(); - try - { - dict.Add(item); - } - finally - { - LockQ.ExitWriteLock(); - } - } - - public virtual void Clear() - { - LockQ.EnterWriteLock(); - try - { - dict.Clear(); - } - finally - { - LockQ.ExitWriteLock(); - } - } - - public virtual bool Contains(KeyValuePair item) - { - LockQ.EnterReadLock(); - try - { - return dict.Contains(item); - } - finally - { - LockQ.ExitReadLock(); - } - } - - public virtual void CopyTo(KeyValuePair[] array, int arrayIndex) - { - LockQ.EnterReadLock(); - try - { - dict.CopyTo(array, arrayIndex); - } - finally - { - LockQ.ExitReadLock(); - } - } - - public virtual bool Remove(KeyValuePair item) - { - LockQ.EnterWriteLock(); - try - { - return dict.Remove(item); - } - finally - { - LockQ.ExitWriteLock(); - } - } - - public virtual void Add(TKey key, TValue value) - { - LockQ.EnterWriteLock(); - try - { - dict.Add(key, value); - } - finally - { - LockQ.ExitWriteLock(); - } - } - - public virtual bool ContainsKey(TKey key) - { - LockQ.EnterReadLock(); - try - { - return dict.ContainsKey(key); - } - finally - { - LockQ.ExitReadLock(); - } - } - - public virtual bool Remove(TKey key) - { - LockQ.EnterWriteLock(); - try - { - return dict.Remove(key); - } - finally - { - LockQ.ExitWriteLock(); - } - } - - public virtual bool TryGetValue(TKey key, out TValue value) - { - LockQ.EnterReadLock(); - try - { - return dict.TryGetValue(key, out value); - } - finally - { - LockQ.ExitReadLock(); - } - } - - /// - /// Merge does a blind remove, and then add. Basically a blind Upsert. - /// - /// Key to lookup - /// New Value - public void MergeSafe(TKey key, TValue newValue) - { - LockQ.EnterWriteLock(); - try - { - // take a writelock immediately since we will always be writing - if (dict.ContainsKey(key)) - dict.Remove(key); - - dict.Add(key, newValue); - } - finally - { - LockQ.ExitWriteLock(); - } - } - - /// - /// This is a blind remove. Prevents the need to check for existence first. - /// - /// Key to remove - public void RemoveSafe(TKey key) - { - LockQ.EnterReadLock(); - try - { - if (dict.ContainsKey(key)) - LockQ.EnterWriteLock(); - try - { - dict.Remove(key); - } - finally - { - LockQ.ExitWriteLock(); - } - } - finally - { - LockQ.ExitReadLock(); - } - } - - // This is the internal dictionary that we are wrapping - readonly IDictionary dict; - - readonly ReaderWriterLockSlim LockQ = new ReaderWriterLockSlim(); - } -} diff --git a/DataStructures/ThreadSafeQueue.cs b/DataStructures/ThreadSafeQueue.cs deleted file mode 100644 index d9197f0..0000000 --- a/DataStructures/ThreadSafeQueue.cs +++ /dev/null @@ -1,233 +0,0 @@ -using System.Collections.Generic; -using System.Threading; - -namespace Svelto.DataStructures -{ - public class ThreadSafeQueue - { - readonly Queue m_Queue; - - readonly ReaderWriterLockSlim LockQ = new ReaderWriterLockSlim(); - - public ThreadSafeQueue() - { - m_Queue = new Queue(); - } - - public ThreadSafeQueue(int capacity) - { - m_Queue = new Queue(capacity); - } - - public ThreadSafeQueue(IEnumerable collection) - { - m_Queue = new Queue(collection); - } - - public IEnumerator GetEnumerator() - { - Queue localQ; - - LockQ.EnterReadLock(); - try - { - localQ = new Queue(m_Queue); - } - - finally - { - LockQ.ExitReadLock(); - } - - foreach (T item in localQ) - yield return item; - } - - public void Enqueue(T item) - { - LockQ.EnterWriteLock(); - try - { - m_Queue.Enqueue(item); - } - - finally - { - LockQ.ExitWriteLock(); - } - } - - public T Dequeue() - { - LockQ.EnterWriteLock(); - try - { - return m_Queue.Dequeue(); - } - - finally - { - LockQ.ExitWriteLock(); - } - } - - public void EnqueueAll(IEnumerable ItemsToQueue) - { - LockQ.EnterWriteLock(); - try - { - foreach (T item in ItemsToQueue) - m_Queue.Enqueue(item); - } - - finally - { - LockQ.ExitWriteLock(); - } - } - - public FasterList DequeueAll() - { - LockQ.EnterWriteLock(); - try - { - FasterList returnList = new FasterList(); - - while (m_Queue.Count > 0) - returnList.Add(m_Queue.Dequeue()); - - return returnList; - } - - finally - { - LockQ.ExitWriteLock(); - } - } - - public void DequeueAllInto(FasterList list) - { - LockQ.EnterWriteLock(); - try - { - while (m_Queue.Count > 0) - list.Add(m_Queue.Dequeue()); - } - - finally - { - LockQ.ExitWriteLock(); - } - } - - public void DequeueInto(FasterList list, int count) - { - LockQ.EnterWriteLock(); - try - { - int originalSize = m_Queue.Count; - while (m_Queue.Count > 0 && originalSize - m_Queue.Count < count) - list.Add(m_Queue.Dequeue()); - } - - finally - { - LockQ.ExitWriteLock(); - } - } - - public FasterList DequeueAllAs() where U:class - { - LockQ.EnterWriteLock(); - try - { - FasterList returnList = new FasterList(); - - while (m_Queue.Count > 0) - returnList.Add(m_Queue.Dequeue() as U); - - return returnList; - } - - finally - { - LockQ.ExitWriteLock(); - } - } - - public T Peek() - { - LockQ.EnterWriteLock(); - try - { - T item = default(T); - - if (m_Queue.Count > 0) - item = m_Queue.Peek(); - - return item; - } - - finally - { - LockQ.ExitWriteLock(); - } - } - - public void Clear() - { - LockQ.EnterWriteLock(); - try - { - m_Queue.Clear(); - } - - finally - { - LockQ.ExitWriteLock(); - } - } - - public bool TryDequeue(out T item) - { - LockQ.EnterWriteLock(); - try - { - if (m_Queue.Count > 0) - { - item = m_Queue.Dequeue(); - - return true; - } - else - { - item = default(T); - - return false; - } - } - - finally - { - LockQ.ExitWriteLock(); - } - } - - public int Count - { - get - { - LockQ.EnterWriteLock(); - try - { - return m_Queue.Count; - } - - finally - { - LockQ.ExitWriteLock(); - } - } - } - } -} diff --git a/DataStructures/WeakReference.cs b/DataStructures/WeakReference.cs deleted file mode 100644 index 0f14cca..0000000 --- a/DataStructures/WeakReference.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -/// -/// Represents a weak reference, which references an object while still allowing -/// that object to be reclaimed by garbage collection. -/// -/// The type of the object that is referenced. - -namespace Svelto.DataStructures -{ -#if !NETFX_CORE - public class WeakReference - : WeakReference where T : class - { - public bool IsValid { get { return Target != null && IsAlive == true; } } - - /// - /// Gets or sets the object (the target) referenced by the - /// current WeakReference{T} object. - /// - public new T Target - { - get - { - return (T)base.Target; - } - set - { - base.Target = value; - } - } - /// - /// Initializes a new instance of the WeakReference{T} class, referencing - /// the specified object. - /// - /// The object to reference. - public WeakReference(T target) - : base(target) - { } - - /// - /// Initializes a new instance of the WeakReference{T} class, referencing - /// the specified object and using the specified resurrection tracking. - /// - /// An object to track. - /// Indicates when to stop tracking the object. - /// If true, the object is tracked - /// after finalization; if false, the object is only tracked - /// until finalization. - public WeakReference(T target, bool trackResurrection) - : base(target, trackResurrection) - { } - } -#else - public class WeakReference : System.WeakReference where T : class - { - public bool IsValid { get { return Target != null && IsAlive == true; } } - - public new T Target - { - get - { - return (T)base.Target; - } - set - { - base.Target = value; - } - } - - public WeakReference(T target) - : base(target) - { } - - public WeakReference(T target, bool trackResurrection) - : base(target, trackResurrection) - { } - } -#endif -} diff --git a/ECS/EngineNodeDB.cs b/ECS/EngineNodeDB.cs deleted file mode 100644 index 0bb5bb8..0000000 --- a/ECS/EngineNodeDB.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using System.Collections.Generic; -using Svelto.DataStructures; - -namespace Svelto.ECS -{ - public class EngineNodeDB : IEngineNodeDB - { - internal EngineNodeDB( Dictionary> nodesDB, - Dictionary> nodesDBdic, - Dictionary> metaNodesDB) - { - _nodesDB = nodesDB; - _nodesDBdic = nodesDBdic; - _metaNodesDB = metaNodesDB; - } - - public FasterReadOnlyListCast QueryNodes() where T:INode - { - var type = typeof(T); - - FasterList nodes; - - if (_nodesDB.TryGetValue(type, out nodes) == false) - return RetrieveEmptyNodeList(); - - return new FasterReadOnlyListCast(nodes); - } - - public ReadOnlyDictionary QueryIndexableNodes() where T:INode - { - var type = typeof(T); - - Dictionary nodes; - - if (_nodesDBdic.TryGetValue(type, out nodes) == false) - return _defaultEmptyNodeDict; - - return new ReadOnlyDictionary(nodes); - } - - public T QueryMetaNode(int metaEntityID) where T : INode - { - return QueryNode(metaEntityID); - } - - public bool TryQueryMetaNode(int metaEntityID, out T node) where T : INode - { - return TryQueryNode(metaEntityID, out node); - } - - public FasterReadOnlyListCast QueryMetaNodes() where T : INode - { - var type = typeof(T); - - FasterList nodes; - - if (_metaNodesDB.TryGetValue(type, out nodes) == false) - return RetrieveEmptyNodeList(); - - return new FasterReadOnlyListCast(nodes); - } - - public bool TryQueryNode(int ID, out T node) where T:INode - { - var type = typeof(T); - - INode internalNode; - - Dictionary nodes; - - if (_nodesDBdic.TryGetValue(type, out nodes) && - nodes.TryGetValue(ID, out internalNode)) - { - node = (T)internalNode; - - return true; - } - - node = default(T); - - return false; - } - - public T QueryNode(int ID) where T:INode - { - var type = typeof(T); - - INode internalNode; Dictionary nodes; - - if (_nodesDBdic.TryGetValue(type, out nodes) && - nodes.TryGetValue(ID, out internalNode)) - return (T)internalNode; - - throw new Exception("Node Not Found"); - } - - static FasterReadOnlyListCast RetrieveEmptyNodeList() where T : INode - { - return FasterReadOnlyListCast.DefaultList; - } - - readonly Dictionary> _nodesDB; - readonly Dictionary> _nodesDBdic; - readonly Dictionary> _metaNodesDB; - - readonly ReadOnlyDictionary _defaultEmptyNodeDict = new ReadOnlyDictionary(new Dictionary()); - } -} diff --git a/ECS/EnginesRoot.cs b/ECS/EnginesRoot.cs deleted file mode 100644 index 404b187..0000000 --- a/ECS/EnginesRoot.cs +++ /dev/null @@ -1,544 +0,0 @@ -using System; -using System.Collections.Generic; -using Svelto.DataStructures; -using Svelto.ECS.Internal; -using Svelto.ECS.NodeSchedulers; -using WeakReference = Svelto.DataStructures.WeakReference; - -#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR -using Svelto.ECS.Profiler; -#endif -#if NETFX_CORE -using System.Reflection; -#endif - -namespace Svelto.ECS -{ - public sealed class EnginesRoot : IEnginesRoot, IEntityFactory - { - public EnginesRoot(NodeSubmissionScheduler nodeScheduler) - { - _nodeEngines = new Dictionary>(); - _activableEngines = new Dictionary>(); - _otherEngines = new FasterList(); - - _engineRootWeakReference = new WeakReference(this); - - _nodesDB = new Dictionary>(); - _nodesDBdic = new Dictionary>(); - - _nodesToAdd = new FasterList(); - _metaNodesToAdd = new FasterList(); - - _metaNodesDB = new Dictionary>(); - _sharedStructNodeLists = new SharedStructNodeLists(); - _sharedGroupedStructNodeLists = new SharedGroupedStructNodesLists(); - - _internalRemove = InternalRemove; - _internalDisable = InternalDisable; - _internalEnable = InternalEnable; - _internalMetaRemove = InternalMetaRemove; - - _scheduler = nodeScheduler; - _scheduler.Schedule(SubmitNodes); - - _structNodeEngineType = typeof(IStructNodeEngine<>); - _groupedStructNodesEngineType = typeof(IGroupedStructNodesEngine<>); - _activableNodeEngineType = typeof(IActivableNodeEngine<>); - - _implementedInterfaceTypes = new Dictionary(); - -#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - UnityEngine.GameObject debugEngineObject = new UnityEngine.GameObject("Engine Debugger"); - debugEngineObject.gameObject.AddComponent(); -#endif - } - - void SubmitNodes() - { - int metaNodesCount = _metaNodesToAdd.Count; - int nodesCount = _nodesToAdd.Count; - - if (metaNodesCount + nodesCount == 0) return; - - bool newNodesHaveBeenAddedWhileIterating; - int startNodes = 0; - int startMetaNodes = 0; - int numberOfReenteringLoops = 0; - - do - { - var nodesToAdd = _nodesToAdd.ToArrayFast(); - - for (int i = startNodes; i < nodesCount; i++) - { - var node = nodesToAdd[i]; - var nodeType = node.GetType(); - - AddNodeToTheDB(node, nodeType); - var nodeWithId = node as INodeWithID; - if (nodeWithId != null) - AddNodeToNodesDictionary(nodeWithId, nodeType); - } - - var metaNodesToAdd = _metaNodesToAdd.ToArrayFast(); - - for (int i = startMetaNodes; i < metaNodesCount; i++) - { - var node = metaNodesToAdd[i]; - var nodeType = node.GetType(); - - AddNodeToMetaDB(node, nodeType); - var nodeWithId = node as INodeWithID; - if (nodeWithId != null) - AddNodeToNodesDictionary(nodeWithId, nodeType); - } - - for (int i = startNodes; i < nodesCount; i++) - { - var node = nodesToAdd[i]; - AddNodeToTheSuitableEngines(node, node.GetType()); - } - - for (int i = startMetaNodes; i < metaNodesCount; i++) - { - var node = metaNodesToAdd[i]; - AddNodeToTheSuitableEngines(node, node.GetType()); - } - - newNodesHaveBeenAddedWhileIterating = - _metaNodesToAdd.Count > metaNodesCount || - _nodesToAdd.Count > nodesCount; - - startNodes = nodesCount; - startMetaNodes = metaNodesCount; - - if (numberOfReenteringLoops > 5) - throw new Exception("possible infinite loop found creating Entities inside INodesEngine Add method, please consider building entities outside INodesEngine Add method"); - - numberOfReenteringLoops++; - - metaNodesCount = _metaNodesToAdd.Count; - nodesCount = _nodesToAdd.Count; - - } while (newNodesHaveBeenAddedWhileIterating); - - _nodesToAdd.Clear(); - _metaNodesToAdd.Clear(); - } - - public void AddEngine(IEngine engine) - { -#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - EngineProfiler.AddEngine(engine); -#endif - var queryableNodeEngine = engine as IQueryableNodeEngine; - if (queryableNodeEngine != null) - queryableNodeEngine.nodesDB = - new EngineNodeDB(_nodesDB, _nodesDBdic, _metaNodesDB); - - var engineType = engine.GetType(); - var implementedInterfaces = engineType.GetInterfaces(); - - CollectImplementedInterfaces(implementedInterfaces); - - var engineAdded = CheckGenericEngines(engine); - - if (CheckLegacyNodesEngine(engine, ref engineAdded) == false) - CheckNodesEngine(engine, engineType, ref engineAdded); - - if (engineAdded == false) - _otherEngines.Add(engine); - - var callBackOnAddEngine = engine as ICallBackOnAddEngine; - if (callBackOnAddEngine != null) - callBackOnAddEngine.Ready(); - } - - void CollectImplementedInterfaces(Type[] implementedInterfaces) - { - _implementedInterfaceTypes.Clear(); - - var type = typeof(IEngine); - - for (int index = 0; index < implementedInterfaces.Length; index++) - { - var interfaceType = implementedInterfaces[index]; - - if (type.IsAssignableFrom(interfaceType) == false) - continue; -#if !NETFX_CORE - - if (false == interfaceType.IsGenericType) -#else - if (false == interfaceType.IsConstructedGenericType) -#endif - { - continue; - } - - var genericTypeDefinition = interfaceType.GetGenericTypeDefinition(); - - _implementedInterfaceTypes.Add(genericTypeDefinition, interfaceType.GetGenericArguments()); - } - } - - bool CheckGenericEngines(IEngine engine) - { - if (_implementedInterfaceTypes.Count == 0) return false; - - bool engineAdded = false; - - if (_implementedInterfaceTypes.ContainsKey(_structNodeEngineType)) - { - ((IStructNodeEngine)engine).CreateStructNodes - (_sharedStructNodeLists); - } - - if (_implementedInterfaceTypes.ContainsKey(_groupedStructNodesEngineType)) - { - ((IGroupedStructNodesEngine)engine).CreateStructNodes - (_sharedGroupedStructNodeLists); - } - - Type[] arguments; - if (_implementedInterfaceTypes.TryGetValue(_activableNodeEngineType, - out arguments)) - { - AddEngine(engine, arguments, _activableEngines); - - engineAdded = true; - } - - return engineAdded; - } - - bool CheckLegacyNodesEngine(IEngine engine, ref bool engineAdded) - { - var nodesEngine = engine as INodesEngine; - if (nodesEngine != null) - { - AddEngine(nodesEngine, nodesEngine.AcceptedNodes(), _nodeEngines); - - engineAdded = true; - - return true; - } - - return false; - } - - bool CheckNodesEngine(IEngine engine, Type engineType, ref bool engineAdded) - { -#if !NETFX_CORE - var baseType = engineType.BaseType; - - if (baseType.IsGenericType -#else - var baseType = engineType.GetTypeInfo().BaseType; - - if (baseType.IsConstructedGenericType -#endif - && engine is INodeEngine) - { - AddEngine(engine as INodeEngine, baseType.GetGenericArguments(), _nodeEngines); - - engineAdded = true; - - return true; - } - - return false; - } - - public void BuildEntity(int ID, EntityDescriptor ed) - { - var entityNodes = ed.BuildNodes(ID, - _internalRemove, - _internalEnable, - _internalDisable - ); - - _nodesToAdd.AddRange(entityNodes); - } - - /// - /// A meta entity is a way to manage a set of entitites that are not easily - /// queriable otherwise. For example you may want to group existing entities - /// by size and type and then use the meta entity node to manage the data - /// shared among the single entities of the same type and size. This will - /// prevent the scenario where the coder is forced to parse all the entities to - /// find the ones of the same size and type. - /// Since the entities are managed through the shared node, the same - /// shared node must be found on the single entities of the same type and size. - /// The shared node of the meta entity is then used by engines that are meant - /// to manage a group of entities through a single node. - /// The same engine can manage several meta entities nodes too. - /// The Engine manages the logic of the Meta Node data and other engines - /// can read back this data through the normal entity as the shared node - /// will be present in their descriptor too. - /// - /// - /// - public void BuildMetaEntity(int metaEntityID, EntityDescriptor ed) - { - var entityNodes = ed.BuildNodes(metaEntityID, - _internalMetaRemove, - _internalEnable, - _internalDisable - ); - - _metaNodesToAdd.AddRange(entityNodes); - } - - /// - /// Using this function is like building a normal entity, but the nodes - /// are grouped by groupID to be better processed inside engines and - /// improve cache locality. Only IGroupStructNodeWithID nodes are grouped - /// other nodes are managed as usual. - /// - /// - /// - /// - public void BuildEntityInGroup(int entityID, int groupID, - EntityDescriptor ed) - { - var entityNodes = ed.BuildNodes(entityID, - _internalRemove, - _internalEnable, - _internalDisable - ); - - _nodesToAdd.AddRange(entityNodes); - - for (int i = 0; i < entityNodes.Count; i++) - { - var groupNode = entityNodes[i] as IGroupedStructNodeWithID; - if (groupNode != null) - groupNode.groupID = groupID; - } - } - - static void AddEngine(IEngine engine, Type[] types, - Dictionary> engines) - { - for (int i = 0; i < types.Length; i++) - { - FasterList list; - - var type = types[i]; - - if (engines.TryGetValue(type, out list) == false) - { - list = new FasterList(); - - engines.Add(type, list); - } - - list.Add(engine); - } - } - - void AddNodeToMetaDB(INode node, Type nodeType) - { - FasterList nodes; - if (_metaNodesDB.TryGetValue(nodeType, out nodes) == false) - nodes = _metaNodesDB[nodeType] = new FasterList(); - - nodes.Add(node); - } - - void AddNodeToTheDB(T node, Type nodeType) where T : INode - { - FasterList nodes; - if (_nodesDB.TryGetValue(nodeType, out nodes) == false) - nodes = _nodesDB[nodeType] = new FasterList(); - - nodes.Add(node); - } - - void AddNodeToNodesDictionary(T node, Type nodeType) where T : INodeWithID - { - Dictionary nodesDic; - - if (_nodesDBdic.TryGetValue(nodeType, out nodesDic) == false) - nodesDic = _nodesDBdic[nodeType] = new Dictionary(); - - nodesDic.Add(node.ID, node); - } - - void AddNodeToTheSuitableEngines(INode node, Type nodeType) - { - FasterList enginesForNode; - - if (_nodeEngines.TryGetValue(nodeType, out enginesForNode)) - { - for (int j = 0; j < enginesForNode.Count; j++) - { -#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - EngineProfiler.MonitorAddDuration(enginesForNode[j] as INodeEngine, node); -#else - (enginesForNode[j] as INodeEngine).Add(node); -#endif - } - } - } - - void RemoveNodeFromTheDB(T node, Type nodeType) where T : INode - { - FasterList nodes; - if (_nodesDB.TryGetValue(nodeType, out nodes) == true) - nodes.UnorderedRemove(node); //should I remove it from the dictionary if length is zero? - } - - void RemoveNodeFromMetaDB(T node, Type nodeType) where T : INode - { - FasterList nodes; - if (_metaNodesDB.TryGetValue(nodeType, out nodes) == true) - nodes.UnorderedRemove(node); //should I remove it from the dictionary if length is zero? - } - - void RemoveNodeFromNodesDictionary(T node, Type nodeType) where T : INodeWithID - { - Dictionary nodesDic; - - if (_nodesDBdic.TryGetValue(nodeType, out nodesDic)) - nodesDic.Remove(node.ID); - } - - void RemoveNodeFromEngines(T node, Type nodeType) where T : INode - { - FasterList enginesForNode; - - if (_nodeEngines.TryGetValue(nodeType, out enginesForNode)) - { - for (int j = 0; j < enginesForNode.Count; j++) - { -#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - EngineProfiler.MonitorRemoveDuration((enginesForNode[j] as INodeEngine), node); -#else - (enginesForNode[j] as INodeEngine).Remove(node); -#endif - } - } - } - - void DisableNodeFromEngines(INode node, Type nodeType) - { - FasterList enginesForNode; - - if (_activableEngines.TryGetValue(nodeType, out enginesForNode)) - { - for (int j = 0; j < enginesForNode.Count; j++) - { - (enginesForNode[j] as IActivableNodeEngine).Disable(node); - } - } - } - - void EnableNodeFromEngines(INode node, Type nodeType) - { - FasterList enginesForNode; - - if (_activableEngines.TryGetValue(nodeType, out enginesForNode)) - { - for (int j = 0; j < enginesForNode.Count; j++) - { - (enginesForNode[j] as IActivableNodeEngine).Enable(node); - } - } - } - - void InternalDisable(FasterList nodes) - { - if (_engineRootWeakReference.IsValid == false) - return; - - for (int i = 0; i < nodes.Count; i++) - { - var node = nodes[i]; - Type nodeType = node.GetType(); - DisableNodeFromEngines(node, nodeType); - } - } - - void InternalEnable(FasterList nodes) - { - if (_engineRootWeakReference.IsValid == false) - return; - - for (int i = 0; i < nodes.Count; i++) - { - var node = nodes[i]; - Type nodeType = node.GetType(); - EnableNodeFromEngines(node, nodeType); - } - } - - void InternalRemove(FasterList nodes) - { - if (_engineRootWeakReference.IsValid == false) - return; - - for (int i = 0; i < nodes.Count; i++) - { - var node = nodes[i]; - Type nodeType = node.GetType(); - - RemoveNodeFromEngines(node, nodeType); - RemoveNodeFromTheDB(node, node.GetType()); - - var nodeWithId = node as INodeWithID; - if (nodeWithId != null) - RemoveNodeFromNodesDictionary(nodeWithId, nodeType); - } - } - - void InternalMetaRemove(FasterList nodes) - { - for (int i = 0; i < nodes.Count; i++) - { - var node = nodes[i]; - Type nodeType = node.GetType(); - - RemoveNodeFromEngines(node, nodeType); - RemoveNodeFromMetaDB(node, nodeType); - - var nodeWithId = node as INodeWithID; - if (nodeWithId != null) - RemoveNodeFromNodesDictionary(nodeWithId, nodeType); - } - } - - readonly Dictionary> _nodeEngines; - readonly Dictionary> _activableEngines; - - readonly FasterList _otherEngines; - - readonly Dictionary> _nodesDB; - readonly Dictionary> _metaNodesDB; - - readonly Dictionary> _nodesDBdic; - - readonly FasterList _nodesToAdd; - readonly FasterList _metaNodesToAdd; - - readonly WeakReference _engineRootWeakReference; - readonly SharedStructNodeLists _sharedStructNodeLists; - readonly SharedGroupedStructNodesLists _sharedGroupedStructNodeLists; - - readonly NodeSubmissionScheduler _scheduler; - - readonly Action> _internalRemove; - readonly Action> _internalEnable; - readonly Action> _internalDisable; - readonly Action> _internalMetaRemove; - - readonly Type _structNodeEngineType; - readonly Type _groupedStructNodesEngineType; - readonly Type _activableNodeEngineType; - - readonly Dictionary _implementedInterfaceTypes; - } -} - diff --git a/ECS/EntityDescriptor.cs b/ECS/EntityDescriptor.cs deleted file mode 100644 index cf459b2..0000000 --- a/ECS/EntityDescriptor.cs +++ /dev/null @@ -1,196 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Svelto.DataStructures; -#if NETFX_CORE -using BindingFlags = System.Reflection.BindingFlags; -#endif - -namespace Svelto.ECS -{ - public class EntityDescriptor - { - protected EntityDescriptor() - { - } - protected EntityDescriptor(INodeBuilder[] nodesToBuild) - { - _nodesToBuild = new FasterList(nodesToBuild); - } - protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor):this(nodesToBuild) - { - ProcessImplementors(componentsImplementor); - } - - public void AddImplementors(params object[] componentsImplementor) - { - ProcessImplementors(componentsImplementor); - } - - void ProcessImplementors(object[] implementors) - { - for (int index = 0; index < implementors.Length; index++) - { - var implementor = implementors[index]; - if (implementor == null) - { - Utility.Console.LogWarning( - "Null implementor, are you using a wild GetComponents to fetch it? " - .FastConcat(ToString())); - } - else - { - if (implementor is IRemoveEntityComponent) - _removingImplementors.Add(implementor as IRemoveEntityComponent); - if (implementor is IDisableEntityComponent) - _disablingImplementors.Add(implementor as IDisableEntityComponent); - if (implementor is IEnableEntityComponent) - _enablingImplementors.Add(implementor as IEnableEntityComponent); - - var interfaces = implementor.GetType().GetInterfaces(); - for (int iindex = 0; iindex < interfaces.Length; iindex++) - { - _implementorsByType[interfaces[iindex]] = implementor; - } - } - } - } - - public void AddNodes(params INodeBuilder[] nodesWithID) - { - _nodesToBuild.AddRange(nodesWithID); - } - - public virtual FasterList BuildNodes(int ID) - { - var nodes = new FasterList(); - - for (int index = 0; index < _nodesToBuild.Count; index++) - { - var nodeBuilder = _nodesToBuild[index]; - var node = nodeBuilder.Build(ID); - - if (nodeBuilder.reflects != FillNodeMode.None) - node = FillNode(node, nodeBuilder.reflects); - - nodes.Add(node); - } - - return nodes; - } - - internal FasterList BuildNodes(int ID, - Action> removeEntity, - Action> enableEntity, - Action> disableEntity) - { - var nodes = BuildNodes(ID); - - SetupImplementors(removeEntity, enableEntity, disableEntity, nodes); - - return nodes; - } - - void SetupImplementors( - Action> removeEntity, - Action> enableEntity, - Action> disableEntity, - FasterList nodes) - { - Action removeEntityAction = () => { removeEntity(nodes); nodes.Clear(); }; - Action disableEntityAction = () => disableEntity(nodes); - Action enableEntityAction = () => enableEntity(nodes); - - for (int index = 0; index < _removingImplementors.Count; index++) - _removingImplementors[index].removeEntity = removeEntityAction; - for (int index = 0; index < _disablingImplementors.Count; index++) - _disablingImplementors[index].disableEntity = disableEntityAction; - for (int index = 0; index < _enablingImplementors.Count; index++) - _enablingImplementors[index].enableEntity = enableEntityAction; - } - - TNode FillNode(TNode node, FillNodeMode mode) where TNode : INode - { - var fields = node.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); - - for (int i = fields.Length - 1; i >= 0; --i) - { - var field = fields[i]; - Type fieldType = field.FieldType; - object component; - - if ((_implementorsByType.TryGetValue(fieldType, out component)) == false) - { - if (mode == FillNodeMode.Strict) - { - Exception e = - new Exception("Svelto.ECS: Implementor not found for a Node. " + "Implementor Type: " + - field.FieldType.Name + " - Node: " + node.GetType().Name + - " - EntityDescriptor " + this); - - throw e; - } - } - else - field.SetValue(node, component); - } - - return node; - } - - readonly FasterList _disablingImplementors = new FasterList(); - readonly FasterList _removingImplementors = new FasterList(); - readonly FasterList _enablingImplementors = new FasterList(); - readonly Dictionary _implementorsByType = new Dictionary(); - - readonly FasterList _nodesToBuild; - } - - public interface INodeBuilder - { - INode Build(int ID); - - FillNodeMode reflects { get; } - } - - public class NodeBuilder : INodeBuilder where NodeType : NodeWithID, new() - { - public INode Build(int ID) - { - NodeWithID node = NodeWithID.BuildNode(ID); - - return (NodeType)node; - } - - public FillNodeMode reflects { get { return FillNodeMode.Strict; } } - } - - public class StructNodeBuilder : INodeBuilder - where NodeType : struct, IStructNodeWithID - { - public INode Build(int ID) - { - var shortID = (short)ID; - IStructNodeWithID node = default(NodeType); - node.ID = shortID; - - return node; - } - - public virtual FillNodeMode reflects { get { return FillNodeMode.Relaxed; } } - } - - public class FastStructNodeBuilder : StructNodeBuilder - where NodeType : struct, IStructNodeWithID - { - public override FillNodeMode reflects { get { return FillNodeMode.None; } } - } - - public enum FillNodeMode - { - Strict, - Relaxed, - - None - } -} diff --git a/ECS/Extensions/Unity/UnitySumbmissionNodeScheduler.cs b/ECS/Extensions/Unity/UnitySumbmissionNodeScheduler.cs deleted file mode 100644 index 9241fdf..0000000 --- a/ECS/Extensions/Unity/UnitySumbmissionNodeScheduler.cs +++ /dev/null @@ -1,41 +0,0 @@ -#if UNITY_5 || UNITY_5_3_OR_NEWER -using System; -using System.Collections; -using UnityEngine; - -namespace Svelto.ECS.NodeSchedulers -{ - public class UnitySumbmissionNodeScheduler : NodeSubmissionScheduler - { - public UnitySumbmissionNodeScheduler() - { - GameObject go = new GameObject("ECSScheduler"); - - _scheduler = go.AddComponent(); - } - - public override void Schedule(Action submitNodes) - { - _scheduler.OnTick += submitNodes; - } - - class Scheduler : MonoBehaviour - { - IEnumerator Start() - { - while (true) - { - yield return _wait; - - OnTick(); - } - } - - internal Action OnTick; - WaitForEndOfFrame _wait = new WaitForEndOfFrame(); - } - - Scheduler _scheduler; - } -} -#endif \ No newline at end of file diff --git a/ECS/GenericEntityDescriptor.cs b/ECS/GenericEntityDescriptor.cs deleted file mode 100644 index 472cdff..0000000 --- a/ECS/GenericEntityDescriptor.cs +++ /dev/null @@ -1,239 +0,0 @@ -namespace Svelto.ECS -{ - public class GenericEntityDescriptor : EntityDescriptor - where T : NodeWithID, new() - { - static GenericEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] { new NodeBuilder() }; - } - public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) - {} - - static readonly INodeBuilder[] _nodesToBuild; - } - - public class GenericEntityDescriptor : EntityDescriptor - where T : NodeWithID, new() - where U : NodeWithID, new() - { - static GenericEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] - { - new NodeBuilder(), - new NodeBuilder() - }; - } - - public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) - {} - - static readonly INodeBuilder[] _nodesToBuild; - } - - public class GenericEntityDescriptor : EntityDescriptor - where T : NodeWithID, new() - where U : NodeWithID, new() - where V : NodeWithID, new() - { - static GenericEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] - { - new NodeBuilder(), - new NodeBuilder(), - new NodeBuilder() - }; - } - public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) - {} - - static readonly INodeBuilder[] _nodesToBuild; - } - - public class GenericEntityDescriptor : EntityDescriptor - where T : NodeWithID, new() - where U : NodeWithID, new() - where V : NodeWithID, new() - where W : NodeWithID, new() - { - static GenericEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] - { - new NodeBuilder(), - new NodeBuilder(), - new NodeBuilder(), - new NodeBuilder() - }; - } - public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) - {} - - static readonly INodeBuilder[] _nodesToBuild; - } - - public class GenericEntityDescriptor : EntityDescriptor - where T : NodeWithID, new() - where U : NodeWithID, new() - where V : NodeWithID, new() - where W : NodeWithID, new() - where X : NodeWithID, new() - { - static GenericEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] - { - new NodeBuilder(), - new NodeBuilder(), - new NodeBuilder(), - new NodeBuilder(), - new NodeBuilder() - }; - } - public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) - {} - - static readonly INodeBuilder[] _nodesToBuild; - } - - public class GenericEntityDescriptor : EntityDescriptor - where T : NodeWithID, new() - where U : NodeWithID, new() - where V : NodeWithID, new() - where W : NodeWithID, new() - where X : NodeWithID, new() - where Y : NodeWithID, new() - { - static GenericEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] - { - new NodeBuilder(), - new NodeBuilder(), - new NodeBuilder(), - new NodeBuilder(), - new NodeBuilder(), - new NodeBuilder() - }; - } - public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) - {} - - static readonly INodeBuilder[] _nodesToBuild; - } - - public class GenericMixedEntityDescriptor : EntityDescriptor - where T : INodeBuilder, new() - { - static GenericMixedEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] - { - new T(), - }; - } - public GenericMixedEntityDescriptor(params object[] componentsImplementor) : - base(_nodesToBuild, componentsImplementor) - { } - - static readonly INodeBuilder[] _nodesToBuild; - } - - public class GenericMixedEntityDescriptor : EntityDescriptor - where T : INodeBuilder, new() - where U : INodeBuilder, new() - where V : INodeBuilder, new() - { - static GenericMixedEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] - { - new T(), - new U(), - new V() - }; - } - public GenericMixedEntityDescriptor(params object[] componentsImplementor) : - base(_nodesToBuild, componentsImplementor) - { } - - static readonly INodeBuilder[] _nodesToBuild; - } - - public class GenericMixedEntityDescriptor : EntityDescriptor - where T : INodeBuilder, new() - where U : INodeBuilder, new() - where V : INodeBuilder, new() - where W : INodeBuilder, new() - { - static GenericMixedEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] - { - new T(), - new U(), - new V(), - new W() - }; - } - public GenericMixedEntityDescriptor(params object[] componentsImplementor) : - base(_nodesToBuild, componentsImplementor) - { } - - static readonly INodeBuilder[] _nodesToBuild; - } - - public class GenericMixedEntityDescriptor : EntityDescriptor - where T : INodeBuilder, new() - where U : INodeBuilder, new() - where V : INodeBuilder, new() - where W : INodeBuilder, new() - where X : INodeBuilder, new() - { - static GenericMixedEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] - { - new T(), - new U(), - new V(), - new W(), - new X() - }; - } - public GenericMixedEntityDescriptor(params object[] componentsImplementor) : - base(_nodesToBuild, componentsImplementor) - { } - - static readonly INodeBuilder[] _nodesToBuild; - } - - public class GenericMixedEntityDescriptor : EntityDescriptor - where T : INodeBuilder, new() - where U : INodeBuilder, new() - where V : INodeBuilder, new() - where W : INodeBuilder, new() - where X : INodeBuilder, new() - where Y : INodeBuilder, new() - { - static GenericMixedEntityDescriptor() - { - _nodesToBuild = new INodeBuilder[] - { - new T(), - new U(), - new V(), - new W(), - new X(), - new Y() - }; - } - public GenericMixedEntityDescriptor(params object[] componentsImplementor) : - base(_nodesToBuild, componentsImplementor) - { } - - static readonly INodeBuilder[] _nodesToBuild; - } -} diff --git a/ECS/GenericEntityDescriptorHolder.cs b/ECS/GenericEntityDescriptorHolder.cs deleted file mode 100644 index 4e51570..0000000 --- a/ECS/GenericEntityDescriptorHolder.cs +++ /dev/null @@ -1,30 +0,0 @@ -#if UNITY_5 || UNITY_5_3_OR_NEWER -using System; - -namespace Svelto.ECS -{ - public class GenericEntityDescriptorHolder: UnityEngine.MonoBehaviour, IEntityDescriptorHolder where T:EntityDescriptor - { - public EntityDescriptor BuildDescriptorType(object[] externalImplentors) - { - I[] implementors; - - if (externalImplentors != null) - { - I[] baseImplentors = gameObject.GetComponents(); - - implementors = new I[externalImplentors.Length + baseImplentors.Length]; - - Array.Copy(baseImplentors, implementors, baseImplentors.Length); - Array.Copy(externalImplentors, 0, implementors, baseImplentors.Length, externalImplentors.Length); - } - else - { - implementors = gameObject.GetComponents(); - } - - return (T)Activator.CreateInstance(typeof(T), implementors); - } - } -} -#endif \ No newline at end of file diff --git a/ECS/ICallBackOnAddEngine.cs b/ECS/ICallBackOnAddEngine.cs deleted file mode 100644 index e77bf6a..0000000 --- a/ECS/ICallBackOnAddEngine.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Svelto.ECS -{ - public interface ICallBackOnAddEngine - { - void Ready(); - } -} diff --git a/ECS/IEngine.cs b/ECS/IEngine.cs deleted file mode 100644 index d811e9a..0000000 --- a/ECS/IEngine.cs +++ /dev/null @@ -1,62 +0,0 @@ -using Svelto.ECS.Internal; - -namespace Svelto.ECS.Internal -{ - public interface IStructNodeEngine : IEngine - { - void CreateStructNodes(SharedStructNodeLists sharedStructNodeLists); - } - - public interface IGroupedStructNodesEngine : IEngine - { - void CreateStructNodes(SharedGroupedStructNodesLists sharedStructNodeLists); - } - - public interface IActivableNodeEngine : IEngine - { - void Enable(INode obj); - void Disable(INode obj); - } - - public interface INodeEngine : IEngine - { - void Add(INode obj); - void Remove(INode obj); - } - - public interface INodesEngine : INodeEngine - { - System.Type[] AcceptedNodes(); - } -} - -namespace Svelto.ECS -{ - public interface IEngine - {} - - public interface IActivableNodeEngine : IActivableNodeEngine where TNodeType : INode - { } - - public interface IQueryableNodeEngine:IEngine - { - IEngineNodeDB nodesDB { set; } - } - - /// - /// The engines can receive and store INodes structs - /// Unboxing will happen during the Add, but the - /// data will then be stored and processed as stucts - /// - public interface IStructNodeEngine : IStructNodeEngine where T:struct, IStructNodeWithID - { } - - /// - /// same as above, but the nodes are grouped by ID - /// usually the ID is the owner of the nodes of that - /// group - /// - public interface IGroupedStructNodesEngine : IGroupedStructNodesEngine where T:struct, IGroupedStructNodeWithID - { } -} - diff --git a/ECS/IEngineNodeDB.cs b/ECS/IEngineNodeDB.cs deleted file mode 100644 index e2ee74f..0000000 --- a/ECS/IEngineNodeDB.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Svelto.DataStructures; - -namespace Svelto.ECS -{ - public interface IEngineNodeDB - { - ReadOnlyDictionary QueryIndexableNodes() where T:INode; - - bool TryQueryNode(int ID, out T node) where T:INode; - T QueryNode(int ID) where T:INode; - - FasterReadOnlyListCast QueryNodes() where T:INode; - - bool TryQueryMetaNode(int metaEntityID, out T node) where T : INode; - T QueryMetaNode(int metaEntityID) where T : INode; - FasterReadOnlyListCast QueryMetaNodes() where T : INode; - } -} - diff --git a/ECS/IEnginesRoot.cs b/ECS/IEnginesRoot.cs deleted file mode 100644 index 14f5957..0000000 --- a/ECS/IEnginesRoot.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Svelto.ECS -{ - public interface IEnginesRoot - { - void AddEngine(IEngine engine); - } - - public interface IEntityFactory - { - void BuildEntity(int ID, EntityDescriptor ED); - - void BuildMetaEntity(int metaEntityID, EntityDescriptor ED); - - void BuildEntityInGroup(int entityID, int groupID, EntityDescriptor ED); - } -} diff --git a/ECS/IEntityDescriptorHolder.cs b/ECS/IEntityDescriptorHolder.cs deleted file mode 100644 index 2c70278..0000000 --- a/ECS/IEntityDescriptorHolder.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Svelto.ECS -{ - /// - /// please use [DisallowMultipleComponent] in your monobehaviours that implement IEntityDescriptorHolder - /// - public interface IEntityDescriptorHolder - { - //I must find a nicer solution for the extraImplentors - EntityDescriptor BuildDescriptorType(object[] extraImplentors = null); - } -} diff --git a/ECS/INode.cs b/ECS/INode.cs deleted file mode 100644 index f9b0c81..0000000 --- a/ECS/INode.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Svelto.ECS -{ - public interface INode - {} - - public interface INodeWithID:INode - { - int ID { get; } - } - - public interface IStructNodeWithID : INode - { - int ID { get; set; } - } - - public interface IGroupedStructNodeWithID : IStructNodeWithID - { - int groupID { get; set; } - } - - public class NodeWithID: INodeWithID - { - public static TNodeType BuildNode(int ID) where TNodeType: NodeWithID, new() - { - return new TNodeType { _ID = ID }; - } - - public int ID { get { return _ID; } } - - protected int _ID; - } -} diff --git a/ECS/IRemoveEntityComponent.cs b/ECS/IRemoveEntityComponent.cs deleted file mode 100644 index 5a3ee3b..0000000 --- a/ECS/IRemoveEntityComponent.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -namespace Svelto.ECS -{ - public interface IRemoveEntityComponent - { - Action removeEntity { get; set; } - } - - public interface IDisableEntityComponent - { - Action disableEntity { get; set; } - } - - public interface IEnableEntityComponent - { - Action enableEntity { get; set; } - } -} diff --git a/ECS/MultiNodesEngine.cs b/ECS/MultiNodesEngine.cs deleted file mode 100644 index 2907917..0000000 --- a/ECS/MultiNodesEngine.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Svelto.ECS.Internal; - -namespace Svelto.ECS.Internal -{ - public abstract class MultiNodesEngine - where T : INode - { - protected abstract void AddNode(T node); - protected abstract void RemoveNode(T node); - } -} - -namespace Svelto.ECS -{ - public abstract class MultiNodesEngine : INodesEngine - { - public abstract System.Type[] AcceptedNodes(); - - public abstract void Add(INode node); - public abstract void Remove(INode node); - } - - public abstract class MultiNodesEngine : MultiNodesEngine, - INodeEngine - where T : INode - where U : INode - { - protected abstract void AddNode(U node); - protected abstract void RemoveNode(U node); - - public void Add(INode node) - { - if (node is T) - AddNode((T)node); - else - AddNode((U)node); - } - - public void Remove(INode node) - { - if (node is T) - RemoveNode((T)node); - else - RemoveNode((U)node); - } - } -} \ No newline at end of file diff --git a/ECS/NodeSubmissionScheduler.cs b/ECS/NodeSubmissionScheduler.cs deleted file mode 100644 index dc86bf2..0000000 --- a/ECS/NodeSubmissionScheduler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Svelto.ECS.NodeSchedulers -{ - public abstract class NodeSubmissionScheduler - { - abstract public void Schedule(Action submitNodes); - } -} \ No newline at end of file diff --git a/ECS/SingleNodeEngine.cs b/ECS/SingleNodeEngine.cs deleted file mode 100644 index f4c58a1..0000000 --- a/ECS/SingleNodeEngine.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Svelto.ECS.Internal; - -namespace Svelto.ECS -{ - public abstract class SingleNodeEngine : INodeEngine - where TNodeType : INode - { - public void Add(INode obj) - { - Add((TNodeType) obj); - } - - public void Remove(INode obj) - { - Remove((TNodeType) obj); - } - - protected abstract void Add(TNodeType node); - protected abstract void Remove(TNodeType node); - } -} diff --git a/ECS/StructNodes.cs b/ECS/StructNodes.cs deleted file mode 100644 index 85ca30d..0000000 --- a/ECS/StructNodes.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Collections.Generic; -using Svelto.DataStructures; -using Svelto.ECS.Internal; - -namespace Svelto.ECS -{ - public class StructNodes where T:struct, IStructNodeWithID - { - public T[] GetList(out int numberOfItems) - { - numberOfItems = _internalList.Count; - return _internalList.ToArrayFast(); - } - - public StructNodes(SharedStructNodeLists container) - { - _internalList = container.GetList(); - } - - public void Add(T node) - { - T convert = (T)node; - - _internalList.Add(convert); - } - - readonly FasterList _internalList; - } - - public class StructGroupNodes - where T : struct, IGroupedStructNodeWithID - { - public StructGroupNodes(SharedGroupedStructNodesLists container) - { - _container = container; - } - - public void Add(int groupID, T node) - { - T convert = (T)node; - - var fasterList = (_container.GetList(groupID) as FasterList); - indices[node.ID] = fasterList.Count; - - fasterList.Add(convert); - } - - public void Remove(int groupID, T node) - { - var fasterList = (_container.GetList(groupID) as FasterList); - var index = indices[node.ID]; - indices.Remove(node.ID); - - if (fasterList.UnorderedRemoveAt(index)) - indices[fasterList[index].ID] = index; - } - - public T[] GetList(int groupID, out int numberOfItems) - { - var fasterList = (_container.GetList(groupID) as FasterList); - numberOfItems = fasterList.Count; - return fasterList.ToArrayFast(); - } - - readonly SharedGroupedStructNodesLists _container; - readonly Dictionary indices = new Dictionary(); - } - - public class SharedStructNodeLists - { - readonly Dictionary _collection; - - internal SharedStructNodeLists() - { - _collection = new Dictionary(); - } - - internal FasterList GetList() where T:struct - { - IFasterList list; - if (_collection.TryGetValue(typeof (T), out list)) - { - return list as FasterList; - } - - list = new FasterList(); - - _collection.Add(typeof (T), list); - - return (FasterList) list; - } - } - - public class SharedGroupedStructNodesLists - { - internal SharedGroupedStructNodesLists() - { - _collection = new Dictionary>(); - } - - internal IFasterList GetList(int groupID) where T : struct - { - Dictionary dic = GetGroup(); - IFasterList localList; - - if (dic.TryGetValue(groupID, out localList)) - return localList; - - localList = new FasterList(); - dic.Add(groupID, localList); - - return localList; - } - - internal Dictionary GetGroup() where T : struct - { - Dictionary dic; - - if (_collection.TryGetValue(typeof(T), out dic)) - { - return dic; - } - - dic = new Dictionary(); - - _collection.Add(typeof(T), dic); - - return dic; - } - - readonly Dictionary> _collection; - } -} \ No newline at end of file diff --git a/ECS/note.txt b/ECS/note.txt deleted file mode 100644 index c041193..0000000 --- a/ECS/note.txt +++ /dev/null @@ -1,111 +0,0 @@ -systems do not hold component data, but only system states -systems cannot be injected -systems are SRP and OCP -systems communicates between component, mediators, producer/consumer, observers. producer/consumer and observers must be defined in the layer of the engine. -systems can have injected dependencies - -components don't have logic -components can have only getter and setter -components cannot define patterns that requires logic. -components cannot issues commands - -High Cohesion[edit] -Main article: Cohesion (computer science) -High Cohesion is an evaluative pattern that attempts to keep objects appropriately focused, manageable and understandable. High cohesion is generally used in support of Low Coupling. High cohesion means that the responsibilities of a given element are strongly related and highly focused. Breaking programs into classes and subsystems is an example of activities that increase the cohesive properties of a system. Alternatively, low cohesion is a situation in which a given element has too many unrelated responsibilities. Elements with low cohesion often suffer from being hard to comprehend, hard to reuse, hard to maintain and averse to change.[3] - -Low Coupling[edit] -Main article: Loose coupling -Low Coupling is an evaluative pattern, which dictates how to assign responsibilities to support: - -lower dependency between the classes, -change in one class having lower impact on other classes, -higher reuse potential. - -events, observers and mediators have the inconvience to hold the reference to the engine, which forces to use cleanup if the engine must be removed. -Observers are easy to clean up from the engine. Mediators needs to be integrated to the framework to be simple to clean up. Component events need the clean up function. -producer/consumer has the inconvienent to force check the number of jobs available everyframe - -Engine can't be removed, they can only be disabled, but the logic of disabling must be handled by the engine itself - -Should components have just one element? Should engines use just nodes? Components are ditacted by the entities and Nodes by the engines - -http://thelinuxlich.github.io/artemis_CSharp/ - -differences: components no events, everthing must be update -give more responsabiltiy to the user, semplicity - -https://github.com/sschmid/Entitas-CSharp/wiki/Overview - -no groups, no queries - -http://entity-systems.wikidot.com/es-articles - -http://www.ashframework.org/ - -it's very important to give a namespace to the engines. In this way it's impossible to create semantically wrong nodes (PlayerNode Vs TargetNode) - -ToDo: - -it's not safe to remove an engine without having called being denitialised internal states. A special ClearOnRemove function must be added for each engine - -namespace GameFramework.RayCast -{ - public class RayCastEngineEngine - { - public RayCastEngine(RayCastEmployer jobList) - { - jobList.onJobassigned += OnRaycastRequested; - } - - public void Add(IComponent obj) - {} - - public void Remove(IComponent obj) - {} - - void OnRaycastRequested(RayCastJob job) - { - RaycastHit shootHit; - - Physics.Raycast(job.rayVector, out shootHit, job.range, _enemyMask); - - job.Done(shootHit); - } - - RayCastEmployer _employer; - - int _enemyMask; - } - - public struct RayCastJob - { - readonly public Ray rayVector; - readonly public float range; - readonly public Action Done; - - public RayCastJob(Ray direction, float distance, Action OnDone) - { - rayVector = direction; - range = distance; - Done = OnDone; - } - } - - public class RayCastEmployer - { - public event Action onJobassigned; - - public void AssignJob(RayCastJob data, Action onJobdone) - { - onJobassigned(data); - } - } -} - -if your code can be read as - -A tells B to do something is direct -A register B event is indirect -althoggh if B tells A something through event is direct again. B must say something like I don't know who you are, but this just happened. you say B.SomethingHappenedToMe() not B.YouMustDoThis(); - -un engine non deve mai avere concetti di un altro engine. dire all'engine sonoro suona morte � sbagliato. � l'engine death che triggera l'evento e l'engine sound ad ascoltarlo. diff --git a/Svelto.Common b/Svelto.Common new file mode 160000 index 0000000..b8c8bff --- /dev/null +++ b/Svelto.Common @@ -0,0 +1 @@ +Subproject commit b8c8bffd9290adf39609d30865fd73567923bb54 diff --git a/Svelto.ECS.csproj b/Svelto.ECS.csproj new file mode 100644 index 0000000..c06df04 --- /dev/null +++ b/Svelto.ECS.csproj @@ -0,0 +1,23 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.0.0\ref\netcoreapp2.0\System.Reflection.Emit.Lightweight.dll + + + + diff --git a/Svelto.ECS/.gitignore b/Svelto.ECS/.gitignore new file mode 100644 index 0000000..ac529bb --- /dev/null +++ b/Svelto.ECS/.gitignore @@ -0,0 +1,4 @@ +/EntitySystem/note.txt +/EntitySystem/note.txt.meta +/*.meta +*.meta diff --git a/Context/ContextNotifier.cs b/Svelto.ECS/Context/ContextNotifier.cs similarity index 100% rename from Context/ContextNotifier.cs rename to Svelto.ECS/Context/ContextNotifier.cs diff --git a/Context/Factories/GameObjectFactory.cs b/Svelto.ECS/Context/Factories/GameObjectFactory.cs similarity index 100% rename from Context/Factories/GameObjectFactory.cs rename to Svelto.ECS/Context/Factories/GameObjectFactory.cs diff --git a/Context/Factories/MonoBehaviourFactory.cs b/Svelto.ECS/Context/Factories/MonoBehaviourFactory.cs similarity index 91% rename from Context/Factories/MonoBehaviourFactory.cs rename to Svelto.ECS/Context/Factories/MonoBehaviourFactory.cs index 7f862ab..bd376b6 100644 --- a/Context/Factories/MonoBehaviourFactory.cs +++ b/Svelto.ECS/Context/Factories/MonoBehaviourFactory.cs @@ -2,7 +2,6 @@ #region using System; -using Svelto.DataStructures; using UnityEngine; #endregion diff --git a/Context/ICompositionRoot.cs b/Svelto.ECS/Context/ICompositionRoot.cs similarity index 100% rename from Context/ICompositionRoot.cs rename to Svelto.ECS/Context/ICompositionRoot.cs diff --git a/Context/IContextNotifer.cs b/Svelto.ECS/Context/IContextNotifer.cs similarity index 100% rename from Context/IContextNotifer.cs rename to Svelto.ECS/Context/IContextNotifer.cs diff --git a/Svelto.ECS/Context/IUnityCompositionRoot.cs b/Svelto.ECS/Context/IUnityCompositionRoot.cs new file mode 100644 index 0000000..c4db99a --- /dev/null +++ b/Svelto.ECS/Context/IUnityCompositionRoot.cs @@ -0,0 +1,11 @@ +#if UNITY_5 || UNITY_5_3_OR_NEWER +namespace Svelto.Context +{ + public interface IUnityCompositionRoot + { + void OnContextCreated(UnityContext contextHolder); + void OnContextInitialized(); + void OnContextDestroyed(); + } +} +#endif \ No newline at end of file diff --git a/Context/IWaitForFrameworkDestruction.cs b/Svelto.ECS/Context/IWaitForFrameworkDestruction.cs similarity index 88% rename from Context/IWaitForFrameworkDestruction.cs rename to Svelto.ECS/Context/IWaitForFrameworkDestruction.cs index 622fa3e..e830787 100644 --- a/Context/IWaitForFrameworkDestruction.cs +++ b/Svelto.ECS/Context/IWaitForFrameworkDestruction.cs @@ -1,5 +1,3 @@ -using System; - namespace Svelto.Context { public interface IWaitForFrameworkDestruction diff --git a/Context/IWaitForFrameworkInitialization.cs b/Svelto.ECS/Context/IWaitForFrameworkInitialization.cs similarity index 88% rename from Context/IWaitForFrameworkInitialization.cs rename to Svelto.ECS/Context/IWaitForFrameworkInitialization.cs index 937cbbc..f1b8dfb 100644 --- a/Context/IWaitForFrameworkInitialization.cs +++ b/Svelto.ECS/Context/IWaitForFrameworkInitialization.cs @@ -1,5 +1,3 @@ -using System; - namespace Svelto.Context { public interface IWaitForFrameworkInitialization diff --git a/Context/UnityContext.cs b/Svelto.ECS/Context/UnityContext.cs similarity index 76% rename from Context/UnityContext.cs rename to Svelto.ECS/Context/UnityContext.cs index 9591861..925a147 100644 --- a/Context/UnityContext.cs +++ b/Svelto.ECS/Context/UnityContext.cs @@ -13,6 +13,11 @@ public abstract class UnityContext:MonoBehaviour } } +//a Unity context is a platform specific context wrapper. +//Unity will drive the ICompositionRoot interface. +//OnContextCreated is called during the Awake of this MB +//OnContextInitialized is called one frame after the MB started +//OnContextDestroyed is called when the MB is destroyed public class UnityContext: UnityContext where T:class, ICompositionRoot, new() { protected override void OnAwake() diff --git a/Svelto.ECS/ECS/DataStructures/TypeSafeDictionary.cs b/Svelto.ECS/ECS/DataStructures/TypeSafeDictionary.cs new file mode 100644 index 0000000..c7cdc14 --- /dev/null +++ b/Svelto.ECS/ECS/DataStructures/TypeSafeDictionary.cs @@ -0,0 +1,51 @@ +using Svelto.DataStructures; +using System.Collections.Generic; + +namespace Svelto.ECS.Internal +{ + /// + /// This is just a place holder at the moment + /// I always wanted to create my own Dictionary + /// data structure as excercise, but never had the + /// time to. At the moment I need the custom interface + /// wrapped though. + /// + + public interface ITypeSafeDictionary + { + void FillWithIndexedEntityViews(ITypeSafeList entityViews); + bool Remove(int entityId); + IEntityView GetIndexedEntityView(int entityID); + } + + class TypeSafeDictionary : Dictionary, ITypeSafeDictionary where TValue:IEntityView + { + internal static readonly ReadOnlyDictionary Default = + new ReadOnlyDictionary(new Dictionary()); + + public void FillWithIndexedEntityViews(ITypeSafeList entityViews) + { + int count; + var buffer = FasterList.NoVirt.ToArrayFast((FasterList) entityViews, out count); + + for (int i = 0; i < count; i++) + { + var entityView = buffer[i]; + + Add(entityView.ID, entityView); + } + } + + new public bool Remove(int entityId) + { + base.Remove(entityId); + + return this.Count > 0; + } + + public IEntityView GetIndexedEntityView(int entityID) + { + return this[entityID]; + } + } +} diff --git a/Svelto.ECS/ECS/DataStructures/TypeSafeFasterListForECS.cs b/Svelto.ECS/ECS/DataStructures/TypeSafeFasterListForECS.cs new file mode 100644 index 0000000..17235f2 --- /dev/null +++ b/Svelto.ECS/ECS/DataStructures/TypeSafeFasterListForECS.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Svelto.DataStructures; + +namespace Svelto.ECS.Internal +{ + public interface ITypeSafeList: IEnumerable + { + void AddRange(ITypeSafeList entityViewListValue); + + ITypeSafeList Create(); + bool isQueryiableEntityView { get; } + bool UnorderedRemove(int entityID); + ITypeSafeDictionary CreateIndexedDictionary(); + IEntityView[] ToArrayFast(out int count); + void ReserveCapacity(int capacity); + } + + class TypeSafeFasterListForECS: FasterList where T:IEntityView + { + protected TypeSafeFasterListForECS() + { + _mappedIndices = new Dictionary(); + } + + protected TypeSafeFasterListForECS(int size):base(size) + { + _mappedIndices = new Dictionary(); + } + + public bool UnorderedRemove(int entityID) + { + var index = _mappedIndices[entityID]; + + DesignByContract.Check.Assert(entityID == this[index].ID, "Something went wrong with the Svelto.ECS code, please contact the author"); + + _mappedIndices.Remove(entityID); + + if (UnorderedRemoveAt(index)) + _mappedIndices[this[index].ID] = index; + + return this.Count > 0; + } + + public void AddRange(ITypeSafeList entityViewListValue) + { + var index = this.Count; + + base.AddRange(entityViewListValue as FasterList); + + for (int i = index; i < Count; ++i) + _mappedIndices[this[i].ID] = i; + } + + new public void Add(T entityView) + { + var index = this.Count; + + base.Add(entityView); + + _mappedIndices[entityView.ID] = index; + } + + public void ReserveCapacity(int capacity) + { + if (this.ToArrayFast().Length < capacity) + Resize(capacity); + } + + public int GetIndexFromID(int entityID) + { + return _mappedIndices[entityID]; + } + + readonly Dictionary _mappedIndices; + } + + class TypeSafeFasterListForECSForStructs : TypeSafeFasterListForECS, ITypeSafeList where T:struct, IEntityStruct + { + public TypeSafeFasterListForECSForStructs(int size):base(size) + {} + + public TypeSafeFasterListForECSForStructs() + {} + + public ITypeSafeList Create() + { + return new TypeSafeFasterListForECSForStructs(); + } + + public bool isQueryiableEntityView + { + get { return false; } + } + + public ITypeSafeDictionary CreateIndexedDictionary() + { + throw new Exception("Not Allowed"); + } + + public IEntityView[] ToArrayFast(out int count) + { + throw new Exception("Not Allowed"); + } + + public ITypeSafeList Create(int size) + { + return new TypeSafeFasterListForECSForStructs(size); + } + } + + class TypeSafeFasterListForECSForClasses : TypeSafeFasterListForECS, ITypeSafeList where T:EntityView, new() + { + public TypeSafeFasterListForECSForClasses(int size):base(size) + {} + + public TypeSafeFasterListForECSForClasses() + {} + + public ITypeSafeList Create() + { + return new TypeSafeFasterListForECSForClasses(); + } + + public bool isQueryiableEntityView + { + get { return true; } + } + + public ITypeSafeDictionary CreateIndexedDictionary() + { + return new TypeSafeDictionary(); + } + + public IEntityView[] ToArrayFast(out int count) + { + count = this.Count; + + return this.ToArrayFast(); + } + + public ITypeSafeList Create(int size) + { + return new TypeSafeFasterListForECSForClasses(size); + } + } +} diff --git a/ECS/Dispatcher/DispatchOnChange.cs b/Svelto.ECS/ECS/Dispatcher/DispatchOnChange.cs similarity index 100% rename from ECS/Dispatcher/DispatchOnChange.cs rename to Svelto.ECS/ECS/Dispatcher/DispatchOnChange.cs diff --git a/ECS/Dispatcher/DispatcherOnSet.cs b/Svelto.ECS/ECS/Dispatcher/DispatcherOnSet.cs similarity index 100% rename from ECS/Dispatcher/DispatcherOnSet.cs rename to Svelto.ECS/ECS/Dispatcher/DispatcherOnSet.cs diff --git a/Svelto.ECS/ECS/EnginesRootEngines.cs b/Svelto.ECS/ECS/EnginesRootEngines.cs new file mode 100644 index 0000000..e8b557d --- /dev/null +++ b/Svelto.ECS/ECS/EnginesRootEngines.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Svelto.DataStructures; +using Svelto.ECS.Internal; +using Svelto.ECS.Schedulers; +using Svelto.WeakEvents; + +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR +using Svelto.ECS.Profiler; +#endif + +namespace Svelto.ECS +{ + public partial class EnginesRoot : IDisposable + { +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR + /// + /// I still need to find a good solution for this. Need to move somewhere else + /// + static EnginesRoot() + { + UnityEngine.GameObject debugEngineObject = new UnityEngine.GameObject("Svelto.ECS.Profiler"); + debugEngineObject.gameObject.AddComponent(); + UnityEngine.GameObject.DontDestroyOnLoad(debugEngineObject); + } +#endif + /// + /// Engines root contextualize your engines and entities. You don't need to limit yourself to one EngineRoot + /// as multiple engines root could promote separation of scopes. The EntitySubmissionScheduler checks + /// periodically if new entity must be submited to the database and the engines. It's an external + /// dependencies to be indipendent by the running platform as the user can define it. + /// The EntitySubmissionScheduler cannot hold an EnginesRoot reference, that's why + /// it must receive a weak reference of the EnginesRoot callback. + /// + public EnginesRoot(EntitySubmissionScheduler entityViewScheduler) + { + _entityViewEngines = new Dictionary>(); + _otherEngines = new FasterList(); + + _entityViewsDB = new Dictionary(); + _metaEntityViewsDB = new Dictionary(); + _groupEntityViewsDB = new Dictionary>(); + _entityViewsDBDic = new Dictionary(); + + _entityViewsToAdd = new DoubleBufferedEntityViews>(); + _metaEntityViewsToAdd = new DoubleBufferedEntityViews>(); + _groupedEntityViewsToAdd = new DoubleBufferedEntityViews>>(); + + _DB = new EntityViewsDB(_entityViewsDB, _entityViewsDBDic, _metaEntityViewsDB, _groupEntityViewsDB); + + _scheduler = entityViewScheduler; + _scheduler.Schedule(new WeakAction(SubmitEntityViews)); + } + + public void AddEngine(IEngine engine) + { +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR + Profiler.EngineProfiler.AddEngine(engine); +#endif + var viewEngine = engine as IHandleEntityViewEngine; + + if (viewEngine != null) + CheckEntityViewsEngine(viewEngine); + else + _otherEngines.Add(engine); + + var queryableEntityViewEngine = engine as IQueryingEntityViewEngine; + if (queryableEntityViewEngine != null) + { + queryableEntityViewEngine.entityViewsDB = _DB; + queryableEntityViewEngine.Ready(); + } + } + + void CheckEntityViewsEngine(IEngine engine) + { + var baseType = engine.GetType().GetBaseType(); + + while (baseType != _object) + { + if (baseType.IsGenericTypeEx()) + { + var genericArguments = baseType.GetGenericArgumentsEx(); + AddEngine(engine as IHandleEntityViewEngine, genericArguments, _entityViewEngines); + + return; + } + + baseType = baseType.GetBaseType(); + } + + throw new ArgumentException("Not Supported Engine " + engine.ToString()); + } + + //The T parameter allows to pass datastructure sthat not necessarly are + //defined with IEngine, but must be defined with IEngine implementations + static void AddEngine(T engine, Type[] entityViewTypes, + Dictionary> engines) where T:IEngine + { + for (int i = 0; i < entityViewTypes.Length; i++) + { + var type = entityViewTypes[i]; + + AddEngine(engine, engines, type); + } + } + + static void AddEngine(T engine, Dictionary> engines, Type type) where T : IEngine + { + FasterList list; + if (engines.TryGetValue(type, out list) == false) + { + list = new FasterList(); + + engines.Add(type, list); + } + + list.Add(engine); + } + + readonly Dictionary> _entityViewEngines; + readonly FasterList _otherEngines; + + static readonly Type _entityViewType= typeof(EntityView); + static readonly Type _object = typeof(object); + + class DoubleBufferedEntityViews where T : class, IDictionary, new() + { + readonly T _entityViewsToAddBufferA = new T(); + readonly T _entityViewsToAddBufferB = new T(); + + internal DoubleBufferedEntityViews() + { + this.other = _entityViewsToAddBufferA; + this.current = _entityViewsToAddBufferB; + } + + internal T other; + internal T current; + + internal void Swap() + { + var toSwap = other; + other = current; + current = toSwap; + } + } + } +} \ No newline at end of file diff --git a/Svelto.ECS/ECS/EnginesRootEntities.cs b/Svelto.ECS/ECS/EnginesRootEntities.cs new file mode 100644 index 0000000..fea2823 --- /dev/null +++ b/Svelto.ECS/ECS/EnginesRootEntities.cs @@ -0,0 +1,411 @@ +using System; +using System.Collections.Generic; +using Svelto.DataStructures; +using Svelto.ECS.Internal; + +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR +using Svelto.ECS.Profiler; +#endif + +namespace Svelto.ECS +{ + public partial class EnginesRoot : IDisposable + { + /// + /// an EnginesRoot reference cannot be held by anything else than the Composition Root + /// where it has been created. IEntityFactory and IEntityFunctions allow a weakreference + /// of the EnginesRoot to be passed around. + /// + /// + public IEntityFactory GenerateEntityFactory() + { + return new GenericEntityFactory(new DataStructures.WeakReference(this)); + } + + public IEntityFunctions GenerateEntityFunctions() + { + return new GenericEntityFunctions(new DataStructures.WeakReference(this)); + } + + /// + /// The EntityDescriptor doesn't need to be ever instantiated. It just describes the Entity + /// itself in terms of EntityViews to build. The Implementors are passed to fill the + /// references of the EntityViews components. Please read the articles on my blog + /// to understand better the terminologies + /// + /// + /// + /// + void BuildEntity(int entityID, object[] implementors = null) where T : IEntityDescriptor, new() + { + EntityFactory.BuildEntityViews + (entityID, _entityViewsToAdd.current, EntityDescriptorTemplate.Default, implementors); + } + + /// + /// When the type of the entity is not known (this is a special case!) an EntityDescriptorInfo + /// can be built in place of the generic parameter T. + /// + /// + /// + /// + void BuildEntity(int entityID, IEntityDescriptorInfo entityDescriptor, object[] implementors) + { + EntityFactory.BuildEntityViews + (entityID, _entityViewsToAdd.current, entityDescriptor, implementors); + } + + /// + /// A meta entity is a way to manage a set of entitites that are not easily + /// queriable otherwise. For example you may want to group existing entities + /// by size and type and then use the meta entity entityView to manage the data + /// shared among the single entities of the same type and size. This will + /// prevent the scenario where the coder is forced to parse all the entities to + /// find the ones of the same size and type. + /// Since the entities are managed through the shared entityView, the same + /// shared entityView must be found on the single entities of the same type and size. + /// The shared entityView of the meta entity is then used by engines that are meant + /// to manage a group of entities through a single entityView. + /// The same engine can manage several meta entities entityViews too. + /// The Engine manages the logic of the Meta EntityView data and other engines + /// can read back this data through the normal entity as the shared entityView + /// will be present in their descriptor too. + /// It's a way to control a group of Entities through a entityView only. + /// This set of entities can share exactly the same entityView reference if + /// built through this function. In this way, if you need to set a variable + /// on a group of entities, instead to inject N entityViews and iterate over + /// them to set the same value, you can inject just one entityView, set the value + /// and be sure that the value is shared between entities. + /// + /// + /// + /// + void BuildMetaEntity(int metaEntityID, object[] implementors) where T : IEntityDescriptor, new() + { + EntityFactory.BuildEntityViews(metaEntityID, _metaEntityViewsToAdd.current, + EntityDescriptorTemplate.Default, implementors); + } + + /// + /// Using this function is like building a normal entity, but the entityViews + /// are grouped by groupID to be more efficently processed inside engines and + /// improve cache locality. Either class entityViews and struct entityViews can be + /// grouped. + /// + /// + /// + /// + /// + void BuildEntityInGroup(int entityID, int groupID, object[] implementors = null) where T : IEntityDescriptor, new() + { + EntityFactory.BuildGroupedEntityViews(entityID, groupID, + _groupedEntityViewsToAdd.current, + EntityDescriptorTemplate.Default, + implementors); + } + + void BuildEntityInGroup(int entityID, int groupID, IEntityDescriptorInfo entityDescriptor, object[] implementors = null) + { + EntityFactory.BuildGroupedEntityViews(entityID, groupID, + _groupedEntityViewsToAdd.current, + entityDescriptor, implementors); + } + + void Preallocate(int size) where T : IEntityDescriptor, new() + { + var entityViewsToBuild = ((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild; + int count = entityViewsToBuild.Length; + + for (int index = 0; index < count; index++) + { + var entityViewBuilder = entityViewsToBuild[index]; + var entityViewType = entityViewBuilder.GetEntityViewType(); + + ITypeSafeList dbList; + if (_entityViewsDB.TryGetValue(entityViewType, out dbList) == false) + _entityViewsDB[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size); + else + dbList.ReserveCapacity(size); + + if (_entityViewsToAdd.current.TryGetValue(entityViewType, out dbList) == false) + _entityViewsToAdd.current[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size); + else + dbList.ReserveCapacity(size); + } + } + + void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo) + { + var removeEntityImplementor = removeInfo as RemoveEntityImplementor; + + if (removeEntityImplementor.isInAGroup) + InternalRemove(removeEntityImplementor.removeEntityInfo.entityViewsToBuild, entityID, removeEntityImplementor.groupID, _entityViewsDB); + else + InternalRemoveFromDBAndEngines(removeEntityImplementor.removeEntityInfo.entityViewsToBuild, entityID, _entityViewsDB); + } + + void RemoveEntity(int entityID) where T : IEntityDescriptor, new() + { + InternalRemoveFromDBAndEngines( ((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild, entityID, _entityViewsDB); + } + + void RemoveMetaEntity(int metaEntityID) where T : IEntityDescriptor, new() + { + InternalRemoveFromDBAndEngines(((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild, metaEntityID, _metaEntityViewsDB); + } + + void RemoveEntityFromGroup(int entityID, int groupID) where T : IEntityDescriptor, new() + { + InternalRemoveFromDBAndEngines(((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild, entityID, _groupEntityViewsDB[groupID]); + } + + void RemoveEntitiesGroup(int groupID) + { + foreach (var group in _groupEntityViewsDB[groupID]) + { + var entityViewType = group.Key; + + int count; + var entities = group.Value.ToArrayFast(out count); + + for (int i = 0; i < count; i++) + { + var entityID = entities[i].ID; + + InternalRemoveEntityViewFromDBAndEngines(_entityViewsDB, entityViewType, entityID); + } + } + + _groupEntityViewsDB.Remove(groupID); + } + + void InternalRemoveEntityViewFromDBAndEngines(Dictionary entityViewsDB, + Type entityViewType, int entityID) + { + var entityViews = entityViewsDB[entityViewType]; + if (entityViews.UnorderedRemove(entityID) == false) + entityViewsDB.Remove(entityViewType); + + if (entityViews.isQueryiableEntityView) + { + var typeSafeDictionary = _entityViewsDBDic[entityViewType]; + var entityView = typeSafeDictionary.GetIndexedEntityView(entityID); + + if (typeSafeDictionary.Remove(entityID) == false) + _entityViewsDBDic.Remove(entityViewType); + + for (var current = entityViewType; current != _entityViewType; current = current.BaseType) + RemoveEntityViewFromEngines(_entityViewEngines, entityView, current); + } + } + + void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) where T : IEntityDescriptor, new() + { + DesignByContract.Check.Require(fromGroupID != toGroupID, "can't move an entity to the same group where it already belongs to"); + + var entityViewBuilders = ((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild; + int entityViewBuildersCount = entityViewBuilders.Length; + + var dictionary = _groupEntityViewsDB[fromGroupID]; + + Dictionary groupedEntityViewsTyped; + if (_groupEntityViewsDB.TryGetValue(toGroupID, out groupedEntityViewsTyped) == false) + { + groupedEntityViewsTyped = new Dictionary(); + + _groupEntityViewsDB.Add(toGroupID, groupedEntityViewsTyped); + } + + for (int i = 0; i < entityViewBuildersCount; i++) + { + IEntityViewBuilder entityViewBuilder = entityViewBuilders[i]; + Type entityViewType = entityViewBuilder.GetEntityViewType(); + + ITypeSafeList fromSafeList = dictionary[entityViewType]; + ITypeSafeList toSafeList; + + if (groupedEntityViewsTyped.TryGetValue(entityViewType, out toSafeList) == false) + { + toSafeList = fromSafeList.Create(); + } + + entityViewBuilder.MoveEntityView(entityID, fromSafeList, toSafeList); + + if (fromSafeList.UnorderedRemove(entityID) == false) + dictionary.Remove(entityViewType); + } + + if (dictionary.Count == 0) _groupEntityViewsDB.Remove(fromGroupID); + } + + void InternalRemoveFromDBAndEngines(IEntityViewBuilder[] entityViewBuilders, int entityID, + Dictionary entityViewsDB) + { + int entityViewBuildersCount = entityViewBuilders.Length; + + for (int i = 0; i < entityViewBuildersCount; i++) + { + Type entityViewType = entityViewBuilders[i].GetEntityViewType(); + + InternalRemoveEntityViewFromDBAndEngines(entityViewsDB, entityViewType, entityID); + } + } + + void InternalRemove(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID, + Dictionary entityViewsDB) + { + InternalRemoveFromGroupDB(entityViewBuilders, entityID, groupID); + + InternalRemoveFromDBAndEngines(entityViewBuilders, entityID, entityViewsDB); + } + + void InternalRemoveFromGroupDB(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID) + { + int entityViewBuildersCount = entityViewBuilders.Length; + + Dictionary dictionary = _groupEntityViewsDB[groupID]; + + for (int i = 0; i < entityViewBuildersCount; i++) + { + Type entityViewType = entityViewBuilders[i].GetEntityViewType(); + + if (dictionary[entityViewType].UnorderedRemove(entityID) == false) + dictionary.Remove(entityViewType); + } + + if (dictionary.Count == 0) _groupEntityViewsDB.Remove(groupID); + } + + static void RemoveEntityViewFromEngines(Dictionary> entityViewEngines, + IEntityView entityView, Type entityViewType) + { + FasterList enginesForEntityView; + + if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView)) + { + int count; + var fastList = FasterList.NoVirt.ToArrayFast(enginesForEntityView, out count); + + for (int j = 0; j < count; j++) + { +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR + EngineProfiler.MonitorRemoveDuration(fastList[j], entityView); +#else + fastList[j].Remove(entityView); +#endif + } + } + } + + class GenericEntityFactory : IEntityFactory + { + DataStructures.WeakReference _weakEngine; + + public GenericEntityFactory(DataStructures.WeakReference weakReference) + { + _weakEngine = weakReference; + } + + public void BuildEntity(int entityID, object[] implementors = null) where T : IEntityDescriptor, new() + { + _weakEngine.Target.BuildEntity(entityID, implementors); + } + + public void BuildEntity(int entityID, IEntityDescriptorInfo entityDescriptor, object[] implementors = null) + { + _weakEngine.Target.BuildEntity(entityID, entityDescriptor, implementors); + } + + public void BuildMetaEntity(int metaEntityID, object[] implementors = null) where T : IEntityDescriptor, new() + { + _weakEngine.Target.BuildMetaEntity(metaEntityID, implementors); + } + + public void BuildEntityInGroup(int entityID, int groupID, object[] implementors = null) where T : IEntityDescriptor, new() + { + _weakEngine.Target.BuildEntityInGroup(entityID, groupID, implementors); + } + + public void BuildEntityInGroup(int entityID, int groupID, IEntityDescriptorInfo entityDescriptor, object[] implementors = null) + { + _weakEngine.Target.BuildEntityInGroup(entityID, groupID, entityDescriptor, implementors); + } + + public void Preallocate(int size) where T : IEntityDescriptor, new() + { + _weakEngine.Target.Preallocate(size); + } + } + + class GenericEntityFunctions : IEntityFunctions + { + public GenericEntityFunctions(DataStructures.WeakReference weakReference) + { + _weakReference = weakReference; + } + + public void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo) + { + _weakReference.Target.RemoveEntity(entityID, removeInfo); + } + + public void RemoveEntity(int entityID) where T : IEntityDescriptor, new() + { + _weakReference.Target.RemoveEntity(entityID); + } + + public void RemoveMetaEntity(int metaEntityID) where T : IEntityDescriptor, new() + { + _weakReference.Target.RemoveEntity(metaEntityID); + } + + public void RemoveEntityFromGroup(int entityID, int groupID) where T : IEntityDescriptor, new() + { + _weakReference.Target.RemoveEntity(entityID); + } + + public void RemoveGroupedEntities(int groupID) + { + _weakReference.Target.RemoveEntitiesGroup(groupID); + } + + public void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) where T : IEntityDescriptor, new() + { + _weakReference.Target.SwapEntityGroup(entityID, fromGroupID, toGroupID); + } + + readonly DataStructures.WeakReference _weakReference; + } + + public void Dispose() + { + foreach (var entity in _entityViewsDB) + { + if (entity.Value.isQueryiableEntityView == true) + { + foreach (var entityView in entity.Value) + { + RemoveEntityViewFromEngines(_entityViewEngines, entityView as EntityView, entity.Key); + } + } + } + + foreach (var entity in _metaEntityViewsDB) + { + foreach (var entityView in entity.Value) + { + RemoveEntityViewFromEngines(_entityViewEngines, entityView as EntityView, entity.Key); + } + } + } + + readonly EntityViewsDB _DB; + + readonly Dictionary _entityViewsDB; + readonly Dictionary _metaEntityViewsDB; + readonly Dictionary> _groupEntityViewsDB; + + readonly Dictionary _entityViewsDBDic; + + } +} \ No newline at end of file diff --git a/Svelto.ECS/ECS/EnginesRootSubmission.cs b/Svelto.ECS/ECS/EnginesRootSubmission.cs new file mode 100644 index 0000000..c2343b9 --- /dev/null +++ b/Svelto.ECS/ECS/EnginesRootSubmission.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using Svelto.DataStructures; +using Svelto.ECS.Internal; +using Svelto.ECS.Schedulers; + +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR +using Svelto.ECS.Profiler; +#endif + +namespace Svelto.ECS +{ + public partial class EnginesRoot : IDisposable + { + void SubmitEntityViews() + { + bool newEntityViewsHaveBeenAddedWhileIterating = + _metaEntityViewsToAdd.current.Count > 0 + || _entityViewsToAdd.current.Count > 0 + || _groupedEntityViewsToAdd.current.Count > 0; + + int numberOfReenteringLoops = 0; + + while (newEntityViewsHaveBeenAddedWhileIterating) + { + //use other as source from now on + //current will be use to write new entityViews + _entityViewsToAdd.Swap(); + _metaEntityViewsToAdd.Swap(); + _groupedEntityViewsToAdd.Swap(); + + if (_entityViewsToAdd.other.Count > 0) + AddEntityViewsToTheDBAndSuitableEngines(_entityViewsToAdd.other, _entityViewsDB); + + if (_metaEntityViewsToAdd.other.Count > 0) + AddEntityViewsToTheDBAndSuitableEngines(_metaEntityViewsToAdd.other, _metaEntityViewsDB); + + if (_groupedEntityViewsToAdd.other.Count > 0) + AddGroupEntityViewsToTheDBAndSuitableEngines(_groupedEntityViewsToAdd.other, _groupEntityViewsDB, _entityViewsDB); + + //other can be cleared now + _entityViewsToAdd.other.Clear(); + _metaEntityViewsToAdd.other.Clear(); + _groupedEntityViewsToAdd.other.Clear(); + + //has current new entityViews? + newEntityViewsHaveBeenAddedWhileIterating = + _metaEntityViewsToAdd.current.Count > 0 + || _entityViewsToAdd.current.Count > 0 + || _groupedEntityViewsToAdd.current.Count > 0; + + if (numberOfReenteringLoops > 5) + throw new Exception("possible infinite loop found creating Entities inside IEntityViewsEngine Add method, please consider building entities outside IEntityViewsEngine Add method"); + + numberOfReenteringLoops++; + } + } + + void AddEntityViewsToTheDBAndSuitableEngines(Dictionary entityViewsToAdd, + Dictionary entityViewsDB) + { + foreach (var entityViewList in entityViewsToAdd) + { + AddEntityViewToDB(entityViewsDB, entityViewList); + + if (entityViewList.Value.isQueryiableEntityView) + { + AddEntityViewToEntityViewsDictionary(_entityViewsDBDic, entityViewList.Value, entityViewList.Key); + } + } + + foreach (var entityViewList in entityViewsToAdd) + { + if (entityViewList.Value.isQueryiableEntityView) + { + var type = entityViewList.Key; + for (var current = type; current != _entityViewType; current = current.BaseType) + AddEntityViewToTheSuitableEngines(_entityViewEngines, entityViewList.Value, + current); + } + } + } + + void AddGroupEntityViewsToTheDBAndSuitableEngines(Dictionary> groupedEntityViewsToAdd, + Dictionary> groupEntityViewsDB, + Dictionary entityViewsDB) + { + foreach (var group in groupedEntityViewsToAdd) + { + AddEntityViewsToGroupDB(groupEntityViewsDB, @group); + + AddEntityViewsToTheDBAndSuitableEngines(group.Value, entityViewsDB); + } + } + + static void AddEntityViewsToGroupDB(Dictionary> groupEntityViewsDB, + KeyValuePair> @group) + { + Dictionary groupedEntityViewsByType; + + if (groupEntityViewsDB.TryGetValue(@group.Key, out groupedEntityViewsByType) == false) + groupedEntityViewsByType = groupEntityViewsDB[@group.Key] = new Dictionary(); + + foreach (var entityView in @group.Value) + { + groupedEntityViewsByType.Add(entityView.Key, entityView.Value); + } + } + + static void AddEntityViewToDB(Dictionary entityViewsDB, KeyValuePair entityViewList) + { + ITypeSafeList dbList; + + if (entityViewsDB.TryGetValue(entityViewList.Key, out dbList) == false) + dbList = entityViewsDB[entityViewList.Key] = entityViewList.Value.Create(); + + dbList.AddRange(entityViewList.Value); + } + + static void AddEntityViewToEntityViewsDictionary(Dictionary entityViewsDBdic, + ITypeSafeList entityViews, Type entityViewType) + { + ITypeSafeDictionary entityViewsDic; + + if (entityViewsDBdic.TryGetValue(entityViewType, out entityViewsDic) == false) + entityViewsDic = entityViewsDBdic[entityViewType] = entityViews.CreateIndexedDictionary(); + + entityViewsDic.FillWithIndexedEntityViews(entityViews); + } + + static void AddEntityViewToTheSuitableEngines(Dictionary> entityViewEngines, ITypeSafeList entityViewsList, Type entityViewType) + { + FasterList enginesForEntityView; + + if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView)) + { + int viewsCount; + + var entityViews = entityViewsList.ToArrayFast(out viewsCount); + + for (int i = 0; i < viewsCount; i++) + { + int count; + var fastList = FasterList.NoVirt.ToArrayFast(enginesForEntityView, out count); + IEntityView entityView = entityViews[i]; + for (int j = 0; j < count; j++) + { +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR + EngineProfiler.MonitorAddDuration(fastList[j], entityView); +#else + fastList[j].Add(entityView); +#endif + } + } + } + } + + readonly DoubleBufferedEntityViews> _entityViewsToAdd; + readonly DoubleBufferedEntityViews> _metaEntityViewsToAdd; + readonly DoubleBufferedEntityViews>> _groupedEntityViewsToAdd; + + readonly EntitySubmissionScheduler _scheduler; + + } +} \ No newline at end of file diff --git a/Svelto.ECS/ECS/EntityDescriptor.cs b/Svelto.ECS/ECS/EntityDescriptor.cs new file mode 100644 index 0000000..d6c5aa3 --- /dev/null +++ b/Svelto.ECS/ECS/EntityDescriptor.cs @@ -0,0 +1,272 @@ +using Svelto.DataStructures; +using Svelto.ECS.Internal; +using Svelto.Utilities; +using System; +using System.Collections.Generic; + +namespace Svelto.ECS +{ + public interface IEntityDescriptor + { + IEntityViewBuilder[] entityViewsToBuild { get; } + } + + public class EntityDescriptor:IEntityDescriptor + { + protected EntityDescriptor(IEntityViewBuilder[] entityViewsToBuild) + { + this.entityViewsToBuild = entityViewsToBuild; + } + + public IEntityViewBuilder[] entityViewsToBuild { get; private set; } + } + + public interface IEntityDescriptorInfo + {} + + public static class EntityDescriptorTemplate where TType : IEntityDescriptor, new() + { + public static readonly IEntityDescriptorInfo Default = new EntityDescriptorInfo(new TType()); + } + + public class DynamicEntityDescriptorInfo : EntityDescriptorInfo where TType : IEntityDescriptor, new() + { + public DynamicEntityDescriptorInfo(FasterList extraEntityViews) + { + DesignByContract.Check.Require(extraEntityViews.Count > 0, "don't use a DynamicEntityDescriptorInfo if you don't need to use extra EntityViews"); + + var descriptor = new TType(); + int length = descriptor.entityViewsToBuild.Length; + + entityViewsToBuild = new IEntityViewBuilder[length + extraEntityViews.Count]; + + Array.Copy(descriptor.entityViewsToBuild, 0, entityViewsToBuild, 0, length); + Array.Copy(extraEntityViews.ToArrayFast(), 0, entityViewsToBuild, length, extraEntityViews.Count); + + removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuild); + name = descriptor.ToString(); + } + } +} + +namespace Svelto.ECS.Internal +{ + public class EntityDescriptorInfo:IEntityDescriptorInfo + { + internal IEntityViewBuilder[] entityViewsToBuild; + internal RemoveEntityImplementor removeEntityImplementor; + internal string name; + + internal EntityDescriptorInfo(IEntityDescriptor descriptor) + { + name = descriptor.ToString(); + entityViewsToBuild = descriptor.entityViewsToBuild; + + removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuild); + } + + protected EntityDescriptorInfo() + {} + } + + static class EntityFactory + { + internal static void BuildGroupedEntityViews(int entityID, int groupID, + Dictionary> groupEntityViewsByType, + IEntityDescriptorInfo eentityViewsToBuildDescriptor, + object[] implementors) + { + var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; + Dictionary groupedEntityViewsTyped; + + if (groupEntityViewsByType.TryGetValue(groupID, out groupedEntityViewsTyped) == false) + { + groupedEntityViewsTyped = new Dictionary(); + groupEntityViewsByType.Add(groupID, groupedEntityViewsTyped); + } + + //I would like to find a better solution for this + var removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuildDescriptor.entityViewsToBuild, groupID); + + InternalBuildEntityViews(entityID, groupedEntityViewsTyped, entityViewsToBuildDescriptor, implementors, removeEntityImplementor); + } + + internal static void BuildEntityViews(int entityID, + Dictionary entityViewsByType, + IEntityDescriptorInfo eentityViewsToBuildDescriptor, + object[] implementors) + { + var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; + var removeEntityImplementor = entityViewsToBuildDescriptor.removeEntityImplementor; + + InternalBuildEntityViews(entityID, entityViewsByType, entityViewsToBuildDescriptor, implementors, removeEntityImplementor); + } + + static void InternalBuildEntityViews(int entityID, + Dictionary entityViewsByType, + IEntityDescriptorInfo eentityViewsToBuildDescriptor, + object[] implementors, RemoveEntityImplementor removeEntityImplementor) + { + var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; + var entityViewsToBuild = entityViewsToBuildDescriptor.entityViewsToBuild; + int count = entityViewsToBuild.Length; + + for (int index = 0; index < count; index++) + { + var entityViewBuilder = entityViewsToBuild[index]; + var entityViewType = entityViewBuilder.GetEntityViewType(); + + //only class EntityView will be returned + //struct EntityView cannot be filled so it will be null. + var entityViewObjectToFill = + BuildEntityView(entityID, entityViewsByType, entityViewType, entityViewBuilder); + + //the semantic of this code must still be improved + //but only classes can be filled, so I am aware + //it's a EntityView + if (entityViewObjectToFill != null) + { + FillEntityView(entityViewObjectToFill as EntityView, implementors, removeEntityImplementor, + entityViewsToBuildDescriptor.name); + } + } + } + + static IEntityView BuildEntityView(int entityID, Dictionary entityViewsByType, + Type entityViewType, IEntityViewBuilder entityViewBuilder) + { + ITypeSafeList entityViewsList; + + var entityViewsPoolWillBeCreated = + entityViewsByType.TryGetValue(entityViewType, out entityViewsList) == false; + + IEntityView entityViewObjectToFill; + + //passing the undefined entityViewsByType inside the entityViewBuilder will allow + //it to be created with the correct type and casted back to the undefined list. + //that's how the list will be eventually of the target type. + entityViewBuilder.BuildEntityViewAndAddToList(ref entityViewsList, entityID, out entityViewObjectToFill); + + if (entityViewsPoolWillBeCreated) + entityViewsByType.Add(entityViewType, entityViewsList); + + return entityViewObjectToFill as IEntityView; + } + + //this is used to avoid newing a dictionary every time, but it's used locally only and it's clearead for each use +#if DEBUG && !PROFILER + static readonly Dictionary> implementorsByType = new Dictionary>(); +#else + static readonly Dictionary implementorsByType = new Dictionary(); +#endif + + static void FillEntityView(EntityView entityView, object[] implementors, RemoveEntityImplementor removeEntity, + string entityDescriptorName) + { + for (int index = 0; index < implementors.Length; index++) + { + var implementor = implementors[index]; + + if (implementor != null) + { + var type = implementor.GetType(); + + Type[] interfaces; + if (_cachedTypes.TryGetValue(type, out interfaces) == false) + interfaces = _cachedTypes[type] = type.GetInterfacesEx(); + + for (int iindex = 0; iindex < interfaces.Length; iindex++) + { + var componentType = interfaces[iindex]; +#if DEBUG && !PROFILER + Tuple implementorHolder; + + if (implementorsByType.TryGetValue(componentType, out implementorHolder) == true) + implementorHolder.item2++; + else + implementorsByType[componentType] = new Tuple(implementor, 1); +#else + implementorsByType[componentType] = implementor; +#endif + } + } +#if DEBUG && !PROFILER + else + Utility.Console.LogError(NULL_IMPLEMENTOR_ERROR.FastConcat(entityView.ToString())); +#endif + } + + int count; + + //Very efficent way to collect the fields of every EntityViewType + KeyValuePair>[] setters = + FasterList>>.NoVirt.ToArrayFast(entityView.entityViewBlazingFastReflection, out count); + + var removeEntityComponentType = typeof(IRemoveEntityComponent); + + for (int i = 0; i < count; i++) + { + var keyValuePair = setters[i]; + Type fieldType = keyValuePair.Key; + + if (fieldType != removeEntityComponentType) + { +#if DEBUG && !PROFILER + Tuple component; +#else + object component; +#endif + + if (implementorsByType.TryGetValue(fieldType, out component) == false) + { + Exception e = new Exception(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name + " - EntityView: " + + entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName); + + throw e; + } +#if DEBUG && !PROFILER + if (component.item2 > 1) + Utility.Console.LogError(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat( + "Component Type: ", fieldType.Name, " implementor: ", + component.item1.ToString()) + " - EntityView: " + + entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName); +#endif +#if DEBUG && !PROFILER + keyValuePair.Value.Call(entityView, component.item1); +#else + keyValuePair.Value.Call(entityView, component); +#endif + } + else + { + keyValuePair.Value.Call(entityView, removeEntity); + } + } + + implementorsByType.Clear(); + } +#if DEBUG && !PROFILER + struct Tuple + { + public T1 item1; + public T2 item2; + + public Tuple(T1 implementor, T2 v) + { + item1 = implementor; + item2 = v; + } + } +#endif + static Dictionary _cachedTypes = new Dictionary(); + + const string DUPLICATE_IMPLEMENTOR_ERROR = + "Svelto.ECS the same component is implemented with more than one implementor. This is considered an error and MUST be fixed. "; + + const string NULL_IMPLEMENTOR_ERROR = + "Svelto.ECS Null implementor, please be careful about the implementors passed to avoid performance loss "; + + const string NOT_FOUND_EXCEPTION = "Svelto.ECS Implementor not found for an EntityView. "; + } +} + diff --git a/Svelto.ECS/ECS/EntitySubmissionScheduler.cs b/Svelto.ECS/ECS/EntitySubmissionScheduler.cs new file mode 100644 index 0000000..cfa8168 --- /dev/null +++ b/Svelto.ECS/ECS/EntitySubmissionScheduler.cs @@ -0,0 +1,9 @@ +using Svelto.WeakEvents; + +namespace Svelto.ECS.Schedulers +{ + public abstract class EntitySubmissionScheduler + { + abstract public void Schedule(WeakAction submitEntityViews); + } +} \ No newline at end of file diff --git a/Svelto.ECS/ECS/EntityView.cs b/Svelto.ECS/ECS/EntityView.cs new file mode 100644 index 0000000..b8e56fa --- /dev/null +++ b/Svelto.ECS/ECS/EntityView.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Svelto.DataStructures; +using Svelto.Utilities; + +namespace Svelto.ECS +{ + public interface IEntityView + { + int ID { get; } + } + + public interface IEntityStruct:IEntityView + { + new int ID { set; } + } + + public class EntityView : IEntityView + { + public int ID { get { return _ID; } } + + internal FasterList>> entityViewBlazingFastReflection; + internal int _ID; + } + + static class EntityView where T: EntityView, new() + { + internal static T BuildEntityView(int ID) + { + if (FieldCache.list.Count == 0) + { + var type = typeof(T); + + var fields = type.GetFields(BindingFlags.Public | + BindingFlags.Instance); + + for (int i = fields.Length - 1; i >= 0; --i) + { + var field = fields[i]; + + CastedAction setter = FastInvoke.MakeSetter(field); + + FieldCache.list.Add(new KeyValuePair>(field.FieldType, setter)); + } + } + + return new T { _ID = ID, entityViewBlazingFastReflection = FieldCache.list }; + } + + //check if I can remove W + static class FieldCache where W:T + { + internal static readonly FasterList>> list + = new FasterList>>(); + } + } +} + diff --git a/Svelto.ECS/ECS/EntityViewBuilder.cs b/Svelto.ECS/ECS/EntityViewBuilder.cs new file mode 100644 index 0000000..7b89bcd --- /dev/null +++ b/Svelto.ECS/ECS/EntityViewBuilder.cs @@ -0,0 +1,99 @@ +using System; +using Svelto.ECS.Internal; + +namespace Svelto.ECS +{ + public interface IEntityViewBuilder + { + void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView); + ITypeSafeList Preallocate(ref ITypeSafeList list, int size); + + Type GetEntityViewType(); + void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList); + } + + public class EntityViewBuilder : IEntityViewBuilder where EntityViewType : EntityView, new() + { + public void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView) + { + if (list == null) + list = new TypeSafeFasterListForECSForClasses(); + + var castedList = list as TypeSafeFasterListForECSForClasses; + + var lentityView = EntityView.BuildEntityView(entityID); + + castedList.Add(lentityView); + + entityView = lentityView; + } + + public ITypeSafeList Preallocate(ref ITypeSafeList list, int size) + { + if (list == null) + list = new TypeSafeFasterListForECSForClasses(size); + else + list.ReserveCapacity(size); + + return list; + } + + public Type GetEntityViewType() + { + return _entityViewType; + } + + public void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList) + { + var fromCastedList = fromSafeList as TypeSafeFasterListForECSForClasses; + var toCastedList = toSafeList as TypeSafeFasterListForECSForClasses; + + toCastedList.Add(fromCastedList[fromCastedList.GetIndexFromID(entityID)]); + } + + readonly Type _entityViewType = typeof(EntityViewType); + } + + public class EntityViewStructBuilder : IEntityViewBuilder where EntityViewType : struct, IEntityStruct + { + public void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView) + { + var structEntityView = default(EntityViewType); + structEntityView.ID = entityID; + + if (list == null) + list = new TypeSafeFasterListForECSForStructs(); + + var castedList = list as TypeSafeFasterListForECSForStructs; + + castedList.Add(structEntityView); + + entityView = null; + } + + public ITypeSafeList Preallocate(ref ITypeSafeList list, int size) + { + if (list == null) + list = new TypeSafeFasterListForECSForStructs(size); + else + list.ReserveCapacity(size); + + return list; + } + + public Type GetEntityViewType() + { + return _entityViewType; + } + + public void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList) + { + var fromCastedList = fromSafeList as TypeSafeFasterListForECSForStructs; + var toCastedList = toSafeList as TypeSafeFasterListForECSForStructs; + + toCastedList.Add(fromCastedList[fromCastedList.GetIndexFromID(entityID)]); + } + + readonly Type _entityViewType = typeof(EntityViewType); + } +} \ No newline at end of file diff --git a/Svelto.ECS/ECS/EntityViewsDB.cs b/Svelto.ECS/ECS/EntityViewsDB.cs new file mode 100644 index 0000000..b92c5ed --- /dev/null +++ b/Svelto.ECS/ECS/EntityViewsDB.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using Svelto.DataStructures; + +namespace Svelto.ECS.Internal +{ + class EntityViewsDB : IEntityViewsDB + { + internal EntityViewsDB( Dictionary entityViewsDB, + Dictionary entityViewsDBdic, + Dictionary metaEntityViewsDB, + Dictionary> groupEntityViewsDB) + { + _entityViewsDB = entityViewsDB; + _entityViewsDBdic = entityViewsDBdic; + _metaEntityViewsDB = metaEntityViewsDB; + _groupEntityViewsDB = groupEntityViewsDB; + } + + public FasterReadOnlyList QueryEntityViews() where T:EntityView, new() + { + var type = typeof(T); + + ITypeSafeList entityViews; + + if (_entityViewsDB.TryGetValue(type, out entityViews) == false) + return RetrieveEmptyEntityViewList(); + + return new FasterReadOnlyList((FasterList)entityViews); + } + + public FasterReadOnlyList QueryGroupedEntityViews(int @group) where T:EntityView, new() + { + Dictionary entityViews; + + if (_groupEntityViewsDB.TryGetValue(group, out entityViews) == false) + return RetrieveEmptyEntityViewList(); + + return new FasterReadOnlyList(entityViews as FasterList); + } + + public T[] QueryEntityViewsAsArray(out int count) where T : IEntityView + { + var type = typeof(T); + count = 0; + + ITypeSafeList entityViews; + + if (_entityViewsDB.TryGetValue(type, out entityViews) == false) + return RetrieveEmptyEntityViewArray(); + + var castedEntityViews = (FasterList)entityViews; + + return FasterList < T > .NoVirt.ToArrayFast(castedEntityViews, out count); + } + + public T[] QueryGroupedEntityViewsAsArray(int @group, out int count) where T : IEntityView + { + var type = typeof(T); + count = 0; + + Dictionary entityViews; + + if (_groupEntityViewsDB.TryGetValue(group, out entityViews) == false) + return RetrieveEmptyEntityViewArray(); + + var castedEntityViews = (FasterList)entityViews[type]; + + count = castedEntityViews.Count; + + return FasterList.NoVirt.ToArrayFast(castedEntityViews, out count); + } + + public ReadOnlyDictionary QueryIndexableEntityViews() where T:IEntityView + { + var type = typeof(T); + + ITypeSafeDictionary entityViews; + + if (_entityViewsDBdic.TryGetValue(type, out entityViews) == false) + return TypeSafeDictionary.Default; + + return new ReadOnlyDictionary(entityViews as Dictionary); + } + + public bool TryQueryEntityView(int ID, out T entityView) where T : IEntityView + { + var type = typeof(T); + + T internalEntityView; + + ITypeSafeDictionary entityViews; + TypeSafeDictionary casted; + + _entityViewsDBdic.TryGetValue(type, out entityViews); + casted = entityViews as TypeSafeDictionary; + + if (casted != null && + casted.TryGetValue(ID, out internalEntityView)) + { + entityView = internalEntityView; + + return true; + } + + entityView = default(T); + + return false; + } + + public T QueryEntityView(int ID) where T : IEntityView + { + var type = typeof(T); + + T internalEntityView; ITypeSafeDictionary entityViews; + TypeSafeDictionary casted; + + _entityViewsDBdic.TryGetValue(type, out entityViews); + casted = entityViews as TypeSafeDictionary; + + if (casted != null && + casted.TryGetValue(ID, out internalEntityView)) + return (T)internalEntityView; + + throw new Exception("EntityView Not Found"); + } + + public T QueryMetaEntityView(int metaEntityID) where T:EntityView, new() + { + return QueryEntityView(metaEntityID); + } + + public bool TryQueryMetaEntityView(int metaEntityID, out T entityView) where T:EntityView, new() + { + return TryQueryEntityView(metaEntityID, out entityView); + } + + public FasterReadOnlyList QueryMetaEntityViews() where T:EntityView, new() + { + var type = typeof(T); + + ITypeSafeList entityViews; + + if (_metaEntityViewsDB.TryGetValue(type, out entityViews) == false) + return RetrieveEmptyEntityViewList(); + + return new FasterReadOnlyList((FasterList)entityViews); + } + + static FasterReadOnlyList RetrieveEmptyEntityViewList() + { + return FasterReadOnlyList.DefaultList; + } + + static T[] RetrieveEmptyEntityViewArray() + { + return FasterList.DefaultList.ToArrayFast(); + } + + readonly Dictionary _entityViewsDB; + readonly Dictionary _entityViewsDBdic; + readonly Dictionary _metaEntityViewsDB; + readonly Dictionary> _groupEntityViewsDB; + } +} diff --git a/Svelto.ECS/ECS/Experimental/StructNodeCollections.cs b/Svelto.ECS/ECS/Experimental/StructNodeCollections.cs new file mode 100644 index 0000000..1b81938 --- /dev/null +++ b/Svelto.ECS/ECS/Experimental/StructNodeCollections.cs @@ -0,0 +1,180 @@ +#if EXPERIMENTAL +using System; +using System.Collections.Generic; +using Svelto.DataStructures; +using Svelto.ECS.Experimental.Internal; + +namespace Svelto.ECS.Experimental.Internal +{ + public interface IStructEntityViewEngine : IEngine + { + void CreateStructEntityViews(SharedStructEntityViewLists sharedStructEntityViewLists); + } + + public interface IGroupedStructEntityViewsEngine : IEngine + { + void CreateStructEntityViews(SharedGroupedStructEntityViewsLists sharedStructEntityViewLists); + } +} + +namespace Svelto.ECS.Experimental +{ + public interface IGroupedEntityView + { + int groupID { get; set; } + } + + /// + /// The engines can receive and store IEntityViews structs + /// Unboxing will happen during the Add, but the + /// data will then be stored and processed as stucts + /// + public interface IStructEntityViewEngine : IStructEntityViewEngine where T:struct, IEntityStruct + { } + + /// + /// same as above, but the entityViews are grouped by ID + /// usually the ID is the owner of the entityViews of that + /// group + /// + public interface IGroupedStructEntityViewsEngine : IGroupedStructEntityViewsEngine where T : struct, IGroupedEntityView + { + void Add(ref T entityView); + void Remove(ref T entityView); + } + + public sealed class StructEntityViews where T:struct, IEntityStruct + { + public T[] GetList(out int numberOfItems) + { + numberOfItems = _internalList.Count; + return _internalList.ToArrayFast(); + } + + public StructEntityViews(SharedStructEntityViewLists container) + { + _internalList = SharedStructEntityViewLists.NoVirt.GetList(container); + } + + public void Add(T entityView) + { + T convert = (T)entityView; + + _internalList.Add(convert); + } + + readonly FasterList _internalList; + } + + public struct StructGroupEntityViews + where T : struct, IEntityView + { + public StructGroupEntityViews(SharedGroupedStructEntityViewsLists container) + { + _container = container; + indices = new Dictionary(); + } + + public void Add(int groupID, T entityView) + { + T convert = (T)entityView; + + var fasterList = (SharedGroupedStructEntityViewsLists.NoVirt.GetList(_container, groupID) as FasterList); + indices[entityView.ID] = fasterList.Count; + + fasterList.Add(convert); + } + + public void Remove(int groupID, T entityView) + { + var fasterList = (SharedGroupedStructEntityViewsLists.NoVirt.GetList(_container, groupID) as FasterList); + var index = indices[entityView.ID]; + indices.Remove(entityView.ID); + + if (fasterList.UnorderedRemoveAt(index)) + indices[fasterList[index].ID] = index; + } + + public T[] GetList(int groupID, out int numberOfItems) + { + var fasterList = (SharedGroupedStructEntityViewsLists.NoVirt.GetList(_container, groupID) as FasterList); + + return FasterList.NoVirt.ToArrayFast(fasterList, out numberOfItems); + } + + readonly SharedGroupedStructEntityViewsLists _container; + readonly Dictionary indices; + } + + public class SharedStructEntityViewLists + { + internal SharedStructEntityViewLists() + { + _collection = new Dictionary(); + } + + internal static class NoVirt + { + internal static FasterList GetList(SharedStructEntityViewLists obj) where T : struct + { + IFasterList list; + if (obj._collection.TryGetValue(typeof(T), out list)) + { + return list as FasterList; + } + + list = new FasterList(); + + obj._collection.Add(typeof(T), list); + + return (FasterList)list; + } + } + + readonly Dictionary _collection; + } + + public class SharedGroupedStructEntityViewsLists + { + internal SharedGroupedStructEntityViewsLists() + { + _collection = new Dictionary>(); + } + + internal static class NoVirt + { + internal static IFasterList GetList(SharedGroupedStructEntityViewsLists list, int groupID) where T : struct + { + Dictionary dic = GetGroup(list); + IFasterList localList; + + if (dic.TryGetValue(groupID, out localList)) + return localList; + + localList = new FasterList(); + dic.Add(groupID, localList); + + return localList; + } + + internal static Dictionary GetGroup(SharedGroupedStructEntityViewsLists list) where T : struct + { + Dictionary dic; + + if (list._collection.TryGetValue(typeof(T), out dic)) + { + return dic; + } + + dic = new Dictionary(); + + list._collection.Add(typeof(T), dic); + + return dic; + } + } + + readonly Dictionary> _collection; + } +} +#endif \ No newline at end of file diff --git a/Svelto.ECS/ECS/Extensions/Unity/GenericEntityDescriptorHolder.cs b/Svelto.ECS/ECS/Extensions/Unity/GenericEntityDescriptorHolder.cs new file mode 100644 index 0000000..fb672cb --- /dev/null +++ b/Svelto.ECS/ECS/Extensions/Unity/GenericEntityDescriptorHolder.cs @@ -0,0 +1,14 @@ +#if UNITY_5 || UNITY_5_3_OR_NEWER +namespace Svelto.ECS +{ + public class GenericEntityDescriptorHolder: + UnityEngine.MonoBehaviour , IEntityDescriptorHolder + where T: class, IEntityDescriptor, new() + { + public IEntityDescriptorInfo RetrieveDescriptor() + { + return EntityDescriptorTemplate.Default; + } + } +} +#endif \ No newline at end of file diff --git a/Svelto.ECS/ECS/Extensions/Unity/UnitySumbmissionEntityViewScheduler .cs b/Svelto.ECS/ECS/Extensions/Unity/UnitySumbmissionEntityViewScheduler .cs new file mode 100644 index 0000000..4eab8cd --- /dev/null +++ b/Svelto.ECS/ECS/Extensions/Unity/UnitySumbmissionEntityViewScheduler .cs @@ -0,0 +1,53 @@ +#if UNITY_5 || UNITY_5_3_OR_NEWER +using System.Collections; +using Svelto.WeakEvents; +using UnityEngine; + +namespace Svelto.ECS.Schedulers.Unity +{ + //The EntityViewSubmissionScheduler has been introduced to make + //the entityView submission logic platform indipendent. + //Please don't be tempted to create your own submission to + //adapt to your game level code design. For example, + //you may be tempted to write a submission logic to submit + //the entityViews immediatly just because convenient for your game + //logic. This is not how it works. + + public class UnitySumbmissionEntityViewScheduler : EntitySubmissionScheduler + { + public UnitySumbmissionEntityViewScheduler() + { + GameObject go = new GameObject("ECSScheduler"); + + _scheduler = go.AddComponent(); + } + + public override void Schedule(WeakAction submitEntityViews) + { + _scheduler.OnTick = submitEntityViews; + } + + class Scheduler : MonoBehaviour + { + IEnumerator Start() + { + while (true) + { + yield return _wait; + + if (OnTick.IsValid) + OnTick.Invoke(); + else + yield break; + } + } + + internal WeakAction OnTick; + + WaitForEndOfFrame _wait = new WaitForEndOfFrame(); + } + + Scheduler _scheduler; + } +} +#endif \ No newline at end of file diff --git a/Svelto.ECS/ECS/GenericEntityDescriptor.cs b/Svelto.ECS/ECS/GenericEntityDescriptor.cs new file mode 100644 index 0000000..a717870 --- /dev/null +++ b/Svelto.ECS/ECS/GenericEntityDescriptor.cs @@ -0,0 +1,110 @@ +using System.Runtime.InteropServices; + +namespace Svelto.ECS +{ + public class GenericEntityDescriptor:IEntityDescriptor where T : EntityView, new() + { + static GenericEntityDescriptor() + { + entityViewBuilders = new IEntityViewBuilder[] { new EntityViewBuilder() }; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return entityViewBuilders; } + } + + public static readonly IEntityViewBuilder[] entityViewBuilders; + + } + + public class GenericEntityDescriptor : IEntityDescriptor where T : EntityView, new() + where U : EntityView, new() + { + static GenericEntityDescriptor() + { + entityViewBuilders = new IEntityViewBuilder[] {new EntityViewBuilder(), new EntityViewBuilder()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return entityViewBuilders; } + } + + public static readonly IEntityViewBuilder[] entityViewBuilders; + } + + public class GenericEntityDescriptor : IEntityDescriptor where T : EntityView, new() + where U : EntityView, new() + where V : EntityView, new() + { + static GenericEntityDescriptor() + { + entityViewBuilders = new IEntityViewBuilder[] {new EntityViewBuilder(), new EntityViewBuilder(), new EntityViewBuilder()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return entityViewBuilders; } + } + + public static readonly IEntityViewBuilder[] entityViewBuilders; + } + + public class GenericEntityDescriptor : IEntityDescriptor where T : EntityView, new() + where U : EntityView, new() + where V : EntityView, new() + where W : EntityView, new() + { + static GenericEntityDescriptor() + { + entityViewBuilders = new IEntityViewBuilder[] {new EntityViewBuilder(), new EntityViewBuilder(), new EntityViewBuilder(), new EntityViewBuilder()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return entityViewBuilders; } + } + + public static readonly IEntityViewBuilder[] entityViewBuilders; + } + + public class GenericEntityDescriptor : IEntityDescriptor where T : EntityView, new() + where U : EntityView, new() + where V : EntityView, new() + where W : EntityView, new() + where X : EntityView, new() + { + static GenericEntityDescriptor() + { + entityViewBuilders = new IEntityViewBuilder[] {new EntityViewBuilder(), new EntityViewBuilder(), new EntityViewBuilder(), new EntityViewBuilder(), new EntityViewBuilder()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return entityViewBuilders; } + } + + public static readonly IEntityViewBuilder[] entityViewBuilders; + } + + public class GenericEntityDescriptor : IEntityDescriptor where T : EntityView, new() + where U : EntityView, new() + where V : EntityView, new() + where W : EntityView, new() + where X : EntityView, new() + where Y : EntityView, new() + { + static GenericEntityDescriptor() + { + entityViewBuilders = new IEntityViewBuilder[] {new EntityViewBuilder(), new EntityViewBuilder(), new EntityViewBuilder(), new EntityViewBuilder(), new EntityViewBuilder(), new EntityViewBuilder()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return entityViewBuilders; } + } + + public static readonly IEntityViewBuilder[] entityViewBuilders; + } +} diff --git a/Svelto.ECS/ECS/IEngine.cs b/Svelto.ECS/ECS/IEngine.cs new file mode 100644 index 0000000..98597d5 --- /dev/null +++ b/Svelto.ECS/ECS/IEngine.cs @@ -0,0 +1,21 @@ +namespace Svelto.ECS.Internal +{ + public interface IHandleEntityViewEngine : IEngine + { + void Add(IEntityView entityView); + void Remove(IEntityView entityView); + } +} + +namespace Svelto.ECS +{ + public interface IEngine + {} + + public interface IQueryingEntityViewEngine : IEngine + { + IEntityViewsDB entityViewsDB { set; } + + void Ready(); + } +} diff --git a/Svelto.ECS/ECS/IEnginesInterfaces.cs b/Svelto.ECS/ECS/IEnginesInterfaces.cs new file mode 100644 index 0000000..36f9aab --- /dev/null +++ b/Svelto.ECS/ECS/IEnginesInterfaces.cs @@ -0,0 +1,29 @@ +namespace Svelto.ECS +{ + public interface IEntityFactory + { + void Preallocate(int size) where T : IEntityDescriptor, new(); + + void BuildEntity(int entityID, object[] implementors = null) where T:IEntityDescriptor, new(); + void BuildEntity(int entityID, IEntityDescriptorInfo entityDescriptorInfo, object[] implementors); + + void BuildMetaEntity(int metaEntityID, object[] implementors = null) where T:IEntityDescriptor, new(); + + void BuildEntityInGroup(int entityID, int groupID, object[] implementors = null) where T:IEntityDescriptor, new(); + void BuildEntityInGroup(int entityID, int groupID, IEntityDescriptorInfo entityDescriptor, object[] implementors); + } + + public interface IEntityFunctions + { + void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo); + void RemoveEntity(int entityID) where T:IEntityDescriptor, new(); + + void RemoveMetaEntity(int metaEntityID) where T:IEntityDescriptor, new(); + + void RemoveEntityFromGroup(int entityID, int groupID) where T:IEntityDescriptor, new(); + + void RemoveGroupedEntities(int groupID); + + void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) where T : IEntityDescriptor, new(); + } +} diff --git a/Svelto.ECS/ECS/IEntityDescriptorHolder.cs b/Svelto.ECS/ECS/IEntityDescriptorHolder.cs new file mode 100644 index 0000000..c144811 --- /dev/null +++ b/Svelto.ECS/ECS/IEntityDescriptorHolder.cs @@ -0,0 +1,7 @@ +namespace Svelto.ECS +{ + public interface IEntityDescriptorHolder + { + IEntityDescriptorInfo RetrieveDescriptor(); + } +} diff --git a/Svelto.ECS/ECS/IEntityViewsDB.cs b/Svelto.ECS/ECS/IEntityViewsDB.cs new file mode 100644 index 0000000..a6eb0c6 --- /dev/null +++ b/Svelto.ECS/ECS/IEntityViewsDB.cs @@ -0,0 +1,22 @@ +using Svelto.DataStructures; + +namespace Svelto.ECS +{ + public interface IEntityViewsDB + { + FasterReadOnlyList QueryEntityViews() where T:EntityView, new(); + FasterReadOnlyList QueryMetaEntityViews() where T: EntityView, new(); + FasterReadOnlyList QueryGroupedEntityViews(int group) where T: EntityView, new(); + + T[] QueryEntityViewsAsArray(out int count) where T: IEntityView; + T[] QueryGroupedEntityViewsAsArray(int @group, out int count) where T: IEntityView; + + ReadOnlyDictionary QueryIndexableEntityViews() where T: IEntityView; + bool TryQueryEntityView(int ID, out T entityView) where T : IEntityView; + T QueryEntityView(int ID) where T: IEntityView; + + bool TryQueryMetaEntityView(int metaEntityID, out T entityView) where T: EntityView, new(); + T QueryMetaEntityView(int metaEntityID) where T: EntityView, new(); + } +} + diff --git a/Svelto.ECS/ECS/MixedEntityDescriptor.cs b/Svelto.ECS/ECS/MixedEntityDescriptor.cs new file mode 100644 index 0000000..f91ad54 --- /dev/null +++ b/Svelto.ECS/ECS/MixedEntityDescriptor.cs @@ -0,0 +1,107 @@ +namespace Svelto.ECS +{ + public class MixedEntityDescriptor:IEntityDescriptor where T : class, IEntityViewBuilder, new() + { + static MixedEntityDescriptor() + { + _entityViewsToBuild = new IEntityViewBuilder[] {new T()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return _entityViewsToBuild; } + } + + static readonly IEntityViewBuilder[] _entityViewsToBuild; + } + + public class MixedEntityDescriptor : IEntityDescriptor where T : class, IEntityViewBuilder, new() + where U : class, IEntityViewBuilder, new() + { + static MixedEntityDescriptor() + { + _entityViewsToBuild = new IEntityViewBuilder[] {new T(), new U()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return _entityViewsToBuild; } + } + + static readonly IEntityViewBuilder[] _entityViewsToBuild; + } + + public class MixedEntityDescriptor : IEntityDescriptor where T : class, IEntityViewBuilder, new() + where U : class, IEntityViewBuilder, new() + where V : class, IEntityViewBuilder, new() + { + static MixedEntityDescriptor() + { + _entityViewsToBuild = new IEntityViewBuilder[] {new T(), new U(), new V()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return _entityViewsToBuild; } + } + + static readonly IEntityViewBuilder[] _entityViewsToBuild; + } + + public class MixedEntityDescriptor : IEntityDescriptor where T : class, IEntityViewBuilder, new() + where U : class, IEntityViewBuilder, new() + where V : class, IEntityViewBuilder, new() + where W : class, IEntityViewBuilder, new() + { + static MixedEntityDescriptor() + { + _entityViewsToBuild = new IEntityViewBuilder[] {new T(), new U(), new V(), new W()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return _entityViewsToBuild; } + } + + static readonly IEntityViewBuilder[] _entityViewsToBuild; + } + + public class MixedEntityDescriptor : IEntityDescriptor where T : class, IEntityViewBuilder, new() + where U : class, IEntityViewBuilder, new() + where V : class, IEntityViewBuilder, new() + where W : class, IEntityViewBuilder, new() + where X : class, IEntityViewBuilder, new() + { + static MixedEntityDescriptor() + { + _entityViewsToBuild = new IEntityViewBuilder[] {new T(), new U(), new V(), new W(), new X()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return _entityViewsToBuild; } + } + + static readonly IEntityViewBuilder[] _entityViewsToBuild; + } + + public class MixedEntityDescriptor : IEntityDescriptor where T : class, IEntityViewBuilder, new() + where U : class, IEntityViewBuilder, new() + where V : class, IEntityViewBuilder, new() + where W : class, IEntityViewBuilder, new() + where X : class, IEntityViewBuilder, new() + where Y : class, IEntityViewBuilder, new() + { + static MixedEntityDescriptor() + { + _entityViewsToBuild = new IEntityViewBuilder[] {new T(), new U(), new V(), new W(), new X(), new Y()}; + } + + public IEntityViewBuilder[] entityViewsToBuild + { + get { return _entityViewsToBuild; } + } + + static readonly IEntityViewBuilder[] _entityViewsToBuild; + } +} diff --git a/Svelto.ECS/ECS/MultiEntityViewsEngine.cs b/Svelto.ECS/ECS/MultiEntityViewsEngine.cs new file mode 100644 index 0000000..324bc36 --- /dev/null +++ b/Svelto.ECS/ECS/MultiEntityViewsEngine.cs @@ -0,0 +1,118 @@ +using Svelto.ECS.Internal; + +namespace Svelto.ECS.Internal +{ + public abstract class MultiEntityViewsEngine:IHandleEntityViewEngine where T:EntityView, new() + { + protected abstract void Add(T entityView); + protected abstract void Remove(T entityView); + + public virtual void Add(IEntityView entityView) + { + Add((T) entityView); + } + + public virtual void Remove(IEntityView entityView) + { + Remove((T) entityView); + } + } +} + +namespace Svelto.ECS +{ + public abstract class MultiEntityViewsEngine : MultiEntityViewsEngine + where U:EntityView, new() where T : EntityView, new() + { + protected abstract void Add(U entityView); + protected abstract void Remove(U entityView); + + public override void Add(IEntityView entityView) + { + var castedEntityView = entityView as U; + if (castedEntityView != null) + { + Add(castedEntityView); + } + else + { + base.Add(entityView); + } + } + + public override void Remove(IEntityView entityView) + { + if (entityView is U) + { + Remove((U) entityView); + } + else + { + base.Remove(entityView); + } + } + } + + public abstract class MultiEntityViewsEngine : MultiEntityViewsEngine + where V : EntityView, new() where U : EntityView, new() where T : EntityView, new() + { + protected abstract void Add(V entityView); + protected abstract void Remove(V entityView); + + public override void Add(IEntityView entityView) + { + var castedEntityView = entityView as V; + if (castedEntityView != null) + { + Add(castedEntityView); + } + else + base.Add(entityView); + } + + public override void Remove(IEntityView entityView) + { + var castedEntityView = entityView as V; + if (castedEntityView != null) + { + Remove(castedEntityView); + } + else + base.Remove(entityView); + } + } + + /// + /// Please do not add more MultiEntityViewsEngine + /// if you use more than 4 nodes, your engine has + /// already too many responsabilities. + /// + public abstract class MultiEntityViewsEngine : MultiEntityViewsEngine + where W : EntityView, new() where V : EntityView, new() where U : EntityView, new() where T : EntityView, new() + { + protected abstract void Add(W entityView); + protected abstract void Remove(W entityView); + + public override void Add(IEntityView entityView) + { + var castedEntityView = entityView as W; + if (castedEntityView != null) + { + Add(castedEntityView); + } + else + base.Add(entityView); + } + + public override void Remove(IEntityView entityView) + { + var castedEntityView = entityView as W; + if (castedEntityView != null) + { + Remove(castedEntityView); + } + else + base.Remove(entityView); + } + } +} \ No newline at end of file diff --git a/ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs b/Svelto.ECS/ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs similarity index 99% rename from ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs rename to Svelto.ECS/ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs index b1fb2da..0947e8a 100644 --- a/ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs +++ b/Svelto.ECS/ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs @@ -1,6 +1,6 @@ #if UNITY_EDITOR + using System; -using System.Collections.Generic; using UnityEditor; using UnityEngine; diff --git a/ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs b/Svelto.ECS/ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs similarity index 100% rename from ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs rename to Svelto.ECS/ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs diff --git a/ECS/Profiler/Editor/EngineProfiler/EnginesMonitor.cs b/Svelto.ECS/ECS/Profiler/Editor/EngineProfiler/EnginesMonitor.cs similarity index 100% rename from ECS/Profiler/Editor/EngineProfiler/EnginesMonitor.cs rename to Svelto.ECS/ECS/Profiler/Editor/EngineProfiler/EnginesMonitor.cs diff --git a/ECS/Profiler/Editor/EngineProfiler/ProfilerEditorLayout.cs b/Svelto.ECS/ECS/Profiler/Editor/EngineProfiler/ProfilerEditorLayout.cs similarity index 100% rename from ECS/Profiler/Editor/EngineProfiler/ProfilerEditorLayout.cs rename to Svelto.ECS/ECS/Profiler/Editor/EngineProfiler/ProfilerEditorLayout.cs diff --git a/ECS/Profiler/EngineInfo.cs b/Svelto.ECS/ECS/Profiler/EngineInfo.cs similarity index 51% rename from ECS/Profiler/EngineInfo.cs rename to Svelto.ECS/ECS/Profiler/EngineInfo.cs index ceffef9..038af1c 100644 --- a/ECS/Profiler/EngineInfo.cs +++ b/Svelto.ECS/ECS/Profiler/EngineInfo.cs @@ -33,34 +33,23 @@ namespace Svelto.ECS.Profiler double _accumulatedAddDuration; double _minAddDuration; double _maxAddDuration; - int _nodesAddedCount; + int _entityViewsAddedCount; double _accumulatedRemoveDuration; double _minRemoveDuration; double _maxRemoveDuration; - int _nodesRemovedCount; + int _entityViewsRemovedCount; - public IEngine engine { get { return _engine; } } public string engineName { get { return _engineName; } } - public Type engineType { get { return _engineType; } } - - public double lastUpdateDuration { get { return _lastUpdateDuration[(int) UpdateType.Update]; } } - public double lastFixedUpdateDuration { get { return _lastUpdateDuration[(int)UpdateType.LateUpdate]; } } - public double lastLateUpdateDuration { get { return _lastUpdateDuration[(int)UpdateType.FixedUpdate]; } } - + public double minAddDuration { get { return _minAddDuration; } } public double minRemoveDuration { get { return _minRemoveDuration; } } - public double minUpdateDuration { get { return _minUpdateDuration[(int)UpdateType.Update]; } } public double maxAddDuration { get { return _maxAddDuration; } } public double maxRemoveDuration { get { return _maxRemoveDuration; } } - public double maxUpdateDuration { get { return _maxUpdateDuration[(int)UpdateType.Update]; } } - public double averageAddDuration { get { return _nodesAddedCount == 0 ? 0 : _accumulatedAddDuration / _nodesAddedCount; } } - public double averageRemoveDuration { get { return _nodesRemovedCount == 0 ? 0 : _accumulatedRemoveDuration / _nodesRemovedCount; } } - public double averageUpdateDuration { get { return _updateFrameTimes[(int)UpdateType.Update].Count == 0 ? 0 : _accumulatedUpdateDuration[(int)UpdateType.Update] / _updateFrameTimes[(int)UpdateType.Update].Count; } } - public double averageLateUpdateDuration { get { return _updateFrameTimes[(int)UpdateType.LateUpdate].Count == 0 ? 0 : _accumulatedUpdateDuration[(int)UpdateType.LateUpdate] / _updateFrameTimes[(int)UpdateType.LateUpdate].Count; } } - public double averageFixedUpdateDuration { get { return _updateFrameTimes[(int)UpdateType.FixedUpdate].Count == 0 ? 0 : _accumulatedUpdateDuration[(int)UpdateType.FixedUpdate] / _updateFrameTimes[(int)UpdateType.FixedUpdate].Count; } } + public double averageAddDuration { get { return _entityViewsAddedCount == 0 ? 0 : _accumulatedAddDuration / _entityViewsAddedCount; } } + public double averageRemoveDuration { get { return _entityViewsRemovedCount == 0 ? 0 : _accumulatedRemoveDuration / _entityViewsRemovedCount; } } public EngineInfo(IEngine engine) { @@ -79,42 +68,6 @@ namespace Svelto.ECS.Profiler ResetDurations(); } - public void AddUpdateDuration(double updateDuration) - { - AddUpdateDurationForType(updateDuration, (int)UpdateType.Update); - } - - public void AddLateUpdateDuration(double updateDuration) - { - AddUpdateDurationForType(updateDuration, (int)UpdateType.LateUpdate); - } - - public void AddFixedUpdateDuration(double updateDuration) - { - AddUpdateDurationForType(updateDuration, (int)UpdateType.FixedUpdate); - } - - void AddUpdateDurationForType(double updateDuration, int updateType) - { - if (updateDuration < _minUpdateDuration[updateType] || _minUpdateDuration[updateType] == 0) - { - _minUpdateDuration[updateType] = updateDuration; - } - if (updateDuration > _maxUpdateDuration[updateType]) - { - _maxUpdateDuration[updateType] = updateDuration; - } - - if (_updateFrameTimes[updateType].Count == NUM_FRAMES_TO_AVERAGE) - { - _accumulatedUpdateDuration[updateType] -= _updateFrameTimes[updateType].Dequeue(); - } - - _accumulatedUpdateDuration[updateType] += updateDuration; - _updateFrameTimes[updateType].Enqueue(updateDuration); - _lastUpdateDuration[updateType] = updateDuration; - } - public void AddAddDuration(double duration) { if (duration < _minAddDuration || _minAddDuration == 0) @@ -126,7 +79,7 @@ namespace Svelto.ECS.Profiler _maxAddDuration = duration; } _accumulatedAddDuration += duration; - _nodesAddedCount += 1; + _entityViewsAddedCount += 1; } public void AddRemoveDuration(double duration) @@ -140,7 +93,7 @@ namespace Svelto.ECS.Profiler _maxRemoveDuration = duration; } _accumulatedRemoveDuration += duration; - _nodesRemovedCount += 1; + _entityViewsRemovedCount += 1; } public void ResetDurations() @@ -156,12 +109,12 @@ namespace Svelto.ECS.Profiler _accumulatedAddDuration = 0; _minAddDuration = 0; _maxAddDuration = 0; - _nodesAddedCount = 0; + _entityViewsAddedCount = 0; _accumulatedRemoveDuration = 0; _minRemoveDuration = 0; _maxRemoveDuration = 0; - _nodesRemovedCount = 0; + _entityViewsRemovedCount = 0; } } } diff --git a/ECS/Profiler/EngineProfiler.cs b/Svelto.ECS/ECS/Profiler/EngineProfiler.cs similarity index 84% rename from ECS/Profiler/EngineProfiler.cs rename to Svelto.ECS/ECS/Profiler/EngineProfiler.cs index 2b07067..a74333b 100644 --- a/ECS/Profiler/EngineProfiler.cs +++ b/Svelto.ECS/ECS/Profiler/EngineProfiler.cs @@ -12,31 +12,30 @@ namespace Svelto.ECS.Profiler { static readonly Stopwatch _stopwatch = new Stopwatch(); - public static void MonitorAddDuration(INodeEngine engine, INode node) + public static void MonitorAddDuration(IHandleEntityViewEngine engine, IEntityView entityView) { EngineInfo info; if (engineInfos.TryGetValue(engine.GetType(), out info)) { - _stopwatch.Reset(); _stopwatch.Start(); - engine.Add(node); + engine.Add(entityView); _stopwatch.Stop(); - info.AddAddDuration(_stopwatch.Elapsed.TotalMilliseconds); + _stopwatch.Reset(); } } - public static void MonitorRemoveDuration(INodeEngine engine, INode node) + public static void MonitorRemoveDuration(IHandleEntityViewEngine engine, IEntityView entityView) { EngineInfo info; if (engineInfos.TryGetValue(engine.GetType(), out info)) { - _stopwatch.Reset(); _stopwatch.Start(); - engine.Remove(node); + engine.Remove(entityView); _stopwatch.Stop(); - + info.AddRemoveDuration(_stopwatch.Elapsed.TotalMilliseconds); + _stopwatch.Reset(); } } diff --git a/ECS/Profiler/EngineProfilerBehaviour.cs b/Svelto.ECS/ECS/Profiler/EngineProfilerBehaviour.cs similarity index 57% rename from ECS/Profiler/EngineProfilerBehaviour.cs rename to Svelto.ECS/ECS/Profiler/EngineProfilerBehaviour.cs index a350ae7..b9bd384 100644 --- a/ECS/Profiler/EngineProfilerBehaviour.cs +++ b/Svelto.ECS/ECS/Profiler/EngineProfilerBehaviour.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using UnityEngine; +using UnityEngine.SceneManagement; //This profiler is based on the Entitas Visual Debugging tool //https://github.com/sschmid/Entitas-CSharp @@ -16,6 +17,21 @@ namespace Svelto.ECS.Profiler { EngineProfiler.ResetDurations(); } + + void OnEnable() + { + SceneManager.sceneLoaded += OnLevelFinishedLoading; + } + + void OnDisable() + { + SceneManager.sceneLoaded -= OnLevelFinishedLoading; + } + + void OnLevelFinishedLoading(Scene arg0, LoadSceneMode arg1) + { + ResetDurations(); + } } } #endif \ No newline at end of file diff --git a/Svelto.ECS/ECS/RemoveEntityImplementor.cs b/Svelto.ECS/ECS/RemoveEntityImplementor.cs new file mode 100644 index 0000000..0ad6a93 --- /dev/null +++ b/Svelto.ECS/ECS/RemoveEntityImplementor.cs @@ -0,0 +1,36 @@ +namespace Svelto.ECS.Internal +{ + sealed class RemoveEntityImplementor : IRemoveEntityComponent + { + public RemoveEntityImplementor(IEntityViewBuilder[] entityViews, int groupID):this(entityViews) + { + this.groupID = groupID; + isInAGroup = true; + } + + internal RemoveEntityImplementor(IEntityViewBuilder[] entityViews) + { + removeEntityInfo = new RemoveEntityInfo(entityViews); + } + + internal readonly RemoveEntityInfo removeEntityInfo; + internal readonly int groupID; + internal readonly bool isInAGroup; + } +} + +namespace Svelto.ECS +{ + public interface IRemoveEntityComponent + {} + + public struct RemoveEntityInfo + { + internal readonly IEntityViewBuilder[] entityViewsToBuild; + + public RemoveEntityInfo(IEntityViewBuilder[] entityViews) : this() + { + this.entityViewsToBuild = entityViews; + } + } +} diff --git a/ECS/Sequencer.cs b/Svelto.ECS/ECS/Sequencer.cs similarity index 100% rename from ECS/Sequencer.cs rename to Svelto.ECS/ECS/Sequencer.cs diff --git a/Svelto.ECS/ECS/SingleEntityViewEngine.cs b/Svelto.ECS/ECS/SingleEntityViewEngine.cs new file mode 100644 index 0000000..605f775 --- /dev/null +++ b/Svelto.ECS/ECS/SingleEntityViewEngine.cs @@ -0,0 +1,20 @@ +using Svelto.ECS.Internal; + +namespace Svelto.ECS +{ + public abstract class SingleEntityViewEngine : IHandleEntityViewEngine where T:EntityView, new() + { + public void Add(IEntityView entityView) + { + Add((T)entityView); //when byref returns will be vailable, this should be passed by reference, not copy! + } + + public void Remove(IEntityView entityView) + { + Remove((T)entityView); + } + + protected abstract void Add(T entityView); + protected abstract void Remove(T entityView); + } +} diff --git a/Factories/IGameObjectFactory.cs b/Svelto.ECS/Factories/IGameObjectFactory.cs similarity index 87% rename from Factories/IGameObjectFactory.cs rename to Svelto.ECS/Factories/IGameObjectFactory.cs index 7879bf3..03f35ce 100644 --- a/Factories/IGameObjectFactory.cs +++ b/Svelto.ECS/Factories/IGameObjectFactory.cs @@ -1,3 +1,4 @@ +#if UNITY_5_3_OR_NEWER || UNITY_5 using UnityEngine; namespace Svelto.Factories @@ -10,3 +11,4 @@ namespace Svelto.Factories GameObject Build(GameObject prefab); } } +#endif \ No newline at end of file diff --git a/Factories/IMonoBehaviourFactory.cs b/Svelto.ECS/Factories/IMonoBehaviourFactory.cs similarity index 80% rename from Factories/IMonoBehaviourFactory.cs rename to Svelto.ECS/Factories/IMonoBehaviourFactory.cs index cbf5e05..f32a349 100644 --- a/Factories/IMonoBehaviourFactory.cs +++ b/Svelto.ECS/Factories/IMonoBehaviourFactory.cs @@ -1,3 +1,5 @@ +#if UNITY_5_3_OR_NEWER || UNITY_5 + using System; using UnityEngine; @@ -9,3 +11,4 @@ namespace Svelto.Factories } } +#endif \ No newline at end of file diff --git a/LICENSE b/Svelto.ECS/LICENSE similarity index 100% rename from LICENSE rename to Svelto.ECS/LICENSE diff --git a/README.md b/Svelto.ECS/README.md similarity index 90% rename from README.md rename to Svelto.ECS/README.md index 3d8107a..ef18d33 100644 --- a/README.md +++ b/Svelto.ECS/README.md @@ -5,14 +5,18 @@ Svelto Entity Component System for Unity Real Entity-Component-System for c# and Unity (it can be adapted for other c# platforms too). Enables to write encapsulated, uncoupled, highly efficient, data oriented, cache friendly, multi-threaded, code without pain. -you can find a working example to learn how to use the framework here: +you can find working examples to learn how to use the framework here: -https://github.com/sebas77/Svelto-ECS-Example +https://github.com/sebas77/Svelto-ECS-Example (unity) + +https://github.com/sebas77/Svelto.ECS.Vanilla.Example (.net core and standard) I advise to clone the example repositories separately from the framework one, both under the same Unity project Assets folder. relative article: +http://www.sebaslab.com/svelto-ecs-2-0-almost-production-ready/ + http://www.sebaslab.com/ecs-1-0/ If you want to know more about the theory and rationale behind this framework: diff --git a/Utilities/Console.cs b/Utilities/Console.cs deleted file mode 100644 index cf11720..0000000 --- a/Utilities/Console.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -#if NETFX_CORE -using Windows.System.Diagnostics; -#else -using System.Diagnostics; -#endif -using System.Text; - -namespace Utility -{ - public static class Console - { - static StringBuilder _stringBuilder = new StringBuilder(256); -#if UNITY_5_3_OR_NEWER || UNITY_5 - public static ILogger logger = new SlowLoggerUnity(); -#else - public static ILogger logger = new SimpleLogger(); -#endif - public static volatile bool BatchLog = false; - - //Hack, have to find the right solution - public static Action onException; - - static Console() - { - onException = (e, obj, message, stack) => - { - UnityEngine.Debug.LogException(e, (UnityEngine.Object)obj); - }; - } - - public static void Log(string txt) - { - logger.Log(txt); - } - - public static void LogError(string txt) - { - string toPrint; - - lock (_stringBuilder) - { - _stringBuilder.Length = 0; - _stringBuilder.Append("-!!!!!!-> "); - _stringBuilder.Append(txt); - - toPrint = _stringBuilder.ToString(); - } - - logger.Log(toPrint, null, LogType.Error); - } - - public static void LogError(string txt, string stack) - { - string toPrint; - - lock (_stringBuilder) - { - _stringBuilder.Length = 0; - _stringBuilder.Append("-!!!!!!-> "); - _stringBuilder.Append(txt); - - toPrint = _stringBuilder.ToString(); - } - - logger.Log(toPrint, stack, LogType.Error); - } - - public static void LogException(Exception e) - { - LogException(e, null); - } - - public static void LogException(Exception e, UnityEngine.Object obj) - { - string toPrint; - string stackTrace; - - lock (_stringBuilder) - { - _stringBuilder.Length = 0; - _stringBuilder.Append("-!!!!!!-> ").Append(e.Message); - - stackTrace = e.StackTrace; - - if (e.InnerException != null) - { - e = e.InnerException; - - _stringBuilder.Append(" Inner Message: ").Append(e.Message).Append(" Inner Stacktrace:") - .Append(e.StackTrace); - - stackTrace = e.StackTrace; - } - - toPrint = _stringBuilder.ToString(); - } - - onException(e, obj, toPrint, stackTrace); - } - - public static void LogWarning(string txt) - { - string toPrint; - - lock (_stringBuilder) - { - _stringBuilder.Length = 0; - _stringBuilder.Append("------> "); - _stringBuilder.Append(txt); - - toPrint = _stringBuilder.ToString(); - } - - logger.Log(toPrint, null, LogType.Warning); - } - - /// - /// Use this function if you don't want the message to be batched - /// - /// - public static void SystemLog(string txt) - { - string toPrint; - - lock (_stringBuilder) - { -#if NETFX_CORE - string currentTimeString = DateTime.UtcNow.ToString("dd/mm/yy hh:ii:ss"); - string processTimeString = (DateTime.UtcNow - ProcessDiagnosticInfo.GetForCurrentProcess().ProcessStartTime.DateTime).ToString(); -#else - string currentTimeString = DateTime.UtcNow.ToLongTimeString(); //ensure includes seconds - string processTimeString = (DateTime.Now - Process.GetCurrentProcess().StartTime).ToString(); -#endif - - _stringBuilder.Length = 0; - _stringBuilder.Append("[").Append(currentTimeString); - _stringBuilder.Append("][").Append(processTimeString); - _stringBuilder.Length = _stringBuilder.Length - 3; //remove some precision that we don't need - _stringBuilder.Append("] ").AppendLine(txt); - - toPrint = _stringBuilder.ToString(); - } - -#if !UNITY_EDITOR && !NETFX_CORE - System.Console.WriteLine(toPrint); -#else - UnityEngine.Debug.Log(toPrint); -#endif - } - } -} \ No newline at end of file diff --git a/Utilities/DesignByContract.cs b/Utilities/DesignByContract.cs deleted file mode 100644 index b6a22d7..0000000 --- a/Utilities/DesignByContract.cs +++ /dev/null @@ -1,459 +0,0 @@ -// from: http://www.codeproject.com/Articles/1863/Design-by-Contract-Framework -// Provides support for Design By Contract -// as described by Bertrand Meyer in his seminal book, -// Object-Oriented Software Construction (2nd Ed) Prentice Hall 1997 -// (See chapters 11 and 12). -// -// See also Building Bug-free O-O Software: An Introduction to Design by Contract -// http://www.eiffel.com/doc/manuals/technology/contract/ -// -// The following conditional compilation symbols are supported: -// -// These suggestions are based on Bertrand Meyer's Object-Oriented Software Construction (2nd Ed) p393 -// -// DBC_CHECK_ALL - Check assertions - implies checking preconditions, postconditions and invariants -// DBC_CHECK_INVARIANT - Check invariants - implies checking preconditions and postconditions -// DBC_CHECK_POSTCONDITION - Check postconditions - implies checking preconditions -// DBC_CHECK_PRECONDITION - Check preconditions only, e.g., in Release build -// -// A suggested default usage scenario is the following: -// -// #if DEBUG -// #define DBC_CHECK_ALL -// #else -// #define DBC_CHECK_PRECONDITION -// #endif -// -// Alternatively, you can define these in the project properties dialog. - -#if DEBUG && !PROFILER -#define DBC_CHECK_ALL -#endif - -using System; -using System.Diagnostics; - -namespace DesignByContract -{ - /// - /// Design By Contract Checks. - /// - /// Each method generates an exception or - /// a trace assertion statement if the contract is broken. - /// - /// - /// This example shows how to call the Require method. - /// Assume DBC_CHECK_PRECONDITION is defined. - /// - /// public void Test(int x) - /// { - /// try - /// { - /// Check.Require(x > 1, "x must be > 1"); - /// } - /// catch (System.Exception ex) - /// { - /// Console.WriteLine(ex.ToString()); - /// } - /// } - /// - /// If you wish to use trace assertion statements, intended for Debug scenarios, - /// rather than exception handling then set - /// - /// Check.UseAssertions = true - /// - /// You can specify this in your application entry point and maybe make it - /// dependent on conditional compilation flags or configuration file settings, e.g., - /// - /// #if DBC_USE_ASSERTIONS - /// Check.UseAssertions = true; - /// #endif - /// - /// You can direct output to a Trace listener. For example, you could insert - /// - /// Trace.Listeners.Clear(); - /// Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); - /// - /// - /// or direct output to a file or the Event Log. - /// - /// (Note: For ASP.NET clients use the Listeners collection - /// of the Debug, not the Trace, object and, for a Release build, only exception-handling - /// is possible.) - /// - /// - public sealed class Check - { - #region Interface - - /// - /// Precondition check. - /// - [Conditional("DBC_CHECK_ALL"), - Conditional("DBC_CHECK_INVARIANT"), - Conditional("DBC_CHECK_POSTCONDITION"), - Conditional("DBC_CHECK_PRECONDITION")] - public static void Require(bool assertion, string message) - { - if (UseExceptions) - { - if (!assertion) - throw new PreconditionException(message); - } - else - { - Trace.Assert(assertion, "Precondition: " + message); - } - } - - /// - /// Precondition check. - /// - [Conditional("DBC_CHECK_ALL"), - Conditional("DBC_CHECK_INVARIANT"), - Conditional("DBC_CHECK_POSTCONDITION"), - Conditional("DBC_CHECK_PRECONDITION")] - public static void Require(bool assertion, string message, Exception inner) - { - if (UseExceptions) - { - if (!assertion) - throw new PreconditionException(message, inner); - } - else - { - Trace.Assert(assertion, "Precondition: " + message); - } - } - - /// - /// Precondition check. - /// - [Conditional("DBC_CHECK_ALL"), - Conditional("DBC_CHECK_INVARIANT"), - Conditional("DBC_CHECK_POSTCONDITION"), - Conditional("DBC_CHECK_PRECONDITION")] - public static void Require(bool assertion) - { - if (UseExceptions) - { - if (!assertion) - throw new PreconditionException("Precondition failed."); - } - else - { - Trace.Assert(assertion, "Precondition failed."); - } - } - - /// - /// Postcondition check. - /// - [Conditional("DBC_CHECK_ALL"), - Conditional("DBC_CHECK_INVARIANT"), - Conditional("DBC_CHECK_POSTCONDITION")] - public static void Ensure(bool assertion, string message) - { - if (UseExceptions) - { - if (!assertion) - throw new PostconditionException(message); - } - else - { - Trace.Assert(assertion, "Postcondition: " + message); - } - } - - /// - /// Postcondition check. - /// - [Conditional("DBC_CHECK_ALL"), - Conditional("DBC_CHECK_INVARIANT"), - Conditional("DBC_CHECK_POSTCONDITION")] - public static void Ensure(bool assertion, string message, Exception inner) - { - if (UseExceptions) - { - if (!assertion) - throw new PostconditionException(message, inner); - } - else - { - Trace.Assert(assertion, "Postcondition: " + message); - } - } - - /// - /// Postcondition check. - /// - [Conditional("DBC_CHECK_ALL"), - Conditional("DBC_CHECK_INVARIANT"), - Conditional("DBC_CHECK_POSTCONDITION")] - public static void Ensure(bool assertion) - { - if (UseExceptions) - { - if (!assertion) - throw new PostconditionException("Postcondition failed."); - } - else - { - Trace.Assert(assertion, "Postcondition failed."); - } - } - - /// - /// Invariant check. - /// - [Conditional("DBC_CHECK_ALL"), - Conditional("DBC_CHECK_INVARIANT")] - public static void Invariant(bool assertion, string message) - { - if (UseExceptions) - { - if (!assertion) - throw new InvariantException(message); - } - else - { - Trace.Assert(assertion, "Invariant: " + message); - } - } - - /// - /// Invariant check. - /// - [Conditional("DBC_CHECK_ALL"), - Conditional("DBC_CHECK_INVARIANT")] - public static void Invariant(bool assertion, string message, Exception inner) - { - if (UseExceptions) - { - if (!assertion) - throw new InvariantException(message, inner); - } - else - { - Trace.Assert(assertion, "Invariant: " + message); - } - } - - /// - /// Invariant check. - /// - [Conditional("DBC_CHECK_ALL"), - Conditional("DBC_CHECK_INVARIANT")] - public static void Invariant(bool assertion) - { - if (UseExceptions) - { - if (!assertion) - throw new InvariantException("Invariant failed."); - } - else - { - Trace.Assert(assertion, "Invariant failed."); - } - } - - /// - /// Assertion check. - /// - [Conditional("DBC_CHECK_ALL")] - public static void Assert(bool assertion, string message) - { - if (UseExceptions) - { - if (!assertion) - throw new AssertionException(message); - } - else - { - Trace.Assert(assertion, "Assertion: " + message); - } - } - - /// - /// Assertion check. - /// - [Conditional("DBC_CHECK_ALL")] - public static void Assert(bool assertion, string message, Exception inner) - { - if (UseExceptions) - { - if (!assertion) - throw new AssertionException(message, inner); - } - else - { - Trace.Assert(assertion, "Assertion: " + message); - } - } - - /// - /// Assertion check. - /// - [Conditional("DBC_CHECK_ALL")] - public static void Assert(bool assertion) - { - if (UseExceptions) - { - if (!assertion) - throw new AssertionException("Assertion failed."); - } - else - { - Trace.Assert(assertion, "Assertion failed."); - } - } - - /// - /// Set this if you wish to use Trace Assert statements - /// instead of exception handling. - /// (The Check class uses exception handling by default.) - /// - public static bool UseAssertions - { - get - { - return useAssertions; - } - set - { - useAssertions = value; - } - } - - #endregion // Interface - - #region Implementation - - // No creation - private Check() {} - - /// - /// Is exception handling being used? - /// - private static bool UseExceptions - { - get - { - return !useAssertions; - } - } - - // Are trace assertion statements being used? - // Default is to use exception handling. - private static bool useAssertions = false; - - #endregion // Implementation - - } // End Check - - internal class Trace - { - internal static void Assert(bool assertion, string v) - { -#if NETFX_CORE - System.Diagnostics.Contracts.Contract.Assert(assertion, v); -#else - System.Diagnostics.Trace.Assert(assertion, v); -#endif - } - } - - #region Exceptions - - /// - /// Exception raised when a contract is broken. - /// Catch this exception type if you wish to differentiate between - /// any DesignByContract exception and other runtime exceptions. - /// - /// - public class DesignByContractException : Exception - { - protected DesignByContractException() {} - protected DesignByContractException(string message) : base(message) {} - protected DesignByContractException(string message, Exception inner) : base(message, inner) {} - } - - /// - /// Exception raised when a precondition fails. - /// - public class PreconditionException : DesignByContractException - { - /// - /// Precondition Exception. - /// - public PreconditionException() {} - /// - /// Precondition Exception. - /// - public PreconditionException(string message) : base(message) {} - /// - /// Precondition Exception. - /// - public PreconditionException(string message, Exception inner) : base(message, inner) {} - } - - /// - /// Exception raised when a postcondition fails. - /// - public class PostconditionException : DesignByContractException - { - /// - /// Postcondition Exception. - /// - public PostconditionException() {} - /// - /// Postcondition Exception. - /// - public PostconditionException(string message) : base(message) {} - /// - /// Postcondition Exception. - /// - public PostconditionException(string message, Exception inner) : base(message, inner) {} - } - - /// - /// Exception raised when an invariant fails. - /// - public class InvariantException : DesignByContractException - { - /// - /// Invariant Exception. - /// - public InvariantException() {} - /// - /// Invariant Exception. - /// - public InvariantException(string message) : base(message) {} - /// - /// Invariant Exception. - /// - public InvariantException(string message, Exception inner) : base(message, inner) {} - } - - /// - /// Exception raised when an assertion fails. - /// - public class AssertionException : DesignByContractException - { - /// - /// Assertion Exception. - /// - public AssertionException() {} - /// - /// Assertion Exception. - /// - public AssertionException(string message) : base(message) {} - /// - /// Assertion Exception. - /// - public AssertionException(string message, Exception inner) : base(message, inner) {} - } - - #endregion // Exception classes - -} // End Design By Contract diff --git a/Utilities/FastConcatUtility.cs b/Utilities/FastConcatUtility.cs deleted file mode 100644 index db83efa..0000000 --- a/Utilities/FastConcatUtility.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.Text; - -public static class FastConcatUtility -{ - static readonly StringBuilder _stringBuilder = new StringBuilder(256); - - public static string FastConcat(this string str1, T str2) - { - lock (_stringBuilder) - { - _stringBuilder.Length = 0; - - _stringBuilder.Append(str1); - _stringBuilder.Append(str2); - - return _stringBuilder.ToString(); - } - } - - public static string FastConcat(this string str1, string str2, string str3) - { - lock (_stringBuilder) - { - _stringBuilder.Length = 0; - - _stringBuilder.Append(str1); - _stringBuilder.Append(str2); - _stringBuilder.Append(str3); - - return _stringBuilder.ToString(); - } - } - - public static string FastConcat(this string str1, string str2, string str3, string str4) - { - lock (_stringBuilder) - { - _stringBuilder.Length = 0; - - _stringBuilder.Append(str1); - _stringBuilder.Append(str2); - _stringBuilder.Append(str3); - _stringBuilder.Append(str4); - - - return _stringBuilder.ToString(); - } - } - - public static string FastConcat(this string str1, string str2, string str3, string str4, string str5) - { - lock (_stringBuilder) - { - _stringBuilder.Length = 0; - - _stringBuilder.Append(str1); - _stringBuilder.Append(str2); - _stringBuilder.Append(str3); - _stringBuilder.Append(str4); - _stringBuilder.Append(str5); - - return _stringBuilder.ToString(); - } - } - - public static string FastJoin(this string[] str) - { - lock (_stringBuilder) - { - _stringBuilder.Length = 0; - - for (int i = 0; i < str.Length; i++) - _stringBuilder.Append(str[i]); - - return _stringBuilder.ToString(); - } - } - - public static string FastJoin(this string[] str, string str1) - { - lock (_stringBuilder) - { - _stringBuilder.Length = 0; - - for (int i = 0; i < str.Length; i++) - _stringBuilder.Append(str[i]); - - _stringBuilder.Append(str1); - - return _stringBuilder.ToString(); - } - } -} - -namespace Utility -{ -#if UNITY_5 || UNITY_5_3_OR_NEWER -#endif -} diff --git a/Utilities/ILogger.cs b/Utilities/ILogger.cs deleted file mode 100644 index 20eaa23..0000000 --- a/Utilities/ILogger.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Utility -{ - public enum LogType - { - Log, - Exception, - Warning, - Error - } - public interface ILogger - { - void Log (string txt, string stack = null, LogType type = LogType.Log); - } -} \ No newline at end of file diff --git a/Utilities/Murmur3.cs b/Utilities/Murmur3.cs deleted file mode 100644 index 6e83e68..0000000 --- a/Utilities/Murmur3.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System; -using System.IO; - -/// -/// Murmur hash. -/// -/// Creates an evenly destributed uint hash from a string. -/// Very fast and fairly unique -/// - -public class Murmur3 -{ - static public uint MurmurHash3_x86_32(byte[] data, uint length, uint seed) - { - uint nblocks = length >> 2; - - uint h1 = seed; - - const uint c1 = 0xcc9e2d51; - const uint c2 = 0x1b873593; - - //---------- - // body - - int i = 0 ; - - for (uint j = nblocks; j > 0 ; --j) - { - uint k1l = BitConverter.ToUInt32(data, i); - - k1l *= c1; - k1l = rotl32(k1l, 15); - k1l *= c2; - - h1 ^= k1l; - h1 = rotl32(h1, 13); - h1 = h1 * 5 + 0xe6546b64; - - i+=4; - } - - //---------- - // tail - - nblocks <<= 2; - - uint k1 = 0; - - uint tailLength = length & 3; - - if (tailLength == 3) - k1 ^= (uint)data[2 + nblocks] << 16; - if (tailLength >= 2) - k1 ^= (uint)data[1 + nblocks] << 8; - if (tailLength >= 1) - { - k1 ^= data[nblocks]; - k1 *= c1; k1 = rotl32(k1, 15); k1 *= c2; h1 ^= k1; - } - - //---------- - // finalization - - h1 ^= length; - - h1 = fmix32(h1); - - return h1; - } - - static uint fmix32(uint h) - { - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - - return h; - } - - static uint rotl32(uint x, byte r) - { - return (x << r) | (x >> (32 - r)); - } - - static public bool VerificationTest() - { - byte[] key = new byte[256]; - byte[] hashes = new byte[1024]; - - for (uint i = 0; i < 256; i++) - { - key[i] = (byte)i; - - uint result = MurmurHash3_x86_32(key, i, 256 - i); - - Buffer.BlockCopy(BitConverter.GetBytes(result), 0, hashes, (int)i * 4, 4); - } - - // Then hash the result array - - uint finalr = MurmurHash3_x86_32(hashes, 1024, 0); - - uint verification = 0xB0F57EE3; - - //---------- - - if (verification != finalr) - { - return false; - } - else - { - System.Diagnostics.Debug.WriteLine("works"); - - return true; - } - } -} diff --git a/Utilities/PropertyInfoExtensions.cs b/Utilities/PropertyInfoExtensions.cs deleted file mode 100644 index 87b18d8..0000000 --- a/Utilities/PropertyInfoExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Reflection; - -public static class NetFXCoreWrappers -{ - public static MethodInfo GetMethodInfoEx(this Delegate delegateEx) - { -#if NETFX_CORE - var method = delegateEx.GetMethodInfo(); -#else - var method = delegateEx.Method; -#endif - return method; - } - - public static Type GetDeclaringType(this MethodInfo methodInfo) - { -#if NETFX_CORE - return methodInfo.DeclaringType; -#else - return methodInfo.ReflectedType; -#endif - } -} diff --git a/Utilities/SimpleLogger.cs b/Utilities/SimpleLogger.cs deleted file mode 100644 index 454e1dc..0000000 --- a/Utilities/SimpleLogger.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Utility -{ - public class SimpleLogger : ILogger - { - public void Log(string txt, string stack = null, LogType type = LogType.Log) - { - switch (type) - { - case LogType.Log: - Console.SystemLog(stack != null ? txt.FastConcat(stack) : txt); - break; - case LogType.Exception: - Console.SystemLog("Log of exceptions not supported"); - break; - case LogType.Warning: - Console.SystemLog(stack != null ? txt.FastConcat(stack) : txt); - break; - case LogType.Error: - Console.SystemLog(stack != null ? txt.FastConcat(stack) : txt); - break; - } - } - } -} \ No newline at end of file diff --git a/Utilities/SlowLoggerUnity.cs b/Utilities/SlowLoggerUnity.cs deleted file mode 100644 index 6d5a33d..0000000 --- a/Utilities/SlowLoggerUnity.cs +++ /dev/null @@ -1,26 +0,0 @@ -#if UNITY_5_3_OR_NEWER || UNITY_5 -namespace Utility -{ - public class SlowLoggerUnity : ILogger - { - public void Log(string txt, string stack = null, LogType type = LogType.Log) - { - switch (type) - { - case LogType.Log: - UnityEngine.Debug.Log(stack != null ? txt.FastConcat(stack) : txt); - break; - case LogType.Exception: - UnityEngine.Debug.LogError("Log of exceptions not supported"); - break; - case LogType.Warning: - UnityEngine.Debug.LogWarning(stack != null ? txt.FastConcat(stack) : txt); - break; - case LogType.Error: - UnityEngine.Debug.LogError(stack != null ? txt.FastConcat(stack) : txt); - break; - } - } - } -} -#endif \ No newline at end of file diff --git a/WeakEvents/SafeEvent.cs b/WeakEvents/SafeEvent.cs deleted file mode 100644 index 846e58c..0000000 --- a/WeakEvents/SafeEvent.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; - -public static class SafeEvent -{ - public static void SafeRaise(this Action onEvent, T val) - { - if (onEvent != null) - { - var length = onEvent.GetInvocationList().Length; - for (int index = 0; index < length; index++) - { - Action handler = (Action) onEvent.GetInvocationList()[index]; - - try - { - if (handler != null) handler.Invoke(val); - } - catch (Exception e) - { - Utility.Console.LogException(e); - } - } - } - } - - public static void SafeRaise(this Action onEvent) - { - if (onEvent != null) - { - var length = onEvent.GetInvocationList().Length; - for (int index = 0; index < length; index++) - { - Action handler = (Action)onEvent.GetInvocationList()[index]; - - try - { - if (handler != null) handler.Invoke(); - } - catch (Exception e) - { - Utility.Console.LogException(e); - } - } - } - } -} - diff --git a/WeakEvents/WeakAction.cs b/WeakEvents/WeakAction.cs deleted file mode 100644 index 8c5ece6..0000000 --- a/WeakEvents/WeakAction.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Reflection; -using System.Runtime.CompilerServices; - -namespace Svelto.WeakEvents -{ - public class WeakAction : WeakAction - { - public WeakAction(Action listener) - : base(listener.Target, listener.GetMethodInfoEx()) - {} - - public void Invoke(T1 data1, T2 data2) - { - _data[0] = data1; - _data[1] = data2; - - Invoke_Internal(_data); - } - - readonly object[] _data = new object[2]; - } - - public class WeakAction : WeakActionBase - { - public WeakAction(Action listener) - : base(listener.Target, listener.GetMethodInfoEx()) - {} - - public void Invoke(T data) - { - _data[0] = data; - - Invoke_Internal(_data); - } - - readonly object[] _data = new object[1]; - } - - public class WeakAction : WeakActionBase - { - public WeakAction(Action listener) : base(listener) - {} - - public WeakAction(object listener, MethodInfo method) : base(listener, method) - {} - - public void Invoke() - { - Invoke_Internal(null); - } - } - - public abstract class WeakActionBase - { - protected readonly DataStructures.WeakReference ObjectRef; - protected readonly MethodInfo Method; - - public bool IsValid - { - get { return ObjectRef.IsValid; } - } - - protected WeakActionBase(Action listener) - : this(listener.Target, listener.GetMethodInfoEx()) - {} - - protected WeakActionBase(object listener, MethodInfo method) - { - ObjectRef = new DataStructures.WeakReference(listener); - - Method = method; - -#if NETFX_CORE - var attributes = (CompilerGeneratedAttribute[])method.GetType().GetTypeInfo().GetCustomAttributes(typeof(CompilerGeneratedAttribute), false); - if (attributes.Length != 0) - throw new ArgumentException("Cannot create weak event to anonymous method with closure."); -#else - if (method.DeclaringType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Length != 0) - throw new ArgumentException("Cannot create weak event to anonymous method with closure."); -#endif - } - - protected void Invoke_Internal(object[] data) - { - if (ObjectRef.IsValid) - Method.Invoke(ObjectRef.Target, data); - else - Utility.Console.LogWarning("Target of weak action has been garbage collected"); - } - } -} \ No newline at end of file diff --git a/WeakEvents/WeakActionStruct.cs b/WeakEvents/WeakActionStruct.cs deleted file mode 100644 index 7686934..0000000 --- a/WeakEvents/WeakActionStruct.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -//careful, you must handle the destruction of the GCHandles! -namespace Svelto.WeakEvents -{ - public struct WeakActionStruct : IEquatable>, IDisposable - { - public WeakActionStruct(Action listener) - { - WeakActionStructUtility.Init(listener.Target, listener.GetMethodInfoEx(), out _objectRef, out _method); - } - - public bool Invoke(object[] args) - { - return WeakActionStructUtility.Invoke(ref _objectRef, _method, args); - } - - public bool Equals(WeakActionStruct other) - { - return WeakActionStructUtility.IsMatch(_objectRef.Target, _method, - other._objectRef.Target, other._method); - } - - public void Dispose() - { - _objectRef.Free(); - } - - public bool IsMatch(object otherObject, MethodInfo otherMethod) - { - return WeakActionStructUtility.IsMatch(_objectRef.Target, _method, - otherObject, otherMethod); - } - - GCHandle _objectRef; - readonly MethodInfo _method; - } - - public struct WeakActionStruct : IEquatable>, IDisposable - { - public WeakActionStruct(Action listener) - { - WeakActionStructUtility.Init(listener.Target, listener.GetMethodInfoEx(), - out _objectRef, out _method); - } - - public bool Invoke(object[] args) - { - return WeakActionStructUtility.Invoke(ref _objectRef, _method, args); - } - - public bool Equals(WeakActionStruct other) - { - return WeakActionStructUtility.IsMatch(_objectRef.Target, _method, - other._objectRef.Target, other._method); - } - - public void Dispose() - { - _objectRef.Free(); - } - - public bool IsMatch(object otherObject, MethodInfo otherMethod) - { - return WeakActionStructUtility.IsMatch(_objectRef.Target, _method, - otherObject, otherMethod); - } - - GCHandle _objectRef; - readonly MethodInfo _method; - } - - public struct WeakActionStruct : IEquatable, IDisposable - { - public WeakActionStruct(Action listener) - { - WeakActionStructUtility.Init(listener.Target, listener.GetMethodInfoEx(), - out _objectRef, out _method); - } - - public bool Invoke() - { - return WeakActionStructUtility.Invoke(ref _objectRef, _method, null); - } - - public bool Equals(WeakActionStruct other) - { - return WeakActionStructUtility.IsMatch(_objectRef.Target, _method, - other._objectRef.Target, other._method); - } - - public void Dispose() - { - _objectRef.Free(); - } - - public bool IsMatch(object otherObject, MethodInfo otherMethod) - { - return WeakActionStructUtility.IsMatch(_objectRef.Target, _method, - otherObject, otherMethod); - } - - GCHandle _objectRef; - readonly MethodInfo _method; - } - - static class WeakActionStructUtility - { - internal static void Init(object target, MethodInfo method, - out GCHandle objectRef, out MethodInfo methodOut) - { - objectRef = GCHandle.Alloc(target, GCHandleType.Weak); - methodOut = method; - -#if DEBUG && !PROFILER -#if NETFX_CORE - Method = listener.GetMethodInfo(); - var attributes = (CompilerGeneratedAttribute[])Method.GetType().GetTypeInfo().GetCustomAttributes(typeof(CompilerGeneratedAttribute), false); - if(attributes.Length != 0) - throw new ArgumentException("Cannot create weak event to anonymous method with closure."); -#else - if (method.DeclaringType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Length != 0) - throw new ArgumentException("Cannot create weak event to anonymous method with closure."); -#endif -#endif - } - - public static bool Invoke(ref GCHandle objectRef, MethodInfo method, object[] args) - { - if (objectRef.IsAllocated && objectRef.Target != null) - { - method.Invoke(objectRef.Target, args); - return true; - } - - Dispose(ref objectRef); - return false; - } - - public static void Dispose(ref GCHandle objectRef) - { - objectRef.Free(); - } - - public static bool IsMatch(object objectRef, MethodInfo method, - object _objectRef, MethodInfo _method) - { - return _method.Equals(method) && objectRef.Equals(_objectRef); - } - } -} \ No newline at end of file diff --git a/WeakEvents/WeakEvent.cs b/WeakEvents/WeakEvent.cs deleted file mode 100644 index 485df35..0000000 --- a/WeakEvents/WeakEvent.cs +++ /dev/null @@ -1,163 +0,0 @@ -using Svelto.DataStructures; -using System; -using System.Reflection; - -namespace Svelto.WeakEvents -{ - public class WeakEvent - { - public static WeakEvent operator+(WeakEvent c1, Action x) - { - if (c1 == null) c1 = new WeakEvent(); - c1._subscribers.Add(new WeakActionStruct(x)); - - return c1; - } - - public static WeakEvent operator-(WeakEvent c1, Action x) - { - DesignByContract.Check.Require(x != null); - c1.Remove(x.Target, x.GetMethodInfoEx()); - - return c1; - } - - public void Invoke() - { - for (int i = 0; i < _subscribers.Count; i++) - if (_subscribers[i].Invoke() == false) - _subscribers.UnorderedRemoveAt(i--); - } - - void Remove(object thisObject, MethodInfo thisMethod) - { - for (int i = 0; i < _subscribers.Count; ++i) - { - var otherObject = _subscribers[i]; - - if (otherObject.IsMatch(thisObject, thisMethod)) - { - _subscribers.UnorderedRemoveAt(i); - break; - } - } - } - - ~WeakEvent() - { - for (int i = 0; i < _subscribers.Count; i++) - _subscribers[i].Dispose(); - } - - readonly FasterList - _subscribers = new FasterList(); - } - - public class WeakEvent - { - public static WeakEvent operator+(WeakEvent c1, Action x) - { - if (c1 == null) c1 = new WeakEvent(); - c1._subscribers.Add(new WeakActionStruct(x)); - - return c1; - } - - public static WeakEvent operator-(WeakEvent c1, Action x) - { - DesignByContract.Check.Require(x != null); - c1.Remove(x.Target, x.GetMethodInfoEx()); - - return c1; - } - - public void Invoke(T1 arg1) - { - args[0] = arg1; - - for (int i = 0; i < _subscribers.Count; i++) - if (_subscribers[i].Invoke(args) == false) - _subscribers.UnorderedRemoveAt(i--); - } - - void Remove(object thisObject, MethodInfo thisMethod) - { - for (int i = 0; i < _subscribers.Count; ++i) - { - var otherObject = _subscribers[i]; - - if (otherObject.IsMatch(thisObject, thisMethod)) - { - _subscribers.UnorderedRemoveAt(i); - break; - } - } - } - - ~WeakEvent() - { - for (int i = 0; i < _subscribers.Count; i++) - _subscribers[i].Dispose(); - } - - readonly object[] args = new object[1]; - - readonly FasterList> - _subscribers = new FasterList>(); - } - - public class WeakEvent - { - public static WeakEvent operator+(WeakEvent c1, Action x) - { - if (c1 == null) c1 = new WeakEvent(); - c1._subscribers.Add(new WeakActionStruct(x)); - - return c1; - } - - public static WeakEvent operator-(WeakEvent c1, Action x) - { - DesignByContract.Check.Require(x != null); - c1.Remove(x.Target, x.GetMethodInfoEx()); - - return c1; - } - - public void Invoke(T1 arg1, T2 arg2) - { - args[0] = arg1; - args[1] = arg2; - - for (int i = 0; i < _subscribers.Count; i++) - if (_subscribers[i].Invoke(args) == false) - _subscribers.UnorderedRemoveAt(i--); - } - - void Remove(object thisObject, MethodInfo thisMethod) - { - for (int i = 0; i < _subscribers.Count; ++i) - { - var otherObject = _subscribers[i]; - - if (otherObject.IsMatch(thisObject, thisMethod)) - { - _subscribers.UnorderedRemoveAt(i); - - break; - } - } - } - - ~WeakEvent() - { - for (int i = 0; i < _subscribers.Count; i++) - _subscribers[i].Dispose(); - } - - readonly object[] args = new object[2]; - - readonly FasterList> - _subscribers = new FasterList>(); - } -}