Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
5.8KB

  1. using System;
  2. using System.Collections.Generic;
  3. using Svelto.DataStructures;
  4. using Svelto.Ticker;
  5. namespace Svelto.ES
  6. {
  7. public sealed class EnginesRoot: IEnginesRoot, IEndOfFrameTickable, IEntityFactory
  8. {
  9. const int _INITIAL_SIZE = 100;
  10. const int _INITIAL_INTERNAL_SIZE = 10;
  11. public EnginesRoot(ITicker ticker)
  12. {
  13. ticker.Add(this);
  14. _nodeEngines = new Dictionary<Type, FasterList<INodeEngine<INode>>>();
  15. _engineRootWeakReference = new WeakReference<EnginesRoot>(this);
  16. _otherEnginesReferences = new FasterList<IEngine>();
  17. _nodesDB = new Dictionary<Type, FasterList<INode>>(_INITIAL_SIZE);
  18. _nodesDBdic = new Dictionary<Type, Dictionary<int, INode>>(_INITIAL_SIZE);
  19. _nodesToAdd = new Queue<INode>(_INITIAL_SIZE);
  20. }
  21. public void EndOfFrameTick(float deltaSec)
  22. {
  23. while (_nodesToAdd.Count > 0) InternalAdd(_nodesToAdd.Dequeue());
  24. }
  25. public void AddEngine(IEngine engine)
  26. {
  27. if (engine is IQueryableNodeEngine)
  28. (engine as IQueryableNodeEngine).nodesDB = new EngineNodeDB(_nodesDB, _nodesDBdic);
  29. if (engine is INodesEngine)
  30. {
  31. var nodesEngine = engine as INodesEngine;
  32. AddEngine(nodesEngine, nodesEngine.AcceptedNodes(), _nodeEngines);
  33. return;
  34. }
  35. var baseType = engine.GetType().BaseType;
  36. if (baseType.IsGenericType)
  37. {
  38. var genericType = baseType.GetGenericTypeDefinition();
  39. if (genericType == typeof(SingleManagedNodeEngine<>))
  40. {
  41. AddEngine(engine as INodeEngine<INode>, baseType.GetGenericArguments(), _nodeEngines);
  42. return;
  43. }
  44. }
  45. _otherEnginesReferences.Add(engine);
  46. }
  47. public void BuildEntity(int ID, EntityDescriptor ed)
  48. {
  49. var entityNodes = ed.BuildNodes(ID, (node) => _engineRootWeakReference.Target.InternalRemove(node));
  50. for (int i = 0; i < entityNodes.Count; i++)
  51. _nodesToAdd.Enqueue(entityNodes[i]);
  52. }
  53. static void AddEngine<T>(T engine, Type[] types, Dictionary<Type, FasterList<INodeEngine<INode>>> engines) where T:INodeEngine<INode>
  54. {
  55. for (int i = 0; i < types.Length; i++)
  56. {
  57. FasterList<INodeEngine<INode>> list;
  58. var type = types[i];
  59. if (engines.TryGetValue(type, out list) == false)
  60. {
  61. list = new FasterList<INodeEngine<INode>>();
  62. engines.Add(type, list);
  63. }
  64. list.Add(engine);
  65. }
  66. }
  67. void InternalAdd<T>(T node) where T:INode
  68. {
  69. Type nodeType = node.GetType();
  70. AddNodeToTheSuitableEngines(node, nodeType);
  71. AddNodeToTheDB(node, nodeType);
  72. }
  73. void InternalRemove<T>(T node) where T:INode
  74. {
  75. Type nodeType = node.GetType();
  76. RemoveNodeFromEngines(node, nodeType);
  77. RemoveNodeFromTheDB(node, nodeType);
  78. }
  79. void AddNodeToTheDB<T>(T node, Type nodeType) where T : INode
  80. {
  81. FasterList<INode> nodes;
  82. if (_nodesDB.TryGetValue(nodeType, out nodes) == false)
  83. nodes = _nodesDB[nodeType] = new FasterList<INode>(_INITIAL_INTERNAL_SIZE);
  84. nodes.Add(node);
  85. if (node is NodeWithID)
  86. {
  87. Dictionary<int, INode> nodesDic;
  88. if (_nodesDBdic.TryGetValue(nodeType, out nodesDic) == false)
  89. nodesDic = _nodesDBdic[nodeType] = new Dictionary<int, INode>(_INITIAL_INTERNAL_SIZE);
  90. nodesDic[(node as NodeWithID).ID] = node;
  91. }
  92. }
  93. void AddNodeToTheSuitableEngines<T>(T node, Type nodeType) where T : INode
  94. {
  95. FasterList<INodeEngine<INode>> enginesForNode;
  96. if (_nodeEngines.TryGetValue(nodeType, out enginesForNode))
  97. for (int j = 0; j < enginesForNode.Count; j++)
  98. enginesForNode[j].Add(node);
  99. }
  100. void RemoveNodeFromTheDB<T>(T node, Type nodeType) where T : INode
  101. {
  102. FasterList<INode> nodes;
  103. if (_nodesDB.TryGetValue(nodeType, out nodes) == true)
  104. nodes.Remove(node); //should I remove it from the dictionary if length is zero?
  105. if (node is NodeWithID)
  106. {
  107. Dictionary<int, INode> nodesDic;
  108. if (_nodesDBdic.TryGetValue(nodeType, out nodesDic))
  109. nodesDic.Remove((node as NodeWithID).ID);
  110. }
  111. }
  112. void RemoveNodeFromEngines<T>(T node, Type nodeType) where T : INode
  113. {
  114. FasterList<INodeEngine<INode>> enginesForNode;
  115. if (_nodeEngines.TryGetValue(nodeType, out enginesForNode))
  116. for (int j = 0; j < enginesForNode.Count; j++)
  117. enginesForNode[j].Remove(node);
  118. }
  119. Dictionary<Type, FasterList<INodeEngine<INode>>> _nodeEngines;
  120. FasterList<IEngine> _otherEnginesReferences;
  121. Dictionary<Type, FasterList<INode>> _nodesDB;
  122. Dictionary<Type, Dictionary<int, INode>> _nodesDBdic;
  123. Queue<INode> _nodesToAdd;
  124. WeakReference<EnginesRoot> _engineRootWeakReference;
  125. //integrated pooling system
  126. //add debug panel like Entitas has
  127. //GCHandle should be used to reduce the number of strong references
  128. //datastructure could be thread safe
  129. //future enhancements:
  130. }
  131. }