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.

172 lines
5.6KB

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