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.

132 lines
4.5KB

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace Svelto.ECS
  5. {
  6. public class Steps
  7. {
  8. internal readonly Dictionary<IEngine, To> _steps;
  9. public Steps(params Step[] values)
  10. {
  11. _steps = new Dictionary<IEngine, To>();
  12. for (var i = 0; i < values.Length; i++)
  13. _steps.Add(values[i].from, values[i].to);
  14. }
  15. }
  16. public class To
  17. {
  18. public To(IStep engine)
  19. {
  20. this.engine = engine;
  21. }
  22. public To(params IStep[] engines)
  23. {
  24. this.engines = engines;
  25. }
  26. public IStep engine { get; set; }
  27. public IStep[] engines { get; set; }
  28. }
  29. public class To<C>:To, IEnumerable where C : struct, IConvertible
  30. {
  31. internal readonly Dictionary<C, IStep<C>[]> _tos = new Dictionary<C, IStep<C>[]>();
  32. public IEnumerator GetEnumerator()
  33. {
  34. throw new NotImplementedException();
  35. }
  36. public void Add(C condition, params IStep<C>[] engine)
  37. {
  38. _tos[condition] = engine;
  39. }
  40. }
  41. public interface IStep
  42. {
  43. void Step(EGID id);
  44. }
  45. public interface IStep<in C> where C:struct,IConvertible
  46. {
  47. void Step(C condition, EGID id);
  48. }
  49. public struct Step
  50. {
  51. public IEngine from { get; set; }
  52. public To to { get; set; }
  53. }
  54. /// <summary>
  55. /// The sequencer has just one goal: define a complex sequence of engines to call. The sequence is not
  56. /// just "sequential", but can create branches and loops.
  57. /// With the time, I figure out that the majority of the times this class is useful in the rare cases where
  58. /// order execution of the engine is necessary/
  59. /// Using branching is even rarer, but still useful sometimes.
  60. /// I used loops only once.
  61. /// There is the chance that this class will become obsolete over the time, as by design engines should
  62. /// never rely on the order of execution
  63. /// Using this class to let engines from different EnginesRoot communicate will also become obsolete, as
  64. /// better solution will be implemented once I have the time
  65. /// Trying to work out how to initialize this structure can be painful. This is by design as this class must
  66. /// be initialized using the following pattern:
  67. /// instancedSequence.SetSequence(
  68. /// new Steps //list of steps
  69. /// (
  70. /// new Step // first step
  71. /// {
  72. /// from = menuOptionEnablerEngine, //starting engine
  73. /// to = new To<ItemActionsPanelEnableCondition> //targets
  74. /// {
  75. /// {
  76. /// ItemActionsPanelEnableCondition.Enable, //condition 1
  77. /// menuPanelEnablerEngine //targets for condition 1
  78. /// },
  79. /// {
  80. /// ItemActionsPanelEnableCondition.Disable,//condition 2
  81. /// menuPanelEnablerEngine //targets for condition 2
  82. /// }
  83. /// }
  84. /// })
  85. /// );
  86. /// </summary>
  87. public class Sequencer<S> where S: Sequencer<S>, new()
  88. {
  89. public void SetSequence(Steps steps)
  90. {
  91. _steps = steps;
  92. }
  93. public void Next<C>(IEngine engine, C condition, EGID id) where C:struct, IConvertible
  94. {
  95. var branch = condition;
  96. var to = (_steps._steps[engine] as To<C>);
  97. var steps = to._tos[branch];
  98. for (var i = 0; i < steps.Length; i++)
  99. steps[i].Step(condition, id);
  100. }
  101. public void Next(IEngine engine, EGID id)
  102. {
  103. var to = _steps._steps[engine];
  104. var steps = to.engines;
  105. if (steps != null && steps.Length > 1)
  106. for (var i = 0; i < steps.Length; i++)
  107. steps[i].Step(id);
  108. else
  109. to.engine.Step(id);
  110. }
  111. Steps _steps;
  112. }
  113. }