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.

EnginesRoot.cs 28KB

9 years ago
9 years ago
7 years ago
7 years ago
9 years ago
7 years ago
7 years ago
9 years ago
9 years ago
9 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
9 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
9 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  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 sealed class EnginesRoot : IDisposable
  19. {
  20. public EnginesRoot(EntitySubmissionScheduler entityViewScheduler)
  21. {
  22. _entityViewEngines = new Dictionary<Type, FasterList<IHandleEntityViewEngine>>();
  23. _otherEngines = new FasterList<IEngine>();
  24. _entityViewsDB = new Dictionary<Type, ITypeSafeList>();
  25. _metaEntityViewsDB = new Dictionary<Type, ITypeSafeList>();
  26. _groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>();
  27. _entityViewsDBdic = new Dictionary<Type, ITypeSafeDictionary>();
  28. _entityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
  29. _metaEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
  30. _groupedEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>>();
  31. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  32. _addEntityViewToEngine = AddEntityViewToEngine;
  33. _removeEntityViewFromEngine = RemoveEntityViewFromEngine;
  34. #endif
  35. _engineEntityViewDB = new EngineEntityViewDB(_entityViewsDB, _entityViewsDBdic, _metaEntityViewsDB, _groupEntityViewsDB);
  36. _scheduler = entityViewScheduler;
  37. _scheduler.Schedule(new WeakAction(SubmitEntityViews));
  38. #if EXPERIMENTAL
  39. _sharedStructEntityViewLists = new SharedStructEntityViewLists();
  40. _sharedGroupedStructEntityViewLists = new SharedGroupedStructEntityViewsLists();
  41. _structEntityViewEngineType = typeof(IStructEntityViewEngine<>);
  42. _groupedStructEntityViewsEngineType = typeof(IGroupedStructEntityViewsEngine<>);
  43. _implementedInterfaceTypes = new Dictionary<Type, Type[]>();
  44. #endif
  45. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  46. UnityEngine.GameObject debugEngineObject = new UnityEngine.GameObject("Engine Debugger");
  47. debugEngineObject.gameObject.AddComponent<EngineProfilerBehaviour>();
  48. #endif
  49. }
  50. public IEntityFactory GenerateEntityFactory()
  51. {
  52. return new GenericEntityFactory(new DataStructures.WeakReference<EnginesRoot>(this));
  53. }
  54. public IEntityFunctions GenerateEntityFunctions()
  55. {
  56. return new GenericEntityFunctions(new DataStructures.WeakReference<EnginesRoot>(this));
  57. }
  58. void BuildEntity<T>(int entityID, object[] implementors = null) where T:IEntityDescriptor, new()
  59. {
  60. EntityFactory.BuildEntityViews
  61. (entityID, _entityViewsToAdd.current, EntityDescriptorTemplate<T>.Default, implementors);
  62. }
  63. void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptor, object[] implementors = null)
  64. {
  65. EntityFactory.BuildEntityViews
  66. (entityID, _entityViewsToAdd.current, entityDescriptor, implementors);
  67. }
  68. /// <summary>
  69. /// A meta entity is a way to manage a set of entitites that are not easily
  70. /// queriable otherwise. For example you may want to group existing entities
  71. /// by size and type and then use the meta entity entityView to manage the data
  72. /// shared among the single entities of the same type and size. This will
  73. /// prevent the scenario where the coder is forced to parse all the entities to
  74. /// find the ones of the same size and type.
  75. /// Since the entities are managed through the shared entityView, the same
  76. /// shared entityView must be found on the single entities of the same type and size.
  77. /// The shared entityView of the meta entity is then used by engines that are meant
  78. /// to manage a group of entities through a single entityView.
  79. /// The same engine can manage several meta entities entityViews too.
  80. /// The Engine manages the logic of the Meta EntityView data and other engines
  81. /// can read back this data through the normal entity as the shared entityView
  82. /// will be present in their descriptor too.
  83. /// It's a way to control a group of Entities through a entityView only.
  84. /// This set of entities can share exactly the same entityView reference if
  85. /// built through this function. In this way, if you need to set a variable
  86. /// on a group of entities, instead to inject N entityViews and iterate over
  87. /// them to set the same value, you can inject just one entityView, set the value
  88. /// and be sure that the value is shared between entities.
  89. /// </summary>
  90. /// <param name="metaEntityID"></param>
  91. /// <param name="ed"></param>
  92. /// <param name="implementors"></param>
  93. void BuildMetaEntity<T>(int metaEntityID, object[] implementors) where T:IEntityDescriptor, new()
  94. {
  95. EntityFactory.BuildEntityViews(metaEntityID, _entityViewsToAdd.current,
  96. EntityDescriptorTemplate<T>.Default, implementors);
  97. }
  98. /// <summary>
  99. /// Using this function is like building a normal entity, but the entityViews
  100. /// are grouped by groupID to be better processed inside engines and
  101. /// improve cache locality. Only IGroupStructEntityViewWithID entityViews are grouped
  102. /// other entityViews are managed as usual.
  103. /// </summary>
  104. /// <param name="entityID"></param>
  105. /// <param name="groupID"></param>
  106. /// <param name="ed"></param>
  107. /// <param name="implementors"></param>
  108. void BuildEntityInGroup<T>(int entityID, int groupID, object[] implementors = null) where T:IEntityDescriptor, new()
  109. {
  110. EntityFactory.BuildGroupedEntityViews(entityID, groupID,
  111. _groupedEntityViewsToAdd.current,
  112. EntityDescriptorTemplate<T>.Default,
  113. implementors);
  114. }
  115. void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors = null)
  116. {
  117. EntityFactory.BuildGroupedEntityViews(entityID, groupID,
  118. _groupedEntityViewsToAdd.current,
  119. entityDescriptor, implementors);
  120. }
  121. void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo)
  122. {
  123. var removeEntityImplementor = removeInfo as RemoveEntityImplementor;
  124. if (removeEntityImplementor.removeEntityInfo.isInAGroup)
  125. InternalRemove(removeEntityImplementor.removeEntityInfo.descriptor.entityViewsToBuild, entityID, removeEntityImplementor.removeEntityInfo.groupID, _entityViewsDB);
  126. else
  127. InternalRemove(removeEntityImplementor.removeEntityInfo.descriptor.entityViewsToBuild, entityID, _entityViewsDB);
  128. }
  129. void RemoveEntity<T>(int entityID) where T : IEntityDescriptor, new()
  130. {
  131. InternalRemove(EntityDescriptorTemplate<T>.Default.descriptor.entityViewsToBuild, entityID, _entityViewsDB);
  132. }
  133. void RemoveMetaEntity<T>(int metaEntityID) where T : IEntityDescriptor, new()
  134. {
  135. InternalRemove(EntityDescriptorTemplate<T>.Default.descriptor.entityViewsToBuild, metaEntityID, _metaEntityViewsDB);
  136. }
  137. void RemoveEntityFromGroup<T>(int entityID, int groupID) where T : IEntityDescriptor, new()
  138. {
  139. InternalRemove(EntityDescriptorTemplate<T>.Default.descriptor.entityViewsToBuild, entityID, _groupEntityViewsDB[groupID]);
  140. }
  141. void Preallocate<T>(int size) where T : IEntityDescriptor, new()
  142. {
  143. var entityViewsToBuild = EntityDescriptorTemplate<T>.Default.descriptor.entityViewsToBuild;
  144. int count = entityViewsToBuild.Length;
  145. for (int index = 0; index < count; index++)
  146. {
  147. var entityViewBuilder = entityViewsToBuild[index];
  148. var entityViewType = entityViewBuilder.GetEntityViewType();
  149. ITypeSafeList dbList;
  150. if (_entityViewsDB.TryGetValue(entityViewType, out dbList) == false)
  151. _entityViewsDB[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size);
  152. else
  153. dbList.ReserveCapacity(size);
  154. if (_entityViewsToAdd.current.TryGetValue(entityViewType, out dbList) == false)
  155. _entityViewsToAdd.current[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size);
  156. else
  157. dbList.ReserveCapacity(size);
  158. }
  159. }
  160. public void AddEngine(IEngine engine)
  161. {
  162. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  163. Profiler.EngineProfiler.AddEngine(engine);
  164. #endif
  165. var engineType = engine.GetType();
  166. #if EXPERIMENTAL
  167. bool engineAdded;
  168. var implementedInterfaces = engineType.GetInterfaces();
  169. CollectImplementedInterfaces(implementedInterfaces);
  170. engineAdded = CheckSpecialEngine(engine);
  171. #endif
  172. var viewEngine = engine as IHandleEntityViewEngine;
  173. if (viewEngine != null)
  174. CheckEntityViewsEngine(viewEngine, engineType);
  175. else
  176. _otherEngines.Add(engine);
  177. var queryableEntityViewEngine = engine as IQueryingEntityViewEngine;
  178. if (queryableEntityViewEngine != null)
  179. {
  180. queryableEntityViewEngine.entityViewsDB = _engineEntityViewDB;
  181. queryableEntityViewEngine.Ready();
  182. }
  183. }
  184. #if EXPERIMENTAL
  185. void CollectImplementedInterfaces(Type[] implementedInterfaces)
  186. {
  187. _implementedInterfaceTypes.Clear();
  188. var type = typeof(IHandleEntityViewEngine);
  189. for (int index = 0; index < implementedInterfaces.Length; index++)
  190. {
  191. var interfaceType = implementedInterfaces[index];
  192. if (type.IsAssignableFrom(interfaceType) == false)
  193. continue;
  194. if (false == interfaceType.IsGenericTypeEx())
  195. {
  196. continue;
  197. }
  198. var genericTypeDefinition = interfaceType.GetGenericTypeDefinition();
  199. _implementedInterfaceTypes.Add(genericTypeDefinition, interfaceType.GetGenericArguments());
  200. }
  201. }
  202. bool CheckSpecialEngine(IEngine engine)
  203. {
  204. if (_implementedInterfaceTypes.Count == 0) return false;
  205. bool engineAdded = false;
  206. if (_implementedInterfaceTypes.ContainsKey(_structEntityViewEngineType))
  207. {
  208. ((IStructEntityViewEngine)engine).CreateStructEntityViews
  209. (_sharedStructEntityViewLists);
  210. }
  211. if (_implementedInterfaceTypes.ContainsKey(_groupedStructEntityViewsEngineType))
  212. {
  213. ((IGroupedStructEntityViewsEngine)engine).CreateStructEntityViews
  214. (_sharedGroupedStructEntityViewLists);
  215. }
  216. return engineAdded;
  217. }
  218. #endif
  219. void CheckEntityViewsEngine(IEngine engine, Type engineType)
  220. {
  221. var baseType = engineType.GetBaseType();
  222. if (baseType.IsGenericTypeEx())
  223. {
  224. var genericArguments = baseType.GetGenericArguments();
  225. AddEngine(engine as IHandleEntityViewEngine, genericArguments, _entityViewEngines);
  226. #if EXPERIMENTAL
  227. var activableEngine = engine as IHandleActivableEntityEngine;
  228. if (activableEngine != null)
  229. AddEngine(activableEngine, genericArguments, _activableViewEntitiesEngines);
  230. #endif
  231. return;
  232. }
  233. throw new Exception("Not Supported Engine");
  234. }
  235. static void AddEngine<T>(T engine, Type[] types,
  236. Dictionary<Type, FasterList<T>> engines)
  237. {
  238. for (int i = 0; i < types.Length; i++)
  239. {
  240. FasterList<T> list;
  241. var type = types[i];
  242. if (engines.TryGetValue(type, out list) == false)
  243. {
  244. list = new FasterList<T>();
  245. engines.Add(type, list);
  246. }
  247. list.Add(engine);
  248. }
  249. }
  250. void AddEntityViewsToTheDBAndSuitableEngines(Dictionary<Type, ITypeSafeList> entityViewsToAdd,
  251. Dictionary<Type, ITypeSafeList> entityViewsDB)
  252. {
  253. foreach (var entityViewList in entityViewsToAdd)
  254. {
  255. AddEntityViewToDB(entityViewsDB, entityViewList);
  256. if (entityViewList.Value.isQueryiableEntityView)
  257. {
  258. AddEntityViewToEntityViewsDictionary(_entityViewsDBdic, entityViewList.Value, entityViewList.Key);
  259. }
  260. }
  261. foreach (var entityViewList in entityViewsToAdd)
  262. {
  263. if (entityViewList.Value.isQueryiableEntityView)
  264. {
  265. AddEntityViewToTheSuitableEngines(_entityViewEngines, entityViewList.Value,
  266. entityViewList.Key);
  267. }
  268. }
  269. }
  270. void AddGroupEntityViewsToTheDBAndSuitableEngines(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupedEntityViewsToAdd,
  271. Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB,
  272. Dictionary<Type, ITypeSafeList> entityViewsDB)
  273. {
  274. foreach (var group in groupedEntityViewsToAdd)
  275. {
  276. AddEntityViewsToTheDBAndSuitableEngines(group.Value, entityViewsDB);
  277. AddEntityViewsToGroupDB(groupEntityViewsDB, @group);
  278. }
  279. }
  280. static void AddEntityViewsToGroupDB(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB,
  281. KeyValuePair<int, Dictionary<Type, ITypeSafeList>> @group)
  282. {
  283. Dictionary<Type, ITypeSafeList> groupedEntityViewsByType;
  284. if (groupEntityViewsDB.TryGetValue(@group.Key, out groupedEntityViewsByType) == false)
  285. groupedEntityViewsByType = groupEntityViewsDB[@group.Key] = new Dictionary<Type, ITypeSafeList>();
  286. foreach (var entityView in @group.Value)
  287. {
  288. groupedEntityViewsByType.Add(entityView.Key, entityView.Value);
  289. }
  290. }
  291. static void AddEntityViewToDB(Dictionary<Type, ITypeSafeList> entityViewsDB, KeyValuePair<Type, ITypeSafeList> entityViewList)
  292. {
  293. ITypeSafeList dbList;
  294. if (entityViewsDB.TryGetValue(entityViewList.Key, out dbList) == false)
  295. dbList = entityViewsDB[entityViewList.Key] = entityViewList.Value.Create();
  296. dbList.AddRange(entityViewList.Value);
  297. }
  298. static void AddEntityViewToEntityViewsDictionary(Dictionary<Type, ITypeSafeDictionary> entityViewsDBdic,
  299. ITypeSafeList entityViews, Type entityViewType)
  300. {
  301. ITypeSafeDictionary entityViewsDic;
  302. if (entityViewsDBdic.TryGetValue(entityViewType, out entityViewsDic) == false)
  303. entityViewsDic = entityViewsDBdic[entityViewType] = entityViews.CreateIndexedDictionary();
  304. entityViewsDic.FillWithIndexedEntityViews(entityViews);
  305. }
  306. static void AddEntityViewToTheSuitableEngines(Dictionary<Type, FasterList<IHandleEntityViewEngine>> entityViewEngines, ITypeSafeList entityViewsList, Type entityViewType)
  307. {
  308. FasterList<IHandleEntityViewEngine> enginesForEntityView;
  309. if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView))
  310. {
  311. int viewsCount;
  312. var entityViews = entityViewsList.ToArrayFast(out viewsCount);
  313. for (int i = 0; i < viewsCount; i++)
  314. {
  315. int count;
  316. var fastList = FasterList<IHandleEntityViewEngine>.NoVirt.ToArrayFast(enginesForEntityView, out count);
  317. IEntityView entityView = entityViews[i];
  318. for (int j = 0; j < count; j++)
  319. {
  320. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  321. EngineProfiler.MonitorAddDuration(_addEntityViewToEngine, fastList[j], entityView);
  322. #else
  323. fastList[j].Add(entityView);
  324. #endif
  325. }
  326. }
  327. }
  328. }
  329. void InternalRemove(IEntityViewBuilder[] entityViewBuilders, int entityID,
  330. Dictionary<Type, ITypeSafeList> entityViewsDB)
  331. {
  332. int entityViewBuildersCount = entityViewBuilders.Length;
  333. for (int i = 0; i < entityViewBuildersCount; i++)
  334. {
  335. Type entityViewType = entityViewBuilders[i].GetEntityViewType();
  336. ITypeSafeList entityViews = entityViewsDB[entityViewType];
  337. if (entityViews.UnorderedRemove(entityID) == false)
  338. entityViewsDB.Remove(entityViewType);
  339. if (entityViews.isQueryiableEntityView)
  340. {
  341. var typeSafeDictionary = _entityViewsDBdic[entityViewType];
  342. var entityView = typeSafeDictionary.GetIndexedEntityView(entityID);
  343. if (typeSafeDictionary.Remove(entityID) == false)
  344. _entityViewsDBdic.Remove(entityViewType);
  345. RemoveEntityViewFromEngines(_entityViewEngines, entityView, entityViewType);
  346. }
  347. }
  348. }
  349. void InternalRemove(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID,
  350. Dictionary<Type, ITypeSafeList> entityViewsDB)
  351. {
  352. int entityViewBuildersCount = entityViewBuilders.Length;
  353. for (int i = 0; i < entityViewBuildersCount; i++)
  354. {
  355. Type entityViewType = entityViewBuilders[i].GetEntityViewType();
  356. Dictionary<Type, ITypeSafeList> dictionary = _groupEntityViewsDB[groupID];
  357. if (dictionary[entityViewType].UnorderedRemove(entityID) == false)
  358. dictionary.Remove(entityViewType);
  359. if (dictionary.Count == 0) _groupEntityViewsDB.Remove(groupID);
  360. }
  361. InternalRemove(entityViewBuilders, entityID, entityViewsDB);
  362. }
  363. static void RemoveEntityViewFromEngines(Dictionary<Type, FasterList<IHandleEntityViewEngine>> entityViewEngines,
  364. IEntityView entityView, Type entityViewType)
  365. {
  366. FasterList<IHandleEntityViewEngine> enginesForEntityView;
  367. if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView))
  368. {
  369. int count;
  370. var fastList = FasterList<IHandleEntityViewEngine>.NoVirt.ToArrayFast(enginesForEntityView, out count);
  371. for (int j = 0; j < count; j++)
  372. {
  373. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  374. EngineProfiler.MonitorRemoveDuration(_removeEntityViewFromEngine, fastList[j], entityView);
  375. #else
  376. fastList[j].Remove(entityView);
  377. #endif
  378. }
  379. }
  380. }
  381. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  382. static void AddEntityViewToEngine(IHandleEntityViewEngine engine, IEntityView entityView)
  383. {
  384. engine.Add(entityView);
  385. }
  386. static void RemoveEntityViewFromEngine(IHandleEntityViewEngine engine, IEntityView entityView)
  387. {
  388. engine.Remove(entityView);
  389. }
  390. #endif
  391. void SubmitEntityViews()
  392. {
  393. bool newEntityViewsHaveBeenAddedWhileIterating =
  394. _metaEntityViewsToAdd.current.Count > 0
  395. || _entityViewsToAdd.current.Count > 0
  396. || _groupedEntityViewsToAdd.current.Count > 0;
  397. int numberOfReenteringLoops = 0;
  398. while (newEntityViewsHaveBeenAddedWhileIterating)
  399. {
  400. //use other as source from now on
  401. //current will be use to write new entityViews
  402. _entityViewsToAdd.Swap();
  403. _metaEntityViewsToAdd.Swap();
  404. _groupedEntityViewsToAdd.Swap();
  405. if ( _entityViewsToAdd.other.Count > 0)
  406. AddEntityViewsToTheDBAndSuitableEngines(_entityViewsToAdd.other, _entityViewsDB);
  407. if ( _metaEntityViewsToAdd.other.Count > 0)
  408. AddEntityViewsToTheDBAndSuitableEngines(_metaEntityViewsToAdd.other, _metaEntityViewsDB);
  409. if (_groupedEntityViewsToAdd.other.Count > 0)
  410. AddGroupEntityViewsToTheDBAndSuitableEngines(_groupedEntityViewsToAdd.other, _groupEntityViewsDB, _entityViewsDB);
  411. //other can be cleared now
  412. _entityViewsToAdd.other.Clear();
  413. _metaEntityViewsToAdd.other.Clear();
  414. _groupedEntityViewsToAdd.other.Clear();
  415. //has current new entityViews?
  416. newEntityViewsHaveBeenAddedWhileIterating =
  417. _metaEntityViewsToAdd.current.Count > 0
  418. || _entityViewsToAdd.current.Count > 0
  419. || _groupedEntityViewsToAdd.current.Count > 0;
  420. if (numberOfReenteringLoops > 5)
  421. throw new Exception("possible infinite loop found creating Entities inside IEntityViewsEngine Add method, please consider building entities outside IEntityViewsEngine Add method");
  422. numberOfReenteringLoops++;
  423. }
  424. }
  425. readonly Dictionary<Type, FasterList<IHandleEntityViewEngine>> _entityViewEngines;
  426. readonly FasterList<IEngine> _otherEngines;
  427. readonly Dictionary<Type, ITypeSafeList> _entityViewsDB;
  428. readonly Dictionary<Type, ITypeSafeList> _metaEntityViewsDB;
  429. readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB;
  430. readonly Dictionary<Type, ITypeSafeDictionary> _entityViewsDBdic;
  431. readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _entityViewsToAdd;
  432. readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _metaEntityViewsToAdd;
  433. readonly DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>> _groupedEntityViewsToAdd;
  434. readonly EntitySubmissionScheduler _scheduler;
  435. #if EXPERIMENTAL
  436. readonly Type _structEntityViewEngineType;
  437. readonly Type _groupedStructEntityViewsEngineType;
  438. readonly SharedStructEntityViewLists _sharedStructEntityViewLists;
  439. readonly SharedGroupedStructEntityViewsLists _sharedGroupedStructEntityViewLists;
  440. readonly Dictionary<Type, Type[]> _implementedInterfaceTypes;
  441. #endif
  442. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  443. static Action<IHandleEntityViewEngine, IEntityView> _addEntityViewToEngine;
  444. static Action<IHandleEntityViewEngine, IEntityView> _removeEntityViewFromEngine;
  445. #endif
  446. readonly EngineEntityViewDB _engineEntityViewDB;
  447. class DoubleBufferedEntityViews<T> where T : class, IDictionary, new()
  448. {
  449. readonly T _entityViewsToAddBufferA = new T();
  450. readonly T _entityViewsToAddBufferB = new T();
  451. public DoubleBufferedEntityViews()
  452. {
  453. this.other = _entityViewsToAddBufferA;
  454. this.current = _entityViewsToAddBufferB;
  455. }
  456. public T other { get; private set; }
  457. public T current { get; private set; }
  458. public void Swap()
  459. {
  460. var toSwap = other;
  461. other = current;
  462. current = toSwap;
  463. }
  464. }
  465. class GenericEntityFactory : IEntityFactory
  466. {
  467. DataStructures.WeakReference<EnginesRoot> _weakEngine;
  468. public GenericEntityFactory(DataStructures.WeakReference<EnginesRoot> weakReference)
  469. {
  470. _weakEngine = weakReference;
  471. }
  472. public void BuildEntity<T>(int entityID, object[] implementors = null) where T : IEntityDescriptor, new()
  473. {
  474. _weakEngine.Target.BuildEntity<T>(entityID, implementors);
  475. }
  476. public void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptor, object[] implementors = null)
  477. {
  478. _weakEngine.Target.BuildEntity(entityID, entityDescriptor, implementors);
  479. }
  480. public void BuildMetaEntity<T>(int metaEntityID, object[] implementors = null) where T : IEntityDescriptor, new()
  481. {
  482. _weakEngine.Target.BuildMetaEntity<T>(metaEntityID, implementors);
  483. }
  484. public void BuildEntityInGroup<T>(int entityID, int groupID, object[] implementors = null) where T : IEntityDescriptor, new()
  485. {
  486. _weakEngine.Target.BuildEntityInGroup<T>(entityID, groupID, implementors);
  487. }
  488. public void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors = null)
  489. {
  490. _weakEngine.Target.BuildEntityInGroup(entityID, groupID, entityDescriptor, implementors);
  491. }
  492. public void Preallocate<T>(int size) where T : IEntityDescriptor, new()
  493. {
  494. _weakEngine.Target.Preallocate<T>(size);
  495. }
  496. }
  497. class GenericEntityFunctions : IEntityFunctions
  498. {
  499. public GenericEntityFunctions(DataStructures.WeakReference<EnginesRoot> weakReference)
  500. {
  501. _weakReference = weakReference;
  502. }
  503. public void RemoveEntity(int entityID, IRemoveEntityComponent entityTemplate)
  504. {
  505. _weakReference.Target.RemoveEntity(entityID, entityTemplate);
  506. }
  507. public void RemoveEntity<T>(int entityID) where T : IEntityDescriptor, new()
  508. {
  509. _weakReference.Target.RemoveEntity<T>(entityID);
  510. }
  511. public void RemoveMetaEntity<T>(int metaEntityID) where T : IEntityDescriptor, new()
  512. {
  513. _weakReference.Target.RemoveEntity<T>(metaEntityID);
  514. }
  515. public void RemoveEntityFromGroup<T>(int entityID, int groupID) where T : IEntityDescriptor, new()
  516. {
  517. _weakReference.Target.RemoveEntity<T>(entityID);
  518. }
  519. readonly DataStructures.WeakReference<EnginesRoot> _weakReference;
  520. }
  521. public void Dispose()
  522. {
  523. foreach (var entity in _entityViewsDB)
  524. {
  525. if (entity.Value.isQueryiableEntityView == true)
  526. {
  527. foreach (var entityView in entity.Value)
  528. {
  529. RemoveEntityViewFromEngines(_entityViewEngines, entityView as EntityView, entity.Key);
  530. }
  531. }
  532. }
  533. foreach (var entity in _metaEntityViewsDB)
  534. {
  535. foreach (var entityView in entity.Value)
  536. {
  537. RemoveEntityViewFromEngines(_entityViewEngines, entityView as EntityView, entity.Key);
  538. }
  539. }
  540. }
  541. }
  542. }