Signal.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #pragma once
  2. #include "Defines.h"
  3. #include <functional>
  4. #include <map>
  5. #include <cstdint>
  6. namespace gameplay
  7. {
  8. /**
  9. * Defines a signal for an event that can be emitted.
  10. *
  11. * Multiple function slots can be registered to any signals
  12. * which are added to classes to represent various event signals.
  13. *
  14. * usage:
  15. *
  16. * // create new signal
  17. * Signal<std::string, uint32_t> signal;
  18. *
  19. * // attach a slot
  20. * signal.connect([](std::string arg1, uint32_t arg2)
  21. * {
  22. * std::cout << arg1 << " " << arg2 << std::endl;
  23. * });
  24. *
  25. * // emit a signal event
  26. * signal.emit("The answer:", 42);
  27. */
  28. template <typename... Args>
  29. class GP_API Signal
  30. {
  31. public:
  32. /**
  33. * Constructor
  34. */
  35. Signal(){};
  36. /**
  37. * Constructor.
  38. */
  39. Signal(Signal const&)
  40. {
  41. }
  42. /**
  43. * Constructor.
  44. */
  45. Signal(Signal&& other) noexcept :
  46. _slots(std::move(other._slots)),
  47. _current_id(other._current_id)
  48. {
  49. }
  50. /**
  51. * Destructor.
  52. */
  53. ~Signal(){};
  54. Signal& operator=(Signal const& other)
  55. {
  56. if (this != &other)
  57. {
  58. disconnect_all();
  59. }
  60. return *this;
  61. }
  62. Signal& operator=(Signal&& other) noexcept
  63. {
  64. if (this != &other)
  65. {
  66. _slots = std::move(other._slots);
  67. _current_id = other._current_id;
  68. }
  69. return *this;
  70. }
  71. /**
  72. * Connects a std::function to the signal.
  73. *
  74. * @param slot The callback function slot.
  75. * @return The slot connection id. It can be used to disconnect the function.
  76. */
  77. uint32_t connect(std::function<void(Args...)> const& slot) const
  78. {
  79. _slots.insert(std::make_pair(++_current_id, slot));
  80. return _current_id;
  81. }
  82. /**
  83. * Connects a member function of an object instance to this Signal.
  84. */
  85. template <typename T>
  86. uint32_t connect_member(T* inst, void (T::* func)(Args...))
  87. {
  88. return connect([=](Args... args)
  89. {
  90. (inst->*func)(args...);
  91. });
  92. }
  93. /**
  94. * Connect a const member function of an object to this Signal.
  95. */
  96. template <typename T>
  97. uint32_t connect_member(T* inst, void (T::* func)(Args...) const)
  98. {
  99. return connect([=](Args... args) { (inst->*func)(args...); });
  100. }
  101. /**
  102. * Disconnects a previously connected function slot.
  103. */
  104. void disconnect(uint32_t id) const
  105. {
  106. _slots.erase(id);
  107. }
  108. /**
  109. * Disconnects all previously connected function slots.
  110. */
  111. void disconnect_all() const
  112. {
  113. _slots.clear();
  114. }
  115. /**
  116. * Emits and calls all connected functions.
  117. */
  118. void emit(Args... p)
  119. {
  120. for (auto const& it : _slots)
  121. {
  122. it.second(p...);
  123. }
  124. }
  125. /**
  126. * Calls only one connected function.
  127. *
  128. * @param id The id of the connected slot function to be called.
  129. */
  130. void emit_for(uint32_t id, Args... p)
  131. {
  132. auto const& it = _slots.find(id);
  133. if (it != _slots.end())
  134. {
  135. it->second(p...);
  136. }
  137. }
  138. /**
  139. * Emits and calls all connected functions except for one.
  140. *
  141. * @param id The connnection id to ignore.
  142. */
  143. void emit_for_all_but_one(uint32_t id, Args... p)
  144. {
  145. for (auto const& it : _slots)
  146. {
  147. if (it.first != id)
  148. {
  149. it.second(p...);
  150. }
  151. }
  152. }
  153. private:
  154. mutable std::map<uint32_t, std::function<void(Args...)>> _slots;
  155. mutable uint32_t _current_id{ 0 };
  156. };
  157. }