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.

125 lines
5.0KB

  1. using System;
  2. using System.Collections.Generic;
  3. using Svelto.DataStructures;
  4. using Svelto.ECS.Internal;
  5. using Svelto.Utilities;
  6. namespace Svelto.ECS
  7. {
  8. #if DEBUG && !PROFILER
  9. struct ECSTuple<T1, T2>
  10. {
  11. public readonly T1 implementorType;
  12. public T2 numberOfImplementations;
  13. public ECSTuple(T1 implementor, T2 v)
  14. {
  15. implementorType = implementor;
  16. numberOfImplementations = v;
  17. }
  18. }
  19. #endif
  20. static class EntityViewUtility
  21. {
  22. public static void FillEntityView<T>(this IEntityBuilder entityBuilder
  23. , ref T entityView
  24. , FasterList<KeyValuePair<Type, ActionCast<T>>>
  25. entityViewBlazingFastReflection
  26. , IEnumerable<object> implementors,
  27. #if DEBUG && !PROFILER
  28. Dictionary<Type, ECSTuple<object, int>> implementorsByType
  29. #else
  30. Dictionary<Type, object> implementorsByType
  31. #endif
  32. , Dictionary<Type, Type[]> cachedTypes
  33. )
  34. {
  35. //efficient way to collect the fields of every EntityViewType
  36. var setters =
  37. FasterList<KeyValuePair<Type, ActionCast<T>>>.NoVirt.ToArrayFast(entityViewBlazingFastReflection, out var count);
  38. foreach (var implementor in implementors)
  39. {
  40. if (implementor != null)
  41. {
  42. var type = implementor.GetType();
  43. if (cachedTypes.TryGetValue(type, out var interfaces) == false)
  44. interfaces = cachedTypes[type] = type.GetInterfacesEx();
  45. for (var iindex = 0; iindex < interfaces.Length; iindex++)
  46. {
  47. var componentType = interfaces[iindex];
  48. #if DEBUG && !PROFILER
  49. if (implementorsByType.TryGetValue(componentType, out var implementorData))
  50. {
  51. implementorData.numberOfImplementations++;
  52. implementorsByType[componentType] = implementorData;
  53. }
  54. else
  55. implementorsByType[componentType] = new ECSTuple<object, int>(implementor, 1);
  56. #else
  57. implementorsByType[componentType] = implementor;
  58. #endif
  59. }
  60. }
  61. #if DEBUG && !PROFILER
  62. else
  63. {
  64. Console.Log(NULL_IMPLEMENTOR_ERROR.FastConcat(" entityView ",
  65. entityBuilder.GetEntityType().ToString()));
  66. }
  67. #endif
  68. }
  69. for (var i = 0; i < count; i++)
  70. {
  71. var fieldSetter = setters[i];
  72. var fieldType = fieldSetter.Key;
  73. #if DEBUG && !PROFILER
  74. ECSTuple<object, int> component;
  75. #else
  76. object component;
  77. #endif
  78. if (implementorsByType.TryGetValue(fieldType, out component) == false)
  79. {
  80. var e = new ECSException(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name +
  81. " - EntityView: " + entityBuilder.GetEntityType().Name);
  82. throw e;
  83. }
  84. #if DEBUG && !PROFILER
  85. if (component.numberOfImplementations > 1)
  86. throw new ECSException(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat(
  87. "Component Type: ", fieldType.Name,
  88. " implementor: ",
  89. component.implementorType
  90. .ToString()) +
  91. " - EntityView: " +
  92. entityBuilder.GetEntityType().Name);
  93. #endif
  94. #if DEBUG && !PROFILER
  95. fieldSetter.Value(ref entityView, component.implementorType);
  96. #else
  97. fieldSetter.Value(ref entityView, component);
  98. #endif
  99. }
  100. implementorsByType.Clear();
  101. }
  102. const string DUPLICATE_IMPLEMENTOR_ERROR =
  103. "<color=teal>Svelto.ECS</color> the same component is implemented with more than one implementor. This is " +
  104. "considered an error and MUST be fixed. ";
  105. const string NULL_IMPLEMENTOR_ERROR =
  106. "<color=teal>Svelto.ECS</color> Null implementor, please be careful about the implementors passed to avoid " +
  107. "performance loss ";
  108. const string NOT_FOUND_EXCEPTION = "<color=teal>Svelto.ECS</color> Implementor not found for an EntityView. ";
  109. }
  110. }