Browse Source

- INodesEngine is now Legacy. EnginesRoot still support it, but I will probably add a new Legacy Engine Root to support INodesEngine. Best thing would be to transform all the INodesEngine into MultiNodesEngine

- Support for grouped nodes (adding and querying them) is almost complete
- EngineRoot and EngineNodeDB can now support nodes as struct and class
- INodeEngine Add and Remove functions accept only NodeWithID (classes only)
-
tags/Rel2b
sebas77 6 years ago
parent
commit
5897f66b2d
16 changed files with 612 additions and 486 deletions
  1. +31
    -4
      ECS/DataStructures/TypeSafeDictionary.cs
  2. +82
    -0
      ECS/DataStructures/TypeSafeFasterListForECS.cs
  3. +0
    -51
      ECS/DataStructures/TypeSafeList.cs
  4. +46
    -12
      ECS/EngineNodeDB.cs
  5. +270
    -189
      ECS/EnginesRoot.cs
  6. +78
    -84
      ECS/EntityDescriptor.cs
  7. +13
    -7
      ECS/IEngine.cs
  8. +11
    -7
      ECS/IEngineNodeDB.cs
  9. +7
    -5
      ECS/INode.cs
  10. +41
    -60
      ECS/MultiNodesEngine.cs
  11. +7
    -26
      ECS/NodeBuilder.cs
  12. +2
    -2
      ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs
  13. +3
    -7
      ECS/Profiler/EngineProfiler.cs
  14. +1
    -1
      ECS/Profiler/EngineProfilerBehaviour.cs
  15. +5
    -16
      ECS/SingleNodeEngine.cs
  16. +15
    -15
      ECS/StructNodes.cs

+ 31
- 4
ECS/DataStructures/TypeSafeDictionary.cs View File

@@ -1,7 +1,8 @@
using Svelto.DataStructures;
using System.Collections.Generic;
using Svelto.ECS.Internal;

namespace Svelto.ECS
namespace Svelto.ECS.Internal
{
/// <summary>
/// This is just a place holder at the moment
@@ -13,11 +14,37 @@ namespace Svelto.ECS

public interface ITypeSafeDictionary
{

void FillWithIndexedNodes(ITypeSafeList nodes);
void Remove(int entityId);
NodeWithID GetIndexedNode(int entityID);
}

public class TypeSafeDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ITypeSafeDictionary
class TypeSafeDictionary<TValue> : Dictionary<int, TValue>, ITypeSafeDictionary where TValue:NodeWithID
{
internal static readonly ReadOnlyDictionary<TKey, TValue> Default = new ReadOnlyDictionary<TKey, TValue>(new TypeSafeDictionary<TKey, TValue>());
internal static readonly ReadOnlyDictionary<int, TValue> Default =
new ReadOnlyDictionary<int, TValue>(new Dictionary<int, TValue>());
public void FillWithIndexedNodes(ITypeSafeList nodes)
{
int count;
var buffer = FasterList<TValue>.NoVirt.ToArrayFast((FasterList<TValue>) nodes, out count);

for (int i = 0; i < count; i++)
{
var node = buffer[i];

Add(node.ID, node);
}
}

public void Remove(int entityId)
{
throw new System.NotImplementedException();
}

public NodeWithID GetIndexedNode(int entityID)
{
return this[entityID];
}
}
}

+ 82
- 0
ECS/DataStructures/TypeSafeFasterListForECS.cs View File

@@ -0,0 +1,82 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Svelto.DataStructures;

namespace Svelto.ECS.Internal
{
public interface ITypeSafeList: IEnumerable
{
void AddRange(ITypeSafeList nodeListValue);

ITypeSafeList Create();
bool isQueryiableNode { get; }
void UnorderedRemove(int index);
ITypeSafeDictionary CreateIndexedDictionary();
}

class TypeSafeFasterListForECS<T>: FasterList<T> where T:INode
{
protected TypeSafeFasterListForECS()
{
_mappedIndices = new Dictionary<int, int>();
}
public void UnorderedRemove(int mappedIndex)
{
var index = _mappedIndices[mappedIndex];
_mappedIndices.Remove(mappedIndex);

if (UnorderedRemoveAt(index))
_mappedIndices[this[index].ID] = index;
}
public void AddRange(ITypeSafeList nodeListValue)
{
var index = this.Count;
AddRange(nodeListValue as FasterList<T>);
for (int i = index; i < Count; ++i)
_mappedIndices[this[i].ID] = this.Count;
}

readonly Dictionary<int, int> _mappedIndices;
}

class TypeSafeFasterListForECSForStructs<T> : TypeSafeFasterListForECS<T>, ITypeSafeList where T:struct, INode
{
public ITypeSafeList Create()
{
return new TypeSafeFasterListForECSForStructs<T>();
}

public bool isQueryiableNode
{
get { return false; }
}

public ITypeSafeDictionary CreateIndexedDictionary()
{
throw new Exception("Not Allowed");
}
}
class TypeSafeFasterListForECSForClasses<T> : TypeSafeFasterListForECS<T>, ITypeSafeList where T:NodeWithID
{
public ITypeSafeList Create()
{
return new TypeSafeFasterListForECSForClasses<T>();
}

public bool isQueryiableNode
{
get { return true; }
}

public ITypeSafeDictionary CreateIndexedDictionary()
{
return new TypeSafeDictionary<T>();
}
}
}

+ 0
- 51
ECS/DataStructures/TypeSafeList.cs View File

@@ -1,51 +0,0 @@
using Svelto.DataStructures;
using Svelto.ECS.Internal;

namespace Svelto.ECS
{
public interface ITypeSafeList
{
void Clear();
void AddRange(ITypeSafeList nodeListValue);

ITypeSafeList Create();
ITypeSafeDictionary CreateIndexedDictionary();
void AddToIndexedDictionary(ITypeSafeDictionary nodesDic);
}

public class TypeSafeFasterList<T> : FasterList<T>, ITypeSafeList
{
public TypeSafeFasterList()
{
}

public void AddRange(ITypeSafeList nodeListValue)
{
AddRange(nodeListValue as FasterList<T>);
}

public ITypeSafeList Create()
{
return new TypeSafeFasterList<T>();
}

public ITypeSafeDictionary CreateIndexedDictionary()
{
return new TypeSafeDictionary<int, T>();
}

public void AddToIndexedDictionary(ITypeSafeDictionary nodesDic)
{
var dic = nodesDic as TypeSafeDictionary<int, T>;

var buffer = NoVirt.ToArrayFast(this);

for (int i = 0; i < Count; i++)
{
T node = buffer[i];

dic[(node as NodeWithID).ID] = node;
}
}
}
}

+ 46
- 12
ECS/EngineNodeDB.cs View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Svelto.DataStructures;
using Svelto.ECS.Internal;

namespace Svelto.ECS
{
@@ -8,11 +9,13 @@ namespace Svelto.ECS
{
internal EngineNodeDB( Dictionary<Type, ITypeSafeList> nodesDB,
Dictionary<Type, ITypeSafeDictionary> nodesDBdic,
Dictionary<Type, ITypeSafeList> metaNodesDB)
Dictionary<Type, ITypeSafeList> metaNodesDB,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupNodesDB)
{
_nodesDB = nodesDB;
_nodesDBdic = nodesDBdic;
_metaNodesDB = metaNodesDB;
_groupNodesDB = groupNodesDB;
}

public FasterReadOnlyList<T> QueryNodes<T>()
@@ -27,24 +30,46 @@ namespace Svelto.ECS
return new FasterReadOnlyList<T>((FasterList<T>)nodes);
}

public ReadOnlyDictionary<int, T> QueryIndexableNodes<T>()
public FasterReadOnlyList<T> QueryGroupedNodes<T>(int @group)
{
return new FasterReadOnlyList<T>(_groupNodesDB[group] as FasterList<T>);
}

public T[] QueryNodesAsArray<T>(out int count) where T : struct
{
var type = typeof(T);
count = 0;
ITypeSafeList nodes;

if (_nodesDB.TryGetValue(type, out nodes) == false)
return null;
var castedNodes = (FasterList<T>)nodes;

count = castedNodes.Count;

return castedNodes.ToArrayFast();
}

public ReadOnlyDictionary<int, T> QueryIndexableNodes<T>() where T:NodeWithID
{
var type = typeof(T);

ITypeSafeDictionary nodes;

if (_nodesDBdic.TryGetValue(type, out nodes) == false)
return TypeSafeDictionary<int, T>.Default;
return TypeSafeDictionary<T>.Default;

return new ReadOnlyDictionary<int, T>(nodes as Dictionary<int, T>);
}

public T QueryMetaNode<T>(int metaEntityID)
public T QueryMetaNode<T>(int metaEntityID) where T:NodeWithID
{
return QueryNode<T>(metaEntityID);
}

public bool TryQueryMetaNode<T>(int metaEntityID, out T node)
public bool TryQueryMetaNode<T>(int metaEntityID, out T node) where T:NodeWithID
{
return TryQueryNode(metaEntityID, out node);
}
@@ -61,18 +86,22 @@ namespace Svelto.ECS
return new FasterReadOnlyList<T>((FasterList<T>)nodes);
}

public bool TryQueryNode<T>(int ID, out T node)
public bool TryQueryNode<T>(int ID, out T node) where T:NodeWithID
{
var type = typeof(T);

T internalNode;

ITypeSafeDictionary nodes;
TypeSafeDictionary<T> casted;

if (_nodesDBdic.TryGetValue(type, out nodes) &&
(nodes as Dictionary<int, T>).TryGetValue(ID, out internalNode))
_nodesDBdic.TryGetValue(type, out nodes);
casted = nodes as TypeSafeDictionary<T>;

if (casted != null &&
casted.TryGetValue(ID, out internalNode))
{
node = internalNode;
node = (T) internalNode;

return true;
}
@@ -82,14 +111,18 @@ namespace Svelto.ECS
return false;
}

public T QueryNode<T>(int ID)
public T QueryNode<T>(int ID) where T:NodeWithID
{
var type = typeof(T);

T internalNode; ITypeSafeDictionary nodes;
TypeSafeDictionary<T> casted;

_nodesDBdic.TryGetValue(type, out nodes);
casted = nodes as TypeSafeDictionary<T>;

if (_nodesDBdic.TryGetValue(type, out nodes) &&
(nodes as Dictionary<int, T>).TryGetValue(ID, out internalNode))
if (casted != null &&
casted.TryGetValue(ID, out internalNode))
return (T)internalNode;

throw new Exception("Node Not Found");
@@ -103,5 +136,6 @@ namespace Svelto.ECS
readonly Dictionary<Type, ITypeSafeList> _nodesDB;
readonly Dictionary<Type, ITypeSafeDictionary> _nodesDBdic;
readonly Dictionary<Type, ITypeSafeList> _metaNodesDB;
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupNodesDB;
}
}

+ 270
- 189
ECS/EnginesRoot.cs View File

@@ -1,12 +1,13 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Svelto.DataStructures;
using Svelto.ECS.Internal;
using Svelto.ECS.Legacy;
using Svelto.ECS.NodeSchedulers;
using System.Reflection;
using Svelto.ECS.Profiler;
using Svelto.Utilities;
using UnityEngine.UI;
using UnityEngine.XR.WSA.Persistence;

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
using Svelto.ECS.Profiler;
@@ -16,9 +17,9 @@ namespace Svelto.ECS.Internal
{
struct BuildNodeCallbackStruct
{
public Action<ITypeSafeList> _internalRemove;
public Action<ITypeSafeList> _internalEnable;
public Action<ITypeSafeList> _internalDisable;
public Action<FasterList<INodeBuilder>, int> internalRemove;
public Action<FasterList<INodeBuilder>, int> internalEnable;
public Action<FasterList<INodeBuilder>, int> internalDisable;
}
}

@@ -32,22 +33,37 @@ namespace Svelto.ECS
_activableEngines = new Dictionary<Type, FasterList<IEngine>>();
_otherEngines = new FasterList<IEngine>();

//_engineRootWeakReference = new DataStructures.WeakReference<EnginesRoot>(this);
_engineRootWeakReference = new DataStructures.WeakReference<EnginesRoot>(this);

_nodesDB = new Dictionary<Type, ITypeSafeList>();
_metaNodesDB = new Dictionary<Type, ITypeSafeList>();
_groupNodesDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>();
_nodesDBdic = new Dictionary<Type, ITypeSafeDictionary>();
_sharedStructNodeLists = new SharedStructNodeLists();
_sharedGroupedStructNodeLists = new SharedGroupedStructNodesLists();

_nodesToAdd = new DoubleBufferedNodes<Dictionary<Type, ITypeSafeList>>();
_metaNodesToAdd = new DoubleBufferedNodes<Dictionary<Type, ITypeSafeList>>();
_groupedNodesToAdd = new DoubleBufferedNodes<Dictionary<int, Dictionary<Type, ITypeSafeList>>>();
_callBackStructForBuiltGroupedNodes = new BuildNodeCallbackStruct();

_nodesToAdd = new Dictionary<Type, ITypeSafeList>();
_metaNodesToAdd = new Dictionary<Type, ITypeSafeList>();
_groupedNodesToAdd = new Dictionary<Type, Dictionary<int, ITypeSafeList>>();
_callBackStructForBuiltGroupedNodes.internalRemove = InternalRemove;
_callBackStructForBuiltGroupedNodes.internalDisable = InternalDisable;
_callBackStructForBuiltGroupedNodes.internalEnable = InternalEnable;
_callBackStruct = new BuildNodeCallbackStruct();
_callBackStructForBuiltNodes = new BuildNodeCallbackStruct();

/* _callBackStruct._internalRemove = InternalRemove;
_callBackStruct._internalDisable = InternalDisable;
_callBackStruct._internalEnable = InternalEnable;
_callBackStruct._internalMetaRemove = InternalMetaRemove;*/
_callBackStructForBuiltNodes.internalRemove = InternalGroupedRemove;
_callBackStructForBuiltNodes.internalDisable = InternalDisable;
_callBackStructForBuiltNodes.internalEnable = InternalEnable;
_callBackStructForBuiltMetaNodes = new BuildNodeCallbackStruct();

_callBackStructForBuiltMetaNodes.internalRemove = InternalMetaRemove;
_callBackStructForBuiltMetaNodes.internalDisable = InternalDisable;
_callBackStructForBuiltMetaNodes.internalEnable = InternalEnable;

_scheduler = nodeScheduler;
_scheduler.Schedule(SubmitNodes);
@@ -58,15 +74,15 @@ namespace Svelto.ECS
_implementedInterfaceTypes = new Dictionary<Type, Type[]>();

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
GameObject debugEngineObject = new GameObject("Engine Debugger");
#if UNITY_EDITOR
UnityEngine.GameObject debugEngineObject = new UnityEngine.GameObject("Engine Debugger");
debugEngineObject.gameObject.AddComponent<EngineProfilerBehaviour>();
#endif
}

public void BuildEntity(int ID, EntityDescriptor ed)
{
ed.BuildNodes(ID, _nodesToAdd, ref _callBackStruct);
ed.BuildNodes(ID, _nodesToAdd.other, ref _callBackStructForBuiltNodes);
}

/// <summary>
@@ -95,7 +111,7 @@ namespace Svelto.ECS
/// <param name="ed"></param>
public void BuildMetaEntity(int metaEntityID, EntityDescriptor ed)
{
ed.BuildNodes(metaEntityID, _metaNodesToAdd, ref _callBackStruct);
ed.BuildNodes(metaEntityID, _metaNodesToAdd.other, ref _callBackStructForBuiltMetaNodes);
}

/// <summary>
@@ -110,18 +126,18 @@ namespace Svelto.ECS
public void BuildEntityInGroup(int entityID, int groupID,
EntityDescriptor ed)
{
ed.BuildGroupedNodes(entityID, groupID, _groupedNodesToAdd, ref _callBackStruct);
ed.BuildGroupedNodes(entityID, groupID, _groupedNodesToAdd.other, ref _callBackStructForBuiltGroupedNodes);
}

public void AddEngine(IEngine engine)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
#if UNITY_EDITOR
EngineProfiler.AddEngine(engine);
#endif
var queryableNodeEngine = engine as IQueryableNodeEngine;
if (queryableNodeEngine != null)
queryableNodeEngine.nodesDB =
new EngineNodeDB(_nodesDB, _nodesDBdic, _metaNodesDB);
new EngineNodeDB(_nodesDB, _nodesDBdic, _metaNodesDB, _groupNodesDB);

var engineType = engine.GetType();
var implementedInterfaces = engineType.GetInterfaces();
@@ -171,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))
@@ -235,36 +263,75 @@ namespace Svelto.ECS
}
}

static void AddNodesToTheDBAndSuitableEngines(Dictionary<Type, ITypeSafeList> nodesToAdd,
static void AddNodesToTheDBAndSuitableEngines(Dictionary<Type, ITypeSafeList> nodesToAdd,
Dictionary<Type, FasterList<IEngine>> nodeEngines,
Dictionary<Type, ITypeSafeDictionary> nodesDBdic,
Dictionary<Type, ITypeSafeList> nodesDB)
{
foreach (var nodeList in nodesToAdd)
{
ITypeSafeList dbList;
AddNodeToDB(nodesDB, nodeList);

if (nodesDB.TryGetValue(nodeList.Key, out dbList) == false)
dbList = nodesDB[nodeList.Key] = nodeList.Value.Create();
if (nodeList.Value.isQueryiableNode)
{
AddNodeToNodesDictionary(nodesDBdic, nodeList.Value, nodeList.Key);
foreach (var node in nodeList.Value)
AddNodeToTheSuitableEngines(nodeEngines, node as NodeWithID, nodeList.Key);
}
}
}

dbList.AddRange(nodeList.Value);
static void AddGroupNodesToTheDBAndSuitableEngines(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupedNodesToAdd,
Dictionary<Type, FasterList<IEngine>> nodeEngines,
Dictionary<Type, ITypeSafeDictionary> nodesDBdic,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupNodesDB,
Dictionary<Type, ITypeSafeList> nodesDB)
{
foreach (var group in groupedNodesToAdd)
{
AddNodesToTheDBAndSuitableEngines(group.Value, nodeEngines, nodesDBdic, nodesDB);

AddNodeToNodesDictionary(nodesDBdic, nodeList.Value, nodeList.Key);
AddNodesToTheSuitableEngines(nodeEngines, nodeList.Value, nodeList.Key);
AddNodesToGroupDB(groupNodesDB, @group);
}
}

static void AddNodesToGroupDB(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupNodesDB,
KeyValuePair<int, Dictionary<Type, ITypeSafeList>> @group)
{
Dictionary<Type, ITypeSafeList> groupedNodesByType;

if (groupNodesDB.TryGetValue(@group.Key, out groupedNodesByType) == false)
groupedNodesByType = groupNodesDB[@group.Key] = new Dictionary<Type, ITypeSafeList>();

foreach (var node in @group.Value)
{
groupedNodesByType.Add(node.Key, node.Value);
}
}

static void AddNodeToDB(Dictionary<Type, ITypeSafeList> nodesDB, KeyValuePair<Type, ITypeSafeList> nodeList)
{
ITypeSafeList dbList;

if (nodesDB.TryGetValue(nodeList.Key, out dbList) == false)
dbList = nodesDB[nodeList.Key] = nodeList.Value.Create();

dbList.AddRange(nodeList.Value);
}
static void AddNodeToNodesDictionary(Dictionary<Type, ITypeSafeDictionary> nodesDBdic, ITypeSafeList nodes, Type nodeType)
static void AddNodeToNodesDictionary(Dictionary<Type, ITypeSafeDictionary> nodesDBdic,
ITypeSafeList nodes, Type nodeType)
{
ITypeSafeDictionary nodesDic;

if (nodesDBdic.TryGetValue(nodeType, out nodesDic) == false)
nodesDic = nodesDBdic[nodeType] = nodes.CreateIndexedDictionary();

nodes.AddToIndexedDictionary(nodesDic);
nodesDic.FillWithIndexedNodes(nodes);
}

static void AddNodesToTheSuitableEngines(Dictionary<Type, FasterList<IEngine>> nodeEngines, ITypeSafeList nodes, Type nodeType)
static void AddNodeToTheSuitableEngines(Dictionary<Type, FasterList<IEngine>> nodeEngines, NodeWithID node, Type nodeType)
{
FasterList<IEngine> enginesForNode;

@@ -273,191 +340,170 @@ namespace Svelto.ECS
for (int j = 0; j < enginesForNode.Count; j++)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
EngineProfiler.MonitorAddDuration(AddNodeToEngine, enginesForNode[j] as INodeEngine, node);
EngineProfiler.MonitorRemoveDuration(RemoveNodeFromEngine, (enginesForNode[j] as INodeEngine), node);
#else
(enginesForNode[j] as INodeEngine).Add(nodes);
(enginesForNode[j] as INodeEngine).Add(node);
#endif
}
}
}
/*
void RemoveNodeFromTheDB<T>(T node, Type nodeType) where T : INode
{
FasterList<INode> nodes;
if (_nodesDB.TryGetValue(nodeType, out nodes) == true)
nodes.UnorderedRemove(node); //should I remove it from the dictionary if length is zero?
}
/*
void DisableNodeFromEngines(INode node, Type nodeType)
{
ITypeSafeList enginesForNode;

void RemoveNodeFromMetaDB<T>(T node, Type nodeType) where T : INode
if (_activableEngines.TryGetValue(nodeType, out enginesForNode))
{
for (int j = 0; j < enginesForNode.Count; j++)
{
FasterList<INode> nodes;
if (_metaNodesDB.TryGetValue(nodeType, out nodes) == true)
nodes.UnorderedRemove(node); //should I remove it from the dictionary if length is zero?
(enginesForNode[j] as IActivableNodeEngine).Disable(node);
}
}
}

void RemoveNodeFromNodesDictionary<T>(T node, Type nodeType) where T : INodeWithID
{
Dictionary<int, INode> nodesDic;

if (_nodesDBdic.TryGetValue(nodeType, out nodesDic))
nodesDic.Remove(node.ID);
}
void EnableNodeFromEngines(INode node, Type nodeType)
{
ITypeSafeList enginesForNode;

void RemoveNodeFromEngines<T>(T node, Type nodeType) where T : INode
if (_activableEngines.TryGetValue(nodeType, out enginesForNode))
{
for (int j = 0; j < enginesForNode.Count; j++)
{
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] as INodeEngine), node);
#else
(enginesForNode[j] as INodeEngine).Remove(node);
#endif
}
}
(enginesForNode[j] as IActivableNodeEngine).Enable(node);
}
}
}*/
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
void AddNodeToEngine(IEngine engine, INode node)
{
(engine as INodeEngine).Add(node);
}

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 RemoveNodeFromEngine(IEngine engine, INode node)
{
(engine as INodeEngine).Remove(node);
}
#endif

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(IEngine engine, INode node)
{
(engine as INodeEngine).Add(node);
}
void InternalDisable(FasterList<INodeBuilder> nodeBuilders, int entityID)
{
/* if (_engineRootWeakReference.IsValid == false)
return;

void RemoveNodeFromEngine(IEngine engine, INode node)
{
(engine as INodeEngine).Remove(node);
}
#endif
/*
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);
}
}
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 InternalEnable(FasterList<INodeBuilder> nodeBuilders, int entityID)
{/*
if (_engineRootWeakReference.IsValid == false)
return;

void InternalRemove(IFasterList 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);
}*/
}

for (int i = 0; i < nodes.Count; i++)
{
var node = nodes[i];
Type nodeType = node.GetType();
void InternalRemove(FasterList<INodeBuilder> nodeBuilders, int entityID)
{
if (_engineRootWeakReference.IsValid == false)
return;

RemoveNodeFromEngines(node, nodeType);
RemoveNodeFromTheDB(node, node.GetType());
int nodeBuildersCount = nodeBuilders.Count;
for (int i = 0; i < nodeBuildersCount; i++)
{
Type nodeType = nodeBuilders[i].GetType();

var nodeWithId = node as INodeWithID;
if (nodeWithId != null)
RemoveNodeFromNodesDictionary(nodeWithId, nodeType);
}
}
ITypeSafeList nodes;
if (_nodesDB.TryGetValue(nodeType, out nodes) == true)
nodes.UnorderedRemove(entityID);

void InternalMetaRemove(FasterList<INode> nodes)
if (nodes.isQueryiableNode)
{
for (int i = 0; i < nodes.Count; i++)
{
var node = nodes[i];
Type nodeType = node.GetType();

RemoveNodeFromEngines(node, nodeType);
RemoveNodeFromMetaDB(node, nodeType);

var nodeWithId = node as INodeWithID;
if (nodeWithId != null)
RemoveNodeFromNodesDictionary(nodeWithId, nodeType);
}
var node = _nodesDBdic[nodeType].GetIndexedNode(entityID);
_nodesDBdic[nodeType].Remove(entityID);

RemoveNodeFromEngines(_nodeEngines, node, nodeType);
}
}
}
void InternalGroupedRemove(FasterList<INodeBuilder> nodeBuilders, int entityID)
{
}

readonly DataStructures.WeakReference<EnginesRoot> _engineRootWeakReference;
void InternalMetaRemove(FasterList<INodeBuilder> nodeBuilders, int entityID)
{
}
static void RemoveNodeFromEngines(Dictionary<Type, FasterList<IEngine>> nodeEngines, NodeWithID node, Type nodeType)
{
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] as INodeEngine), node);
#else
(enginesForNode[j] as INodeEngine).Remove(node);
#endif
}
}
}

void SubmitNodes()
{
int metaNodesCount = _metaNodesToAdd.Count;
int nodesCount = _nodesToAdd.Count;

if (metaNodesCount + nodesCount == 0) return;
_nodesToAdd.Swap();
_metaNodesToAdd.Swap();
_groupedNodesToAdd.Swap();
bool newNodesHaveBeenAddedWhileIterating =
_metaNodesToAdd.Count > 0
|| _nodesToAdd.Count > 0
|| _groupedNodesToAdd.Count > 0;

bool newNodesHaveBeenAddedWhileIterating;
int startNodes = 0;
int startMetaNodes = 0;
int numberOfReenteringLoops = 0;

do
while (newNodesHaveBeenAddedWhileIterating)
{
AddNodesToTheDBAndSuitableEngines(_nodesToAdd, _nodeEngines, _nodesDBdic, _nodesDB);
AddNodesToTheDBAndSuitableEngines(_metaNodesToAdd, _nodeEngines, _nodesDBdic, _metaNodesDB);

if ( _nodesToAdd.Count > 0)
AddNodesToTheDBAndSuitableEngines(_nodesToAdd.current, _nodeEngines, _nodesDBdic, _nodesDB);
if ( _metaNodesToAdd.Count > 0)
AddNodesToTheDBAndSuitableEngines(_metaNodesToAdd.current, _nodeEngines, _nodesDBdic, _metaNodesDB);
if (_groupedNodesToAdd.Count > 0)
AddGroupNodesToTheDBAndSuitableEngines(_groupedNodesToAdd.current, _nodeEngines, _nodesDBdic, _groupNodesDB, _nodesDB);
_nodesToAdd.Clear();
_metaNodesToAdd.Clear();
_groupedNodesToAdd.Clear();

_nodesToAdd.Swap();
_metaNodesToAdd.Swap();
_groupedNodesToAdd.Swap();
newNodesHaveBeenAddedWhileIterating =
_metaNodesToAdd.Count > metaNodesCount ||
_nodesToAdd.Count > nodesCount;

startNodes = nodesCount;
startMetaNodes = metaNodesCount;
_metaNodesToAdd.Count > 0
|| _nodesToAdd.Count > 0
|| _groupedNodesToAdd.Count > 0;

if (numberOfReenteringLoops > 5)
throw new Exception("possible infinite loop found creating Entities inside INodesEngine Add method, please consider building entities outside INodesEngine Add method");

numberOfReenteringLoops++;

metaNodesCount = _metaNodesToAdd.Count;
nodesCount = _nodesToAdd.Count;

} while (newNodesHaveBeenAddedWhileIterating);

_nodesToAdd.Clear();
_metaNodesToAdd.Clear();
}
}

readonly Dictionary<Type, FasterList<IEngine>> _nodeEngines;
@@ -467,25 +513,60 @@ namespace Svelto.ECS

readonly Dictionary<Type, ITypeSafeList> _nodesDB;
readonly Dictionary<Type, ITypeSafeList> _metaNodesDB;
readonly Dictionary<Type, Dictionary<int, ITypeSafeList>> _groupNodesDB;
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupNodesDB;
readonly Dictionary<Type, ITypeSafeDictionary> _nodesDBdic;

/// <summary>
/// Need to think about how to make BuildEntity thread safe as well
/// </summary>
readonly Dictionary<Type, ITypeSafeList> _nodesToAdd;
readonly Dictionary<Type, ITypeSafeList> _metaNodesToAdd;
readonly Dictionary<Type, Dictionary<int, ITypeSafeList>> _groupedNodesToAdd;
readonly DoubleBufferedNodes<Dictionary<Type, ITypeSafeList>> _nodesToAdd;
readonly DoubleBufferedNodes<Dictionary<Type, ITypeSafeList>> _metaNodesToAdd;
readonly DoubleBufferedNodes<Dictionary<int, Dictionary<Type, ITypeSafeList>>> _groupedNodesToAdd;
readonly NodeSubmissionScheduler _scheduler;

readonly Type _structNodeEngineType;
readonly Type _groupedStructNodesEngineType;
readonly Type _activableNodeEngineType;
readonly SharedStructNodeLists _sharedStructNodeLists;
readonly SharedGroupedStructNodesLists _sharedGroupedStructNodeLists;

readonly Dictionary<Type, Type[]> _implementedInterfaceTypes;
readonly Dictionary<Type, Type[]> _implementedInterfaceTypes;
readonly DataStructures.WeakReference<EnginesRoot> _engineRootWeakReference;
BuildNodeCallbackStruct _callBackStruct;
BuildNodeCallbackStruct _callBackStructForBuiltNodes;
BuildNodeCallbackStruct _callBackStructForBuiltGroupedNodes;
BuildNodeCallbackStruct _callBackStructForBuiltMetaNodes;

class DoubleBufferedNodes<T> where T : class, IDictionary, new()
{
readonly T _nodesToAddBufferA = new T();
readonly T _nodesToAddBufferB = new T();

public DoubleBufferedNodes()
{
this.other = _nodesToAddBufferA;
this.current = _nodesToAddBufferB;
}

public T other { get; private set; }
public T current { get; private set; }

public int Count
{
get { return current.Count; }
}
public void Clear()
{
current.Clear();
}

public void Swap()
{
var toSwap = other;
other = current;
current = toSwap;
}
}
}
}

+ 78
- 84
ECS/EntityDescriptor.cs View File

@@ -8,24 +8,6 @@ namespace Svelto.ECS
{
public class EntityDescriptor
{
protected EntityDescriptor()
{}

/// <summary>
/// if you want to avoid allocation in run-time, you can prebuild
/// EntityDescriptors and use them to build entities at different
/// times
/// </summary>
protected EntityDescriptor(INodeBuilder[] nodesToBuild)
{
_nodesToBuild = new FasterList<INodeBuilder>(nodesToBuild);
}
protected EntityDescriptor(INodeBuilder[] nodesToBuild,
params object[] componentsImplementor):this(nodesToBuild)
{
ProcessImplementors(componentsImplementor);
}

public void AddImplementors(params object[] componentsImplementor)
{
ProcessImplementors(componentsImplementor);
@@ -38,7 +20,7 @@ namespace Svelto.ECS

internal void BuildGroupedNodes
(int entityID, int groupID,
Dictionary<Type, Dictionary<int, ITypeSafeList>> groupNodes,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupNodesByType,
ref BuildNodeCallbackStruct callBackstruct)
{
for (int index = 0; index < _nodesToBuild.Count; index++)
@@ -46,62 +28,68 @@ namespace Svelto.ECS
var nodeBuilder = _nodesToBuild[index];
var nodeType = nodeBuilder.GetNodeType();
Dictionary<int, ITypeSafeList> groupedNodesTyped;
Dictionary<Type, ITypeSafeList> groupedNodesTyped;
if (groupNodes.TryGetValue(nodeType, out groupedNodesTyped) == false)
if (groupNodesByType.TryGetValue(groupID, out groupedNodesTyped) == false)
{
groupedNodesTyped = new Dictionary<int, ITypeSafeList>();
groupedNodesTyped = new Dictionary<Type, ITypeSafeList>();
groupNodes.Add(nodeType, groupedNodesTyped);
groupNodesByType.Add(groupID, groupedNodesTyped);
};
ITypeSafeList nodes;

var mustAdd = groupedNodesTyped.TryGetValue(groupID, out nodes) == false;

var node = nodeBuilder.BuildAndAddToList(ref nodes, entityID);

if (mustAdd)
groupedNodesTyped[groupID] = nodes;

if (node != null && nodeBuilder.reflects != FillNodeMode.None)
{
node = FillNode(node, nodeBuilder.reflects);
SetupImplementors(ref callBackstruct, nodes);
}

/* var groupNode = node as IGroupedNode;
if (groupNode != null)
groupNode.groupID = groupID;*/
BuildAndFillNode(entityID, groupedNodesTyped, nodeType, nodeBuilder);
}
SetupImplementors(ref callBackstruct, entityID);
}

internal void BuildNodes(int entityID,
Dictionary<Type, ITypeSafeList> nodesToAdd,
Dictionary<Type, ITypeSafeList> nodesByType,
ref BuildNodeCallbackStruct callBackstruct)
{
for (int index = 0; index < _nodesToBuild.Count; index++)
int count = _nodesToBuild.Count;
for (int index = 0; index < count; index++)
{
var nodeBuilder = _nodesToBuild[index];
var nodeType = nodeBuilder.GetNodeType();
BuildAndFillNode(entityID, nodesByType, nodeType, nodeBuilder);
}
SetupImplementors(ref callBackstruct, entityID);
}
void BuildAndFillNode(int entityID, Dictionary<Type, ITypeSafeList> groupedNodesTyped, Type nodeType, INodeBuilder nodeBuilder)
{
ITypeSafeList nodes;

ITypeSafeList nodes;

var mustAdd = nodesToAdd.TryGetValue(nodeType, out nodes) == false;
var node = nodeBuilder.BuildAndAddToList(ref nodes, entityID);
var nodesPoolWillBeCreated = groupedNodesTyped.TryGetValue(nodeType, out nodes) == false;
var nodeObjectToFill = nodeBuilder.BuildNodeAndAddToList(ref nodes, entityID);

if (mustAdd)
nodesToAdd[nodeType] = nodes;
if (nodesPoolWillBeCreated)
groupedNodesTyped.Add(nodeType, nodes);

if (node != null && nodeBuilder.reflects != FillNodeMode.None)
{
FillNode(node, nodeBuilder.reflects);
SetupImplementors(ref callBackstruct, nodes);
}
}
//the semantic of this code must still be improved
//but only classes can be filled, so I am aware
//it's a NodeWithID
if (nodeObjectToFill != null)
FillNode(nodeObjectToFill as NodeWithID);
}
/// <summary>
/// if you want to avoid allocation in run-time, you can prebuild
/// EntityDescriptors and use them to build entities at different
/// times
/// </summary>
protected EntityDescriptor(INodeBuilder[] nodesToBuild)
{
_nodesToBuild = new FasterList<INodeBuilder>(nodesToBuild);
}
protected EntityDescriptor(INodeBuilder[] nodesToBuild,
params object[] componentsImplementor):this(nodesToBuild)
{
ProcessImplementors(componentsImplementor);
}
void ProcessImplementors(object[] implementors)
@@ -144,30 +132,41 @@ namespace Svelto.ECS

void SetupImplementors(
ref BuildNodeCallbackStruct callBackstruct,
ITypeSafeList nodes)
int entityID)
{
var RemoveEntity = callBackstruct._internalRemove;
var DisableEntity = callBackstruct._internalDisable;
var EnableEntity = callBackstruct._internalEnable;
var RemoveEntity = callBackstruct.internalRemove;
var DisableEntity = callBackstruct.internalDisable;
var EnableEntity = callBackstruct.internalEnable;
Action removeEntityAction = () => { RemoveEntity(nodes); nodes.Clear(); };
Action disableEntityAction = () => DisableEntity(nodes);
Action enableEntityAction = () => EnableEntity(nodes);

int removingImplementorsCount = _removingImplementors.Count;
for (int index = 0; index < removingImplementorsCount; index++)
_removingImplementors[index].Target.removeEntity = removeEntityAction;
if (removingImplementorsCount > 0)
{
Action removeEntityAction = () => RemoveEntity(_nodesToBuild, entityID);
for (int index = 0; index < removingImplementorsCount; index++)
_removingImplementors[index].Target.removeEntity = removeEntityAction;
}

int disablingImplementorsCount = _disablingImplementors.Count;
for (int index = 0; index < disablingImplementorsCount; index++)
_disablingImplementors[index].Target.disableEntity = disableEntityAction;
if (disablingImplementorsCount > 0)
{
Action disableEntityAction = () => DisableEntity(_nodesToBuild, entityID);
for (int index = 0; index < disablingImplementorsCount; index++)
_disablingImplementors[index].Target.disableEntity = disableEntityAction;
}

int enablingImplementorsCount = _enablingImplementors.Count;
for (int index = 0; index < enablingImplementorsCount; index++)
_enablingImplementors[index].Target.enableEntity = enableEntityAction;
if (enablingImplementorsCount > 0)
{
Action enableEntityAction = () => EnableEntity(_nodesToBuild, entityID);
for (int index = 0; index < enablingImplementorsCount; index++)
_enablingImplementors[index].Target.enableEntity = enableEntityAction;
}
}

TNode FillNode<TNode>(TNode node, FillNodeMode mode) where TNode : INode
void FillNode<TNode>(TNode node) where TNode : NodeWithID
{
var fields = node.GetType().GetFields(BindingFlags.Public |
BindingFlags.Instance);
@@ -180,15 +179,12 @@ namespace Svelto.ECS
if (_implementorsByType.TryGetValue(fieldType, out component) == false)
{
if (mode == FillNodeMode.Strict)
{
Exception e =
new Exception(NOT_FOUND_EXCEPTION +
field.FieldType.Name + " - Node: " + node.GetType().Name +
" - EntityDescriptor " + this);

throw e;
}
}
else
field.SetValue(node, component.Target);
@@ -205,10 +201,8 @@ namespace Svelto.ECS
#endif

}

return node;
}
readonly FasterList<DataStructures.WeakReference<IDisableEntityComponent>> _disablingImplementors = new FasterList<DataStructures.WeakReference<IDisableEntityComponent>>();
readonly FasterList<DataStructures.WeakReference<IRemoveEntityComponent>> _removingImplementors = new FasterList<DataStructures.WeakReference<IRemoveEntityComponent>>();
readonly FasterList<DataStructures.WeakReference<IEnableEntityComponent>> _enablingImplementors = new FasterList<DataStructures.WeakReference<IEnableEntityComponent>>();
@@ -217,8 +211,8 @@ namespace Svelto.ECS
#if DEBUG && !PROFILER
readonly Dictionary<Type, int> _implementorCounterByType = new Dictionary<Type, int>();
#endif
readonly FasterList<INodeBuilder> _nodesToBuild;
readonly FasterList<INodeBuilder> _nodesToBuild;
const string DUPLICATE_IMPLEMENTOR_ERROR = "the same component is implemented with more than one implementor. This is considered an error and MUST be fixed. ";
const string NULL_IMPLEMENTOR_ERROR = "Null implementor, are you using a wild GetComponents<Monobehaviour> to fetch it? ";
const string NOT_FOUND_EXCEPTION = "Svelto.ECS: Implementor not found for a Node. Implementor Type: ";


+ 13
- 7
ECS/IEngine.cs View File

@@ -1,4 +1,4 @@
using Svelto.DataStructures;
using Rewired.Utils;
using Svelto.ECS.Internal;

namespace Svelto.ECS.Internal
@@ -15,16 +15,19 @@ namespace Svelto.ECS.Internal

public interface IActivableNodeEngine : IEngine
{
void Enable(ITypeSafeList nodes);
void Disable(ITypeSafeList nodes);
void Enable(NodeWithID node);
void Disable(NodeWithID node);
}

public interface INodeEngine : IEngine
{
void Add(ITypeSafeList nodes);
void Remove(ITypeSafeList nodes);
void Add(NodeWithID node);
void Remove(NodeWithID node);
}
}

namespace Svelto.ECS.Legacy
{
public interface INodesEngine : INodeEngine
{
System.Type[] AcceptedNodes();
@@ -57,7 +60,10 @@ namespace Svelto.ECS
/// usually the ID is the owner of the nodes of that
/// group
/// </summary>
public interface IGroupedStructNodesEngine<T> : IGroupedStructNodesEngine where T:struct, IGroupedNode
{ }
public interface IGroupedStructNodesEngine<T> : IGroupedStructNodesEngine where T : struct, IGroupedNode
{
void Add(ref T node);
void Remove(ref T node);
}
}


+ 11
- 7
ECS/IEngineNodeDB.cs View File

@@ -4,15 +4,19 @@ namespace Svelto.ECS
{
public interface IEngineNodeDB
{
ReadOnlyDictionary<int, T> QueryIndexableNodes<T>();
bool TryQueryNode<T>(int ID, out T node);
T QueryNode<T>(int ID);
FasterReadOnlyList<T> QueryNodes<T>();

bool TryQueryMetaNode<T>(int metaEntityID, out T node);
T QueryMetaNode<T>(int metaEntityID);
FasterReadOnlyList<T> QueryMetaNodes<T>();
FasterReadOnlyList<T> QueryGroupedNodes<T>(int group);
T[] QueryNodesAsArray<T>(out int count) where T:struct;
ReadOnlyDictionary<int, T> QueryIndexableNodes<T>() where T:NodeWithID;
bool TryQueryNode<T>(int ID, out T node) where T:NodeWithID;
T QueryNode<T>(int ID) where T:NodeWithID;

bool TryQueryMetaNode<T>(int metaEntityID, out T node) where T:NodeWithID;
T QueryMetaNode<T>(int metaEntityID) where T:NodeWithID;
}
}


+ 7
- 5
ECS/INode.cs View File

@@ -1,17 +1,19 @@
namespace Svelto.ECS
{
public interface INode
{}

public interface IStructNodeWithID : INode
{
int ID { get; set; }
int ID { get; }
}
public interface IGroupedNode
{
int groupID { get; set; }
}
public interface IStructNodeWithID : INode
{
new int ID { get; set; }
}

public class NodeWithID: INode
{


+ 41
- 60
ECS/MultiNodesEngine.cs View File

@@ -3,102 +3,83 @@ using Svelto.ECS.Internal;

namespace Svelto.ECS.Internal
{
public abstract class MultiNodesEngine<T> where T:class
public abstract class MultiNodesEngine<T>:INodeEngine where T:NodeWithID
{
protected abstract void AddNode(T node);
protected abstract void RemoveNode(T node);
protected abstract void Add(T node);
protected abstract void Remove(T node);
public virtual void Add(NodeWithID node)
{
Add((T) node);
}

public virtual void Remove(NodeWithID node)
{
Remove((T) node);
}
}
}

namespace Svelto.ECS
{
public abstract class MultiNodesEngine : INodesEngine
{
public abstract System.Type[] AcceptedNodes();

public abstract void Add(ITypeSafeList nodeWrapper);
public abstract void Remove(ITypeSafeList nodeWrapper);
}

public abstract class MultiNodesEngine<T, U> : MultiNodesEngine<T>,
INodeEngine where T:class where U:class
public abstract class MultiNodesEngine<T, U> : MultiNodesEngine<T>
where T:NodeWithID where U:NodeWithID
{
protected abstract void AddNode(U node);
protected abstract void RemoveNode(U node);
protected abstract void Add(U node);
protected abstract void Remove(U node);

public virtual void Add(ITypeSafeList nodes)
public override void Add(NodeWithID node)
{
if (nodes is FasterList<U>)
var castedNode = node as U;
if (castedNode != null)
{
var strongTypeNodes = (FasterList<U>)nodes;

for (int i = 0; i < strongTypeNodes.Count; i++)
{
AddNode(strongTypeNodes[i]);
}
Add(castedNode);
}
else
if (nodes is FasterList<T>)
{
var strongTypeNodes = (FasterList<T>)nodes;

for (int i = 0; i < strongTypeNodes.Count; i++)
{
AddNode(strongTypeNodes[i]);
}
base.Add(node);
}
}

public virtual void Remove(ITypeSafeList nodeWrapper)
public override void Remove(NodeWithID node)
{
/* if (nodeWrapper is NodeWrapper<T>)
if (node is U)
{
T node;
nodeWrapper.GetNode<T>(out node);

RemoveNode(ref node);
Remove((U) node);
}
else
{
U node;
nodeWrapper.GetNode<U>(out node);

RemoveNode(ref node);
}*/
base.Remove(node);
}
}
}

public abstract class MultiNodesEngine<T, U, V> : MultiNodesEngine<T, U> where T: class where U : class
public abstract class MultiNodesEngine<T, U, V> : MultiNodesEngine<T, U>
where T: NodeWithID where U : NodeWithID where V:NodeWithID
{
protected abstract void AddNode(V node);
protected abstract void RemoveNode(V node);
protected abstract void Add(V node);
protected abstract void Remove(V node);

public override void Add(ITypeSafeList nodes)
public override void Add(NodeWithID node)
{
if (nodes is FasterList<V>)
var castedNode = node as V;
if (castedNode != null)
{
var strongTypeNodes = (FasterList<V>)nodes;

for (int i = 0; i < strongTypeNodes.Count; i++)
{
AddNode(strongTypeNodes[i]);
}
Add(castedNode);
}
else
base.Add(nodes);
base.Add(node);
}

public override void Remove(ITypeSafeList nodeWrapper)
public override void Remove(NodeWithID node)
{
/* if (nodeWrapper is V)
var castedNode = node as V;
if (castedNode != null)
{
V node;
nodeWrapper.GetNode<V>(out node);

RemoveNode(ref node);
Remove(castedNode);
}
else
base.Remove(nodeWrapper);*/
base.Remove(node);
}
}
}

+ 7
- 26
ECS/NodeBuilder.cs View File

@@ -6,21 +6,19 @@ namespace Svelto.ECS
{
public interface INodeBuilder
{
INode BuildAndAddToList(ref ITypeSafeList list, int entityID);
INode BuildNodeAndAddToList(ref ITypeSafeList list, int entityID);

Type GetNodeType();

FillNodeMode reflects { get; }
}

public class NodeBuilder<NodeType> : INodeBuilder where NodeType : NodeWithID, new()
{
public INode BuildAndAddToList(ref ITypeSafeList list, int entityID)
public INode BuildNodeAndAddToList(ref ITypeSafeList list, int entityID)
{
if (list == null)
list = new TypeSafeFasterList<NodeType>();
list = new TypeSafeFasterListForECSForClasses<NodeType>();

var castedList = list as FasterList<NodeType>;
var castedList = list as TypeSafeFasterListForECSForClasses<NodeType>;

var node = NodeWithID.BuildNode<NodeType>(entityID);

@@ -29,11 +27,6 @@ namespace Svelto.ECS
return node;
}

public FillNodeMode reflects
{
get { return FillNodeMode.Strict; }
}

public Type GetNodeType()
{
return typeof(NodeType);
@@ -42,15 +35,15 @@ namespace Svelto.ECS

public class StructNodeBuilder<NodeType> : INodeBuilder where NodeType : struct, IStructNodeWithID
{
public INode BuildAndAddToList(ref ITypeSafeList list, int entityID)
public INode BuildNodeAndAddToList(ref ITypeSafeList list, int entityID)
{
var node = default(NodeType);
node.ID = entityID;
if (list == null)
list = new TypeSafeFasterList<NodeType>();
list = new TypeSafeFasterListForECSForStructs<NodeType>();

var castedList = list as FasterList<NodeType>;
var castedList = list as TypeSafeFasterListForECSForStructs<NodeType>;

castedList.Add(node);

@@ -61,17 +54,5 @@ namespace Svelto.ECS
{
return typeof(NodeType);
}

public virtual FillNodeMode reflects
{
get { return FillNodeMode.None; }
}
}
public enum FillNodeMode
{
Strict,
None
}
}

+ 2
- 2
ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs View File

@@ -1,6 +1,6 @@
#if asdUNITY_EDITOR
#if UNITY_EDITOR

using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;



+ 3
- 7
ECS/Profiler/EngineProfiler.cs View File

@@ -1,4 +1,3 @@
#if asdDEBUG
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -13,10 +12,9 @@ namespace Svelto.ECS.Profiler
{
static readonly Stopwatch _stopwatch = new Stopwatch();

public static void MonitorAddDuration(Action<INodeEngine, INodeWrapper> addingFunc, INodeEngine engine, INodeWrapper node)
public static void MonitorAddDuration(Action<INodeEngine, INode> addingFunc, INodeEngine engine, INode node)
{
EngineInfo info;
if (engineInfos.TryGetValue(engine.GetType(), out info))
{
_stopwatch.Start();
@@ -27,15 +25,14 @@ namespace Svelto.ECS.Profiler
}
}

public static void MonitorRemoveDuration(Action<INodeEngine, INodeWrapper> removeFunc, INodeEngine engine, INodeWrapper node)
public static void MonitorRemoveDuration(Action<INodeEngine, INode> removeFunc, INodeEngine engine, NodeWithID node)
{
EngineInfo info;
if (engineInfos.TryGetValue(engine.GetType(), out info))
{
_stopwatch.Start();
removeFunc(engine, node);
// engine.Remove(node);
engine.Remove(node);
_stopwatch.Reset();

info.AddRemoveDuration(_stopwatch.Elapsed.TotalMilliseconds);
@@ -61,4 +58,3 @@ namespace Svelto.ECS.Profiler
public static readonly Dictionary<Type, EngineInfo> engineInfos = new Dictionary<Type, EngineInfo>();
}
}
#endif

+ 1
- 1
ECS/Profiler/EngineProfilerBehaviour.cs View File

@@ -1,4 +1,4 @@
#if asdUNITY_EDITOR
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using UnityEngine;


+ 5
- 16
ECS/SingleNodeEngine.cs View File

@@ -1,28 +1,17 @@
using Svelto.DataStructures;
using Svelto.ECS.Internal;

namespace Svelto.ECS
{
public abstract class SingleNodeEngine<T> : INodeEngine where T:class
public abstract class SingleNodeEngine<T> : INodeEngine where T:NodeWithID
{
public void Add(ITypeSafeList nodes)
public void Add(NodeWithID node)
{
var strongTypeNodes = (FasterList<T>)nodes;

for (int i = 0; i < strongTypeNodes.Count; i++)
{
Add(strongTypeNodes[i]); //when byref returns will be vailable, this should be passed by reference, not copy!
}
Add((T)node); //when byref returns will be vailable, this should be passed by reference, not copy!
}

public void Remove(ITypeSafeList nodes)
public void Remove(NodeWithID node)
{
/*
T node;
nodeWrapper.GetNode(out node);
Remove(node);*/
Remove((T)node);
}

protected abstract void Add(T node);


+ 15
- 15
ECS/StructNodes.cs View File

@@ -60,8 +60,8 @@ namespace Svelto.ECS
public T[] GetList(int groupID, out int numberOfItems)
{
var fasterList = (SharedGroupedStructNodesLists.NoVirt.GetList<T>(_container, groupID) as FasterList<T>);
numberOfItems = FasterList<T>.NoVirt.Count(fasterList);
return FasterList<T>.NoVirt.ToArrayFast(fasterList);
return FasterList<T>.NoVirt.ToArrayFast(fasterList, out numberOfItems);
}

readonly SharedGroupedStructNodesLists _container;
@@ -72,20 +72,20 @@ namespace Svelto.ECS
{
internal SharedStructNodeLists()
{
_collection = new Dictionary<Type, ITypeSafeList>();
_collection = new Dictionary<Type, IFasterList>();
}

internal static class NoVirt
{
internal static FasterList<T> GetList<T>(SharedStructNodeLists obj) where T : struct
{
ITypeSafeList list;
IFasterList list;
if (obj._collection.TryGetValue(typeof(T), out list))
{
return list as FasterList<T>;
}

list = new TypeSafeFasterList<T>();
list = new FasterList<T>();

obj._collection.Add(typeof(T), list);

@@ -93,42 +93,42 @@ namespace Svelto.ECS
}
}

readonly Dictionary<Type, ITypeSafeList> _collection;
readonly Dictionary<Type, IFasterList> _collection;
}

public class SharedGroupedStructNodesLists
{
internal SharedGroupedStructNodesLists()
{
_collection = new Dictionary<Type, Dictionary<int, ITypeSafeList>>();
_collection = new Dictionary<Type, Dictionary<int, IFasterList>>();
}

internal static class NoVirt
{
internal static ITypeSafeList GetList<T>(SharedGroupedStructNodesLists list, int groupID) where T : struct
internal static IFasterList GetList<T>(SharedGroupedStructNodesLists list, int groupID) where T : struct
{
Dictionary<int, ITypeSafeList> dic = GetGroup<T>(list);
ITypeSafeList localList;
Dictionary<int, IFasterList> dic = GetGroup<T>(list);
IFasterList localList;

if (dic.TryGetValue(groupID, out localList))
return localList;

localList = new TypeSafeFasterList<T>();
localList = new FasterList<T>();
dic.Add(groupID, localList);

return localList;
}

internal static Dictionary<int, ITypeSafeList> GetGroup<T>(SharedGroupedStructNodesLists list) where T : struct
internal static Dictionary<int, IFasterList> GetGroup<T>(SharedGroupedStructNodesLists list) where T : struct
{
Dictionary<int, ITypeSafeList> dic;
Dictionary<int, IFasterList> dic;

if (list._collection.TryGetValue(typeof(T), out dic))
{
return dic;
}

dic = new Dictionary<int, ITypeSafeList>();
dic = new Dictionary<int, IFasterList>();

list._collection.Add(typeof(T), dic);

@@ -136,6 +136,6 @@ namespace Svelto.ECS
}
}

readonly Dictionary<Type, Dictionary<int, ITypeSafeList>> _collection;
readonly Dictionary<Type, Dictionary<int, IFasterList>> _collection;
}
}

Loading…
Cancel
Save