@@ -1,2 +1,4 @@ | |||
/EntitySystem/note.txt | |||
/EntitySystem/note.txt.meta | |||
/*.meta | |||
*.meta |
@@ -1,9 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 9e37272d8aa8b6e4cb7b1fc15f1e57a8 | |||
folderAsset: yes | |||
timeCreated: 1431201025 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: d74bed1689bb4114aa8a1f95cd95c788 | |||
timeCreated: 1431300049 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,9 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: ec4bd87e898bf7c42823fb5ec2456b43 | |||
folderAsset: yes | |||
timeCreated: 1431630831 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 613a705e128b35e4f9361e29f4661191 | |||
timeCreated: 1431630831 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 369e3378b91069c4aadba2af5aa8882b | |||
timeCreated: 1431630831 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,7 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 48c80cc65bea8254ba8082043f53405e | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: a28c8df5741efe54ea588a1bcea92f0f | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 36b1da25aaa515e4bad98fa0f61bc662 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 93cf465dd97f6144390620250c362485 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,7 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 54e46daa2d2d723499a114d6d8de9dc2 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} |
@@ -1,9 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 6663fc83070cb0842b4665b38356feb2 | |||
folderAsset: yes | |||
timeCreated: 1463348260 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -9,7 +9,7 @@ namespace Svelto.DataStructures | |||
// isn't taken into account (we would have to do a shift in both arrays) | |||
// Could be added as an option? | |||
class CircularBufferIndexer<TKey, TVal> : IDictionary<TKey, TVal> | |||
public class CircularBufferIndexer<TKey, TVal> : IDictionary<TKey, TVal> | |||
{ | |||
public ICollection<TKey> Keys | |||
{ | |||
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 0d87fb4479e8365499c162fe0fc94acc | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -121,6 +121,8 @@ namespace Svelto.DataStructures | |||
public struct FasterReadOnlyList<T> : IList<T> | |||
{ | |||
public static FasterReadOnlyList<T> DefaultList = new FasterReadOnlyList<T>(new FasterList<T>()); | |||
public int Count { get { return _list.Count; } } | |||
public bool IsReadOnly { get { return true; } } | |||
@@ -193,7 +195,8 @@ namespace Svelto.DataStructures | |||
{ | |||
public FasterListThreadSafe(FasterList<T> list) | |||
{ | |||
_list = list; | |||
if (list == null) throw new ArgumentException("invalid list"); | |||
_list = list; | |||
_lockQ = new ReaderWriterLockSlim(); | |||
} | |||
@@ -273,6 +276,19 @@ namespace Svelto.DataStructures | |||
} | |||
} | |||
public void FastClear() | |||
{ | |||
_lockQ.EnterWriteLock(); | |||
try | |||
{ | |||
_list.FastClear(); | |||
} | |||
finally | |||
{ | |||
_lockQ.ExitWriteLock(); | |||
} | |||
} | |||
public bool Contains(T item) | |||
{ | |||
_lockQ.EnterReadLock(); | |||
@@ -288,14 +304,14 @@ namespace Svelto.DataStructures | |||
public void CopyTo(T[] array, int arrayIndex) | |||
{ | |||
_lockQ.EnterWriteLock(); | |||
_lockQ.EnterReadLock(); | |||
try | |||
{ | |||
_list.CopyTo(array, arrayIndex); | |||
} | |||
finally | |||
{ | |||
_lockQ.ExitWriteLock(); | |||
_lockQ.ExitReadLock(); | |||
} | |||
} | |||
@@ -351,6 +367,19 @@ namespace Svelto.DataStructures | |||
} | |||
} | |||
public void UnorderedRemoveAt(int index) | |||
{ | |||
_lockQ.EnterWriteLock(); | |||
try | |||
{ | |||
_list.UnorderedRemoveAt(index); | |||
} | |||
finally | |||
{ | |||
_lockQ.ExitWriteLock(); | |||
} | |||
} | |||
IEnumerator<T> IEnumerable<T>.GetEnumerator() | |||
{ | |||
throw new NotImplementedException(); | |||
@@ -368,7 +397,7 @@ namespace Svelto.DataStructures | |||
public struct FasterReadOnlyListCast<T, U> : IList<U> where U:T | |||
{ | |||
public static FasterList<T> DefaultList = new FasterList<T>(); | |||
public static FasterReadOnlyListCast<T, U> DefaultList = new FasterReadOnlyListCast<T, U>(new FasterList<T>()); | |||
public int Count { get { return _list.Count; } } | |||
public bool IsReadOnly { get { return true; } } | |||
@@ -402,7 +431,7 @@ namespace Svelto.DataStructures | |||
public void CopyTo(U[] array, int arrayIndex) | |||
{ | |||
throw new NotImplementedException(); | |||
Array.Copy(_list.ToArrayFast(), 0, array, arrayIndex, _list.Count); | |||
} | |||
public bool Remove(U item) | |||
@@ -438,7 +467,10 @@ namespace Svelto.DataStructures | |||
readonly FasterList<T> _list; | |||
} | |||
public class FasterList<T> : IList<T> | |||
public interface IFasterList | |||
{} | |||
public class FasterList<T> : IList<T>, IFasterList | |||
{ | |||
const int MIN_SIZE = 4; | |||
@@ -513,7 +545,7 @@ namespace Svelto.DataStructures | |||
for (int i = 0; i < initialSize; i++) | |||
list.Add(new U()); | |||
list.Clear(); | |||
list._count = 0; | |||
return list; | |||
} | |||
@@ -553,6 +585,11 @@ namespace Svelto.DataStructures | |||
_count += count; | |||
} | |||
public void AddRange(T[] items) | |||
{ | |||
AddRange(items, items.Length); | |||
} | |||
public FasterReadOnlyList<T> AsReadOnly() | |||
{ | |||
return new FasterReadOnlyList<T>(this); | |||
@@ -562,12 +599,12 @@ namespace Svelto.DataStructures | |||
/// Careful, you could keep on holding references you don't want to hold to anymore | |||
/// Use DeepClear in case. | |||
/// </summary> | |||
public void Clear() | |||
public void FastClear() | |||
{ | |||
_count = 0; | |||
} | |||
public void DeepClear() | |||
public void Clear() | |||
{ | |||
Array.Clear(_buffer, 0, _buffer.Length); | |||
@@ -689,32 +726,32 @@ namespace Svelto.DataStructures | |||
return _buffer; | |||
} | |||
public bool UnorderredRemove(T item) | |||
public bool UnorderedRemove(T item) | |||
{ | |||
var index = IndexOf(item); | |||
if (index == -1) | |||
return false; | |||
UnorderredRemoveAt(index); | |||
UnorderedRemoveAt(index); | |||
return true; | |||
} | |||
public T UnorderredRemoveAt(int index) | |||
public bool UnorderedRemoveAt(int index) | |||
{ | |||
DesignByContract.Check.Require(index < _count && _count > 0, "out of bound index"); | |||
T item = _buffer[index]; | |||
if (index == --_count) | |||
return item; | |||
{ | |||
_buffer[_count] = default(T); | |||
return false; | |||
} | |||
T swap = _buffer[index]; | |||
_buffer[index] = _buffer[_count]; | |||
_buffer[_count] = swap; | |||
_buffer[_count] = default(T); | |||
return item; | |||
return true; | |||
} | |||
IEnumerator IEnumerable.GetEnumerator() | |||
@@ -752,14 +789,15 @@ namespace Svelto.DataStructures | |||
Resize(_count); | |||
} | |||
public bool Reuse(int index, out T result) | |||
public bool Reuse<U>(int index, out U result) | |||
where U:class, T | |||
{ | |||
result = default(T); | |||
result = default(U); | |||
if (index >= _buffer.Length) | |||
return false; | |||
result = _buffer[index]; | |||
result = (U)_buffer[index]; | |||
return result != null; | |||
} | |||
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: d19e59cbec974dd4d821a7dd21f87a88 | |||
timeCreated: 1472488070 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 0cfa789b3147c2e4e80d067693a58103 | |||
timeCreated: 1455809369 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,142 @@ | |||
using System.Collections.Generic; | |||
using System.Threading; | |||
//from unify wiki | |||
namespace Svelto.DataStructures | |||
{ | |||
public class SingleLinkNode<T> | |||
{ | |||
// Note; the Next member cannot be a property since | |||
// it participates in many CAS operations | |||
public SingleLinkNode<T> Next; | |||
public T Item; | |||
} | |||
public static class SyncMethods | |||
{ | |||
public static bool CAS<T>(ref T location, T comparand, T newValue) where T : class | |||
{ | |||
return | |||
(object)comparand == | |||
(object)Interlocked.CompareExchange<T>(ref location, newValue, comparand); | |||
} | |||
} | |||
public class LockFreeLinkPool<T> | |||
{ | |||
private SingleLinkNode<T> head; | |||
public LockFreeLinkPool() | |||
{ | |||
head = new SingleLinkNode<T>(); | |||
} | |||
public void Push(SingleLinkNode<T> newNode) | |||
{ | |||
newNode.Item = default(T); | |||
do | |||
{ | |||
newNode.Next = head.Next; | |||
} while (!SyncMethods.CAS<SingleLinkNode<T>>(ref head.Next, newNode.Next, newNode)); | |||
return; | |||
} | |||
public bool Pop(out SingleLinkNode<T> node) | |||
{ | |||
do | |||
{ | |||
node = head.Next; | |||
if (node == null) | |||
{ | |||
return false; | |||
} | |||
} while (!SyncMethods.CAS<SingleLinkNode<T>>(ref head.Next, node, node.Next)); | |||
return true; | |||
} | |||
} | |||
public class LockFreeQueue<T> | |||
{ | |||
SingleLinkNode<T> head; | |||
SingleLinkNode<T> tail; | |||
LockFreeLinkPool<T> trash; | |||
public LockFreeQueue() | |||
{ | |||
head = new SingleLinkNode<T>(); | |||
tail = head; | |||
trash = new LockFreeLinkPool<T>(); | |||
} | |||
public void Enqueue(T item) | |||
{ | |||
SingleLinkNode<T> oldTail = null; | |||
SingleLinkNode<T> oldTailNext; | |||
SingleLinkNode<T> newNode; | |||
if (!trash.Pop(out newNode)) | |||
{ | |||
newNode = new SingleLinkNode<T>(); | |||
} | |||
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<SingleLinkNode<T>>(ref tail.Next, null, newNode); | |||
else | |||
SyncMethods.CAS<SingleLinkNode<T>>(ref tail, oldTail, oldTailNext); | |||
} | |||
} | |||
SyncMethods.CAS<SingleLinkNode<T>>(ref tail, oldTail, newNode); | |||
} | |||
public bool Dequeue(out T item) | |||
{ | |||
item = default(T); | |||
SingleLinkNode<T> oldHead = null; | |||
bool haveAdvancedHead = false; | |||
while (!haveAdvancedHead) | |||
{ | |||
oldHead = head; | |||
SingleLinkNode<T> oldTail = tail; | |||
SingleLinkNode<T> oldHeadNext = oldHead.Next; | |||
if (oldHead == head) | |||
{ | |||
if (oldHead == oldTail) | |||
{ | |||
if (oldHeadNext == null) | |||
{ | |||
return false; | |||
} | |||
SyncMethods.CAS<SingleLinkNode<T>>(ref tail, oldTail, oldHeadNext); | |||
} | |||
else | |||
{ | |||
item = oldHeadNext.Item; | |||
haveAdvancedHead = SyncMethods.CAS<SingleLinkNode<T>>(ref head, oldHead, oldHeadNext); | |||
if (haveAdvancedHead) | |||
{ | |||
trash.Push(oldHead); | |||
} | |||
} | |||
} | |||
} | |||
return true; | |||
} | |||
} | |||
} |
@@ -1,5 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 8fffa27a4e8919a4db6fe1369e22e1b5 | |||
folderAsset: yes | |||
DefaultImporter: | |||
userData: |
@@ -66,7 +66,7 @@ namespace Svelto.DataStructures | |||
#endif | |||
public void Clear() | |||
{ | |||
_nodes.Clear(); | |||
_nodes.FastClear(); | |||
_numNodes = 0; | |||
} | |||
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: ac754b29409379046935c0890bab6dc5 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 5d399e4c2c1fe1f47833d6b70bf16184 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 2a6cc02a61a6ff549b1dcac74c71681f | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: e13aaf89d27048246bcf0d30c0993cf3 | |||
timeCreated: 1459332966 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -3,8 +3,6 @@ using System; | |||
using System.Collections.Generic; | |||
using System.Threading; | |||
//note, rewrite like ThreadSafeQueue | |||
namespace Svelto.DataStructures | |||
{ | |||
/// <summary> | |||
@@ -31,10 +29,15 @@ namespace Svelto.DataStructures | |||
{ | |||
get | |||
{ | |||
using (new ReadOnlyLock(dictionaryLock)) | |||
LockQ.EnterReadLock(); | |||
try | |||
{ | |||
return dict.Count; | |||
} | |||
finally | |||
{ | |||
LockQ.ExitReadLock(); | |||
} | |||
} | |||
} | |||
@@ -42,10 +45,15 @@ namespace Svelto.DataStructures | |||
{ | |||
get | |||
{ | |||
using (new ReadOnlyLock(dictionaryLock)) | |||
LockQ.EnterReadLock(); | |||
try | |||
{ | |||
return dict.IsReadOnly; | |||
} | |||
finally | |||
{ | |||
LockQ.ExitReadLock(); | |||
} | |||
} | |||
} | |||
@@ -53,10 +61,15 @@ namespace Svelto.DataStructures | |||
{ | |||
get | |||
{ | |||
using (new ReadOnlyLock(dictionaryLock)) | |||
LockQ.EnterReadLock(); | |||
try | |||
{ | |||
return new FasterList<TKey>(dict.Keys); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitReadLock(); | |||
} | |||
} | |||
} | |||
@@ -64,10 +77,15 @@ namespace Svelto.DataStructures | |||
{ | |||
get | |||
{ | |||
using (new ReadOnlyLock(dictionaryLock)) | |||
LockQ.EnterReadLock(); | |||
try | |||
{ | |||
return new FasterList<TValue>(dict.Values); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitReadLock(); | |||
} | |||
} | |||
} | |||
@@ -75,91 +93,146 @@ namespace Svelto.DataStructures | |||
{ | |||
get | |||
{ | |||
using (new ReadOnlyLock(dictionaryLock)) | |||
LockQ.EnterReadLock(); | |||
try | |||
{ | |||
return dict[key]; | |||
} | |||
finally | |||
{ | |||
LockQ.ExitReadLock(); | |||
} | |||
} | |||
set | |||
{ | |||
using (new WriteLock(dictionaryLock)) | |||
LockQ.EnterWriteLock(); | |||
try | |||
{ | |||
dict[key] = value; | |||
} | |||
finally | |||
{ | |||
LockQ.ExitWriteLock(); | |||
} | |||
} | |||
} | |||
public virtual void Add(KeyValuePair<TKey, TValue> item) | |||
{ | |||
using (new WriteLock(dictionaryLock)) | |||
LockQ.EnterWriteLock(); | |||
try | |||
{ | |||
dict.Add(item); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitWriteLock(); | |||
} | |||
} | |||
public virtual void Clear() | |||
{ | |||
using (new WriteLock(dictionaryLock)) | |||
LockQ.EnterWriteLock(); | |||
try | |||
{ | |||
dict.Clear(); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitWriteLock(); | |||
} | |||
} | |||
public virtual bool Contains(KeyValuePair<TKey, TValue> item) | |||
{ | |||
using (new ReadOnlyLock(dictionaryLock)) | |||
LockQ.EnterReadLock(); | |||
try | |||
{ | |||
return dict.Contains(item); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitReadLock(); | |||
} | |||
} | |||
public virtual void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) | |||
{ | |||
using (new ReadOnlyLock(dictionaryLock)) | |||
LockQ.EnterReadLock(); | |||
try | |||
{ | |||
dict.CopyTo(array, arrayIndex); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitReadLock(); | |||
} | |||
} | |||
public virtual bool Remove(KeyValuePair<TKey, TValue> item) | |||
{ | |||
using (new WriteLock(dictionaryLock)) | |||
LockQ.EnterWriteLock(); | |||
try | |||
{ | |||
return dict.Remove(item); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitWriteLock(); | |||
} | |||
} | |||
public virtual void Add(TKey key, TValue value) | |||
{ | |||
using (new WriteLock(dictionaryLock)) | |||
LockQ.EnterWriteLock(); | |||
try | |||
{ | |||
dict.Add(key, value); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitWriteLock(); | |||
} | |||
} | |||
public virtual bool ContainsKey(TKey key) | |||
{ | |||
using (new ReadOnlyLock(dictionaryLock)) | |||
LockQ.EnterReadLock(); | |||
try | |||
{ | |||
return dict.ContainsKey(key); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitReadLock(); | |||
} | |||
} | |||
public virtual bool Remove(TKey key) | |||
{ | |||
using (new WriteLock(dictionaryLock)) | |||
LockQ.EnterWriteLock(); | |||
try | |||
{ | |||
return dict.Remove(key); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitWriteLock(); | |||
} | |||
} | |||
public virtual bool TryGetValue(TKey key, out TValue value) | |||
{ | |||
using (new ReadOnlyLock(dictionaryLock)) | |||
LockQ.EnterReadLock(); | |||
try | |||
{ | |||
return dict.TryGetValue(key, out value); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitReadLock(); | |||
} | |||
} | |||
/// <summary> | |||
@@ -169,7 +242,8 @@ namespace Svelto.DataStructures | |||
/// <param name = "newValue">New Value</param> | |||
public void MergeSafe(TKey key, TValue newValue) | |||
{ | |||
using (new WriteLock(dictionaryLock)) | |||
LockQ.EnterWriteLock(); | |||
try | |||
{ | |||
// take a writelock immediately since we will always be writing | |||
if (dict.ContainsKey(key)) | |||
@@ -177,6 +251,10 @@ namespace Svelto.DataStructures | |||
dict.Add(key, newValue); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitWriteLock(); | |||
} | |||
} | |||
/// <summary> | |||
@@ -185,132 +263,29 @@ namespace Svelto.DataStructures | |||
/// <param name = "key">Key to remove</param> | |||
public void RemoveSafe(TKey key) | |||
{ | |||
using (new ReadLock(dictionaryLock)) | |||
LockQ.EnterReadLock(); | |||
try | |||
{ | |||
if (dict.ContainsKey(key)) | |||
using (new WriteLock(dictionaryLock)) | |||
{ | |||
dict.Remove(key); | |||
} | |||
LockQ.EnterWriteLock(); | |||
try | |||
{ | |||
dict.Remove(key); | |||
} | |||
finally | |||
{ | |||
LockQ.ExitWriteLock(); | |||
} | |||
} | |||
finally | |||
{ | |||
LockQ.ExitReadLock(); | |||
} | |||
} | |||
// This is the internal dictionary that we are wrapping | |||
readonly IDictionary<TKey, TValue> dict; | |||
[NonSerialized] readonly ReaderWriterLockSlim dictionaryLock = Locks.GetLockInstance(LockRecursionPolicy.NoRecursion); | |||
} | |||
public static class Locks | |||
{ | |||
public static ReaderWriterLockSlim GetLockInstance() | |||
{ | |||
return GetLockInstance(LockRecursionPolicy.SupportsRecursion); | |||
} | |||
public static ReaderWriterLockSlim GetLockInstance(LockRecursionPolicy recursionPolicy) | |||
{ | |||
return new ReaderWriterLockSlim(recursionPolicy); | |||
} | |||
public static void GetReadLock(ReaderWriterLockSlim locks) | |||
{ | |||
var lockAcquired = false; | |||
while (!lockAcquired) | |||
lockAcquired = locks.TryEnterUpgradeableReadLock(1); | |||
} | |||
public static void GetReadOnlyLock(ReaderWriterLockSlim locks) | |||
{ | |||
var lockAcquired = false; | |||
while (!lockAcquired) | |||
lockAcquired = locks.TryEnterReadLock(1); | |||
} | |||
public static void GetWriteLock(ReaderWriterLockSlim locks) | |||
{ | |||
var lockAcquired = false; | |||
while (!lockAcquired) | |||
lockAcquired = locks.TryEnterWriteLock(1); | |||
} | |||
public static void ReleaseLock(ReaderWriterLockSlim locks) | |||
{ | |||
ReleaseWriteLock(locks); | |||
ReleaseReadLock(locks); | |||
ReleaseReadOnlyLock(locks); | |||
} | |||
public static void ReleaseReadLock(ReaderWriterLockSlim locks) | |||
{ | |||
if (locks.IsUpgradeableReadLockHeld) | |||
locks.ExitUpgradeableReadLock(); | |||
} | |||
public static void ReleaseReadOnlyLock(ReaderWriterLockSlim locks) | |||
{ | |||
if (locks.IsReadLockHeld) | |||
locks.ExitReadLock(); | |||
} | |||
public static void ReleaseWriteLock(ReaderWriterLockSlim locks) | |||
{ | |||
if (locks.IsWriteLockHeld) | |||
locks.ExitWriteLock(); | |||
} | |||
} | |||
public abstract class BaseLock : IDisposable | |||
{ | |||
protected ReaderWriterLockSlim _Locks; | |||
public BaseLock(ReaderWriterLockSlim locks) | |||
{ | |||
_Locks = locks; | |||
} | |||
public abstract void Dispose(); | |||
} | |||
public class ReadLock : BaseLock | |||
{ | |||
public ReadLock(ReaderWriterLockSlim locks) | |||
: base(locks) | |||
{ | |||
Locks.GetReadLock(_Locks); | |||
} | |||
public override void Dispose() | |||
{ | |||
Locks.ReleaseReadLock(_Locks); | |||
} | |||
} | |||
public class ReadOnlyLock : BaseLock | |||
{ | |||
public ReadOnlyLock(ReaderWriterLockSlim locks) | |||
: base(locks) | |||
{ | |||
Locks.GetReadOnlyLock(_Locks); | |||
} | |||
public override void Dispose() | |||
{ | |||
Locks.ReleaseReadOnlyLock(_Locks); | |||
} | |||
} | |||
public class WriteLock : BaseLock | |||
{ | |||
public WriteLock(ReaderWriterLockSlim locks) | |||
: base(locks) | |||
{ | |||
Locks.GetWriteLock(_Locks); | |||
} | |||
public override void Dispose() | |||
{ | |||
Locks.ReleaseWriteLock(_Locks); | |||
} | |||
readonly ReaderWriterLockSlim LockQ = new ReaderWriterLockSlim(); | |||
} | |||
} |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: db7c720ce4e437f48b1380223ba08192 | |||
timeCreated: 1470829214 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 57d029cda5232f8468d50d4eb3bf5489 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 205cba76ee94d0e47aba9510ca92c540 | |||
timeCreated: 1452175408 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,7 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 5015ea56c030d6542bd4daa46f59e549 | |||
folderAsset: yes | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,9 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 2eae335fd33e33c4f951bf28bbf4914f | |||
folderAsset: yes | |||
timeCreated: 1462445195 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 908688d3b784d644e88a06e20f9ea159 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: cbb1d54b291794b4686526222ee2bbb6 | |||
timeCreated: 1471250507 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -4,15 +4,15 @@ using Svelto.DataStructures; | |||
namespace Svelto.ECS | |||
{ | |||
class EngineNodeDB : IEngineNodeDB | |||
public class EngineNodeDB : IEngineNodeDB | |||
{ | |||
internal EngineNodeDB( Dictionary<Type, FasterList<INode>> nodesDB, | |||
Dictionary<Type, Dictionary<int, INode>> nodesDBdic, | |||
Dictionary<Type, FasterList<INode>> nodesDBgroups) | |||
Dictionary<Type, FasterList<INode>> metaNodesDB) | |||
{ | |||
_nodesDB = nodesDB; | |||
_nodesDBdic = nodesDBdic; | |||
_nodesDBgroups = nodesDBgroups; | |||
_metaNodesDB = metaNodesDB; | |||
} | |||
public FasterReadOnlyListCast<INode, T> QueryNodes<T>() where T:INode | |||
@@ -35,33 +35,34 @@ namespace Svelto.ECS | |||
return new ReadOnlyDictionary<int, INode>(_nodesDBdic[type]); | |||
} | |||
public T QueryNodeFromGroup<T>(int groupID) where T : INode | |||
public T QueryMetaNode<T>(int metaEntityID) where T : INode | |||
{ | |||
return QueryNode<T>(groupID); | |||
return QueryNode<T>(metaEntityID); | |||
} | |||
public bool QueryNodeFromGroup<T>(int groupID, out T node) where T : INode | |||
public bool TryQueryMetaNode<T>(int metaEntityID, out T node) where T : INode | |||
{ | |||
return QueryNode<T>(groupID, out node); | |||
return TryQueryNode(metaEntityID, out node); | |||
} | |||
public FasterReadOnlyListCast<INode, T> QueryNodesFromGroups<T>() where T : INode | |||
public FasterReadOnlyListCast<INode, T> QueryMetaNodes<T>() where T : INode | |||
{ | |||
var type = typeof(T); | |||
if (_nodesDBgroups.ContainsKey(type) == false) | |||
if (_metaNodesDB.ContainsKey(type) == false) | |||
return RetrieveEmptyNodeList<T>(); | |||
return new FasterReadOnlyListCast<INode, T>(_nodesDBgroups[type]); | |||
return new FasterReadOnlyListCast<INode, T>(_metaNodesDB[type]); | |||
} | |||
public bool QueryNode<T>(int ID, out T node) where T:INode | |||
public bool TryQueryNode<T>(int ID, out T node) where T:INode | |||
{ | |||
var type = typeof(T); | |||
INode internalNode; | |||
if (_nodesDBdic.ContainsKey(type) && _nodesDBdic[type].TryGetValue(ID, out internalNode)) | |||
if (_nodesDBdic.ContainsKey(type) && | |||
_nodesDBdic[type].TryGetValue(ID, out internalNode)) | |||
{ | |||
node = (T)internalNode; | |||
@@ -79,25 +80,32 @@ namespace Svelto.ECS | |||
INode internalNode; | |||
if (_nodesDBdic.ContainsKey(type) && _nodesDBdic[type].TryGetValue(ID, out internalNode)) | |||
if (_nodesDBdic.ContainsKey(type) && | |||
_nodesDBdic[type].TryGetValue(ID, out internalNode)) | |||
return (T)internalNode; | |||
throw new Exception("Node Not Found"); | |||
} | |||
static FasterReadOnlyListCast<INode, T> RetrieveEmptyNodeList<T>() where T : INode | |||
public FasterReadOnlyListCast<INode, T> QueryGroupNodes<T>(int groupID) where T : INode | |||
{ | |||
return new FasterReadOnlyListCast<INode, T>(FasterReadOnlyListCast<INode, T>.DefaultList); | |||
var type = typeof(T); | |||
if (_nodesDB.ContainsKey(type) == false) | |||
return RetrieveEmptyNodeList<T>(); | |||
return new FasterReadOnlyListCast<INode, T>(_nodesDB[type]); | |||
} | |||
Dictionary<Type, FasterList<INode>> _nodesDB; | |||
Dictionary<Type, Dictionary<int, INode>> _nodesDBdic; | |||
Dictionary<Type, FasterList<INode>> _nodesDBgroups; | |||
static FasterReadOnlyListCast<INode, T> RetrieveEmptyNodeList<T>() where T : INode | |||
{ | |||
return FasterReadOnlyListCast<INode, T>.DefaultList; | |||
} | |||
//Dictionary<Type, ThreadSafeFasterList<INode>> _nodesDB; | |||
//Dictionary<Type, ThreadsSafeDictionary<int, INode>> _nodesDBdic; | |||
// Dictionary<Type, ThreadSafeFasterList<INode>> _nodesDBgroups; | |||
readonly Dictionary<Type, FasterList<INode>> _nodesDB; | |||
readonly Dictionary<Type, Dictionary<int, INode>> _nodesDBdic; | |||
readonly Dictionary<Type, FasterList<INode>> _metaNodesDB; | |||
ReadOnlyDictionary<int, INode> _defaultEmptyNodeDict = new ReadOnlyDictionary<int, INode>(new Dictionary<int, INode>()); | |||
readonly ReadOnlyDictionary<int, INode> _defaultEmptyNodeDict = new ReadOnlyDictionary<int, INode>(new Dictionary<int, INode>()); | |||
} | |||
} |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: b8aebbeeaf3d65d438359008c1f5d351 | |||
timeCreated: 1459422025 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -2,6 +2,8 @@ using System; | |||
using System.Collections; | |||
using System.Collections.Generic; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS.Internal; | |||
using Svelto.ECS.NodeSchedulers; | |||
using UnityEngine; | |||
using WeakReference = Svelto.DataStructures.WeakReference<Svelto.ECS.EnginesRoot>; | |||
@@ -14,40 +16,39 @@ using System.Reflection; | |||
namespace Svelto.ECS | |||
{ | |||
class Scheduler : MonoBehaviour | |||
{ | |||
IEnumerator Start() | |||
{ | |||
while (true) | |||
{ | |||
yield return new WaitForEndOfFrame(); | |||
OnTick(); | |||
} | |||
} | |||
internal Action OnTick; | |||
} | |||
public sealed class EnginesRoot : IEnginesRoot, IEntityFactory | |||
{ | |||
public EnginesRoot() | |||
public EnginesRoot(NodeSubmissionScheduler nodeScheduler) | |||
{ | |||
_nodeEngines = new Dictionary<Type, FasterList<INodeEngine<INode>>>(); | |||
_nodeEngines = new Dictionary<Type, FasterList<IEngine>>(); | |||
_activableEngines = new Dictionary<Type, FasterList<IEngine>>(); | |||
_otherEngines = new FasterList<IEngine>(); | |||
_engineRootWeakReference = new WeakReference(this); | |||
_otherEnginesReferences = new FasterList<IEngine>(); | |||
_nodesDB = new Dictionary<Type, FasterList<INode>>(); | |||
_nodesDBdic = new Dictionary<Type, Dictionary<int, INode>>(); | |||
_nodesToAdd = new FasterList<INode>(); | |||
_groupNodesToAdd = new FasterList<INode>(); | |||
_metaNodesToAdd = new FasterList<INode>(); | |||
_metaNodesDB = new Dictionary<Type, FasterList<INode>>(); | |||
_sharedStructNodeLists = new SharedStructNodeLists(); | |||
_sharedGroupedStructNodeLists = new SharedGroupedStructNodesLists(); | |||
_nodesDBgroups = new Dictionary<Type, FasterList<INode>>(); | |||
_internalRemove = InternalRemove; | |||
_internalDisable = InternalDisable; | |||
_internalEnable = InternalEnable; | |||
_internalMetaRemove = InternalMetaRemove; | |||
GameObject go = new GameObject("ECSScheduler"); | |||
_scheduler = nodeScheduler; | |||
_scheduler.Schedule(SubmitNodes); | |||
go.AddComponent<Scheduler>().OnTick += SubmitNodes; | |||
_structNodeEngineType = typeof(IStructNodeEngine<>); | |||
_groupedStructNodesEngineType = typeof(IGroupedStructNodesEngine<>); | |||
_activableNodeEngineType = typeof(IActivableNodeEngine<>); | |||
_implementedInterfaceTypes = new Dictionary<Type, Type[]>(); | |||
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR | |||
GameObject debugEngineObject = new GameObject("Engine Debugger"); | |||
@@ -57,56 +58,75 @@ namespace Svelto.ECS | |||
void SubmitNodes() | |||
{ | |||
int groupNodesCount; | |||
int nodesCount; | |||
int metaNodesCount = _metaNodesToAdd.Count; | |||
int nodesCount = _nodesToAdd.Count; | |||
if (metaNodesCount + nodesCount == 0) return; | |||
bool newNodesHaveBeenAddedWhileIterating; | |||
int startNodes = 0; | |||
int startGroupNodes = 0; | |||
int startMetaNodes = 0; | |||
int numberOfReenteringLoops = 0; | |||
do | |||
{ | |||
groupNodesCount = _groupNodesToAdd.Count; | |||
nodesCount = _nodesToAdd.Count; | |||
var nodesToAdd = _nodesToAdd.ToArrayFast(); | |||
for (int i = startNodes; i < nodesCount; i++) | |||
{ | |||
var node = _nodesToAdd[i]; | |||
AddNodeToTheDB(node, node.GetType()); | |||
var node = nodesToAdd[i]; | |||
var nodeType = node.GetType(); | |||
AddNodeToTheDB(node, nodeType); | |||
var nodeWithId = node as INodeWithID; | |||
if (nodeWithId != null) | |||
AddNodeToNodesDictionary(nodeWithId, nodeType); | |||
} | |||
for (int i = startGroupNodes; i < groupNodesCount; i++) | |||
var metaNodesToAdd = _metaNodesToAdd.ToArrayFast(); | |||
for (int i = startMetaNodes; i < metaNodesCount; i++) | |||
{ | |||
var node = _groupNodesToAdd[i]; | |||
AddNodeToGroupDB(node, node.GetType()); | |||
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]; | |||
var node = nodesToAdd[i]; | |||
AddNodeToTheSuitableEngines(node, node.GetType()); | |||
} | |||
for (int i = startGroupNodes; i < groupNodesCount; i++) | |||
for (int i = startMetaNodes; i < metaNodesCount; i++) | |||
{ | |||
var node = _groupNodesToAdd[i]; | |||
var node = metaNodesToAdd[i]; | |||
AddNodeToTheSuitableEngines(node, node.GetType()); | |||
} | |||
newNodesHaveBeenAddedWhileIterating = _groupNodesToAdd.Count > groupNodesCount || _nodesToAdd.Count > nodesCount; | |||
newNodesHaveBeenAddedWhileIterating = | |||
_metaNodesToAdd.Count > metaNodesCount || | |||
_nodesToAdd.Count > nodesCount; | |||
startNodes = nodesCount; | |||
startGroupNodes = groupNodesCount; | |||
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++; | |||
numberOfReenteringLoops++; | |||
metaNodesCount = _metaNodesToAdd.Count; | |||
nodesCount = _nodesToAdd.Count; | |||
} while (newNodesHaveBeenAddedWhileIterating); | |||
_nodesToAdd.Clear(); | |||
_groupNodesToAdd.Clear(); | |||
_metaNodesToAdd.Clear(); | |||
} | |||
public void AddEngine(IEngine engine) | |||
@@ -114,88 +134,201 @@ namespace Svelto.ECS | |||
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR | |||
EngineProfiler.AddEngine(engine); | |||
#endif | |||
if (engine is IQueryableNodeEngine) | |||
(engine as IQueryableNodeEngine).nodesDB = new EngineNodeDB(_nodesDB, _nodesDBdic, _nodesDBgroups); | |||
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(); | |||
} | |||
if (engine is INodesEngine) | |||
void CollectImplementedInterfaces(Type[] implementedInterfaces) | |||
{ | |||
_implementedInterfaceTypes.Clear(); | |||
for (int index = 0; index < implementedInterfaces.Length; index++) | |||
{ | |||
var nodesEngine = engine as INodesEngine; | |||
var interfaceType = implementedInterfaces[index]; | |||
#if !NETFX_CORE | |||
AddEngine(nodesEngine, nodesEngine.AcceptedNodes(), _nodeEngines); | |||
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); | |||
} | |||
else | |||
if (_implementedInterfaceTypes.ContainsKey(_groupedStructNodesEngineType)) | |||
{ | |||
((IGroupedStructNodesEngine)engine).CreateStructNodes | |||
(_sharedGroupedStructNodeLists); | |||
} | |||
var engineType = engine.GetType(); | |||
// Type baseInterface = null; | |||
Type[] arguments; | |||
if (_implementedInterfaceTypes.TryGetValue(_activableNodeEngineType, | |||
out arguments)) | |||
{ | |||
AddEngine(engine, arguments, _activableEngines); | |||
#if !NETFX_CORE | |||
var baseType = engineType.BaseType; | |||
engineAdded = true; | |||
} | |||
if (baseType.IsGenericType | |||
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 | |||
&& baseType.GetGenericTypeDefinition() == typeof (SingleNodeEngine<>)) | |||
{ | |||
AddEngine(engine as INodeEngine<INode>, baseType.GetGenericArguments(), _nodeEngines); | |||
} | |||
else | |||
_otherEnginesReferences.Add(engine); | |||
&& engine is INodeEngine) | |||
{ | |||
AddEngine(engine as INodeEngine, baseType.GetGenericArguments(), _nodeEngines); | |||
engineAdded = true; | |||
return true; | |||
} | |||
if (engine is ICallBackOnAddEngine) | |||
(engine as ICallBackOnAddEngine).Ready(); | |||
return false; | |||
} | |||
public void BuildEntity(int ID, EntityDescriptor ed) | |||
{ | |||
var entityNodes = ed.BuildNodes(ID, (node) => | |||
{ | |||
if (_engineRootWeakReference.IsValid == true) | |||
InternalRemove(node); | |||
}); | |||
var entityNodes = ed.BuildNodes(ID, | |||
_internalRemove, | |||
_internalEnable, | |||
_internalDisable | |||
); | |||
_nodesToAdd.AddRange(entityNodes); | |||
} | |||
/// <summary> | |||
/// An entity group is a meta entity. It's a way to create a set of entitites that | |||
/// are not easily queriable otherwise. For example you may group existing entities | |||
/// by size and type and then use the groupID to retrieve a single node that is shared | |||
/// among the single entities of the same type and size. This willwd 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 entity group is managed through the shared node, the same | |||
/// 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 is then used by engines that are meant to manage a group of entities | |||
/// through a single node. The same engine can manage several groups of entitites. | |||
/// 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. | |||
/// </summary> | |||
/// <param name="metaEntityID"></param> | |||
/// <param name="ed"></param> | |||
public void BuildMetaEntity(int metaEntityID, EntityDescriptor ed) | |||
{ | |||
var entityNodes = ed.BuildNodes(metaEntityID, | |||
_internalMetaRemove, | |||
_internalEnable, | |||
_internalDisable | |||
); | |||
_metaNodesToAdd.AddRange(entityNodes); | |||
} | |||
/// <summary> | |||
/// 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. | |||
/// </summary> | |||
/// <param name="entityID"></param> | |||
/// <param name="groupID"></param> | |||
/// <param name="ed"></param> | |||
public void BuildEntityGroup(int groupID, EntityDescriptor ed) | |||
public void BuildEntityInGroup(short entityID, short groupID, | |||
EntityDescriptor ed) | |||
{ | |||
var entityNodes = ed.BuildNodes(groupID, (node) => | |||
{ | |||
if (_engineRootWeakReference.IsValid == true) | |||
InternalGroupRemove(node); | |||
}); | |||
var entityNodes = ed.BuildNodes(entityID, | |||
_internalRemove, | |||
_internalEnable, | |||
_internalDisable | |||
); | |||
_groupNodesToAdd.AddRange(entityNodes); | |||
_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<T>(T engine, Type[] types, Dictionary<Type, FasterList<INodeEngine<INode>>> engines) where T : INodeEngine<INode> | |||
static void AddEngine(IEngine engine, Type[] types, | |||
Dictionary<Type, FasterList<IEngine>> engines) | |||
{ | |||
for (int i = 0; i < types.Length; i++) | |||
{ | |||
FasterList<INodeEngine<INode>> list; | |||
FasterList<IEngine> list; | |||
var type = types[i]; | |||
if (engines.TryGetValue(type, out list) == false) | |||
{ | |||
list = new FasterList<INodeEngine<INode>>(); | |||
list = new FasterList<IEngine>(); | |||
engines.Add(type, list); | |||
} | |||
@@ -204,15 +337,13 @@ namespace Svelto.ECS | |||
} | |||
} | |||
void AddNodeToGroupDB(INode node, Type nodeType) | |||
void AddNodeToMetaDB(INode node, Type nodeType) | |||
{ | |||
FasterList<INode> nodes; | |||
if (_nodesDBgroups.TryGetValue(nodeType, out nodes) == false) | |||
nodes = _nodesDBgroups[nodeType] = new FasterList<INode>(); | |||
if (_metaNodesDB.TryGetValue(nodeType, out nodes) == false) | |||
nodes = _metaNodesDB[nodeType] = new FasterList<INode>(); | |||
nodes.Add(node); | |||
AddNodeToNodesDictionary(node, nodeType); | |||
} | |||
void AddNodeToTheDB<T>(T node, Type nodeType) where T : INode | |||
@@ -222,34 +353,30 @@ namespace Svelto.ECS | |||
nodes = _nodesDB[nodeType] = new FasterList<INode>(); | |||
nodes.Add(node); | |||
AddNodeToNodesDictionary(node, nodeType); | |||
} | |||
void AddNodeToNodesDictionary<T>(T node, Type nodeType) where T : INode | |||
void AddNodeToNodesDictionary<T>(T node, Type nodeType) where T : INodeWithID | |||
{ | |||
if (node is NodeWithID) | |||
{ | |||
Dictionary<int, INode> nodesDic; | |||
if (_nodesDBdic.TryGetValue(nodeType, out nodesDic) == false) | |||
nodesDic = _nodesDBdic[nodeType] = new Dictionary<int, INode>(); | |||
Dictionary<int, INode> nodesDic; | |||
nodesDic[(node as NodeWithID).ID] = node; | |||
} | |||
if (_nodesDBdic.TryGetValue(nodeType, out nodesDic) == false) | |||
nodesDic = _nodesDBdic[nodeType] = new Dictionary<int, INode>(); | |||
nodesDic.Add(node.ID, node); | |||
} | |||
void AddNodeToTheSuitableEngines<T>(T node, Type nodeType) where T : INode | |||
void AddNodeToTheSuitableEngines(INode node, Type nodeType) | |||
{ | |||
FasterList<INodeEngine<INode>> enginesForNode; | |||
FasterList<IEngine> enginesForNode; | |||
if (_nodeEngines.TryGetValue(nodeType, out enginesForNode)) | |||
{ | |||
for (int j = 0; j < enginesForNode.Count; j++) | |||
{ | |||
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR | |||
EngineProfiler.MonitorAddDuration(AddNodeToEngine, enginesForNode[j], node); | |||
EngineProfiler.MonitorAddDuration(AddNodeToEngine, enginesForNode[j] as INodeEngine, node); | |||
#else | |||
enginesForNode[j].Add(node); | |||
(enginesForNode[j] as INodeEngine).Add(node); | |||
#endif | |||
} | |||
} | |||
@@ -259,87 +386,168 @@ namespace Svelto.ECS | |||
{ | |||
FasterList<INode> nodes; | |||
if (_nodesDB.TryGetValue(nodeType, out nodes) == true) | |||
nodes.UnorderredRemove(node); //should I remove it from the dictionary if length is zero? | |||
RemoveNodeFromNodesDictionary(node, nodeType); | |||
nodes.UnorderedRemove(node); //should I remove it from the dictionary if length is zero? | |||
} | |||
void RemoveNodeFromNodesDictionary<T>(T node, Type nodeType) where T : INode | |||
void RemoveNodeFromMetaDB<T>(T node, Type nodeType) where T : INode | |||
{ | |||
if (node is NodeWithID) | |||
{ | |||
Dictionary<int, INode> nodesDic; | |||
if (_nodesDBdic.TryGetValue(nodeType, out nodesDic)) | |||
nodesDic.Remove((node as NodeWithID).ID); | |||
} | |||
FasterList<INode> nodes; | |||
if (_metaNodesDB.TryGetValue(nodeType, out nodes) == true) | |||
nodes.UnorderedRemove(node); //should I remove it from the dictionary if length is zero? | |||
} | |||
void RemoveNodeFromGroupDB<T>(T node, Type nodeType) where T : INode | |||
void RemoveNodeFromNodesDictionary<T>(T node, Type nodeType) where T : INodeWithID | |||
{ | |||
FasterList<INode> nodes; | |||
if (_nodesDBgroups.TryGetValue(nodeType, out nodes) == true) | |||
nodes.UnorderredRemove(node); //should I remove it from the dictionary if length is zero? | |||
Dictionary<int, INode> nodesDic; | |||
RemoveNodeFromNodesDictionary(node, nodeType); | |||
if (_nodesDBdic.TryGetValue(nodeType, out nodesDic)) | |||
nodesDic.Remove(node.ID); | |||
} | |||
void RemoveNodeFromEngines<T>(T node, Type nodeType) where T : INode | |||
{ | |||
FasterList<INodeEngine<INode>> enginesForNode; | |||
FasterList<IEngine> enginesForNode; | |||
if (_nodeEngines.TryGetValue(nodeType, out enginesForNode)) | |||
{ | |||
for (int j = 0; j < enginesForNode.Count; j++) | |||
{ | |||
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR | |||
EngineProfiler.MonitorRemoveDuration(RemoveNodeFromEngine, enginesForNode[j], node); | |||
EngineProfiler.MonitorRemoveDuration(RemoveNodeFromEngine, (enginesForNode[j] as INodeEngine), node); | |||
#else | |||
enginesForNode[j].Remove(node); | |||
(enginesForNode[j] as INodeEngine).Remove(node); | |||
#endif | |||
} | |||
} | |||
} | |||
void DisableNodeFromEngines(INode node, Type nodeType) | |||
{ | |||
FasterList<IEngine> 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<IEngine> enginesForNode; | |||
if (_activableEngines.TryGetValue(nodeType, out enginesForNode)) | |||
{ | |||
for (int j = 0; j < enginesForNode.Count; j++) | |||
{ | |||
(enginesForNode[j] as IActivableNodeEngine).Enable(node); | |||
} | |||
} | |||
} | |||
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR | |||
void AddNodeToEngine(INodeEngine<INode> engine, INode node) | |||
void AddNodeToEngine(IEngine engine, INode node) | |||
{ | |||
engine.Add(node); | |||
(engine as INodeEngine).Add(node); | |||
} | |||
void RemoveNodeFromEngine(INodeEngine<INode> engine, INode node) | |||
void RemoveNodeFromEngine(IEngine engine, INode node) | |||
{ | |||
engine.Remove(node); | |||
(engine as INodeEngine).Remove(node); | |||
} | |||
#endif | |||
void InternalRemove<T>(T node) where T : INode | |||
void InternalDisable(FasterList<INode> 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<INode> 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<INode> nodes) | |||
{ | |||
Type nodeType = node.GetType(); | |||
if (_engineRootWeakReference.IsValid == false) | |||
return; | |||
RemoveNodeFromEngines(node, nodeType); | |||
RemoveNodeFromTheDB(node, node.GetType()); | |||
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 InternalGroupRemove<T>(T node) where T : INode | |||
void InternalMetaRemove(FasterList<INode> nodes) | |||
{ | |||
Type nodeType = node.GetType(); | |||
for (int i = 0; i < nodes.Count; i++) | |||
{ | |||
var node = nodes[i]; | |||
Type nodeType = node.GetType(); | |||
RemoveNodeFromEngines(node, nodeType); | |||
RemoveNodeFromMetaDB(node, nodeType); | |||
RemoveNodeFromEngines(node, nodeType); | |||
RemoveNodeFromGroupDB(node, node.GetType()); | |||
var nodeWithId = node as INodeWithID; | |||
if (nodeWithId != null) | |||
RemoveNodeFromNodesDictionary(nodeWithId, nodeType); | |||
} | |||
} | |||
Dictionary<Type, FasterList<INodeEngine<INode>>> _nodeEngines; | |||
FasterList<IEngine> _otherEnginesReferences; | |||
readonly Dictionary<Type, FasterList<IEngine>> _nodeEngines; | |||
readonly Dictionary<Type, FasterList<IEngine>> _activableEngines; | |||
readonly FasterList<IEngine> _otherEngines; | |||
readonly Dictionary<Type, FasterList<INode>> _nodesDB; | |||
readonly Dictionary<Type, FasterList<INode>> _metaNodesDB; | |||
readonly Dictionary<Type, Dictionary<int, INode>> _nodesDBdic; | |||
readonly FasterList<INode> _nodesToAdd; | |||
readonly FasterList<INode> _metaNodesToAdd; | |||
readonly WeakReference _engineRootWeakReference; | |||
readonly SharedStructNodeLists _sharedStructNodeLists; | |||
readonly SharedGroupedStructNodesLists _sharedGroupedStructNodeLists; | |||
Dictionary<Type, FasterList<INode>> _nodesDB; | |||
Dictionary<Type, Dictionary<int, INode>> _nodesDBdic; | |||
readonly NodeSubmissionScheduler _scheduler; | |||
Dictionary<Type, FasterList<INode>> _nodesDBgroups; | |||
readonly Action<FasterList<INode>> _internalRemove; | |||
readonly Action<FasterList<INode>> _internalEnable; | |||
readonly Action<FasterList<INode>> _internalDisable; | |||
readonly Action<FasterList<INode>> _internalMetaRemove; | |||
FasterList<INode> _nodesToAdd; | |||
FasterList<INode> _groupNodesToAdd; | |||
readonly Type _structNodeEngineType; | |||
readonly Type _groupedStructNodesEngineType; | |||
readonly Type _activableNodeEngineType; | |||
WeakReference _engineRootWeakReference; | |||
readonly Dictionary<Type, Type[]> _implementedInterfaceTypes; | |||
} | |||
} | |||
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 89361a8514a38544ebb87df0bd766dc5 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,4 +1,5 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Reflection; | |||
using Svelto.DataStructures; | |||
#if NETFX_CORE | |||
@@ -9,100 +10,176 @@ namespace Svelto.ECS | |||
{ | |||
public class EntityDescriptor | |||
{ | |||
protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor) | |||
protected EntityDescriptor(INodeBuilder[] nodesToBuild) | |||
{ | |||
_implementors = componentsImplementor; | |||
_nodesToBuild = nodesToBuild; | |||
_nodesToBuild = new FasterList<INodeBuilder>(nodesToBuild); | |||
} | |||
protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor):this(nodesToBuild) | |||
{ | |||
ProcessImplementors(componentsImplementor); | |||
} | |||
public void AddImplementors(params object[] componentsImplementor) | |||
{ | |||
var implementors = new object[componentsImplementor.Length + _implementors.Length]; | |||
ProcessImplementors(componentsImplementor); | |||
} | |||
void ProcessImplementors(object[] implementors) | |||
{ | |||
for (int index = 0; index < implementors.Length; index++) | |||
{ | |||
var implementor = implementors[index]; | |||
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); | |||
Array.Copy(_implementors, implementors, _implementors.Length); | |||
Array.Copy(componentsImplementor, 0, implementors, _implementors.Length, componentsImplementor.Length); | |||
var interfaces = implementor.GetType().GetInterfaces(); | |||
_implementors = implementors; | |||
for (int iindex = 0; iindex < interfaces.Length; iindex++) | |||
{ | |||
_implementorsByType[interfaces[iindex]] = implementor; | |||
} | |||
} | |||
} | |||
public void AddNodes(params INodeBuilder[] nodesWithID) | |||
{ | |||
_nodesToBuild.AddRange(nodesWithID); | |||
} | |||
public virtual FasterList<INode> BuildNodes(int ID, Action<INode> removeAction) | |||
public virtual FasterList<INode> BuildNodes(int ID) | |||
{ | |||
var nodes = new FasterList<INode>(); | |||
for (int index = 0; index < _nodesToBuild.Length; index++) | |||
for (int index = 0; index < _nodesToBuild.Count; index++) | |||
{ | |||
var nodeBuilder = _nodesToBuild[index]; | |||
var node = FillNode(nodeBuilder.Build(ID), () => | |||
{ | |||
for (int i = 0; i < nodes.Count; i++) | |||
removeAction(nodes[i]); | |||
var node = nodeBuilder.Build(ID); | |||
nodes.Clear(); | |||
} | |||
); | |||
if (nodeBuilder.reflects != FillNodeMode.None) | |||
node = FillNode(node, nodeBuilder.reflects); | |||
nodes.Add (node); | |||
nodes.Add(node); | |||
} | |||
return nodes; | |||
} | |||
TNode FillNode<TNode>(TNode node, Action removeAction) where TNode: INode | |||
internal FasterList<INode> BuildNodes(int ID, | |||
Action<FasterList<INode>> removeEntity, | |||
Action<FasterList<INode>> enableEntity, | |||
Action<FasterList<INode>> disableEntity) | |||
{ | |||
var fields = node.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); | |||
var nodes = BuildNodes(ID); | |||
for (int i = fields.Length - 1; i >=0 ; --i) | |||
{ | |||
var field = fields[i]; | |||
Type fieldType = field.FieldType; | |||
object component = null; | |||
for (int j = 0; j < _implementors.Length; j++) | |||
{ | |||
var implementor = _implementors[j]; | |||
SetupImplementors(removeEntity, enableEntity, disableEntity, nodes); | |||
if (implementor != null && fieldType.IsAssignableFrom(implementor.GetType())) | |||
{ | |||
component = implementor; | |||
return nodes; | |||
} | |||
if (fieldType.IsAssignableFrom(typeof(IRemoveEntityComponent))) | |||
(component as IRemoveEntityComponent).removeEntity = removeAction; | |||
void SetupImplementors( | |||
Action<FasterList<INode>> removeEntity, | |||
Action<FasterList<INode>> enableEntity, | |||
Action<FasterList<INode>> disableEntity, | |||
FasterList<INode> 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; | |||
} | |||
break; | |||
} | |||
} | |||
TNode FillNode<TNode>(TNode node, FillNodeMode mode) where TNode : INode | |||
{ | |||
var fields = node.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); | |||
if (component == null) | |||
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) | |||
{ | |||
Exception e = new Exception("Svelto.ECS: Implementor not found for a Node. " + | |||
"Implementor Type: " + field.FieldType.Name + " - Node: " + node.GetType().Name + " - EntityDescriptor " + this); | |||
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; | |||
throw e; | |||
} | |||
} | |||
field.SetValue(node, component); | |||
else | |||
field.SetValue(node, component); | |||
} | |||
return node; | |||
} | |||
object[] _implementors; | |||
readonly FasterList<IDisableEntityComponent> _disablingImplementors = new FasterList<IDisableEntityComponent>(); | |||
readonly FasterList<IRemoveEntityComponent> _removingImplementors = new FasterList<IRemoveEntityComponent>(); | |||
readonly FasterList<IEnableEntityComponent> _enablingImplementors = new FasterList<IEnableEntityComponent>(); | |||
readonly Dictionary<Type, object> _implementorsByType = new Dictionary<Type, object>(); | |||
readonly INodeBuilder[] _nodesToBuild; | |||
readonly FasterList<INodeBuilder> _nodesToBuild; | |||
} | |||
public interface INodeBuilder | |||
{ | |||
NodeWithID Build(int ID); | |||
INode Build(int ID); | |||
FillNodeMode reflects { get; } | |||
} | |||
public class NodeBuilder<NodeType> : INodeBuilder where NodeType:NodeWithID, new() | |||
public class NodeBuilder<NodeType> : INodeBuilder where NodeType : NodeWithID, new() | |||
{ | |||
public NodeWithID Build(int ID) | |||
public INode Build(int ID) | |||
{ | |||
NodeWithID node = NodeWithID.BuildNode<NodeType>(ID); | |||
return (NodeType)node; | |||
} | |||
public FillNodeMode reflects { get { return FillNodeMode.Strict; } } | |||
} | |||
public class StructNodeBuilder<NodeType> : 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<NodeType> : StructNodeBuilder<NodeType> | |||
where NodeType : struct, IStructNodeWithID | |||
{ | |||
public override FillNodeMode reflects { get { return FillNodeMode.None; } } | |||
} | |||
public enum FillNodeMode | |||
{ | |||
Strict, | |||
Relaxed, | |||
None | |||
} | |||
} |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 42ab9afd9889862468f4afdac4fffd8b | |||
timeCreated: 1457096903 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,41 @@ | |||
#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<Scheduler>(); | |||
} | |||
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 |
@@ -1,6 +1,6 @@ | |||
namespace Svelto.ECS | |||
{ | |||
class GenericEntityDescriptor<T> : EntityDescriptor | |||
public class GenericEntityDescriptor<T> : EntityDescriptor | |||
where T : NodeWithID, new() | |||
{ | |||
static GenericEntityDescriptor() | |||
@@ -10,10 +10,10 @@ | |||
public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) | |||
{} | |||
static INodeBuilder[] _nodesToBuild; | |||
static readonly INodeBuilder[] _nodesToBuild; | |||
} | |||
class GenericEntityDescriptor<T, U> : EntityDescriptor | |||
public class GenericEntityDescriptor<T, U> : EntityDescriptor | |||
where T : NodeWithID, new() | |||
where U : NodeWithID, new() | |||
{ | |||
@@ -29,10 +29,10 @@ | |||
public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) | |||
{} | |||
static INodeBuilder[] _nodesToBuild; | |||
static readonly INodeBuilder[] _nodesToBuild; | |||
} | |||
class GenericEntityDescriptor<T, U, V> : EntityDescriptor | |||
public class GenericEntityDescriptor<T, U, V> : EntityDescriptor | |||
where T : NodeWithID, new() | |||
where U : NodeWithID, new() | |||
where V : NodeWithID, new() | |||
@@ -47,12 +47,12 @@ | |||
}; | |||
} | |||
public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) | |||
{ | |||
} | |||
static INodeBuilder[] _nodesToBuild; | |||
{} | |||
static readonly INodeBuilder[] _nodesToBuild; | |||
} | |||
class GenericEntityDescriptor<T, U, V, W> : EntityDescriptor | |||
public class GenericEntityDescriptor<T, U, V, W> : EntityDescriptor | |||
where T : NodeWithID, new() | |||
where U : NodeWithID, new() | |||
where V : NodeWithID, new() | |||
@@ -69,12 +69,12 @@ | |||
}; | |||
} | |||
public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) | |||
{ | |||
} | |||
static INodeBuilder[] _nodesToBuild; | |||
{} | |||
static readonly INodeBuilder[] _nodesToBuild; | |||
} | |||
class GenericEntityDescriptor<T, U, V, W, X> : EntityDescriptor | |||
public class GenericEntityDescriptor<T, U, V, W, X> : EntityDescriptor | |||
where T : NodeWithID, new() | |||
where U : NodeWithID, new() | |||
where V : NodeWithID, new() | |||
@@ -93,11 +93,12 @@ | |||
}; | |||
} | |||
public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) | |||
{ | |||
} | |||
static INodeBuilder[] _nodesToBuild; | |||
{} | |||
static readonly INodeBuilder[] _nodesToBuild; | |||
} | |||
class GenericEntityDescriptor<T, U, V, W, X, Y> : EntityDescriptor | |||
public class GenericEntityDescriptor<T, U, V, W, X, Y> : EntityDescriptor | |||
where T : NodeWithID, new() | |||
where U : NodeWithID, new() | |||
where V : NodeWithID, new() | |||
@@ -118,8 +119,121 @@ | |||
}; | |||
} | |||
public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) | |||
{} | |||
static readonly INodeBuilder[] _nodesToBuild; | |||
} | |||
public class GenericMixedEntityDescriptor<T> : 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<T, U, V> : 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<T, U, V, W> : 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() | |||
}; | |||
} | |||
static INodeBuilder[] _nodesToBuild; | |||
public GenericMixedEntityDescriptor(params object[] componentsImplementor) : | |||
base(_nodesToBuild, componentsImplementor) | |||
{ } | |||
static readonly INodeBuilder[] _nodesToBuild; | |||
} | |||
public class GenericMixedEntityDescriptor<T, U, V, W, X> : 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<T, U, V, W, X, Y> : 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; | |||
} | |||
} |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: fd70d1b3107162f4790b1b71a129818f | |||
timeCreated: 1484485852 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: f2bc0783e8d4a7b49a84705c55d8b255 | |||
timeCreated: 1498225965 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,7 +1,7 @@ | |||
namespace Svelto.ECS | |||
{ | |||
interface ICallBackOnAddEngine | |||
public interface ICallBackOnAddEngine | |||
{ | |||
void Ready(); | |||
} | |||
} | |||
} |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 3928de9a08e5b534ab857ea8b5bebdaf | |||
timeCreated: 1497524074 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,21 +1,62 @@ | |||
namespace Svelto.ECS | |||
using Svelto.ECS.Internal; | |||
namespace Svelto.ECS.Internal | |||
{ | |||
public interface IEngine | |||
{} | |||
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<in TNodeType>:IEngine where TNodeType:INode | |||
public interface INodeEngine : IEngine | |||
{ | |||
void Add(TNodeType obj); | |||
void Remove(TNodeType obj); | |||
void Add(INode obj); | |||
void Remove(INode obj); | |||
} | |||
public interface INodesEngine : INodeEngine<INode> | |||
public interface INodesEngine : INodeEngine | |||
{ | |||
System.Type[] AcceptedNodes(); | |||
} | |||
} | |||
namespace Svelto.ECS | |||
{ | |||
public interface IEngine | |||
{} | |||
public interface IActivableNodeEngine<in TNodeType> : IActivableNodeEngine where TNodeType : INode | |||
{ } | |||
public interface IQueryableNodeEngine:IEngine | |||
{ | |||
IEngineNodeDB nodesDB { set; } | |||
} | |||
/// <summary> | |||
/// 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 | |||
/// </summary> | |||
public interface IStructNodeEngine<T> : IStructNodeEngine where T:struct, IStructNodeWithID | |||
{ } | |||
/// <summary> | |||
/// same as above, but the nodes are grouped by ID | |||
/// usually the ID is the owner of the nodes of that | |||
/// group | |||
/// </summary> | |||
public interface IGroupedStructNodesEngine<T> : IGroupedStructNodesEngine where T:struct, IGroupedStructNodeWithID | |||
{ } | |||
} | |||
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 26f6a5fa5638d86448dd3f2d11d62f5c | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -6,14 +6,14 @@ namespace Svelto.ECS | |||
{ | |||
ReadOnlyDictionary<int, INode> QueryIndexableNodes<T>() where T:INode; | |||
bool QueryNode<T>(int ID, out T node) where T:INode; | |||
bool TryQueryNode<T>(int ID, out T node) where T:INode; | |||
T QueryNode<T>(int ID) where T:INode; | |||
FasterReadOnlyListCast<INode, T> QueryNodes<T>() where T:INode; | |||
bool QueryNodeFromGroup<T>(int ID, out T node) where T : INode; | |||
T QueryNodeFromGroup<T>(int ID) where T : INode; | |||
FasterReadOnlyListCast<INode, T> QueryNodesFromGroups<T>() where T : INode; | |||
bool TryQueryMetaNode<T>(int metaEntityID, out T node) where T : INode; | |||
T QueryMetaNode<T>(int metaEntityID) where T : INode; | |||
FasterReadOnlyListCast<INode, T> QueryMetaNodes<T>() where T : INode; | |||
} | |||
} | |||
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 44c24b91989f46048abc15039fd070bc | |||
timeCreated: 1459422024 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,3 +1,5 @@ | |||
using Svelto.ECS.Internal; | |||
namespace Svelto.ECS | |||
{ | |||
public interface IEnginesRoot | |||
@@ -9,6 +11,8 @@ namespace Svelto.ECS | |||
{ | |||
void BuildEntity(int ID, EntityDescriptor ED); | |||
void BuildEntityGroup(int ID, EntityDescriptor ED); | |||
void BuildMetaEntity(int metaEntityID, EntityDescriptor ED); | |||
void BuildEntityInGroup(short entityID, short groupID, EntityDescriptor ED); | |||
} | |||
} |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: b0078c1edf75425478b89366d5fe3bae | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 0badb413a22f42a4b9f68e356e88b07f | |||
timeCreated: 1463438461 | |||
licenseType: Free | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -3,7 +3,22 @@ namespace Svelto.ECS | |||
public interface INode | |||
{} | |||
public class NodeWithID: INode | |||
public interface INodeWithID:INode | |||
{ | |||
int ID { get; } | |||
} | |||
public interface IStructNodeWithID : INode | |||
{ | |||
short ID { get; set; } | |||
} | |||
public interface IGroupedStructNodeWithID : IStructNodeWithID | |||
{ | |||
short groupID { get; set; } | |||
} | |||
public class NodeWithID: INodeWithID | |||
{ | |||
public static TNodeType BuildNode<TNodeType>(int ID) where TNodeType: NodeWithID, new() | |||
{ | |||
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: fc6bea8c56bd7284693db26502c6b65b | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -6,4 +6,14 @@ namespace Svelto.ECS | |||
{ | |||
Action removeEntity { get; set; } | |||
} | |||
public interface IDisableEntityComponent | |||
{ | |||
Action disableEntity { get; set; } | |||
} | |||
public interface IEnableEntityComponent | |||
{ | |||
Action enableEntity { get; set; } | |||
} | |||
} |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: bb9e778a1f85b0d46a065bbd5b549acd | |||
timeCreated: 1462977663 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,47 @@ | |||
using Svelto.ECS.Internal; | |||
namespace Svelto.ECS.Internal | |||
{ | |||
public abstract class MultiNodesEngine<T> | |||
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<T, U> : MultiNodesEngine<T>, | |||
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); | |||
} | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
using System; | |||
namespace Svelto.ECS.NodeSchedulers | |||
{ | |||
public abstract class NodeSubmissionScheduler | |||
{ | |||
abstract public void Schedule(Action submitNodes); | |||
} | |||
} |
@@ -1,9 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 8d07544bb8b417f4a9eaefe0d4771d89 | |||
folderAsset: yes | |||
timeCreated: 1462355668 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,9 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 71a4fc836cd9bde4bbb936a073804ec5 | |||
folderAsset: yes | |||
timeCreated: 1480683133 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,9 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 777a9420fd80746428f9d2c5b718fd2f | |||
folderAsset: yes | |||
timeCreated: 1462351213 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: a2202d1747b86dc428310091a9c1a7ef | |||
timeCreated: 1462469401 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -5,7 +5,7 @@ using UnityEditor; | |||
namespace Svelto.ECS.Profiler | |||
{ | |||
internal class EngineProfilerMenuItem | |||
class EngineProfilerMenuItem | |||
{ | |||
[MenuItem("Engines/Enable Profiler")] | |||
public static void EnableProfiler() | |||
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: e7b6bbeaaa16ab84aaa99c3311199efa | |||
timeCreated: 1462351229 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 30f9f7f6468a96d4da2525c65ecfe637 | |||
timeCreated: 1467633311 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: de0de03babf2e9d4db95c2be94eb8c95 | |||
timeCreated: 1462527509 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 93c5ba48b51186e44b7094eef7028c90 | |||
timeCreated: 1462357591 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,6 +1,7 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using Svelto.ECS.Internal; | |||
//This profiler is based on the Entitas Visual Debugging tool | |||
//https://github.com/sschmid/Entitas-CSharp | |||
@@ -11,7 +12,7 @@ namespace Svelto.ECS.Profiler | |||
{ | |||
static readonly Stopwatch _stopwatch = new Stopwatch(); | |||
public static void MonitorAddDuration(Action<INodeEngine<INode>, INode> addingFunc, INodeEngine<INode> engine, INode node) | |||
public static void MonitorAddDuration(Action<INodeEngine, INode> addingFunc, INodeEngine engine, INode node) | |||
{ | |||
EngineInfo info; | |||
if (engineInfos.TryGetValue(engine.GetType(), out info)) | |||
@@ -25,7 +26,7 @@ namespace Svelto.ECS.Profiler | |||
} | |||
} | |||
public static void MonitorRemoveDuration(Action<INodeEngine<INode>, INode> removeFunc, INodeEngine<INode> engine, INode node) | |||
public static void MonitorRemoveDuration(Action<INodeEngine, INode> removeFunc, INodeEngine engine, INode node) | |||
{ | |||
EngineInfo info; | |||
if (engineInfos.TryGetValue(engine.GetType(), out info)) | |||
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 74b59045fe5033b4b98facadd4d6b114 | |||
timeCreated: 1462355668 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,4 +1,4 @@ | |||
using System; | |||
using System; | |||
using System.Collections.Generic; | |||
using UnityEngine; | |||
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 688f5cf68b171ef4fa0f6aab49644c48 | |||
timeCreated: 1462469401 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 4e1f40937ca5027428ed7193729be1a5 | |||
timeCreated: 1484487023 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,15 +1,18 @@ | |||
namespace Svelto.ECS | |||
using Svelto.ECS.Internal; | |||
namespace Svelto.ECS | |||
{ | |||
public abstract class SingleNodeEngine<TNodeType> : INodeEngine<INode> where TNodeType : class, INode | |||
public abstract class SingleNodeEngine<TNodeType> : INodeEngine | |||
where TNodeType : INode | |||
{ | |||
void INodeEngine<INode>.Add(INode obj) | |||
public void Add(INode obj) | |||
{ | |||
Add(obj as TNodeType); | |||
Add((TNodeType) obj); | |||
} | |||
void INodeEngine<INode>.Remove(INode obj) | |||
public void Remove(INode obj) | |||
{ | |||
Remove(obj as TNodeType); | |||
Remove((TNodeType) obj); | |||
} | |||
protected abstract void Add(TNodeType node); | |||
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 406a5e818b179b743b582c8fec087ac1 | |||
timeCreated: 1469806920 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -0,0 +1,134 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS.Internal; | |||
namespace Svelto.ECS | |||
{ | |||
public class StructNodes<T> where T:struct, IStructNodeWithID | |||
{ | |||
public T[] GetList(out int numberOfItems) | |||
{ | |||
numberOfItems = _internalList.Count; | |||
return _internalList.ToArrayFast(); | |||
} | |||
public StructNodes(SharedStructNodeLists container) | |||
{ | |||
_internalList = container.GetList<T>(); | |||
} | |||
public void Add(T node) | |||
{ | |||
T convert = (T)node; | |||
_internalList.Add(convert); | |||
} | |||
readonly FasterList<T> _internalList; | |||
} | |||
public class StructGroupNodes<T> | |||
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<T>(groupID) as FasterList<T>); | |||
indices[node.ID] = fasterList.Count; | |||
fasterList.Add(convert); | |||
} | |||
public void Remove(int groupID, T node) | |||
{ | |||
var fasterList = (_container.GetList<T>(groupID) as FasterList<T>); | |||
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<T>(groupID) as FasterList<T>); | |||
numberOfItems = fasterList.Count; | |||
return fasterList.ToArrayFast(); | |||
} | |||
readonly SharedGroupedStructNodesLists _container; | |||
readonly Dictionary<int, int> indices = new Dictionary<int, int>(); | |||
} | |||
public class SharedStructNodeLists | |||
{ | |||
readonly Dictionary<Type, IFasterList> _collection; | |||
internal SharedStructNodeLists() | |||
{ | |||
_collection = new Dictionary<Type, IFasterList>(); | |||
} | |||
internal FasterList<T> GetList<T>() where T:struct | |||
{ | |||
IFasterList list; | |||
if (_collection.TryGetValue(typeof (T), out list)) | |||
{ | |||
return list as FasterList<T>; | |||
} | |||
list = new FasterList<T>(); | |||
_collection.Add(typeof (T), list); | |||
return (FasterList<T>) list; | |||
} | |||
} | |||
public class SharedGroupedStructNodesLists | |||
{ | |||
internal SharedGroupedStructNodesLists() | |||
{ | |||
_collection = new Dictionary<Type, Dictionary<int, IFasterList>>(); | |||
} | |||
internal IFasterList GetList<T>(int groupID) where T : struct | |||
{ | |||
Dictionary<int, IFasterList> dic = GetGroup<T>(); | |||
IFasterList localList; | |||
if (dic.TryGetValue(groupID, out localList)) | |||
return localList; | |||
localList = new FasterList<T>(); | |||
dic.Add(groupID, localList); | |||
return localList; | |||
} | |||
internal Dictionary<int, IFasterList> GetGroup<T>() where T : struct | |||
{ | |||
Dictionary<int, IFasterList> dic; | |||
if (_collection.TryGetValue(typeof(T), out dic)) | |||
{ | |||
return dic; | |||
} | |||
dic = new Dictionary<int, IFasterList>(); | |||
_collection.Add(typeof(T), dic); | |||
return dic; | |||
} | |||
readonly Dictionary<Type, Dictionary<int, IFasterList>> _collection; | |||
} | |||
} |
@@ -1,4 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 11a3defaf51bc2147904eb737af5efb7 | |||
TextScriptImporter: | |||
userData: |
@@ -1,9 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 7f7896118ef3c4949898b5c30aea0c47 | |||
folderAsset: yes | |||
timeCreated: 1484044925 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: f3720a403a14c51489b5250365b7185c | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 22ba598cf1fd5124dbb4b999af89a0c5 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: ab819523a7b1394499edac4ffa37556b | |||
timeCreated: 1440946962 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: e772c63482a119748ba160ed807765a3 | |||
timeCreated: 1440946962 | |||
licenseType: Free | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,9 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: b7374ca2eb247d44c8783d7d23f9b89e | |||
folderAsset: yes | |||
timeCreated: 1484394896 | |||
licenseType: Pro | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -26,10 +26,10 @@ | |||
// | |||
// Alternatively, you can define these in the project properties dialog. | |||
#if UNITY_EDITOR || ROBO_TEST_BUILD | |||
#define DBC_CHECK_ALL | |||
#if DEBUG && !PROFILER | |||
#define DBC_CHECK_ALL | |||
#endif | |||
using System; | |||
using System.Diagnostics; | |||
@@ -1,10 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 5a6942e14a8d33d46a05b33d50392652 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -7,7 +7,7 @@ public static class FastConcatUtility | |||
{ | |||
static readonly StringBuilder _stringBuilder = new StringBuilder(256); | |||
public static string FastConcat(this string str1, string str2) | |||
public static string FastConcat<T>(this string str1, T str2) | |||
{ | |||
lock (_stringBuilder) | |||
{ | |||
@@ -136,7 +136,7 @@ namespace Utility | |||
logger.Log(txt); | |||
} | |||
public static void LogError(string txt, bool showCurrentStack = true) | |||
public static void LogError(string txt) | |||
{ | |||
string toPrint; | |||
@@ -148,11 +148,8 @@ namespace Utility | |||
toPrint = _stringBuilder.ToString(); | |||
} | |||
#if !NETFX_CORE | |||
logger.Log(toPrint, showCurrentStack == true ? new StackTrace().ToString() : null, LogType.Error); | |||
#else | |||
logger.Log(toPrint, null, LogType.Error); | |||
#endif | |||
} | |||
public static void LogError(string txt, string stack) | |||
@@ -1,8 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 1f5eede659a66c64a9af2ec703db2691 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: |
@@ -1,4 +1,4 @@ | |||
using System; | |||
using System; | |||
using System.Reflection; | |||
using System.Runtime.CompilerServices; | |||
using System.Runtime.InteropServices; | |||
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: 1662357721652524593d7b0f731aef45 | |||
timeCreated: 1484483913 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@@ -1,5 +1,6 @@ | |||
using Svelto.DataStructures; | |||
using System; | |||
using System.Collections.Generic; | |||
namespace BetterWeakEvents | |||
{ | |||
@@ -13,7 +14,7 @@ namespace BetterWeakEvents | |||
public static WeakEvent<T1, T2> operator-(WeakEvent<T1, T2> c1, Action<T1, T2> x) | |||
{ | |||
c1._subscribers.UnorderredRemove(new WeakAction<T1, T2>(x)); | |||
c1._subscribers.UnorderedRemove(new WeakAction<T1, T2>(x)); | |||
return c1; | |||
} | |||
@@ -21,7 +22,7 @@ namespace BetterWeakEvents | |||
{ | |||
for (int i = 0; i < _subscribers.Count; i++) | |||
if (_subscribers[i].Invoke(arg1, arg2) == false) | |||
_subscribers.UnorderredRemoveAt(i--); | |||
_subscribers.UnorderedRemoveAt(i--); | |||
} | |||
~WeakEvent() | |||
@@ -32,4 +33,4 @@ namespace BetterWeakEvents | |||
protected FasterList<WeakAction<T1, T2>> _subscribers = new FasterList<WeakAction<T1, T2>>(); | |||
} | |||
} | |||
} |
@@ -1,12 +0,0 @@ | |||
fileFormatVersion: 2 | |||
guid: e2ee3763e7dffd4459c588eda6867ddd | |||
timeCreated: 1484480295 | |||
licenseType: Pro | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |