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.

144 lines
6.0KB

  1. using System;
  2. using System.Collections.Generic;
  3. using Svelto.DataStructures;
  4. using Svelto.ECS.Internal;
  5. using Svelto.ECS.Schedulers;
  6. namespace Svelto.ECS
  7. {
  8. public partial class EnginesRoot
  9. {
  10. public struct EntitiesSubmitter
  11. {
  12. public EntitiesSubmitter(EnginesRoot enginesRoot)
  13. {
  14. _weakReference = new DataStructures.WeakReference<EnginesRoot>(enginesRoot);
  15. }
  16. public void Invoke()
  17. {
  18. if (_weakReference.IsValid)
  19. _weakReference.Target.SubmitEntityViews();
  20. }
  21. readonly DataStructures.WeakReference<EnginesRoot> _weakReference;
  22. }
  23. /// <summary>
  24. /// Engines root contextualize your engines and entities. You don't need to limit yourself to one EngineRoot
  25. /// as multiple engines root could promote separation of scopes. The EntitySubmissionScheduler checks
  26. /// periodically if new entity must be submitted to the database and the engines. It's an external
  27. /// dependencies to be independent by the running platform as the user can define it.
  28. /// The EntitySubmissionScheduler cannot hold an EnginesRoot reference, that's why
  29. /// it must receive a weak reference of the EnginesRoot callback.
  30. /// </summary>
  31. public EnginesRoot(IEntitySubmissionScheduler entityViewScheduler)
  32. {
  33. _entitiesOperations = new FasterDictionary<ulong, EntitySubmitOperation>();
  34. serializationDescriptorMap = new SerializationDescriptorMap();
  35. _reactiveEnginesAddRemove = new FasterDictionary<RefWrapper<Type>, FasterList<IEngine>>();
  36. _reactiveEnginesSwap = new FasterDictionary<RefWrapper<Type>, FasterList<IEngine>>();
  37. _enginesSet = new FasterList<IEngine>();
  38. _enginesTypeSet = new HashSet<Type>();
  39. _disposableEngines = new FasterList<IDisposable>();
  40. _transientEntitiesOperations = new FasterList<EntitySubmitOperation>();
  41. _groupEntityViewsDB = new FasterDictionary<uint, FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary>>();
  42. _groupsPerEntity = new FasterDictionary<RefWrapper<Type>, FasterDictionary<uint, ITypeSafeDictionary>>();
  43. _groupedEntityToAdd = new DoubleBufferedEntitiesToAdd();
  44. _entitiesStream = new EntitiesStream();
  45. _entitiesDB = new EntitiesDB(_groupEntityViewsDB, _groupsPerEntity, _entitiesStream);
  46. _scheduler = entityViewScheduler;
  47. _scheduler.onTick = new EntitiesSubmitter(this);
  48. }
  49. public EnginesRoot(IEntitySubmissionScheduler entityViewScheduler, bool isDeserializationOnly):this(entityViewScheduler)
  50. {
  51. _isDeserializationOnly = isDeserializationOnly;
  52. }
  53. public void AddEngine(IEngine engine)
  54. {
  55. var type = engine.GetType();
  56. var refWrapper = new RefWrapper<Type>(type);
  57. DBC.ECS.Check.Require(
  58. _enginesTypeSet.Contains(refWrapper) == false ||
  59. type.ContainsCustomAttribute(typeof(AllowMultipleAttribute)) == true,
  60. "The same engine has been added more than once, if intentional, use [AllowMultiple] class attribute "
  61. .FastConcat(engine.ToString()));
  62. try
  63. {
  64. if (engine is IReactOnAddAndRemove viewEngine)
  65. CheckEntityViewsEngine(viewEngine, _reactiveEnginesAddRemove);
  66. if (engine is IReactOnSwap viewEngineSwap)
  67. CheckEntityViewsEngine(viewEngineSwap, _reactiveEnginesSwap);
  68. _enginesTypeSet.Add(refWrapper);
  69. _enginesSet.Add(engine);
  70. if (engine is IDisposable)
  71. _disposableEngines.Add(engine as IDisposable);
  72. if (engine is IQueryingEntitiesEngine queryableEntityViewEngine)
  73. {
  74. queryableEntityViewEngine.entitiesDB = _entitiesDB;
  75. queryableEntityViewEngine.Ready();
  76. }
  77. }
  78. catch (Exception e)
  79. {
  80. throw new ECSException("Code crashed while adding engine ".FastConcat(engine.GetType().ToString(), " "), e);
  81. }
  82. }
  83. void CheckEntityViewsEngine<T>(T engine, FasterDictionary<RefWrapper<Type>, FasterList<IEngine>> engines)
  84. where T : class, IEngine
  85. {
  86. var interfaces = engine.GetType().GetInterfaces();
  87. foreach (var interf in interfaces)
  88. {
  89. if (interf.IsGenericTypeEx() && typeof(T).IsAssignableFrom(interf))
  90. {
  91. var genericArguments = interf.GetGenericArgumentsEx();
  92. AddEngine(engine, genericArguments, engines);
  93. }
  94. }
  95. }
  96. static void AddEngine<T>(T engine, Type[] entityViewTypes,
  97. FasterDictionary<RefWrapper<Type>, FasterList<IEngine>> engines)
  98. where T : class, IEngine
  99. {
  100. for (var i = 0; i < entityViewTypes.Length; i++)
  101. {
  102. var type = entityViewTypes[i];
  103. AddEngine(engine, engines, type);
  104. }
  105. }
  106. static void AddEngine<T>(T engine, FasterDictionary<RefWrapper<Type>, FasterList<IEngine>> engines, Type type)
  107. where T : class, IEngine
  108. {
  109. if (engines.TryGetValue(new RefWrapper<Type>(type), out var list) == false)
  110. {
  111. list = new FasterList<IEngine>();
  112. engines.Add(new RefWrapper<Type>(type), list);
  113. }
  114. list.Add(engine);
  115. }
  116. readonly FasterDictionary<RefWrapper<Type>, FasterList<IEngine>> _reactiveEnginesAddRemove;
  117. readonly FasterDictionary<RefWrapper<Type>, FasterList<IEngine>> _reactiveEnginesSwap;
  118. readonly FasterList<IDisposable> _disposableEngines;
  119. readonly FasterList<IEngine> _enginesSet;
  120. readonly HashSet<Type> _enginesTypeSet;
  121. }
  122. }