StateStack.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #include "StateStack.hpp"
  2. #include <cassert>
  3. namespace FreeShop {
  4. StateStack::StateStack(State::Context context)
  5. : m_stack()
  6. , m_pendingList()
  7. , m_context(context)
  8. , m_factories()
  9. {
  10. }
  11. void StateStack::update(float delta)
  12. {
  13. // Iterate from top to bottom, stop as soon as update() returns false
  14. for (auto itr = m_stack.rbegin(); itr != m_stack.rend(); ++itr)
  15. {
  16. if (!itr->pointer->update(delta))
  17. break;
  18. }
  19. applyPendingChanges();
  20. }
  21. void StateStack::renderTopScreen(cpp3ds::Window &window)
  22. {
  23. // Draw all active states from bottom to top
  24. for(const StateStackItem& state : m_stack)
  25. if (state.renderEnabled)
  26. state.pointer->renderTopScreen(window);
  27. }
  28. void StateStack::renderBottomScreen(cpp3ds::Window &window)
  29. {
  30. // Draw all active states from bottom to top
  31. for(const StateStackItem& state : m_stack)
  32. if (state.renderEnabled)
  33. state.pointer->renderBottomScreen(window);
  34. }
  35. void StateStack::processEvent(const cpp3ds::Event& event)
  36. {
  37. // Iterate from top to bottom, stop as soon as handleEvent() returns false
  38. for (auto itr = m_stack.rbegin(); itr != m_stack.rend(); ++itr)
  39. {
  40. if (!itr->pointer->processEvent(event))
  41. break;
  42. }
  43. applyPendingChanges();
  44. }
  45. void StateStack::pushState(States::ID stateID, bool renderAlone, StateCallback callback)
  46. {
  47. m_pendingList.push_back(PendingChange(Push, stateID, renderAlone, callback));
  48. }
  49. void StateStack::popState()
  50. {
  51. m_pendingList.push_back(PendingChange(Pop));
  52. }
  53. void StateStack::clearStates()
  54. {
  55. m_pendingList.push_back(PendingChange(Clear));
  56. }
  57. void StateStack::clearStatesUnder()
  58. {
  59. m_pendingList.push_back(PendingChange(ClearUnder));
  60. }
  61. bool StateStack::isEmpty() const
  62. {
  63. return m_stack.empty();
  64. }
  65. State::Ptr StateStack::createState(States::ID stateID, StateCallback callback)
  66. {
  67. auto found = m_factories.find(stateID);
  68. assert(found != m_factories.end());
  69. return found->second(callback);
  70. }
  71. void StateStack::applyPendingChanges()
  72. {
  73. for(const PendingChange& change : m_pendingList)
  74. {
  75. switch (change.action)
  76. {
  77. case Push:
  78. m_stack.push_back({change.stateID, createState(change.stateID, change.callback), change.renderAlone, true});
  79. updateRenderConfig();
  80. break;
  81. case Pop:
  82. m_stack.pop_back();
  83. updateRenderConfig();
  84. break;
  85. case Clear:
  86. m_stack.clear();
  87. break;
  88. case ClearUnder:
  89. if (m_stack.size() > 1)
  90. m_stack.erase(m_stack.begin(), m_stack.end() - 1);
  91. break;
  92. }
  93. }
  94. m_pendingList.clear();
  95. }
  96. void StateStack::updateRenderConfig()
  97. {
  98. bool renderEnabled = true;
  99. for (auto itr = m_stack.rbegin(); itr != m_stack.rend(); ++itr)
  100. {
  101. itr->renderEnabled = renderEnabled;
  102. if (itr->renderAlone)
  103. renderEnabled = false;
  104. }
  105. }
  106. StateStack::PendingChange::PendingChange(Action action, States::ID stateID, bool renderAlone, StateCallback callback)
  107. : action(action)
  108. , stateID(stateID)
  109. , renderAlone(renderAlone)
  110. , callback(callback)
  111. {
  112. }
  113. } // namespace FreeShop