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.

97 lines
3.8KB

  1. using System;
  2. using System.Collections.Generic;
  3. using Svelto.DataStructures;
  4. namespace Svelto.ECS.Internal
  5. {
  6. static class EntityFactory
  7. {
  8. public static FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary> BuildGroupedEntities(EGID egid,
  9. EnginesRoot.DoubleBufferedEntitiesToAdd groupEntitiesToAdd,
  10. IEntityBuilder[] entitiesToBuild,
  11. IEnumerable<object> implementors)
  12. {
  13. var group = FetchEntityGroup(egid.groupID, groupEntitiesToAdd);
  14. BuildEntitiesAndAddToGroup(egid, group, entitiesToBuild, implementors);
  15. return group;
  16. }
  17. static FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary> FetchEntityGroup(uint groupID,
  18. EnginesRoot.DoubleBufferedEntitiesToAdd groupEntityViewsByType)
  19. {
  20. if (groupEntityViewsByType.current.TryGetValue(groupID, out var group) == false)
  21. {
  22. group = new FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary>();
  23. groupEntityViewsByType.current.Add(groupID, group);
  24. }
  25. if (groupEntityViewsByType.currentEntitiesCreatedPerGroup.TryGetValue(groupID, out var value) == false)
  26. groupEntityViewsByType.currentEntitiesCreatedPerGroup[groupID] = 0;
  27. else
  28. groupEntityViewsByType.currentEntitiesCreatedPerGroup[groupID] = value+1;
  29. return group;
  30. }
  31. static void BuildEntitiesAndAddToGroup(EGID entityID,
  32. FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary> group,
  33. IEntityBuilder[] entityBuilders, IEnumerable<object> implementors)
  34. {
  35. #if DEBUG && !PROFILER
  36. HashSet<Type> types = new HashSet<Type>();
  37. #endif
  38. InternalBuild(entityID, group, entityBuilders, implementors
  39. #if DEBUG && !PROFILER
  40. , types
  41. #endif
  42. );
  43. }
  44. static void InternalBuild(EGID entityID, FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary> group,
  45. IEntityBuilder[] entityBuilders, IEnumerable<object> implementors
  46. #if DEBUG && !PROFILER
  47. , HashSet<Type> types
  48. #endif
  49. )
  50. {
  51. var count = entityBuilders.Length;
  52. #if DEBUG && !PROFILER
  53. for (var index = 0; index < count; ++index)
  54. {
  55. var entityViewType = entityBuilders[index].GetEntityType();
  56. if (types.Contains(entityViewType))
  57. {
  58. throw new ECSException("EntityBuilders must be unique inside an EntityDescriptor");
  59. }
  60. types.Add(entityViewType);
  61. }
  62. #endif
  63. for (var index = 0; index < count; ++index)
  64. {
  65. var entityStructBuilder = entityBuilders[index];
  66. var entityViewType = entityStructBuilder.GetEntityType();
  67. BuildEntity(entityID, group, entityViewType, entityStructBuilder, implementors);
  68. }
  69. }
  70. static void BuildEntity(EGID entityID, FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary> group,
  71. Type entityViewType, IEntityBuilder entityBuilder, IEnumerable<object> implementors)
  72. {
  73. var entityViewsPoolWillBeCreated =
  74. group.TryGetValue(new RefWrapper<Type>(entityViewType), out var safeDictionary) == false;
  75. //passing the undefined entityViewsByType inside the entityViewBuilder will allow it to be created with the
  76. //correct type and casted back to the undefined list. that's how the list will be eventually of the target
  77. //type.
  78. entityBuilder.BuildEntityAndAddToList(ref safeDictionary, entityID, implementors);
  79. if (entityViewsPoolWillBeCreated)
  80. group.Add(new RefWrapper<Type>(entityViewType), safeDictionary);
  81. }
  82. }
  83. }