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.

EnginesRootEngines.cs 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using Svelto.DataStructures;
  5. using Svelto.ECS.Internal;
  6. using Svelto.ECS.Schedulers;
  7. using Svelto.Utilities;
  8. using Svelto.WeakEvents;
  9. #if EXPERIMENTAL
  10. using Svelto.ECS.Experimental;
  11. using Svelto.ECS.Experimental.Internal;
  12. #endif
  13. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  14. using Svelto.ECS.Profiler;
  15. #endif
  16. namespace Svelto.ECS
  17. {
  18. public partial class EnginesRoot : IDisposable
  19. {
  20. /// <summary>
  21. /// Engines root contextualize your engines and entities. You don't need to limit yourself to one EngineRoot
  22. /// as multiple engines root could promote separation of scopes. The EntitySubmissionScheduler checks
  23. /// periodically if new entity must be submited to the database and the engines. It's an external
  24. /// dependencies to be indipendent by the running platform as the user can define it.
  25. /// The EntitySubmissionScheduler cannot hold an EnginesRoot reference, that's why
  26. /// it must receive a weak reference of the EnginesRoot callback.
  27. /// </summary>
  28. public EnginesRoot(EntitySubmissionScheduler entityViewScheduler)
  29. {
  30. _entityViewEngines = new Dictionary<Type, FasterList<IHandleEntityViewEngine>>();
  31. _otherEngines = new FasterList<IEngine>();
  32. _entityViewsDB = new Dictionary<Type, ITypeSafeList>();
  33. _metaEntityViewsDB = new Dictionary<Type, ITypeSafeList>();
  34. _groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>();
  35. _entityViewsDBdic = new Dictionary<Type, ITypeSafeDictionary>();
  36. _entityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
  37. _metaEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
  38. _groupedEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>>();
  39. _engineEntityViewDB = new EngineEntityViewDB(_entityViewsDB, _entityViewsDBdic, _metaEntityViewsDB, _groupEntityViewsDB);
  40. _scheduler = entityViewScheduler;
  41. _scheduler.Schedule(new WeakAction(SubmitEntityViews));
  42. #if EXPERIMENTAL
  43. _sharedStructEntityViewLists = new SharedStructEntityViewLists();
  44. _sharedGroupedStructEntityViewLists = new SharedGroupedStructEntityViewsLists();
  45. _structEntityViewEngineType = typeof(IStructEntityViewEngine<>);
  46. _groupedStructEntityViewsEngineType = typeof(IGroupedStructEntityViewsEngine<>);
  47. _implementedInterfaceTypes = new Dictionary<Type, Type[]>();
  48. #endif
  49. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  50. _addEntityViewToEngine = AddEntityViewToEngine;
  51. _removeEntityViewFromEngine = RemoveEntityViewFromEngine;
  52. UnityEngine.GameObject debugEngineObject = new UnityEngine.GameObject("Engine Debugger");
  53. debugEngineObject.gameObject.AddComponent<EngineProfilerBehaviour>();
  54. #endif
  55. }
  56. public void AddEngine(IEngine engine)
  57. {
  58. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  59. Profiler.EngineProfiler.AddEngine(engine);
  60. #endif
  61. var engineType = engine.GetType();
  62. #if EXPERIMENTAL
  63. bool engineAdded;
  64. var implementedInterfaces = engineType.GetInterfaces();
  65. CollectImplementedInterfaces(implementedInterfaces);
  66. engineAdded = CheckSpecialEngine(engine);
  67. #endif
  68. var viewEngine = engine as IHandleEntityViewEngine;
  69. if (viewEngine != null)
  70. CheckEntityViewsEngine(viewEngine, engineType);
  71. else
  72. _otherEngines.Add(engine);
  73. var queryableEntityViewEngine = engine as IQueryingEntityViewEngine;
  74. if (queryableEntityViewEngine != null)
  75. {
  76. queryableEntityViewEngine.entityViewsDB = _engineEntityViewDB;
  77. queryableEntityViewEngine.Ready();
  78. }
  79. }
  80. #if EXPERIMENTAL
  81. void CollectImplementedInterfaces(Type[] implementedInterfaces)
  82. {
  83. _implementedInterfaceTypes.Clear();
  84. var type = typeof(IHandleEntityViewEngine);
  85. for (int index = 0; index < implementedInterfaces.Length; index++)
  86. {
  87. var interfaceType = implementedInterfaces[index];
  88. if (type.IsAssignableFrom(interfaceType) == false)
  89. continue;
  90. if (false == interfaceType.IsGenericTypeEx())
  91. {
  92. continue;
  93. }
  94. var genericTypeDefinition = interfaceType.GetGenericTypeDefinition();
  95. _implementedInterfaceTypes.Add(genericTypeDefinition, interfaceType.GetGenericArguments());
  96. }
  97. }
  98. bool CheckSpecialEngine(IEngine engine)
  99. {
  100. if (_implementedInterfaceTypes.Count == 0) return false;
  101. bool engineAdded = false;
  102. if (_implementedInterfaceTypes.ContainsKey(_structEntityViewEngineType))
  103. {
  104. ((IStructEntityViewEngine)engine).CreateStructEntityViews
  105. (_sharedStructEntityViewLists);
  106. }
  107. if (_implementedInterfaceTypes.ContainsKey(_groupedStructEntityViewsEngineType))
  108. {
  109. ((IGroupedStructEntityViewsEngine)engine).CreateStructEntityViews
  110. (_sharedGroupedStructEntityViewLists);
  111. }
  112. return engineAdded;
  113. }
  114. #endif
  115. void CheckEntityViewsEngine(IEngine engine, Type engineType)
  116. {
  117. var baseType = engineType.GetBaseType();
  118. if (baseType.IsGenericTypeEx())
  119. {
  120. var genericArguments = baseType.GetGenericArguments();
  121. AddEngine(engine as IHandleEntityViewEngine, genericArguments, _entityViewEngines);
  122. #if EXPERIMENTAL
  123. var activableEngine = engine as IHandleActivableEntityEngine;
  124. if (activableEngine != null)
  125. AddEngine(activableEngine, genericArguments, _activableViewEntitiesEngines);
  126. #endif
  127. return;
  128. }
  129. throw new Exception("Not Supported Engine");
  130. }
  131. //The T parameter allows to pass datastructure sthat not necessarly are
  132. //defined with IEngine, but must be defined with IEngine implementations
  133. static void AddEngine<T>(T engine, Type[] types,
  134. Dictionary<Type, FasterList<T>> engines) where T:IEngine
  135. {
  136. for (int i = 0; i < types.Length; i++)
  137. {
  138. FasterList<T> list;
  139. var type = types[i];
  140. if (engines.TryGetValue(type, out list) == false)
  141. {
  142. list = new FasterList<T>();
  143. engines.Add(type, list);
  144. }
  145. list.Add(engine);
  146. }
  147. }
  148. readonly Dictionary<Type, FasterList<IHandleEntityViewEngine>> _entityViewEngines;
  149. readonly FasterList<IEngine> _otherEngines;
  150. readonly Dictionary<Type, ITypeSafeList> _entityViewsDB;
  151. readonly Dictionary<Type, ITypeSafeList> _metaEntityViewsDB;
  152. readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB;
  153. readonly Dictionary<Type, ITypeSafeDictionary> _entityViewsDBdic;
  154. readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _entityViewsToAdd;
  155. readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _metaEntityViewsToAdd;
  156. readonly DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>> _groupedEntityViewsToAdd;
  157. readonly EntitySubmissionScheduler _scheduler;
  158. #if EXPERIMENTAL
  159. readonly Type _structEntityViewEngineType;
  160. readonly Type _groupedStructEntityViewsEngineType;
  161. readonly SharedStructEntityViewLists _sharedStructEntityViewLists;
  162. readonly SharedGroupedStructEntityViewsLists _sharedGroupedStructEntityViewLists;
  163. readonly Dictionary<Type, Type[]> _implementedInterfaceTypes;
  164. #endif
  165. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  166. static Action<IHandleEntityViewEngine, IEntityView> _addEntityViewToEngine;
  167. static Action<IHandleEntityViewEngine, IEntityView> _removeEntityViewFromEngine;
  168. #endif
  169. readonly EngineEntityViewDB _engineEntityViewDB;
  170. class DoubleBufferedEntityViews<T> where T : class, IDictionary, new()
  171. {
  172. readonly T _entityViewsToAddBufferA = new T();
  173. readonly T _entityViewsToAddBufferB = new T();
  174. internal DoubleBufferedEntityViews()
  175. {
  176. this.other = _entityViewsToAddBufferA;
  177. this.current = _entityViewsToAddBufferB;
  178. }
  179. internal T other;
  180. internal T current;
  181. internal void Swap()
  182. {
  183. var toSwap = other;
  184. other = current;
  185. current = toSwap;
  186. }
  187. }
  188. }
  189. }