Mirror of Svelto.ECS because we're a fan of it
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

185 wiersze
6.4KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using System.Threading;
  5. using DBC.ECS;
  6. using Svelto.Common;
  7. using Svelto.DataStructures;
  8. using Svelto.ECS.Hybrid;
  9. using Svelto.ECS.Internal;
  10. using Svelto.Utilities;
  11. namespace Svelto.ECS
  12. {
  13. struct ComponentBuilderComparer : IEqualityComparer<IComponentBuilder>
  14. {
  15. public bool Equals(IComponentBuilder x, IComponentBuilder y)
  16. {
  17. return x.GetEntityComponentType() == y.GetEntityComponentType();
  18. }
  19. public int GetHashCode(IComponentBuilder obj)
  20. {
  21. return obj.GetEntityComponentType().GetHashCode();
  22. }
  23. }
  24. public class ComponentBuilder<T> : IComponentBuilder where T : struct, _IInternalEntityComponent
  25. {
  26. internal static readonly Type ENTITY_COMPONENT_TYPE;
  27. internal static readonly bool IS_ENTITY_VIEW_COMPONENT;
  28. static readonly string ENTITY_COMPONENT_NAME;
  29. static readonly bool IS_UNMANAGED;
  30. #if SLOW_SVELTO_SUBMISSION
  31. public static readonly bool HAS_EGID;
  32. public static readonly bool HAS_REFERENCE;
  33. #endif
  34. static ComponentBuilder()
  35. {
  36. ENTITY_COMPONENT_TYPE = typeof(T);
  37. IS_ENTITY_VIEW_COMPONENT = typeof(IEntityViewComponent).IsAssignableFrom(ENTITY_COMPONENT_TYPE);
  38. #if SLOW_SVELTO_SUBMISSION
  39. HAS_EGID = typeof(INeedEGID).IsAssignableFrom(ENTITY_COMPONENT_TYPE);
  40. HAS_REFERENCE = typeof(INeedEntityReference).IsAssignableFrom(ENTITY_COMPONENT_TYPE);
  41. SetEGIDWithoutBoxing<T>.Warmup();
  42. #endif
  43. ENTITY_COMPONENT_NAME = ENTITY_COMPONENT_TYPE.ToString();
  44. IS_UNMANAGED = TypeCache<T>.isUnmanaged; //attention this is important as it serves as warm up for Type<T>
  45. #if UNITY_NATIVE
  46. if (IS_UNMANAGED)
  47. EntityComponentIDMap.Register<T>(new Filler<T>());
  48. #endif
  49. ComponentBuilderUtilities.CheckFields(ENTITY_COMPONENT_TYPE, IS_ENTITY_VIEW_COMPONENT);
  50. if (IS_ENTITY_VIEW_COMPONENT)
  51. {
  52. EntityViewComponentCache.InitCache();
  53. }
  54. else
  55. {
  56. if (ENTITY_COMPONENT_TYPE != ComponentBuilderUtilities.ENTITY_INFO_COMPONENT &&
  57. TypeCache<T>.isUnmanaged == false)
  58. throw new Exception(
  59. $"Entity Component check failed, unexpected struct type (must be unmanaged) {ENTITY_COMPONENT_TYPE}");
  60. }
  61. }
  62. public ComponentBuilder()
  63. {
  64. _initializer = default;
  65. }
  66. public ComponentBuilder(in T initializer) : this()
  67. {
  68. _initializer = initializer;
  69. }
  70. public bool isUnmanaged => IS_UNMANAGED;
  71. public ComponentID getComponentID => ComponentTypeID<T>.id;
  72. static readonly ThreadLocal<EntityViewComponentCache> _localCache = new ThreadLocal<EntityViewComponentCache>(() => new EntityViewComponentCache());
  73. public void BuildEntityAndAddToList(ITypeSafeDictionary dictionary, EGID egid, IEnumerable<object> implementors)
  74. {
  75. var castedDic = dictionary as ITypeSafeDictionary<T>;
  76. if (IS_ENTITY_VIEW_COMPONENT)
  77. {
  78. T entityComponent = default;
  79. Check.Require(castedDic.ContainsKey(egid.entityID) == false,
  80. $"building an entity with already used entity id! id: '{(ulong)egid}', {ENTITY_COMPONENT_NAME}");
  81. this.SetEntityViewComponentImplementors(ref entityComponent, implementors, _localCache.Value);
  82. castedDic.Add(egid.entityID, entityComponent);
  83. }
  84. else
  85. {
  86. Check.Require(!castedDic.ContainsKey(egid.entityID),
  87. $"building an entity with already used entity id! id: '{egid.entityID}'");
  88. castedDic.Add(egid.entityID, _initializer);
  89. }
  90. }
  91. void IComponentBuilder.Preallocate(ITypeSafeDictionary dictionary, uint size)
  92. {
  93. Preallocate(dictionary, size);
  94. }
  95. public ITypeSafeDictionary CreateDictionary(uint size)
  96. {
  97. return TypeSafeDictionaryFactory<T>.Create(size);
  98. }
  99. public Type GetEntityComponentType()
  100. {
  101. return ENTITY_COMPONENT_TYPE;
  102. }
  103. public override int GetHashCode()
  104. {
  105. return _initializer.GetHashCode();
  106. }
  107. static void Preallocate(ITypeSafeDictionary dictionary, uint size)
  108. {
  109. dictionary.EnsureCapacity(size);
  110. }
  111. readonly T _initializer;
  112. internal class EntityViewComponentCache
  113. {
  114. internal readonly FasterList<KeyValuePair<Type, FastInvokeActionCast<T>>> cachedFields;
  115. internal readonly Dictionary<Type, Type[]> cachedTypes;
  116. //this is just a local static cache that is cleared after every use
  117. #if DEBUG && !PROFILE_SVELTO
  118. internal readonly Dictionary<Type, ECSTuple<object, int>> implementorsByType;
  119. #else
  120. internal readonly Dictionary<Type, object> implementorsByType;
  121. #endif
  122. internal EntityViewComponentCache()
  123. {
  124. cachedFields = new FasterList<KeyValuePair<Type, FastInvokeActionCast<T>>>();
  125. var type = typeof(T);
  126. var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
  127. for (var i = fields.Length - 1; i >= 0; --i)
  128. {
  129. var field = fields[i];
  130. if (field.FieldType.IsInterface == true)
  131. {
  132. var setter = FastInvoke<T>.MakeSetter(field);
  133. //for each interface, cache the setter for this type
  134. cachedFields.Add(new KeyValuePair<Type, FastInvokeActionCast<T>>(field.FieldType, setter));
  135. }
  136. }
  137. #if DEBUG && !PROFILE_SVELTO
  138. if (fields.Length == 0)
  139. Console.LogWarning($"No fields found in component {type}. Are you declaring only properties?");
  140. #endif
  141. cachedTypes = new Dictionary<Type, Type[]>();
  142. #if DEBUG && !PROFILE_SVELTO
  143. implementorsByType = new Dictionary<Type, ECSTuple<object, int>>();
  144. #else
  145. implementorsByType = new Dictionary<Type, object>();
  146. #endif
  147. }
  148. internal static void InitCache()
  149. {
  150. }
  151. }
  152. }
  153. }