Mirror of Svelto.ECS because we're a fan of it
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

214 lignes
9.4KB

  1. //#define VERBOSE
  2. #if !DEBUG || PROFILE_SVELTO
  3. #define DONT_USE
  4. using System.Diagnostics;
  5. #endif
  6. using System;
  7. using System.Collections.Generic;
  8. using Svelto.DataStructures;
  9. namespace Svelto.ECS
  10. {
  11. /// <summary>
  12. /// Note: this check doesn't catch the case when an add and remove is done on the same entity before the next
  13. /// submission. Two operations on the same entity are not allowed between submissions.
  14. /// </summary>
  15. public partial class EnginesRoot
  16. {
  17. enum OperationType
  18. {
  19. Add,
  20. Remove,
  21. SwapFrom,
  22. SwapTo
  23. }
  24. #if DONT_USE
  25. [Conditional("MEANINGLESS")]
  26. #endif
  27. void InitDebugChecks()
  28. {
  29. _multipleOperationOnSameEGIDChecker = new FasterDictionary<EGID, OperationType>();
  30. _idChecker = new FasterDictionary<ExclusiveGroupStruct, HashSet<uint>>();
  31. }
  32. #if DONT_USE
  33. [Conditional("MEANINGLESS")]
  34. #endif
  35. void CheckSwapEntityID(EGID fromEgid, EGID toEgid, Type entityDescriptorType, string caller)
  36. {
  37. if (_multipleOperationOnSameEGIDChecker.TryGetValue(fromEgid, out var fromOperationType) == true)
  38. {
  39. var operationName = OperationName(fromOperationType);
  40. throw new ECSException(
  41. "Executing multiple structural changes (swapFrom) on the same entity is not supported "
  42. .FastConcat(" caller: ", caller, " ").FastConcat(fromEgid.entityID).FastConcat(" groupid: ")
  43. .FastConcat(fromEgid.groupID.ToName()).FastConcat(" type: ")
  44. .FastConcat(entityDescriptorType != null ? entityDescriptorType.Name : "not available")
  45. .FastConcat(" previous operation was: ")
  46. .FastConcat(operationName));
  47. }
  48. if (_multipleOperationOnSameEGIDChecker.TryGetValue(toEgid, out var toOperationType) == true)
  49. {
  50. var operationName = OperationName(toOperationType);
  51. throw new ECSException(
  52. "Executing multiple structural changes (swapTo) on the same entity is not supported "
  53. .FastConcat(" caller: ", caller, " ").FastConcat(toEgid.entityID).FastConcat(" groupid: ")
  54. .FastConcat(toEgid.groupID.ToName()).FastConcat(" type: ")
  55. .FastConcat(entityDescriptorType != null ? entityDescriptorType.Name : "not available")
  56. .FastConcat(" previous operation was: ")
  57. .FastConcat(operationName));
  58. }
  59. HashRemove(fromEgid, entityDescriptorType, false, caller);
  60. HashAdd(toEgid, entityDescriptorType, caller);
  61. _multipleOperationOnSameEGIDChecker.Add(fromEgid, OperationType.SwapFrom);
  62. _multipleOperationOnSameEGIDChecker.Add(toEgid, OperationType.SwapTo);
  63. }
  64. #if DONT_USE
  65. [Conditional("MEANINGLESS")]
  66. #endif
  67. void CheckRemoveEntityID(EGID egid, Type entityDescriptorType, string caller)
  68. {
  69. bool isAllowed = false;
  70. if (_multipleOperationOnSameEGIDChecker.TryGetValue(egid, out var operationType) == true)
  71. {
  72. isAllowed = operationType == OperationType.Remove || operationType == OperationType.SwapFrom;
  73. if (isAllowed)
  74. {
  75. #if VERBOSE
  76. var operationName = OperationName(operationType);
  77. Console.LogDebugWarning(
  78. "Executing multiple structural changes (remove) in one submission on the same entity. Remove supersedes swap and remove operations "
  79. .FastConcat(" caller: ", caller, " ").FastConcat(egid.entityID).FastConcat(" groupid: ")
  80. .FastConcat(egid.groupID.ToName()).FastConcat(" type: ")
  81. .FastConcat(entityDescriptorType != null ? entityDescriptorType.Name : "not available")
  82. .FastConcat(" previous operation was: ")
  83. .FastConcat(operationName));
  84. #endif
  85. }
  86. else
  87. throw new ECSException(
  88. "Executing multiple structural changes (remove) in one submission on the same entity is not supported "
  89. .FastConcat(" caller: ", caller, " ").FastConcat(egid.entityID).FastConcat(" groupid: ")
  90. .FastConcat(egid.groupID.ToName()).FastConcat(" type: ")
  91. .FastConcat(entityDescriptorType != null ? entityDescriptorType.Name : "not available")
  92. .FastConcat(" previous operation was: ")
  93. .FastConcat("add"));
  94. }
  95. HashRemove(egid, entityDescriptorType, isAllowed, caller);
  96. if (isAllowed == false)
  97. _multipleOperationOnSameEGIDChecker.Add(egid, OperationType.Remove);
  98. else
  99. _multipleOperationOnSameEGIDChecker[egid] = OperationType.Remove;
  100. }
  101. #if DONT_USE
  102. [Conditional("MEANINGLESS")]
  103. #endif
  104. void CheckAddEntityID(EGID egid, Type entityDescriptorType, string caller)
  105. {
  106. if (_multipleOperationOnSameEGIDChecker.TryGetValue(egid, out var operationType) == true)
  107. {
  108. var operationName = OperationName(operationType);
  109. throw new ECSException(
  110. "Executing multiple structural changes (build) on the same entity is not supported "
  111. .FastConcat(" caller: ", caller, " ").FastConcat(egid.entityID).FastConcat(" groupid: ")
  112. .FastConcat(egid.groupID.ToName()).FastConcat(" type: ")
  113. .FastConcat(entityDescriptorType != null ? entityDescriptorType.Name : "not available")
  114. .FastConcat(" previous operation was: ")
  115. .FastConcat(operationName));
  116. }
  117. HashAdd(egid, entityDescriptorType, caller);
  118. _multipleOperationOnSameEGIDChecker.Add(egid, OperationType.Add);
  119. }
  120. #if DONT_USE
  121. [Conditional("MEANINGLESS")]
  122. #endif
  123. void RemoveGroupID(ExclusiveBuildGroup groupID)
  124. {
  125. _idChecker.Remove(groupID);
  126. }
  127. #if DONT_USE
  128. [Conditional("MEANINGLESS")]
  129. #endif
  130. void ClearChecksForMultipleOperationsOnTheSameEgid()
  131. {
  132. _multipleOperationOnSameEGIDChecker.Clear();
  133. }
  134. void HashRemove(EGID egid, Type entityDescriptorType, bool isAllowed, string caller)
  135. {
  136. if (_idChecker.TryGetValue(egid.groupID, out HashSet<uint> hash))
  137. {
  138. if (hash.Contains(egid.entityID) == false && isAllowed == false)
  139. throw new ECSException(
  140. "Trying to remove an Entity not present in the database "
  141. .FastConcat(" caller: ", caller, " entityID ").FastConcat(egid.entityID).FastConcat(" groupid: ")
  142. .FastConcat(egid.groupID.ToName()).FastConcat(" type: ")
  143. .FastConcat(entityDescriptorType != null ? entityDescriptorType.Name : "not available"));
  144. }
  145. else
  146. {
  147. throw new ECSException(
  148. "Trying to remove an Entity with a group never used so far "
  149. .FastConcat(" caller: ", caller, " entityID ").FastConcat(egid.entityID).FastConcat(" groupid: ")
  150. .FastConcat(egid.groupID.ToName()).FastConcat(" type: ")
  151. .FastConcat(entityDescriptorType != null ? entityDescriptorType.Name : "not available"));
  152. }
  153. hash.Remove(egid.entityID);
  154. }
  155. void HashAdd(EGID egid, Type entityDescriptorType, string caller)
  156. {
  157. var hash = _idChecker.GetOrAdd(egid.groupID, () => new HashSet<uint>());
  158. if (hash.Contains(egid.entityID) == true)
  159. throw new ECSException(
  160. "Trying to add an Entity already present in the database "
  161. .FastConcat(" caller: ", caller, " entityID ").FastConcat(egid.entityID)
  162. .FastConcat(" groupid: ").FastConcat(egid.groupID.ToName()).FastConcat(" type: ")
  163. .FastConcat(
  164. entityDescriptorType != null
  165. ? entityDescriptorType.Name
  166. : "not available"));
  167. hash.Add(egid.entityID);
  168. }
  169. string OperationName(OperationType operationType)
  170. {
  171. string operationName;
  172. switch (operationType)
  173. {
  174. case OperationType.Remove:
  175. operationName = "remove";
  176. break;
  177. case OperationType.Add:
  178. operationName = "add";
  179. break;
  180. case OperationType.SwapFrom:
  181. operationName = "swapFrom";
  182. break;
  183. default:
  184. operationName = "swapTo";
  185. break;
  186. }
  187. return operationName;
  188. }
  189. DataStructures.FasterDictionary<EGID, OperationType> _multipleOperationOnSameEGIDChecker;
  190. DataStructures.FasterDictionary<ExclusiveGroupStruct, HashSet<uint>> _idChecker;
  191. }
  192. }