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.

546 lines
23KB

  1. using System;
  2. namespace Svelto.ECS
  3. {
  4. public readonly ref struct DoubleEntitiesEnumerator<T1> where T1 : struct, IEntityComponent
  5. {
  6. public DoubleEntitiesEnumerator(GroupsEnumerable<T1> groupsEnumerable) { _groupsEnumerable = groupsEnumerable; }
  7. public EntityGroupsIterator GetEnumerator() { return new EntityGroupsIterator(_groupsEnumerable); }
  8. readonly GroupsEnumerable<T1> _groupsEnumerable;
  9. public ref struct EntityGroupsIterator
  10. {
  11. public EntityGroupsIterator(GroupsEnumerable<T1> groupsEnumerable) : this()
  12. {
  13. _groupsEnumerableA = groupsEnumerable.GetEnumerator();
  14. _groupsEnumerableA.MoveNext();
  15. _groupsEnumerableB = _groupsEnumerableA;
  16. _indexA = 0;
  17. _indexB = 0;
  18. }
  19. public bool MoveNext()
  20. {
  21. //once GroupEnumerables complete, they reset. If they reset and moveNext doesn't happen, they are invalid
  22. while (_groupsEnumerableA.isValid)
  23. {
  24. var (buffersA, _) = _groupsEnumerableA.Current;
  25. var (buffersB, _) = _groupsEnumerableB.Current;
  26. //current index A must iterate as long as is less than the current A group count
  27. while (_indexA < buffersA.count)
  28. {
  29. //current index B must iterate as long as is less than the current B group count
  30. if (++_indexB < buffersB.count)
  31. {
  32. return true;
  33. }
  34. //if B iteration is over, move to the next group
  35. if (_groupsEnumerableB.MoveNext() == false)
  36. {
  37. //if there is no valid next groups, we reset B and we need to move to the next A element
  38. _groupsEnumerableB = _groupsEnumerableA;
  39. (buffersB, _) = _groupsEnumerableB.Current;
  40. ++_indexA; //next A element
  41. _indexB = _indexA;
  42. }
  43. else
  44. //otherwise the current A will be checked against the new B group. IndexB must be reset
  45. //to work on the new group
  46. {
  47. _indexB = -1;
  48. }
  49. }
  50. //the current group A iteration is done, so we move to the next A group
  51. if (_groupsEnumerableA.MoveNext() == true)
  52. {
  53. //there is a new group, we reset the iteration
  54. _indexA = 0;
  55. _indexB = 0;
  56. _groupsEnumerableB = _groupsEnumerableA;
  57. }
  58. else
  59. return false;
  60. }
  61. return false;
  62. }
  63. public void Reset() { throw new Exception(); }
  64. public ValueRef Current
  65. {
  66. get
  67. {
  68. var valueRef = new ValueRef(_groupsEnumerableA.Current, _indexA, _groupsEnumerableB.Current
  69. , _indexB);
  70. return valueRef;
  71. }
  72. }
  73. public void Dispose() { }
  74. GroupsEnumerable<T1>.GroupsIterator _groupsEnumerableA;
  75. GroupsEnumerable<T1>.GroupsIterator _groupsEnumerableB;
  76. int _indexA;
  77. int _indexB;
  78. }
  79. public ref struct ValueRef
  80. {
  81. public readonly GroupsEnumerable<T1>.RefCurrent _current;
  82. public readonly int _indexA;
  83. public readonly GroupsEnumerable<T1>.RefCurrent _refCurrent;
  84. public readonly int _indexB;
  85. public ValueRef
  86. (GroupsEnumerable<T1>.RefCurrent current, int indexA, GroupsEnumerable<T1>.RefCurrent refCurrent
  87. , int indexB)
  88. {
  89. _current = current;
  90. _indexA = indexA;
  91. _refCurrent = refCurrent;
  92. _indexB = indexB;
  93. }
  94. public void Deconstruct
  95. (out EntityCollection<T1> buffers, out int indexA, out EntityCollection<T1> refCurrent, out int indexB)
  96. {
  97. buffers = _current._buffers;
  98. indexA = _indexA;
  99. refCurrent = _refCurrent._buffers;
  100. indexB = _indexB;
  101. }
  102. public void Deconstruct
  103. (out EntityCollection<T1> buffers, out int indexA, out ExclusiveGroupStruct groupA
  104. , out EntityCollection<T1> refCurrent, out int indexB, out ExclusiveGroupStruct groupB)
  105. {
  106. buffers = _current._buffers;
  107. indexA = _indexA;
  108. refCurrent = _refCurrent._buffers;
  109. indexB = _indexB;
  110. groupA = _current._group;
  111. groupB = _refCurrent._group;
  112. }
  113. }
  114. }
  115. public readonly ref struct DoubleIterationEnumerator<T1, T2> where T1 : struct, IEntityComponent
  116. where T2 : struct, IEntityComponent
  117. {
  118. public DoubleIterationEnumerator(GroupsEnumerable<T1, T2> groupsEnumerable)
  119. {
  120. _groupsEnumerable = groupsEnumerable;
  121. }
  122. public EntityGroupsIterator GetEnumerator() { return new EntityGroupsIterator(_groupsEnumerable); }
  123. readonly GroupsEnumerable<T1, T2> _groupsEnumerable;
  124. public ref struct EntityGroupsIterator
  125. {
  126. public EntityGroupsIterator(GroupsEnumerable<T1, T2> groupsEnumerable) : this()
  127. {
  128. _groupsEnumerableA = groupsEnumerable.GetEnumerator();
  129. _groupsEnumerableA.MoveNext();
  130. _groupsEnumerableB = _groupsEnumerableA;
  131. _indexA = 0;
  132. _indexB = 0;
  133. }
  134. public bool MoveNext()
  135. {
  136. //once GroupEnumerables complete, they reset. If they reset and moveNext doesn't happen, they are invalid
  137. while (_groupsEnumerableA.isValid)
  138. {
  139. var (buffersA, _) = _groupsEnumerableA.Current;
  140. var (buffersB, _) = _groupsEnumerableB.Current;
  141. //current index A must iterate as long as is less than the current A group count
  142. while (_indexA < buffersA.count)
  143. {
  144. //current index B must iterate as long as is less than the current B group count
  145. if (++_indexB < buffersB.count)
  146. {
  147. return true;
  148. }
  149. //if B iteration is over, move to the next group
  150. if (_groupsEnumerableB.MoveNext() == false)
  151. {
  152. //if there is no valid next groups, we reset B and we need to move to the next A element
  153. _groupsEnumerableB = _groupsEnumerableA;
  154. (buffersB, _) = _groupsEnumerableB.Current;
  155. ++_indexA; //next A element
  156. _indexB = _indexA;
  157. }
  158. else
  159. //otherwise the current A will be checked against the new B group. IndexB must be reset
  160. //to work on the new group
  161. {
  162. _indexB = -1;
  163. }
  164. }
  165. //the current group A iteration is done, so we move to the next A group
  166. if (_groupsEnumerableA.MoveNext() == true)
  167. {
  168. //there is a new group, we reset the iteration
  169. _indexA = 0;
  170. _indexB = 0;
  171. _groupsEnumerableB = _groupsEnumerableA;
  172. }
  173. else
  174. return false;
  175. }
  176. return false;
  177. }
  178. public void Reset() { throw new Exception(); }
  179. public ValueRef Current
  180. {
  181. get
  182. {
  183. var valueRef = new ValueRef(_groupsEnumerableA.Current, _indexA, _groupsEnumerableB.Current
  184. , _indexB);
  185. return valueRef;
  186. }
  187. }
  188. public void Dispose() { }
  189. GroupsEnumerable<T1, T2>.GroupsIterator _groupsEnumerableA;
  190. GroupsEnumerable<T1, T2>.GroupsIterator _groupsEnumerableB;
  191. int _indexA;
  192. int _indexB;
  193. }
  194. public ref struct ValueRef
  195. {
  196. public readonly GroupsEnumerable<T1, T2>.RefCurrent _current;
  197. public readonly int _indexA;
  198. public readonly GroupsEnumerable<T1, T2>.RefCurrent _refCurrent;
  199. public readonly int _indexB;
  200. public ValueRef
  201. (GroupsEnumerable<T1, T2>.RefCurrent current, int indexA, GroupsEnumerable<T1, T2>.RefCurrent refCurrent
  202. , int indexB)
  203. {
  204. _current = current;
  205. _indexA = indexA;
  206. _refCurrent = refCurrent;
  207. _indexB = indexB;
  208. }
  209. public void Deconstruct(out EntityCollection<T1, T2> buffers, out int indexA,
  210. out EntityCollection<T1, T2> refCurrent, out int indexB)
  211. {
  212. buffers = _current._buffers;
  213. indexA = _indexA;
  214. refCurrent = _refCurrent._buffers;
  215. indexB = _indexB;
  216. }
  217. public void Deconstruct
  218. (out EntityCollection<T1, T2> buffers, out int indexA, out ExclusiveGroupStruct groupA
  219. , out EntityCollection<T1, T2> refCurrent, out int indexB, out ExclusiveGroupStruct groupB)
  220. {
  221. buffers = _current._buffers;
  222. indexA = _indexA;
  223. refCurrent = _refCurrent._buffers;
  224. indexB = _indexB;
  225. groupA = _current._group;
  226. groupB = _refCurrent._group;
  227. }
  228. }
  229. }
  230. /// <summary>
  231. /// Special Enumerator to iterate a group of entities against themselves with complexity n*(n+1)/2 (skips already tested couples)
  232. /// </summary>
  233. /// <typeparam name="T1"></typeparam>
  234. /// <typeparam name="T2"></typeparam>
  235. /// <typeparam name="T3"></typeparam>
  236. public readonly ref struct DoubleEntitiesEnumerator<T1, T2, T3> where T1 : struct, IEntityComponent
  237. where T2 : struct, IEntityComponent
  238. where T3 : struct, IEntityComponent
  239. {
  240. public DoubleEntitiesEnumerator(GroupsEnumerable<T1, T2, T3> groupsEnumerable)
  241. {
  242. _groupsEnumerable = groupsEnumerable;
  243. }
  244. public EntityGroupsIterator GetEnumerator() { return new EntityGroupsIterator(_groupsEnumerable); }
  245. readonly GroupsEnumerable<T1, T2, T3> _groupsEnumerable;
  246. public ref struct EntityGroupsIterator
  247. {
  248. public EntityGroupsIterator(GroupsEnumerable<T1, T2, T3> groupsEnumerable) : this()
  249. {
  250. _groupsEnumerableA = groupsEnumerable.GetEnumerator();
  251. _groupsEnumerableA.MoveNext();
  252. _groupsEnumerableB = _groupsEnumerableA;
  253. _indexA = 0;
  254. _indexB = 0;
  255. }
  256. public bool MoveNext()
  257. {
  258. //once GroupEnumerables complete, they reset. If they reset and moveNext doesn't happen, they are invalid
  259. while (_groupsEnumerableA.isValid)
  260. {
  261. var (buffersA, _) = _groupsEnumerableA.Current;
  262. var (buffersB, _) = _groupsEnumerableB.Current;
  263. //current index A must iterate as long as is less than the current A group count
  264. while (_indexA < buffersA.count)
  265. {
  266. //current index B must iterate as long as is less than the current B group count
  267. if (++_indexB < buffersB.count)
  268. {
  269. return true;
  270. }
  271. //if B iteration is over, move to the next group
  272. if (_groupsEnumerableB.MoveNext() == false)
  273. {
  274. //if there is no valid next groups, we reset B and we need to move to the next A element
  275. _groupsEnumerableB = _groupsEnumerableA;
  276. (buffersB, _) = _groupsEnumerableB.Current;
  277. ++_indexA; //next A element
  278. _indexB = _indexA;
  279. }
  280. else
  281. //otherwise the current A will be checked against the new B group. IndexB must be reset
  282. //to work on the new group
  283. {
  284. _indexB = -1;
  285. }
  286. }
  287. //the current group A iteration is done, so we move to the next A group
  288. if (_groupsEnumerableA.MoveNext() == true)
  289. {
  290. //there is a new group, we reset the iteration
  291. _indexA = 0;
  292. _indexB = 0;
  293. _groupsEnumerableB = _groupsEnumerableA;
  294. }
  295. else
  296. return false;
  297. }
  298. return false;
  299. }
  300. public void Reset() { throw new Exception(); }
  301. public ValueRef Current
  302. {
  303. get
  304. {
  305. var valueRef = new ValueRef(_groupsEnumerableA.Current, _indexA, _groupsEnumerableB.Current
  306. , _indexB);
  307. return valueRef;
  308. }
  309. }
  310. public void Dispose() { }
  311. GroupsEnumerable<T1, T2, T3>.GroupsIterator _groupsEnumerableA;
  312. GroupsEnumerable<T1, T2, T3>.GroupsIterator _groupsEnumerableB;
  313. int _indexA;
  314. int _indexB;
  315. }
  316. public ref struct ValueRef
  317. {
  318. public readonly GroupsEnumerable<T1, T2, T3>.RefCurrent _current;
  319. public readonly int _indexA;
  320. public readonly GroupsEnumerable<T1, T2, T3>.RefCurrent _refCurrent;
  321. public readonly int _indexB;
  322. public ValueRef
  323. (GroupsEnumerable<T1, T2, T3>.RefCurrent current, int indexA
  324. , GroupsEnumerable<T1, T2, T3>.RefCurrent refCurrent, int indexB)
  325. {
  326. _current = current;
  327. _indexA = indexA;
  328. _refCurrent = refCurrent;
  329. _indexB = indexB;
  330. }
  331. public void Deconstruct
  332. (out EntityCollection<T1, T2, T3> buffers, out int indexA, out EntityCollection<T1, T2, T3> refCurrent
  333. , out int indexB)
  334. {
  335. buffers = _current._buffers;
  336. indexA = _indexA;
  337. refCurrent = _refCurrent._buffers;
  338. indexB = _indexB;
  339. }
  340. public void Deconstruct
  341. (out EntityCollection<T1, T2, T3> buffers, out int indexA, out ExclusiveGroupStruct groupA
  342. , out EntityCollection<T1, T2, T3> refCurrent, out int indexB, out ExclusiveGroupStruct groupB)
  343. {
  344. buffers = _current._buffers;
  345. indexA = _indexA;
  346. refCurrent = _refCurrent._buffers;
  347. indexB = _indexB;
  348. groupA = _current._group;
  349. groupB = _refCurrent._group;
  350. }
  351. }
  352. }
  353. /// <summary>
  354. /// Special Enumerator to iterate a group of entities against themselves with complexity n*(n+1)/2 (skips already tested couples)
  355. /// </summary>
  356. /// <typeparam name="T1"></typeparam>
  357. /// <typeparam name="T2"></typeparam>
  358. /// <typeparam name="T3"></typeparam>
  359. /// <typeparam name="T4"></typeparam>
  360. public readonly ref struct DoubleEntitiesEnumerator<T1, T2, T3, T4> where T1 : struct, IEntityComponent
  361. where T2 : struct, IEntityComponent
  362. where T3 : struct, IEntityComponent
  363. where T4 : struct, IEntityComponent
  364. {
  365. public DoubleEntitiesEnumerator(GroupsEnumerable<T1, T2, T3, T4> groupsEnumerable)
  366. {
  367. _groupsEnumerable = groupsEnumerable;
  368. }
  369. public EntityGroupsIterator GetEnumerator() { return new EntityGroupsIterator(_groupsEnumerable); }
  370. readonly GroupsEnumerable<T1, T2, T3, T4> _groupsEnumerable;
  371. public ref struct EntityGroupsIterator
  372. {
  373. public EntityGroupsIterator(GroupsEnumerable<T1, T2, T3, T4> groupsEnumerable) : this()
  374. {
  375. _groupsEnumerableA = groupsEnumerable.GetEnumerator();
  376. _groupsEnumerableA.MoveNext();
  377. _groupsEnumerableB = _groupsEnumerableA;
  378. _indexA = 0;
  379. _indexB = 0;
  380. }
  381. public bool MoveNext()
  382. {
  383. //once GroupEnumerables complete, they reset. If they reset and moveNext doesn't happen, they are invalid
  384. while (_groupsEnumerableA.isValid)
  385. {
  386. var (buffersA, _) = _groupsEnumerableA.Current;
  387. var (buffersB, _) = _groupsEnumerableB.Current;
  388. //current index A must iterate as long as is less than the current A group count
  389. while (_indexA < buffersA.count)
  390. {
  391. //current index B must iterate as long as is less than the current B group count
  392. if (++_indexB < buffersB.count)
  393. {
  394. return true;
  395. }
  396. //if B iteration is over, move to the next group
  397. if (_groupsEnumerableB.MoveNext() == false)
  398. {
  399. //if there is no valid next groups, we reset B and we need to move to the next A element
  400. _groupsEnumerableB = _groupsEnumerableA;
  401. (buffersB, _) = _groupsEnumerableB.Current;
  402. ++_indexA; //next A element
  403. _indexB = _indexA;
  404. }
  405. else
  406. //otherwise the current A will be checked against the new B group. IndexB must be reset
  407. //to work on the new group
  408. {
  409. _indexB = -1;
  410. }
  411. }
  412. //the current group A iteration is done, so we move to the next A group
  413. if (_groupsEnumerableA.MoveNext() == true)
  414. {
  415. //there is a new group, we reset the iteration
  416. _indexA = 0;
  417. _indexB = 0;
  418. _groupsEnumerableB = _groupsEnumerableA;
  419. }
  420. else
  421. return false;
  422. }
  423. return false;
  424. }
  425. public void Reset() { throw new Exception(); }
  426. public ValueRef Current
  427. {
  428. get
  429. {
  430. var valueRef = new ValueRef(_groupsEnumerableA.Current, _indexA, _groupsEnumerableB.Current
  431. , _indexB);
  432. return valueRef;
  433. }
  434. }
  435. public void Dispose() { }
  436. GroupsEnumerable<T1, T2, T3, T4>.GroupsIterator _groupsEnumerableA;
  437. GroupsEnumerable<T1, T2, T3, T4>.GroupsIterator _groupsEnumerableB;
  438. int _indexA;
  439. int _indexB;
  440. }
  441. public ref struct ValueRef
  442. {
  443. public readonly GroupsEnumerable<T1, T2, T3, T4>.RefCurrent _current;
  444. public readonly int _indexA;
  445. public readonly GroupsEnumerable<T1, T2, T3, T4>.RefCurrent _refCurrent;
  446. public readonly int _indexB;
  447. public ValueRef
  448. (GroupsEnumerable<T1, T2, T3, T4>.RefCurrent current, int indexA
  449. , GroupsEnumerable<T1, T2, T3, T4>.RefCurrent refCurrent, int indexB)
  450. {
  451. _current = current;
  452. _indexA = indexA;
  453. _refCurrent = refCurrent;
  454. _indexB = indexB;
  455. }
  456. public void Deconstruct
  457. (out EntityCollection<T1, T2, T3, T4> buffers, out int indexA, out EntityCollection<T1, T2, T3, T4> refCurrent
  458. , out int indexB)
  459. {
  460. buffers = _current._buffers;
  461. indexA = _indexA;
  462. refCurrent = _refCurrent._buffers;
  463. indexB = _indexB;
  464. }
  465. public void Deconstruct
  466. (out EntityCollection<T1, T2, T3, T4> buffers, out int indexA, out ExclusiveGroupStruct groupA
  467. , out EntityCollection<T1, T2, T3, T4> refCurrent, out int indexB, out ExclusiveGroupStruct groupB)
  468. {
  469. buffers = _current._buffers;
  470. indexA = _indexA;
  471. refCurrent = _refCurrent._buffers;
  472. indexB = _indexB;
  473. groupA = _current._group;
  474. groupB = _refCurrent._group;
  475. }
  476. }
  477. }
  478. }