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.

131 lines
5.3KB

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