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.

123 lines
6.1KB

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using Svelto.DataStructures;
  5. using Svelto.DataStructures.Experimental;
  6. using Svelto.ECS.Internal;
  7. using Svelto.ECS.Schedulers;
  8. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  9. using Svelto.ECS.Profiler;
  10. #endif
  11. namespace Svelto.ECS
  12. {
  13. public partial class EnginesRoot : IDisposable
  14. {
  15. void SubmitEntityViews()
  16. {
  17. var entitiesOperations = _entitiesOperations.ToArrayFast();
  18. for (int i = 0; i < _entitiesOperations.Count; i++)
  19. {
  20. switch (entitiesOperations[i].type)
  21. {
  22. case EntitySubmitOperationType.Swap:
  23. SwapEntityGroup(entitiesOperations[i].builders, entitiesOperations[i].id, entitiesOperations[i].fromGroupID, entitiesOperations[i].toGroupID);
  24. break;
  25. case EntitySubmitOperationType.Remove:
  26. MoveEntity(entitiesOperations[i].builders, new EGID(entitiesOperations[i].id, entitiesOperations[i].fromGroupID));
  27. break;
  28. case EntitySubmitOperationType.FirstSwap:
  29. SwapFirstEntityInGroup(entitiesOperations[i].builders, entitiesOperations[i].fromGroupID, entitiesOperations[i].toGroupID);
  30. break;
  31. case EntitySubmitOperationType.RemoveGroup:
  32. RemoveGroupAndEntitiesFromDB(entitiesOperations[i].fromGroupID);
  33. break;
  34. }
  35. }
  36. _entitiesOperations.FastClear();
  37. int numberOfReenteringLoops = 0;
  38. //are there new entities built to process?
  39. while ( _newEntitiesBuiltToProcess > 0)
  40. {
  41. //use other as source from now on
  42. //current will be use to write new entityViews
  43. _groupedEntityToAdd.Swap();
  44. //Note: if N entity of the same type are added on the same frame
  45. //the Add callback is called N times on the same frame.
  46. //if the Add calback builds a new entity, that entity will not
  47. //be available in the database until the N callbacks are done
  48. //solving it could be complicated as callback and database update
  49. //must be interleaved.
  50. if (_groupedEntityToAdd.other.Count > 0)
  51. AddEntityViewsToTheDBAndSuitableEngines(_groupedEntityToAdd.other);
  52. //other can be cleared now, but let's avoid deleting the dictionary every time
  53. _groupedEntityToAdd.ClearOther();
  54. if (numberOfReenteringLoops > 5)
  55. throw new Exception("possible infinite loop found creating Entities inside IEntityViewsEngine Add method, please consider building entities outside IEntityViewsEngine Add method");
  56. _newEntitiesBuiltToProcess = 0;
  57. numberOfReenteringLoops++;
  58. }
  59. }
  60. //todo: groupsToSubmit can be simplified as data structure?
  61. void AddEntityViewsToTheDBAndSuitableEngines(FasterDictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupsOfEntitiesToSubmit)
  62. {
  63. //each group is indexed by entity view type. for each type there is a dictionary indexed by entityID
  64. foreach (var groupOfEntitiesToSubmit in groupsOfEntitiesToSubmit)
  65. {
  66. Dictionary<Type, ITypeSafeDictionary> groupDB;
  67. int groupID = groupOfEntitiesToSubmit.Key;
  68. //if the group doesn't exist in the current DB let's create it first
  69. if (_groupEntityDB.TryGetValue(groupID, out groupDB) == false)
  70. groupDB = _groupEntityDB[groupID] = new Dictionary<Type, ITypeSafeDictionary>();
  71. //add the entityViews in the group
  72. foreach (var entityViewTypeSafeDictionary in groupOfEntitiesToSubmit.Value)
  73. {
  74. ITypeSafeDictionary dbDic;
  75. FasterDictionary<int, ITypeSafeDictionary> groupedGroup = null;
  76. if (groupDB.TryGetValue(entityViewTypeSafeDictionary.Key, out dbDic) == false)
  77. dbDic = groupDB[entityViewTypeSafeDictionary.Key] = entityViewTypeSafeDictionary.Value.Create();
  78. if (_groupedGroups.TryGetValue(entityViewTypeSafeDictionary.Key, out groupedGroup) == false)
  79. groupedGroup = _groupedGroups[entityViewTypeSafeDictionary.Key] = new FasterDictionary<int, ITypeSafeDictionary>();
  80. //Fill the DB with the entity views generate this frame.
  81. dbDic.FillWithIndexedEntities(entityViewTypeSafeDictionary.Value);
  82. groupedGroup[groupID] = dbDic;
  83. }
  84. }
  85. //then submit everything in the engines, so that the DB is up to date
  86. //with all the entity views and struct created by the entity built
  87. foreach (var groupToSubmit in groupsOfEntitiesToSubmit)
  88. {
  89. foreach (var entityViewsPerType in groupToSubmit.Value)
  90. {
  91. entityViewsPerType.Value.AddEntitiesToEngines(_entityEngines);
  92. }
  93. }
  94. }
  95. //one datastructure rule them all:
  96. //split by group
  97. //split by type per group. It's possible to get all the entities of a give type T per group thanks
  98. //to the FasterDictionary capabilities OR it's possible to get a specific entityView indexed by
  99. //ID. This ID doesn't need to be the EGID, it can be just the entityID
  100. readonly FasterDictionary<int, Dictionary<Type, ITypeSafeDictionary>> _groupEntityDB;
  101. readonly Dictionary<Type, FasterDictionary<int, ITypeSafeDictionary>> _groupedGroups; //yes I am being sarcastic
  102. readonly DoubleBufferedEntitiesToAdd<FasterDictionary<int, Dictionary<Type, ITypeSafeDictionary>>> _groupedEntityToAdd;
  103. readonly EntitySubmissionScheduler _scheduler;
  104. readonly FasterList<EntitySubmitOperation> _entitiesOperations;
  105. }
  106. }