- FasterList Clear has been renamed to FastClear. The standard Clear will clean the array like the normal List does - An engine can now receive callback for when nodes are disabled and enabled -tags/Rel1
@@ -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; } } | |||
@@ -274,6 +276,19 @@ namespace Svelto.DataStructures | |||
} | |||
} | |||
public void FastClear() | |||
{ | |||
_lockQ.EnterWriteLock(); | |||
try | |||
{ | |||
_list.FastClear(); | |||
} | |||
finally | |||
{ | |||
_lockQ.ExitWriteLock(); | |||
} | |||
} | |||
public bool Contains(T item) | |||
{ | |||
_lockQ.EnterReadLock(); | |||
@@ -382,6 +397,8 @@ namespace Svelto.DataStructures | |||
public struct FasterReadOnlyListCast<T, U> : IList<U> where U: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; } } | |||
@@ -455,7 +472,6 @@ namespace Svelto.DataStructures | |||
public class FasterList<T> : IList<T>, IFasterList | |||
{ | |||
public static FasterList<T> DefaultList = new FasterList<T>(); | |||
const int MIN_SIZE = 4; | |||
public int Count | |||
@@ -529,7 +545,7 @@ namespace Svelto.DataStructures | |||
for (int i = 0; i < initialSize; i++) | |||
list.Add(new U()); | |||
list.Clear(); | |||
list._count = 0; | |||
return list; | |||
} | |||
@@ -583,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); | |||
@@ -727,11 +743,13 @@ namespace Svelto.DataStructures | |||
DesignByContract.Check.Require(index < _count && _count > 0, "out of bound index"); | |||
if (index == --_count) | |||
{ | |||
_buffer[_count] = default(T); | |||
return false; | |||
} | |||
T swap = _buffer[index]; | |||
_buffer[index] = _buffer[_count]; | |||
_buffer[_count] = swap; | |||
_buffer[_count] = default(T); | |||
return true; | |||
} | |||
@@ -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; | |||
} | |||
} | |||
} |
@@ -66,7 +66,7 @@ namespace Svelto.DataStructures | |||
#endif | |||
public void Clear() | |||
{ | |||
_nodes.Clear(); | |||
_nodes.FastClear(); | |||
_numNodes = 0; | |||
} | |||
@@ -3,8 +3,6 @@ using System; | |||
using System.Collections.Generic; | |||
using System.Threading; | |||
//note, rewrite like ThreadSafeQueue | |||
namespace Svelto.DataStructures | |||
{ | |||
/// <summary> | |||
@@ -1,7 +1,6 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS.Internal; | |||
namespace Svelto.ECS | |||
{ | |||
@@ -9,13 +8,11 @@ namespace Svelto.ECS | |||
{ | |||
internal EngineNodeDB( Dictionary<Type, FasterList<INode>> nodesDB, | |||
Dictionary<Type, Dictionary<int, INode>> nodesDBdic, | |||
Dictionary<Type, FasterList<INode>> metaNodesDB, | |||
Dictionary<Type, IStructGroupNodes> structNodesDB) | |||
Dictionary<Type, FasterList<INode>> metaNodesDB) | |||
{ | |||
_nodesDB = nodesDB; | |||
_nodesDBdic = nodesDBdic; | |||
_metaNodesDB = metaNodesDB; | |||
_structNodesDB = structNodesDB; | |||
} | |||
public FasterReadOnlyListCast<INode, T> QueryNodes<T>() where T:INode | |||
@@ -102,13 +99,12 @@ namespace Svelto.ECS | |||
static FasterReadOnlyListCast<INode, T> RetrieveEmptyNodeList<T>() where T : INode | |||
{ | |||
return new FasterReadOnlyListCast<INode, T>(FasterList<INode>.DefaultList); | |||
return FasterReadOnlyListCast<INode, T>.DefaultList; | |||
} | |||
readonly Dictionary<Type, FasterList<INode>> _nodesDB; | |||
readonly Dictionary<Type, Dictionary<int, INode>> _nodesDBdic; | |||
readonly Dictionary<Type, FasterList<INode>> _metaNodesDB; | |||
readonly Dictionary<Type, IStructGroupNodes> _structNodesDB; | |||
readonly ReadOnlyDictionary<int, INode> _defaultEmptyNodeDict = new ReadOnlyDictionary<int, INode>(new Dictionary<int, INode>()); | |||
} | |||
@@ -16,23 +16,6 @@ using System.Reflection; | |||
namespace Svelto.ECS | |||
{ | |||
class Scheduler : MonoBehaviour | |||
{ | |||
IEnumerator Start() | |||
{ | |||
while (true) | |||
{ | |||
yield return _waitForEndOfFrame; | |||
OnTick(); | |||
} | |||
} | |||
internal Action OnTick; | |||
readonly WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame(); | |||
} | |||
public sealed class EnginesRoot : IEnginesRoot, IEntityFactory | |||
{ | |||
public EnginesRoot(NodeSubmissionScheduler nodeScheduler) | |||
@@ -50,7 +33,8 @@ namespace Svelto.ECS | |||
_metaNodesToAdd = new FasterList<INode>(); | |||
_metaNodesDB = new Dictionary<Type, FasterList<INode>>(); | |||
_structNodesDB = new Dictionary<Type, IStructGroupNodes>(); | |||
_sharedStructNodeLists = new SharedStructNodeLists(); | |||
_sharedGroupedStructNodeLists = new SharedGroupedStructNodesLists(); | |||
_internalRemove = InternalRemove; | |||
_internalDisable = InternalDisable; | |||
@@ -60,6 +44,8 @@ namespace Svelto.ECS | |||
_scheduler = nodeScheduler; | |||
_scheduler.Schedule(SubmitNodes); | |||
_structNodeEngineType = typeof(IStructNodeEngine<>); | |||
_groupedStructNodesEngineType = typeof(IGroupedStructNodesEngine<>); | |||
_activableNodeEngineType = typeof(IActivableNodeEngine<>); | |||
_implementedInterfaceTypes = new Dictionary<Type, Type[]>(); | |||
@@ -84,9 +70,11 @@ namespace Svelto.ECS | |||
do | |||
{ | |||
var nodesToAdd = _nodesToAdd.ToArrayFast(); | |||
for (int i = startNodes; i < nodesCount; i++) | |||
{ | |||
var node = _nodesToAdd[i]; | |||
var node = nodesToAdd[i]; | |||
var nodeType = node.GetType(); | |||
AddNodeToTheDB(node, nodeType); | |||
@@ -95,9 +83,11 @@ namespace Svelto.ECS | |||
AddNodeToNodesDictionary(nodeWithId, nodeType); | |||
} | |||
var metaNodesToAdd = _metaNodesToAdd.ToArrayFast(); | |||
for (int i = startMetaNodes; i < metaNodesCount; i++) | |||
{ | |||
var node = _metaNodesToAdd[i]; | |||
var node = metaNodesToAdd[i]; | |||
var nodeType = node.GetType(); | |||
AddNodeToMetaDB(node, nodeType); | |||
@@ -108,13 +98,13 @@ namespace Svelto.ECS | |||
for (int i = startNodes; i < nodesCount; i++) | |||
{ | |||
var node = _nodesToAdd[i]; | |||
var node = nodesToAdd[i]; | |||
AddNodeToTheSuitableEngines(node, node.GetType()); | |||
} | |||
for (int i = startMetaNodes; i < metaNodesCount; i++) | |||
{ | |||
var node = _metaNodesToAdd[i]; | |||
var node = metaNodesToAdd[i]; | |||
AddNodeToTheSuitableEngines(node, node.GetType()); | |||
} | |||
@@ -147,7 +137,7 @@ namespace Svelto.ECS | |||
var queryableNodeEngine = engine as IQueryableNodeEngine; | |||
if (queryableNodeEngine != null) | |||
queryableNodeEngine.nodesDB = | |||
new EngineNodeDB(_nodesDB, _nodesDBdic, _metaNodesDB, _structNodesDB); | |||
new EngineNodeDB(_nodesDB, _nodesDBdic, _metaNodesDB); | |||
var engineType = engine.GetType(); | |||
var implementedInterfaces = engineType.GetInterfaces(); | |||
@@ -185,8 +175,6 @@ namespace Svelto.ECS | |||
} | |||
var genericTypeDefinition = interfaceType.GetGenericTypeDefinition(); | |||
var a = interfaceType.GetGenericArguments(); | |||
var b = genericTypeDefinition.GetGenericArguments(); | |||
_implementedInterfaceTypes.Add(genericTypeDefinition, | |||
interfaceType.GetGenericArguments()); | |||
@@ -199,6 +187,18 @@ namespace Svelto.ECS | |||
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)) | |||
@@ -298,7 +298,7 @@ namespace Svelto.ECS | |||
/// <param name="entityID"></param> | |||
/// <param name="groupID"></param> | |||
/// <param name="ed"></param> | |||
public void BuildEntityInGroup(int entityID, int groupID, | |||
public void BuildEntityInGroup(short entityID, short groupID, | |||
EntityDescriptor ed) | |||
{ | |||
var entityNodes = ed.BuildNodes(entityID, | |||
@@ -349,19 +349,10 @@ namespace Svelto.ECS | |||
void AddNodeToTheDB<T>(T node, Type nodeType) where T : INode | |||
{ | |||
FasterList<INode> nodes; | |||
if (_nodesDB.TryGetValue(nodeType, out nodes) == false) | |||
nodes = _nodesDB[nodeType] = new FasterList<INode>(); | |||
if (node is IStructNodeWithID == false) | |||
{ | |||
if (_nodesDB.TryGetValue(nodeType, out nodes) == false) | |||
nodes = _nodesDB[nodeType] = new FasterList<INode>(); | |||
nodes.Add(node); | |||
} | |||
else | |||
{ | |||
if (_nodesDB.TryGetValue(nodeType, out nodes) == false) | |||
nodes = _nodesDB[nodeType] = new FasterList<INode>(); | |||
} | |||
nodes.Add(node); | |||
} | |||
void AddNodeToNodesDictionary<T>(T node, Type nodeType) where T : INodeWithID | |||
@@ -535,14 +526,15 @@ namespace Svelto.ECS | |||
readonly Dictionary<Type, FasterList<INode>> _nodesDB; | |||
readonly Dictionary<Type, FasterList<INode>> _metaNodesDB; | |||
readonly Dictionary<Type, IStructGroupNodes> _structNodesDB; | |||
readonly Dictionary<Type, Dictionary<int, INode>> _nodesDBdic; | |||
readonly FasterList<INode> _nodesToAdd; | |||
readonly FasterList<INode> _metaNodesToAdd; | |||
readonly WeakReference _engineRootWeakReference; | |||
readonly WeakReference _engineRootWeakReference; | |||
readonly SharedStructNodeLists _sharedStructNodeLists; | |||
readonly SharedGroupedStructNodesLists _sharedGroupedStructNodeLists; | |||
readonly NodeSubmissionScheduler _scheduler; | |||
@@ -551,6 +543,8 @@ namespace Svelto.ECS | |||
readonly Action<FasterList<INode>> _internalDisable; | |||
readonly Action<FasterList<INode>> _internalMetaRemove; | |||
readonly Type _structNodeEngineType; | |||
readonly Type _groupedStructNodesEngineType; | |||
readonly Type _activableNodeEngineType; | |||
readonly Dictionary<Type, Type[]> _implementedInterfaceTypes; | |||
@@ -10,10 +10,12 @@ namespace Svelto.ECS | |||
{ | |||
public class EntityDescriptor | |||
{ | |||
protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor) | |||
protected EntityDescriptor(INodeBuilder[] nodesToBuild) | |||
{ | |||
_nodesToBuild = new FasterList<INodeBuilder>(nodesToBuild); | |||
} | |||
protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor):this(nodesToBuild) | |||
{ | |||
ProcessImplementors(componentsImplementor); | |||
} | |||
@@ -84,12 +86,9 @@ namespace Svelto.ECS | |||
Action<FasterList<INode>> disableEntity, | |||
FasterList<INode> nodes) | |||
{ | |||
Action removeEntityAction = () => | |||
{ removeEntity(nodes); nodes.Clear(); }; | |||
Action disableEntityAction = () => | |||
{ disableEntity(nodes); }; | |||
Action enableEntityAction = () => | |||
{ enableEntity(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; | |||
@@ -99,7 +98,7 @@ namespace Svelto.ECS | |||
_enablingImplementors[index].enableEntity = enableEntityAction; | |||
} | |||
INode FillNode(INode node, FillNodeMode mode) | |||
TNode FillNode<TNode>(TNode node, FillNodeMode mode) where TNode : INode | |||
{ | |||
var fields = node.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); | |||
@@ -131,21 +130,21 @@ namespace Svelto.ECS | |||
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 FasterList<INodeBuilder> _nodesToBuild; | |||
} | |||
public interface INodeBuilder | |||
{ | |||
INodeWithID Build(int ID); | |||
INode Build(int ID); | |||
FillNodeMode reflects { get; } | |||
} | |||
public class NodeBuilder<NodeType> : INodeBuilder where NodeType : NodeWithID, new() | |||
{ | |||
public INodeWithID Build(int ID) | |||
public INode Build(int ID) | |||
{ | |||
NodeWithID node = NodeWithID.BuildNode<NodeType>(ID); | |||
@@ -155,20 +154,25 @@ namespace Svelto.ECS | |||
public FillNodeMode reflects { get { return FillNodeMode.Strict; } } | |||
} | |||
//To Do: Probably I will need to add an | |||
//FastStructNodeBuilder where reflects is false | |||
public class StructNodeBuilder<NodeType> : INodeBuilder | |||
where NodeType : struct, IStructNodeWithID | |||
{ | |||
public INodeWithID Build(int ID) | |||
public INode Build(int ID) | |||
{ | |||
var shortID = (short)ID; | |||
IStructNodeWithID node = default(NodeType); | |||
node.ID = ID; | |||
node.ID = shortID; | |||
return node; | |||
} | |||
public FillNodeMode reflects { get { return FillNodeMode.Relaxed; } } | |||
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 | |||
@@ -2,6 +2,16 @@ 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); | |||
@@ -32,5 +42,21 @@ namespace Svelto.ECS | |||
{ | |||
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 | |||
{ } | |||
} | |||
@@ -13,6 +13,6 @@ namespace Svelto.ECS | |||
void BuildMetaEntity(int metaEntityID, EntityDescriptor ED); | |||
void BuildEntityInGroup(int entityID, int groupID, EntityDescriptor ED); | |||
void BuildEntityInGroup(short entityID, short groupID, EntityDescriptor ED); | |||
} | |||
} |
@@ -8,14 +8,14 @@ namespace Svelto.ECS | |||
int ID { get; } | |||
} | |||
public interface IStructNodeWithID : INodeWithID | |||
public interface IStructNodeWithID : INode | |||
{ | |||
new int ID { get; set; } | |||
short ID { get; set; } | |||
} | |||
public interface IGroupedStructNodeWithID : IStructNodeWithID | |||
{ | |||
int groupID { get; set; } | |||
short groupID { get; set; } | |||
} | |||
public class NodeWithID: INodeWithID | |||
@@ -5,8 +5,8 @@ namespace Svelto.ECS.Internal | |||
public abstract class MultiNodesEngine<T> | |||
where T : INode | |||
{ | |||
protected internal abstract void Add(T node); | |||
protected internal abstract void Remove(T node); | |||
protected abstract void AddNode(T node); | |||
protected abstract void RemoveNode(T node); | |||
} | |||
} | |||
@@ -20,28 +20,28 @@ namespace Svelto.ECS | |||
public abstract void Remove(INode node); | |||
} | |||
public abstract class MultiNodesEngine<T, U> : MultiNodesEngine<U>, | |||
public abstract class MultiNodesEngine<T, U> : MultiNodesEngine<T>, | |||
INodeEngine | |||
where T : INode | |||
where T : INode | |||
where U : INode | |||
{ | |||
protected abstract void Add(T node); | |||
protected abstract void Remove(T node); | |||
protected abstract void AddNode(U node); | |||
protected abstract void RemoveNode(U node); | |||
public void Add(INode node) | |||
{ | |||
if (node is T) | |||
Add((T) node); | |||
AddNode((T)node); | |||
else | |||
((MultiNodesEngine<U>)(this)).Add((U)node); | |||
AddNode((U)node); | |||
} | |||
public void Remove(INode node) | |||
{ | |||
if (node is T) | |||
Remove((T)node); | |||
RemoveNode((T)node); | |||
else | |||
((MultiNodesEngine<U>)(this)).Remove((U)node); | |||
RemoveNode((U)node); | |||
} | |||
} | |||
} |
@@ -3,7 +3,7 @@ | |||
namespace Svelto.ECS | |||
{ | |||
public abstract class SingleNodeEngine<TNodeType> : INodeEngine | |||
where TNodeType : class, INode | |||
where TNodeType : INode | |||
{ | |||
public void Add(INode obj) | |||
{ | |||
@@ -1,22 +1,21 @@ | |||
using System.Collections.Generic; | |||
using System; | |||
using System.Collections.Generic; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS.Internal; | |||
namespace Svelto.ECS | |||
{ | |||
public class StructNodes<T>: IStructNodes where T:struct, IStructNodeWithID | |||
public class StructNodes<T> where T:struct, IStructNodeWithID | |||
{ | |||
public FasterList<T> list | |||
public T[] GetList(out int numberOfItems) | |||
{ | |||
get | |||
{ | |||
return _internalList; | |||
} | |||
numberOfItems = _internalList.Count; | |||
return _internalList.ToArrayFast(); | |||
} | |||
public StructNodes() | |||
public StructNodes(SharedStructNodeLists container) | |||
{ | |||
_internalList = new FasterList<T>(); | |||
_internalList = container.GetList<T>(); | |||
} | |||
public void Add(T node) | |||
@@ -29,46 +28,107 @@ namespace Svelto.ECS | |||
readonly FasterList<T> _internalList; | |||
} | |||
public class StructGroupNodes<T>: IStructGroupNodes | |||
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 = GetList(groupID); | |||
_indices[node.ID] = fasterList.Count; | |||
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 = GetList(groupID); | |||
var index = _indices[node.ID]; | |||
_indices.Remove(node.ID); | |||
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; | |||
indices[fasterList[index].ID] = index; | |||
} | |||
public FasterList<T> GetList(int groupID) | |||
public T[] GetList(int groupID, out int numberOfItems) | |||
{ | |||
return _nodes[groupID]; | |||
var fasterList = (_container.GetList<T>(groupID) as FasterList<T>); | |||
numberOfItems = fasterList.Count; | |||
return fasterList.ToArrayFast(); | |||
} | |||
readonly Dictionary<int, int> _indices = new Dictionary<int, int>(); | |||
Dictionary<int, FasterList<T>> _nodes = new Dictionary<int, FasterList<T>>(); | |||
readonly SharedGroupedStructNodesLists _container; | |||
readonly Dictionary<int, int> indices = new Dictionary<int, int>(); | |||
} | |||
} | |||
namespace Svelto.ECS.Internal | |||
{ | |||
public interface IStructGroupNodes | |||
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 interface IStructNodes | |||
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; | |||
} | |||
} |
@@ -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; | |||