Mirror of Svelto.ECS because we're a fan of it
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

117 linhas
4.9KB

  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 && !PROFILE_SVELTO
  9. struct ECSTuple<T1, T2>
  10. {
  11. public readonly T1 instance;
  12. public T2 numberOfImplementations;
  13. public ECSTuple(T1 implementor, T2 v)
  14. {
  15. instance = implementor;
  16. numberOfImplementations = v;
  17. }
  18. }
  19. #endif
  20. static class EntityComponentUtility
  21. {
  22. const string DUPLICATE_IMPLEMENTOR_ERROR =
  23. "<color=teal>Svelto.ECS</color> the same component is implemented with more than one implementor. This is " +
  24. "considered an error and MUST be fixed. ";
  25. const string NULL_IMPLEMENTOR_ERROR =
  26. "<color=teal>Svelto.ECS</color> Null implementor, please be careful about the implementors passed to avoid " +
  27. "performance loss ";
  28. const string NOT_FOUND_EXCEPTION =
  29. "<color=teal>Svelto.ECS</color> Implementor not found for an EntityComponent. ";
  30. internal static void SetEntityViewComponentImplementors<T>(this IComponentBuilder componentBuilder,
  31. ref T entityComponent, IEnumerable<object> implementors,
  32. ComponentBuilder<T>.EntityViewComponentCache localCache) where T : struct, _IInternalEntityComponent
  33. {
  34. DBC.ECS.Check.Require(implementors != null,
  35. NULL_IMPLEMENTOR_ERROR.FastConcat(" entityComponent ",
  36. componentBuilder.GetEntityComponentType().ToString()));
  37. var cachedTypeInterfaces = localCache.cachedTypes;
  38. var implementorsByType = localCache.implementorsByType;
  39. var entityComponentBlazingFastReflection = localCache.cachedFields;
  40. foreach (var implementor in implementors)
  41. {
  42. DBC.ECS.Check.Require(implementor != null, "invalid null implementor used to build an entity");
  43. {
  44. var type = implementor.GetType();
  45. //fetch all the interfaces that the implementor implements
  46. if (cachedTypeInterfaces.TryGetValue(type, out var interfaces) == false)
  47. interfaces = cachedTypeInterfaces[type] = type.GetInterfacesEx();
  48. for (var iindex = 0; iindex < interfaces.Length; iindex++)
  49. {
  50. var componentType = interfaces[iindex];
  51. //an implementor can implement multiple interfaces, so for each interface we reference
  52. //the implementation object. Multiple entity view component fields can then be implemented
  53. //by the same implementor
  54. #if DEBUG && !PROFILE_SVELTO
  55. if (implementorsByType.TryGetValue(componentType, out var implementorData))
  56. {
  57. implementorData.numberOfImplementations++;
  58. implementorsByType[componentType] = implementorData;
  59. }
  60. else
  61. implementorsByType[componentType] = new ECSTuple<object, int>(implementor, 1);
  62. #else
  63. implementorsByType[componentType] = implementor;
  64. #endif
  65. }
  66. }
  67. }
  68. //efficient way to collect the fields of every EntityComponentType
  69. var setters = FasterList<KeyValuePair<Type, FastInvokeActionCast<T>>>.NoVirt.ToArrayFast(
  70. entityComponentBlazingFastReflection, out var count);
  71. for (var i = 0; i < count; i++)
  72. {
  73. var fieldSetter = setters[i];
  74. var fieldType = fieldSetter.Key;
  75. #if DEBUG && !PROFILE_SVELTO
  76. ECSTuple<object, int> implementor;
  77. #else
  78. object implementor;
  79. #endif
  80. if (implementorsByType.TryGetValue(fieldType, out implementor) == false)
  81. {
  82. var e = new ECSException(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name +
  83. " - EntityComponent: " + componentBuilder.GetEntityComponentType().Name);
  84. throw e;
  85. }
  86. #if DEBUG && !PROFILE_SVELTO
  87. if (implementor.numberOfImplementations > 1)
  88. throw new ECSException(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat(
  89. "Component Type: ", fieldType.Name, " implementor: ", implementor.instance.ToString()) +
  90. " - EntityComponent: " + componentBuilder.GetEntityComponentType().Name);
  91. #endif
  92. #if DEBUG && !PROFILE_SVELTO
  93. fieldSetter.Value(ref entityComponent, implementor.instance);
  94. #else
  95. fieldSetter.Value(ref entityComponent, implementor);
  96. #endif
  97. }
  98. implementorsByType.Clear();
  99. }
  100. }
  101. }