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.

150 lines
5.6KB

  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.WeakEvents;
  8. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  9. using Svelto.ECS.Profiler;
  10. #endif
  11. namespace Svelto.ECS
  12. {
  13. public partial class EnginesRoot : IDisposable
  14. {
  15. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  16. /// <summary>
  17. /// I still need to find a good solution for this. Need to move somewhere else
  18. /// </summary>
  19. static EnginesRoot()
  20. {
  21. UnityEngine.GameObject debugEngineObject = new UnityEngine.GameObject("Svelto.ECS.Profiler");
  22. debugEngineObject.gameObject.AddComponent<EngineProfilerBehaviour>();
  23. UnityEngine.GameObject.DontDestroyOnLoad(debugEngineObject);
  24. }
  25. #endif
  26. /// <summary>
  27. /// Engines root contextualize your engines and entities. You don't need to limit yourself to one EngineRoot
  28. /// as multiple engines root could promote separation of scopes. The EntitySubmissionScheduler checks
  29. /// periodically if new entity must be submited to the database and the engines. It's an external
  30. /// dependencies to be indipendent by the running platform as the user can define it.
  31. /// The EntitySubmissionScheduler cannot hold an EnginesRoot reference, that's why
  32. /// it must receive a weak reference of the EnginesRoot callback.
  33. /// </summary>
  34. public EnginesRoot(EntitySubmissionScheduler entityViewScheduler)
  35. {
  36. _entityViewEngines = new Dictionary<Type, FasterList<IHandleEntityViewEngine>>();
  37. _otherEngines = new FasterList<IEngine>();
  38. _entityViewsDB = new Dictionary<Type, ITypeSafeList>();
  39. _metaEntityViewsDB = new Dictionary<Type, ITypeSafeList>();
  40. _groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>();
  41. _entityViewsDBDic = new Dictionary<Type, ITypeSafeDictionary>();
  42. _entityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
  43. _metaEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
  44. _groupedEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>>();
  45. _DB = new EntityViewsDB(_entityViewsDB, _entityViewsDBDic, _metaEntityViewsDB, _groupEntityViewsDB);
  46. _scheduler = entityViewScheduler;
  47. _scheduler.Schedule(new WeakAction(SubmitEntityViews));
  48. }
  49. public void AddEngine(IEngine engine)
  50. {
  51. #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
  52. Profiler.EngineProfiler.AddEngine(engine);
  53. #endif
  54. var viewEngine = engine as IHandleEntityViewEngine;
  55. if (viewEngine != null)
  56. CheckEntityViewsEngine(viewEngine);
  57. else
  58. _otherEngines.Add(engine);
  59. var queryableEntityViewEngine = engine as IQueryingEntityViewEngine;
  60. if (queryableEntityViewEngine != null)
  61. {
  62. queryableEntityViewEngine.entityViewsDB = _DB;
  63. queryableEntityViewEngine.Ready();
  64. }
  65. }
  66. void CheckEntityViewsEngine(IEngine engine)
  67. {
  68. var baseType = engine.GetType().GetBaseType();
  69. while (baseType != _object)
  70. {
  71. if (baseType.IsGenericTypeEx())
  72. {
  73. var genericArguments = baseType.GetGenericArgumentsEx();
  74. AddEngine(engine as IHandleEntityViewEngine, genericArguments, _entityViewEngines);
  75. return;
  76. }
  77. baseType = baseType.GetBaseType();
  78. }
  79. throw new ArgumentException("Not Supported Engine " + engine.ToString());
  80. }
  81. //The T parameter allows to pass datastructure sthat not necessarly are
  82. //defined with IEngine, but must be defined with IEngine implementations
  83. static void AddEngine<T>(T engine, Type[] entityViewTypes,
  84. Dictionary<Type, FasterList<T>> engines) where T:IEngine
  85. {
  86. for (int i = 0; i < entityViewTypes.Length; i++)
  87. {
  88. var type = entityViewTypes[i];
  89. AddEngine(engine, engines, type);
  90. }
  91. }
  92. static void AddEngine<T>(T engine, Dictionary<Type, FasterList<T>> engines, Type type) where T : IEngine
  93. {
  94. FasterList<T> list;
  95. if (engines.TryGetValue(type, out list) == false)
  96. {
  97. list = new FasterList<T>();
  98. engines.Add(type, list);
  99. }
  100. list.Add(engine);
  101. }
  102. readonly Dictionary<Type, FasterList<IHandleEntityViewEngine>> _entityViewEngines;
  103. readonly FasterList<IEngine> _otherEngines;
  104. static readonly Type _entityViewType= typeof(EntityView);
  105. static readonly Type _object = typeof(object);
  106. class DoubleBufferedEntityViews<T> where T : class, IDictionary, new()
  107. {
  108. readonly T _entityViewsToAddBufferA = new T();
  109. readonly T _entityViewsToAddBufferB = new T();
  110. internal DoubleBufferedEntityViews()
  111. {
  112. this.other = _entityViewsToAddBufferA;
  113. this.current = _entityViewsToAddBufferB;
  114. }
  115. internal T other;
  116. internal T current;
  117. internal void Swap()
  118. {
  119. var toSwap = other;
  120. other = current;
  121. current = toSwap;
  122. }
  123. }
  124. }
  125. }