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.

197 lines
6.8KB

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