Etterna 0.74.4
Loading...
Searching...
No Matches
MessageManager.h
1#ifndef MessageManager_H
2#define MessageManager_H
3
4#include "LuaManager.h"
5struct lua_State;
6class LuaTable;
7class LuaReference;
8
10enum MessageID
11{
12 Message_CurrentGameChanged,
13 Message_CurrentStyleChanged,
14 Message_PlayModeChanged,
15 Message_CoinsChanged,
16 Message_CurrentSongChanged,
17 Message_CurrentStepsChanged,
18 Message_GameplayLeadInChanged,
19 Message_GameplayModeChanged,
20 Message_EditStepsTypeChanged,
21 Message_EditCourseDifficultyChanged,
22 Message_EditSourceStepsChanged,
23 Message_EditSourceStepsTypeChanged,
24 Message_PreferredStepsTypeChanged,
25 Message_PreferredDifficultyP1Changed,
26 Message_PreferredDifficultyP2Changed,
27 Message_PreferredCourseDifficultyP1Changed,
28 Message_PreferredCourseDifficultyP2Changed,
29 Message_EditCourseEntryIndexChanged,
30 Message_EditLocalProfileIDChanged,
31 Message_NoteCrossed,
32 Message_NoteWillCrossIn400Ms,
33 Message_NoteWillCrossIn800Ms,
34 Message_NoteWillCrossIn1200Ms,
35 Message_CardRemovedP1,
36 Message_CardRemovedP2,
37 Message_BeatCrossed,
38 Message_MenuUpP1,
39 Message_MenuUpP2,
40 Message_MenuDownP1,
41 Message_MenuDownP2,
42 Message_MenuLeftP1,
43 Message_MenuLeftP2,
44 Message_MenuRightP1,
45 Message_MenuRightP2,
46 Message_MenuStartP1,
47 Message_MenuStartP2,
48 Message_MenuSelectionChanged,
49 Message_PlayerJoined,
50 Message_PlayerUnjoined,
51 Message_AutosyncChanged,
52 Message_PreferredSongGroupChanged,
53 Message_PreferredCourseGroupChanged,
54 Message_SortOrderChanged,
55 Message_LessonTry1,
56 Message_LessonTry2,
57 Message_LessonTry3,
58 Message_LessonCleared,
59 Message_LessonFailed,
60 Message_StorageDevicesChanged,
61 Message_AutoJoyMappingApplied,
62 Message_ScreenChanged,
63 Message_SongModified,
64 Message_ScoreMultiplierChangedP1,
65 Message_ScoreMultiplierChangedP2,
66 Message_StarPowerChangedP1,
67 Message_StarPowerChangedP2,
68 Message_CurrentComboChangedP1,
69 Message_CurrentComboChangedP2,
70 Message_StarMeterChangedP1,
71 Message_StarMeterChangedP2,
72 Message_LifeMeterChangedP1,
73 Message_LifeMeterChangedP2,
74 Message_UpdateScreenHeader,
75 Message_LeftClick,
76 Message_RightClick,
77 Message_MiddleClick,
78 Message_MouseWheelUp,
79 Message_MouseWheelDown,
80 Message_ReloadedMetrics,
81 Message_ReloadedScripts,
82 Message_ReloadedOverlayScreens,
83 Message_ReloadedTextures,
84 Message_ReloadedCurrentSong,
85 Message_ReloadedCurrentPack,
86 Message_FavoritesUpdated,
87 Message_PermamirrorUpdated,
88 Message_GoalsUpdated,
89 NUM_MessageID, // leave this at the end
90 MessageID_Invalid
91};
92auto
93MessageIDToString(MessageID m) -> const std::string&;
94
95struct Message
96{
97 explicit Message(const std::string& s);
98 explicit Message(MessageID id);
99 Message(const std::string& s, const LuaReference& params);
100 ~Message();
101
102 void SetName(const std::string& sName) { m_sName = sName; }
103 [[nodiscard]] auto GetName() const -> std::string { return m_sName; }
104
105 [[nodiscard]] auto IsBroadcast() const -> bool { return m_bBroadcast; }
106 void SetBroadcast(const bool b) { m_bBroadcast = b; }
107
108 void PushParamTable(lua_State* L);
109 [[nodiscard]] auto GetParamTable() const -> const LuaReference&;
110 void SetParamTable(const LuaReference& params);
111
112 void GetParamFromStack(lua_State* L, const std::string& sName) const;
113 void SetParamFromStack(lua_State* L, const std::string& sName);
114
115 template<typename T>
116 auto GetParam(const std::string& sName, T& val) const -> bool
117 {
118 Lua* L = LUA->Get();
119 GetParamFromStack(L, sName);
120 bool bRet = LuaHelpers::Pop(L, val);
121 LUA->Release(L);
122 return bRet;
123 }
124
125 template<typename T>
126 void SetParam(const std::string& sName, const T& val)
127 {
128 Lua* L = LUA->Get();
129 LuaHelpers::Push(L, val);
130 SetParamFromStack(L, sName);
131 LUA->Release(L);
132 }
133
134 template<typename T>
135 void SetParam(const std::string& sName, const std::vector<T>& val)
136 {
137 Lua* L = LUA->Get();
138 LuaHelpers::CreateTableFromArray(val, L);
139 SetParamFromStack(L, sName);
140 LUA->Release(L);
141 }
142
143 auto operator==(const std::string& s) const -> bool { return m_sName == s; }
144 auto operator==(const MessageID id) const -> bool
145 {
146 return MessageIDToString(id) == m_sName;
147 }
148
149 private:
150 std::string m_sName;
151 LuaTable* m_pParams;
152 bool m_bBroadcast;
153
154 auto operator=(const Message& rhs) -> Message&; // don't use
155 /* Work around a gcc bug where HandleMessage( Message("Init") ) fails
156 * because the copy ctor is private. The copy ctor is not even used so I
157 * have no idea why it being private is an issue. Also, if the Message
158 * object were constructed implicitly (remove explicit above), it works:
159 * HandleMessage( "Init" ). Leaving this undefined but public changes a
160 * compile time error into a link time error. Hmm.*/
161 public:
162 Message(const Message& rhs); // don't use
163};
164
166{
167 public:
168 virtual ~IMessageSubscriber() = default;
169 virtual void HandleMessage(const Message& msg) = 0;
170 void ClearMessages(const std::string& sMessage = "");
171
172 private:
173 friend class MessageManager;
174};
175
177{
178 public:
179 MessageSubscriber() = default;
181 auto operator=(const MessageSubscriber& cpy) -> MessageSubscriber&;
182
183 //
184 // Messages
185 //
186 void SubscribeToMessage(
187 MessageID message); // will automatically unsubscribe
188 void SubscribeToMessage(
189 const std::string& sMessageName); // will automatically unsubscribe
190
191 void UnsubscribeAll();
192
193 private:
194 std::vector<std::string> m_vsSubscribedTo;
195};
196
199{
200 public:
203
204 static void Subscribe(IMessageSubscriber* pSubscriber,
205 const std::string& sMessage);
206 static void Subscribe(IMessageSubscriber* pSubscriber, MessageID m);
207 static void Unsubscribe(IMessageSubscriber* pSubscriber,
208 const std::string& sMessage);
209 static void Unsubscribe(IMessageSubscriber* pSubscriber, MessageID m);
210 void Broadcast(Message& msg) const;
211 void Broadcast(const std::string& sMessage) const;
212 void Broadcast(MessageID m) const;
213 static auto IsSubscribedToMessage(IMessageSubscriber* pSubscriber,
214 const std::string& sMessage) -> bool;
215
216 static auto IsSubscribedToMessage(IMessageSubscriber* pSubscriber,
217 const MessageID message) -> bool
218 {
219 return IsSubscribedToMessage(pSubscriber, MessageIDToString(message));
220 }
221
222 void SetLogging(bool set) { m_Logging = set; }
223 bool m_Logging;
224
225 // Lua
226 void PushSelf(lua_State* L);
227};
228
229extern MessageManager*
230 MESSAGEMAN; // global and accessible from anywhere in our program
231
232template<class T>
234{
235 MessageID mSendWhenChanged;
236 T val;
237
238 public:
239 explicit BroadcastOnChange(const MessageID m)
240 {
241 val = T();
242 mSendWhenChanged = m;
243 }
244 [[nodiscard]] auto Get() const -> T { return val; }
245 void Set(T t)
246 {
247 val = t;
248 MESSAGEMAN->Broadcast(MessageIDToString(mSendWhenChanged));
249 }
250 operator T() const { return val; }
251 auto operator==(const T& other) const -> bool { return val == other; }
252 auto operator!=(const T& other) const -> bool { return val != other; }
253};
254
256namespace LuaHelpers {
257template<class T>
258void
259Push(lua_State* L, const BroadcastOnChange<T>& Object)
260{
261 LuaHelpers::Push<T>(L, Object.Get());
262}
263}
264
265template<class T>
267{
268 MessageID mSendWhenChanged;
269 T* val;
270
271 public:
272 explicit BroadcastOnChangePtr(const MessageID m)
273 {
274 mSendWhenChanged = m;
275 val = nullptr;
276 }
277 [[nodiscard]] auto Get() const -> T* { return val; }
278 void Set(T* t)
279 {
280 val = t;
281 if (MESSAGEMAN) {
282 MESSAGEMAN->Broadcast(MessageIDToString(mSendWhenChanged));
283 }
284 }
285
286 /* This is only intended to be used for setting temporary values; always
287 * restore the original value when finished, so listeners don't get confused
288 * due to missing a message. */
289 void SetWithoutBroadcast(T* t) { val = t; }
290 operator T*() const { return val; }
291 auto operator->() const -> T* { return val; }
292};
293
294template<class T>
296{
297 MessageID mSendWhenChanged;
298 T* val;
299
300 public:
301 explicit BroadcastOnChangePtrWithSelf(const MessageID m)
302 {
303 mSendWhenChanged = m;
304 val = nullptr;
305 }
306 [[nodiscard]] auto Get() const -> T* { return val; }
307 void Set(T* t)
308 {
309 val = t;
310 if (MESSAGEMAN) {
311 Message msg(MessageIDToString(mSendWhenChanged));
312 msg.SetParam("ptr", t);
313 MESSAGEMAN->Broadcast(msg);
314 }
315 }
316
317 /* This is only intended to be used for setting temporary values; always
318 * restore the original value when finished, so listeners don't get confused
319 * due to missing a message. */
320 void SetWithoutBroadcast(T* t) { val = t; }
321 operator T*() const { return val; }
322 auto operator->() const -> T* { return val; }
323};
324
325#endif
Definition MessageManager.h:296
Definition MessageManager.h:267
Definition MessageManager.h:234
Definition MessageManager.h:166
A self-cleaning Lua reference.
Definition LuaReference.h:10
Definition LuaReference.h:105
Deliver messages to any part of the program as needed.
Definition MessageManager.h:199
Definition MessageManager.h:177
Utilities for working with Lua.
Definition LuaReference.cpp:172
Definition MessageManager.h:96