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.

180 lines
5.9KB

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