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.

186 lines
6.3KB

  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)
  13. {
  14. _nodesToBuild = new FasterList<INodeBuilder>(nodesToBuild);
  15. }
  16. protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor):this(nodesToBuild)
  17. {
  18. ProcessImplementors(componentsImplementor);
  19. }
  20. public void AddImplementors(params object[] componentsImplementor)
  21. {
  22. ProcessImplementors(componentsImplementor);
  23. }
  24. void ProcessImplementors(object[] implementors)
  25. {
  26. for (int index = 0; index < implementors.Length; index++)
  27. {
  28. var implementor = implementors[index];
  29. if (implementor is IRemoveEntityComponent)
  30. _removingImplementors.Add(implementor as IRemoveEntityComponent);
  31. if (implementor is IDisableEntityComponent)
  32. _disablingImplementors.Add(implementor as IDisableEntityComponent);
  33. if (implementor is IEnableEntityComponent)
  34. _enablingImplementors.Add(implementor as IEnableEntityComponent);
  35. var interfaces = implementor.GetType().GetInterfaces();
  36. for (int iindex = 0; iindex < interfaces.Length; iindex++)
  37. {
  38. _implementorsByType[interfaces[iindex]] = implementor;
  39. }
  40. }
  41. }
  42. public void AddNodes(params INodeBuilder[] nodesWithID)
  43. {
  44. _nodesToBuild.AddRange(nodesWithID);
  45. }
  46. public virtual FasterList<INode> BuildNodes(int ID)
  47. {
  48. var nodes = new FasterList<INode>();
  49. for (int index = 0; index < _nodesToBuild.Count; index++)
  50. {
  51. var nodeBuilder = _nodesToBuild[index];
  52. var node = nodeBuilder.Build(ID);
  53. if (nodeBuilder.reflects != FillNodeMode.None)
  54. node = FillNode(node, nodeBuilder.reflects);
  55. nodes.Add(node);
  56. }
  57. return nodes;
  58. }
  59. internal FasterList<INode> BuildNodes(int ID,
  60. Action<FasterList<INode>> removeEntity,
  61. Action<FasterList<INode>> enableEntity,
  62. Action<FasterList<INode>> disableEntity)
  63. {
  64. var nodes = BuildNodes(ID);
  65. SetupImplementors(removeEntity, enableEntity, disableEntity, nodes);
  66. return nodes;
  67. }
  68. void SetupImplementors(
  69. Action<FasterList<INode>> removeEntity,
  70. Action<FasterList<INode>> enableEntity,
  71. Action<FasterList<INode>> disableEntity,
  72. FasterList<INode> nodes)
  73. {
  74. Action removeEntityAction = () => { removeEntity(nodes); nodes.Clear(); };
  75. Action disableEntityAction = () => disableEntity(nodes);
  76. Action enableEntityAction = () => 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. TNode FillNode<TNode>(TNode node, FillNodeMode mode) where TNode : INode
  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. INode Build(int ID);
  117. FillNodeMode reflects { get; }
  118. }
  119. public class NodeBuilder<NodeType> : INodeBuilder where NodeType : NodeWithID, new()
  120. {
  121. public INode 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. public class StructNodeBuilder<NodeType> : INodeBuilder
  129. where NodeType : struct, IStructNodeWithID
  130. {
  131. public INode Build(int ID)
  132. {
  133. var shortID = (short)ID;
  134. IStructNodeWithID node = default(NodeType);
  135. node.ID = shortID;
  136. return node;
  137. }
  138. public virtual FillNodeMode reflects { get { return FillNodeMode.Relaxed; } }
  139. }
  140. public class FastStructNodeBuilder<NodeType> : StructNodeBuilder<NodeType>
  141. where NodeType : struct, IStructNodeWithID
  142. {
  143. public override FillNodeMode reflects { get { return FillNodeMode.None; } }
  144. }
  145. public enum FillNodeMode
  146. {
  147. Strict,
  148. Relaxed,
  149. None
  150. }
  151. }