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.

182 lines
6.1KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using Svelto.DataStructures;
  5. #if NETFX_CORE
  6. using BindingFlags = System.Reflection.BindingFlags;
  7. #endif
  8. namespace Svelto.ECS
  9. {
  10. public class EntityDescriptor
  11. {
  12. protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor)
  13. {
  14. _nodesToBuild = new FasterList<INodeBuilder>(nodesToBuild);
  15. ProcessImplementors(componentsImplementor);
  16. }
  17. public void AddImplementors(params object[] componentsImplementor)
  18. {
  19. ProcessImplementors(componentsImplementor);
  20. }
  21. void ProcessImplementors(object[] implementors)
  22. {
  23. for (int index = 0; index < implementors.Length; index++)
  24. {
  25. var implementor = implementors[index];
  26. if (implementor is IRemoveEntityComponent)
  27. _removingImplementors.Add(implementor as IRemoveEntityComponent);
  28. if (implementor is IDisableEntityComponent)
  29. _disablingImplementors.Add(implementor as IDisableEntityComponent);
  30. if (implementor is IEnableEntityComponent)
  31. _enablingImplementors.Add(implementor as IEnableEntityComponent);
  32. var interfaces = implementor.GetType().GetInterfaces();
  33. for (int iindex = 0; iindex < interfaces.Length; iindex++)
  34. {
  35. _implementorsByType[interfaces[iindex]] = implementor;
  36. }
  37. }
  38. }
  39. public void AddNodes(params INodeBuilder[] nodesWithID)
  40. {
  41. _nodesToBuild.AddRange(nodesWithID);
  42. }
  43. public virtual FasterList<INode> BuildNodes(int ID)
  44. {
  45. var nodes = new FasterList<INode>();
  46. for (int index = 0; index < _nodesToBuild.Count; index++)
  47. {
  48. var nodeBuilder = _nodesToBuild[index];
  49. var node = nodeBuilder.Build(ID);
  50. if (nodeBuilder.reflects != FillNodeMode.None)
  51. node = FillNode(node, nodeBuilder.reflects);
  52. nodes.Add(node);
  53. }
  54. return nodes;
  55. }
  56. internal FasterList<INode> BuildNodes(int ID,
  57. Action<FasterList<INode>> removeEntity,
  58. Action<FasterList<INode>> enableEntity,
  59. Action<FasterList<INode>> disableEntity)
  60. {
  61. var nodes = BuildNodes(ID);
  62. SetupImplementors(removeEntity, enableEntity, disableEntity, nodes);
  63. return nodes;
  64. }
  65. void SetupImplementors(
  66. Action<FasterList<INode>> removeEntity,
  67. Action<FasterList<INode>> enableEntity,
  68. Action<FasterList<INode>> disableEntity,
  69. FasterList<INode> nodes)
  70. {
  71. Action removeEntityAction = () =>
  72. { removeEntity(nodes); nodes.Clear(); };
  73. Action disableEntityAction = () =>
  74. { disableEntity(nodes); };
  75. Action enableEntityAction = () =>
  76. { enableEntity(nodes); };
  77. for (int index = 0; index < _removingImplementors.Count; index++)
  78. _removingImplementors[index].removeEntity = removeEntityAction;
  79. for (int index = 0; index < _disablingImplementors.Count; index++)
  80. _disablingImplementors[index].disableEntity = disableEntityAction;
  81. for (int index = 0; index < _enablingImplementors.Count; index++)
  82. _enablingImplementors[index].enableEntity = enableEntityAction;
  83. }
  84. INode FillNode(INode node, FillNodeMode mode)
  85. {
  86. var fields = node.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
  87. for (int i = fields.Length - 1; i >= 0; --i)
  88. {
  89. var field = fields[i];
  90. Type fieldType = field.FieldType;
  91. object component;
  92. if ((_implementorsByType.TryGetValue(fieldType, out component)) == false)
  93. {
  94. if (mode == FillNodeMode.Strict)
  95. {
  96. Exception e =
  97. new Exception("Svelto.ECS: Implementor not found for a Node. " + "Implementor Type: " +
  98. field.FieldType.Name + " - Node: " + node.GetType().Name +
  99. " - EntityDescriptor " + this);
  100. throw e;
  101. }
  102. }
  103. else
  104. field.SetValue(node, component);
  105. }
  106. return node;
  107. }
  108. readonly FasterList<IDisableEntityComponent> _disablingImplementors = new FasterList<IDisableEntityComponent>();
  109. readonly FasterList<IRemoveEntityComponent> _removingImplementors = new FasterList<IRemoveEntityComponent>();
  110. readonly FasterList<IEnableEntityComponent> _enablingImplementors = new FasterList<IEnableEntityComponent>();
  111. readonly Dictionary<Type, object> _implementorsByType = new Dictionary<Type, object>();
  112. readonly FasterList<INodeBuilder> _nodesToBuild;
  113. }
  114. public interface INodeBuilder
  115. {
  116. INodeWithID Build(int ID);
  117. FillNodeMode reflects { get; }
  118. }
  119. public class NodeBuilder<NodeType> : INodeBuilder where NodeType : NodeWithID, new()
  120. {
  121. public INodeWithID Build(int ID)
  122. {
  123. NodeWithID node = NodeWithID.BuildNode<NodeType>(ID);
  124. return (NodeType)node;
  125. }
  126. public FillNodeMode reflects { get { return FillNodeMode.Strict; } }
  127. }
  128. //To Do: Probably I will need to add an
  129. //FastStructNodeBuilder where reflects is false
  130. public class StructNodeBuilder<NodeType> : INodeBuilder
  131. where NodeType : struct, IStructNodeWithID
  132. {
  133. public INodeWithID Build(int ID)
  134. {
  135. IStructNodeWithID node = default(NodeType);
  136. node.ID = ID;
  137. return node;
  138. }
  139. public FillNodeMode reflects { get { return FillNodeMode.Relaxed; } }
  140. }
  141. public enum FillNodeMode
  142. {
  143. Strict,
  144. Relaxed,
  145. None
  146. }
  147. }