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 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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. UnityEngine.GameObject debugEngineObject = new UnityEngine.GameObject("Engine Debugger");
  51. debugEngineObject.gameObject.AddComponent<EngineProfilerBehaviour>();
  52. #endif
  53. }
  54. public void AddEngine(IEngine engine)
  55. {
  56. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  57. Profiler.EngineProfiler.AddEngine(engine);
  58. #endif
  59. var engineType = engine.GetType();
  60. #if EXPERIMENTAL
  61. bool engineAdded;
  62. var implementedInterfaces = engineType.GetInterfaces();
  63. CollectImplementedInterfaces(implementedInterfaces);
  64. engineAdded = CheckSpecialEngine(engine);
  65. #endif
  66. var viewEngine = engine as IHandleEntityViewEngine;
  67. if (viewEngine != null)
  68. CheckEntityViewsEngine(viewEngine, engineType);
  69. else
  70. _otherEngines.Add(engine);
  71. var queryableEntityViewEngine = engine as IQueryingEntityViewEngine;
  72. if (queryableEntityViewEngine != null)
  73. {
  74. queryableEntityViewEngine.entityViewsDB = _engineEntityViewDB;
  75. queryableEntityViewEngine.Ready();
  76. }
  77. }
  78. #if EXPERIMENTAL
  79. void CollectImplementedInterfaces(Type[] implementedInterfaces)
  80. {
  81. _implementedInterfaceTypes.Clear();
  82. var type = typeof(IHandleEntityViewEngine);
  83. for (int index = 0; index < implementedInterfaces.Length; index++)
  84. {
  85. var interfaceType = implementedInterfaces[index];
  86. if (type.IsAssignableFrom(interfaceType) == false)
  87. continue;
  88. if (false == interfaceType.IsGenericTypeEx())
  89. {
  90. continue;
  91. }
  92. var genericTypeDefinition = interfaceType.GetGenericTypeDefinition();
  93. _implementedInterfaceTypes.Add(genericTypeDefinition, interfaceType.GetGenericArguments());
  94. }
  95. }
  96. bool CheckSpecialEngine(IEngine engine)
  97. {
  98. if (_implementedInterfaceTypes.Count == 0) return false;
  99. bool engineAdded = false;
  100. if (_implementedInterfaceTypes.ContainsKey(_structEntityViewEngineType))
  101. {
  102. ((IStructEntityViewEngine)engine).CreateStructEntityViews
  103. (_sharedStructEntityViewLists);
  104. }
  105. if (_implementedInterfaceTypes.ContainsKey(_groupedStructEntityViewsEngineType))
  106. {
  107. ((IGroupedStructEntityViewsEngine)engine).CreateStructEntityViews
  108. (_sharedGroupedStructEntityViewLists);
  109. }
  110. return engineAdded;
  111. }
  112. #endif
  113. void CheckEntityViewsEngine(IEngine engine, Type engineType)
  114. {
  115. var baseType = engineType.GetBaseType();
  116. if (baseType.IsGenericTypeEx())
  117. {
  118. var genericArguments = baseType.GetGenericArgumentsEx();
  119. AddEngine(engine as IHandleEntityViewEngine, genericArguments, _entityViewEngines);
  120. #if EXPERIMENTAL
  121. var activableEngine = engine as IHandleActivableEntityEngine;
  122. if (activableEngine != null)
  123. AddEngine(activableEngine, genericArguments, _activableViewEntitiesEngines);
  124. #endif
  125. return;
  126. }
  127. throw new Exception("Not Supported Engine");
  128. }
  129. //The T parameter allows to pass datastructure sthat not necessarly are
  130. //defined with IEngine, but must be defined with IEngine implementations
  131. static void AddEngine<T>(T engine, Type[] types,
  132. Dictionary<Type, FasterList<T>> engines) where T:IEngine
  133. {
  134. for (int i = 0; i < types.Length; i++)
  135. {
  136. FasterList<T> list;
  137. var type = types[i];
  138. if (engines.TryGetValue(type, out list) == false)
  139. {
  140. list = new FasterList<T>();
  141. engines.Add(type, list);
  142. }
  143. list.Add(engine);
  144. }
  145. }
  146. readonly Dictionary<Type, FasterList<IHandleEntityViewEngine>> _entityViewEngines;
  147. readonly FasterList<IEngine> _otherEngines;
  148. readonly Dictionary<Type, ITypeSafeList> _entityViewsDB;
  149. readonly Dictionary<Type, ITypeSafeList> _metaEntityViewsDB;
  150. readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB;
  151. readonly Dictionary<Type, ITypeSafeDictionary> _entityViewsDBdic;
  152. readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _entityViewsToAdd;
  153. readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _metaEntityViewsToAdd;
  154. readonly DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>> _groupedEntityViewsToAdd;
  155. readonly EntitySubmissionScheduler _scheduler;
  156. #if EXPERIMENTAL
  157. readonly Type _structEntityViewEngineType;
  158. readonly Type _groupedStructEntityViewsEngineType;
  159. readonly SharedStructEntityViewLists _sharedStructEntityViewLists;
  160. readonly SharedGroupedStructEntityViewsLists _sharedGroupedStructEntityViewLists;
  161. readonly Dictionary<Type, Type[]> _implementedInterfaceTypes;
  162. #endif
  163. readonly EngineEntityViewDB _engineEntityViewDB;
  164. class DoubleBufferedEntityViews<T> where T : class, IDictionary, new()
  165. {
  166. readonly T _entityViewsToAddBufferA = new T();
  167. readonly T _entityViewsToAddBufferB = new T();
  168. internal DoubleBufferedEntityViews()
  169. {
  170. this.other = _entityViewsToAddBufferA;
  171. this.current = _entityViewsToAddBufferB;
  172. }
  173. internal T other;
  174. internal T current;
  175. internal void Swap()
  176. {
  177. var toSwap = other;
  178. other = current;
  179. current = toSwap;
  180. }
  181. }
  182. }
  183. }