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.

179 lines
6.0KB

  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. public EnginesRoot(ITicker ticker)
  10. {
  11. ticker.Add(this);
  12. _nodeEngines = new Dictionary<Type, FasterList<INodeEngine<INode>>>();
  13. _engineRootWeakReference = new WeakReference<EnginesRoot>(this);
  14. _otherEnginesReferences = new FasterList<IEngine>();
  15. _nodesDB = new Dictionary<Type, FasterList<INode>>();
  16. _nodesDBdic = new Dictionary<Type, Dictionary<int, INode>>();
  17. _nodesToAdd = new Queue<INode>();
  18. _nodesToRemove = new Queue<INode>();
  19. }
  20. public void EndOfFrameTick(float deltaSec)
  21. {
  22. while (_nodesToAdd.Count > 0) InternalAdd(_nodesToAdd.Dequeue());
  23. while (_nodesToRemove.Count > 0) InternalRemove(_nodesToRemove.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(SingleNodeEngine<>))
  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) =>
  50. {
  51. if (_engineRootWeakReference.IsValid == true)
  52. _engineRootWeakReference.Target._nodesToRemove.Enqueue(node);
  53. });
  54. for (int i = 0; i < entityNodes.Count; i++)
  55. _nodesToAdd.Enqueue(entityNodes[i]);
  56. }
  57. static void AddEngine<T>(T engine, Type[] types, Dictionary<Type, FasterList<INodeEngine<INode>>> engines) where T:INodeEngine<INode>
  58. {
  59. for (int i = 0; i < types.Length; i++)
  60. {
  61. FasterList<INodeEngine<INode>> list;
  62. var type = types[i];
  63. if (engines.TryGetValue(type, out list) == false)
  64. {
  65. list = new FasterList<INodeEngine<INode>>();
  66. engines.Add(type, list);
  67. }
  68. list.Add(engine);
  69. }
  70. }
  71. void InternalAdd<T>(T node) where T:INode
  72. {
  73. Type nodeType = node.GetType();
  74. AddNodeToTheSuitableEngines(node, nodeType);
  75. AddNodeToTheDB(node, nodeType);
  76. }
  77. void InternalRemove<T>(T node) where T:INode
  78. {
  79. Type nodeType = node.GetType();
  80. RemoveNodeFromEngines(node, nodeType);
  81. RemoveNodeFromTheDB(node, nodeType);
  82. }
  83. void AddNodeToTheDB<T>(T node, Type nodeType) where T : INode
  84. {
  85. FasterList<INode> nodes;
  86. if (_nodesDB.TryGetValue(nodeType, out nodes) == false)
  87. nodes = _nodesDB[nodeType] = new FasterList<INode>();
  88. nodes.Add(node);
  89. if (node is NodeWithID)
  90. {
  91. Dictionary<int, INode> nodesDic;
  92. if (_nodesDBdic.TryGetValue(nodeType, out nodesDic) == false)
  93. nodesDic = _nodesDBdic[nodeType] = new Dictionary<int, INode>();
  94. nodesDic[(node as NodeWithID).ID] = node;
  95. }
  96. }
  97. void AddNodeToTheSuitableEngines<T>(T node, Type nodeType) where T : INode
  98. {
  99. FasterList<INodeEngine<INode>> enginesForNode;
  100. if (_nodeEngines.TryGetValue(nodeType, out enginesForNode))
  101. for (int j = 0; j < enginesForNode.Count; j++)
  102. enginesForNode[j].Add(node);
  103. }
  104. void RemoveNodeFromTheDB<T>(T node, Type nodeType) where T : INode
  105. {
  106. FasterList<INode> nodes;
  107. if (_nodesDB.TryGetValue(nodeType, out nodes) == true)
  108. nodes.Remove(node); //should I remove it from the dictionary if length is zero?
  109. if (node is NodeWithID)
  110. {
  111. Dictionary<int, INode> nodesDic;
  112. if (_nodesDBdic.TryGetValue(nodeType, out nodesDic))
  113. nodesDic.Remove((node as NodeWithID).ID);
  114. }
  115. }
  116. void RemoveNodeFromEngines<T>(T node, Type nodeType) where T : INode
  117. {
  118. FasterList<INodeEngine<INode>> enginesForNode;
  119. if (_nodeEngines.TryGetValue(nodeType, out enginesForNode))
  120. for (int j = 0; j < enginesForNode.Count; j++)
  121. enginesForNode[j].Remove(node);
  122. }
  123. Dictionary<Type, FasterList<INodeEngine<INode>>> _nodeEngines;
  124. FasterList<IEngine> _otherEnginesReferences;
  125. Dictionary<Type, FasterList<INode>> _nodesDB;
  126. Dictionary<Type, Dictionary<int, INode>> _nodesDBdic;
  127. Queue<INode> _nodesToAdd;
  128. Queue<INode> _nodesToRemove;
  129. WeakReference<EnginesRoot> _engineRootWeakReference;
  130. //integrated pooling system
  131. //add debug panel like Entitas has
  132. //GCHandle should be used to reduce the number of strong references
  133. //datastructure could be thread safe
  134. //future enhancements:
  135. }
  136. }