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.

184 lines
7.2KB

  1. using System;
  2. using System.Collections.Generic;
  3. using Svelto.DataStructures;
  4. using Svelto.DataStructures.Experimental;
  5. namespace Svelto.ECS.Internal
  6. {
  7. partial class EntitiesDB : IEntitiesDB
  8. {
  9. internal EntitiesDB(FasterDictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupEntityViewsDB,
  10. Dictionary<Type, FasterDictionary<int, ITypeSafeDictionary>> groupedGroups)
  11. {
  12. _groupEntityViewsDB = groupEntityViewsDB;
  13. _groupedGroups = groupedGroups;
  14. }
  15. public ReadOnlyCollectionStruct<T> QueryEntityViews<T>(int @group) where T:class, IEntityStruct
  16. {
  17. TypeSafeDictionary<T> typeSafeDictionary;
  18. if (QueryEntitySafeDictionary(@group, out typeSafeDictionary) == false) return RetrieveEmptyEntityViewList<T>();
  19. return typeSafeDictionary.Values;
  20. }
  21. public T[] QueryEntities<T>(int @group, out int count) where T : IEntityStruct
  22. {
  23. TypeSafeDictionary<T> typeSafeDictionary;
  24. count = 0;
  25. if (QueryEntitySafeDictionary(@group, out typeSafeDictionary) == false) return RetrieveEmptyEntityViewArray<T>();
  26. return typeSafeDictionary.GetValuesArray(out count);
  27. }
  28. public T[] QueryEntities<T>(ExclusiveGroup @group, out int targetsCount) where T : IEntityStruct
  29. {
  30. return QueryEntities<T>((int) @group, out targetsCount);
  31. }
  32. public EGIDMapper<T> QueryMappedEntities<T>(int groupID) where T : IEntityStruct
  33. {
  34. TypeSafeDictionary<T> typeSafeDictionary;
  35. if (QueryEntitySafeDictionary(groupID, out typeSafeDictionary) == false)
  36. throw new EntitiesDBException("Entity group not found type: ".FastConcat(typeof(T)).FastConcat(" groupID: ").FastConcat(groupID));
  37. EGIDMapper<T> mapper;
  38. mapper.map = typeSafeDictionary;
  39. int count;
  40. typeSafeDictionary.GetValuesArray(out count);
  41. return mapper;
  42. }
  43. public EGIDMapper<T> QueryMappedEntities<T>(ExclusiveGroup groupID) where T : IEntityStruct
  44. {
  45. return QueryMappedEntities<T>((int) groupID);
  46. }
  47. public T[] QueryEntitiesAndIndex<T>(EGID entityGID, out uint index) where T : IEntityStruct
  48. {
  49. T[] array;
  50. if ((array = QueryEntitiesAndIndexInternal<T>(entityGID, out index)) != null)
  51. return array;
  52. throw new EntitiesDBException("Entity not found id: ".FastConcat(entityGID.entityID).FastConcat(" groupID: ").FastConcat(entityGID.groupID));
  53. }
  54. public bool TryQueryEntitiesAndIndex<T>(EGID entityGid, out uint index, out T[] array) where T : IEntityStruct
  55. {
  56. if ((array = QueryEntitiesAndIndexInternal<T>(entityGid, out index)) != null)
  57. return true;
  58. return false;
  59. }
  60. public T QueryEntityView<T>(EGID entityGID) where T : class, IEntityStruct
  61. {
  62. T entityView;
  63. if (TryQueryEntityViewInGroupInternal(entityGID, out entityView) == false)
  64. throw new EntitiesDBException("Entity not found id: ".FastConcat(entityGID.entityID).FastConcat(" groupID: ").FastConcat(entityGID.groupID));
  65. return entityView;
  66. }
  67. public bool Exists<T>(EGID entityGID) where T : IEntityStruct
  68. {
  69. TypeSafeDictionary<T> casted;
  70. if (QueryEntitySafeDictionary(entityGID.groupID, out casted) == false) return false;
  71. return casted != null && casted.ContainsKey(entityGID.entityID);
  72. }
  73. public bool HasAny<T>(int @group) where T : IEntityStruct
  74. {
  75. int count;
  76. QueryEntities<T>(group, out count);
  77. return count > 0;
  78. }
  79. public bool HasAny<T>(ExclusiveGroup @group) where T : IEntityStruct
  80. {
  81. return HasAny<T>((int) group);
  82. }
  83. public bool TryQueryEntityView<T>(EGID entityegid, out T entityView) where T : class, IEntityStruct
  84. {
  85. return TryQueryEntityViewInGroupInternal(entityegid, out entityView);
  86. }
  87. bool TryQueryEntityViewInGroupInternal<T>(EGID entityGID, out T entityView) where T:class, IEntityStruct
  88. {
  89. entityView = null;
  90. TypeSafeDictionary<T> safeDictionary;
  91. if (QueryEntitySafeDictionary(entityGID.groupID, out safeDictionary) == false) return false;
  92. return safeDictionary.TryGetValue(entityGID.entityID, out entityView) != false;
  93. }
  94. T[] QueryEntitiesAndIndexInternal<T>(EGID entityGID, out uint index) where T : IEntityStruct
  95. {
  96. TypeSafeDictionary<T> safeDictionary;
  97. index = 0;
  98. if (QueryEntitySafeDictionary(entityGID.groupID, out safeDictionary) == false)
  99. return null;
  100. if (safeDictionary.TryFindElementIndex(entityGID.entityID, out index) == false)
  101. return null;
  102. int count;
  103. return safeDictionary.GetValuesArray(out count);
  104. }
  105. bool QueryEntitySafeDictionary<T>(int @group, out TypeSafeDictionary<T> typeSafeDictionary) where T : IEntityStruct
  106. {
  107. Dictionary<Type, ITypeSafeDictionary> entitiesInGroupPerType;
  108. typeSafeDictionary = null;
  109. //search for the group
  110. if (_groupEntityViewsDB.TryGetValue(@group, out entitiesInGroupPerType) == false)
  111. return false;
  112. //search for the indexed entities in the group
  113. ITypeSafeDictionary safeDictionary;
  114. if (entitiesInGroupPerType.TryGetValue(typeof(T), out safeDictionary) == false)
  115. return false;
  116. //return the indexes entities if they exist
  117. typeSafeDictionary = (safeDictionary as TypeSafeDictionary<T>);
  118. return true;
  119. }
  120. static void SafetyChecks<T>(TypeSafeDictionary<T> typeSafeDictionary, int count) where T : IEntityStruct
  121. {
  122. #if DEBUG
  123. if (typeSafeDictionary.Count != count)
  124. throw new EntitiesDBException("Entities cannot be swapped or removed during an iteration");
  125. #endif
  126. }
  127. static ReadOnlyCollectionStruct<T> RetrieveEmptyEntityViewList<T>()
  128. {
  129. return ReadOnlyCollectionStruct<T>.DefaultList;
  130. }
  131. static T[] RetrieveEmptyEntityViewArray<T>()
  132. {
  133. return FasterList<T>.DefaultList.ToArrayFast();
  134. }
  135. //grouped set of entity views, this is the standard way to handle entity views
  136. //entity views are grouped per group, then indexable per type, then indexable per EGID.
  137. //however the TypeSafeDictionary can return an array of values directly, that can be
  138. //iterated over, so that is possible to iterate over all the entity views of
  139. //a specific type inside a specific group.
  140. readonly FasterDictionary<int, Dictionary<Type, ITypeSafeDictionary>> _groupEntityViewsDB;
  141. //needed to be able to iterate over all the entities of the same type regardless the group
  142. //may change in future
  143. readonly Dictionary<Type, FasterDictionary<int, ITypeSafeDictionary>> _groupedGroups;
  144. }
  145. }