1 /**
2 * @file
3 * @todo Remove direct access to nodes
4 */
5
6 /*
7 Copyright (C) 2002-2013 UFO: Alien Invasion.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18 See the GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 */
25
26 #include "../../cl_shared.h"
27 /* UI_InitOptionIteratorAtIndex */
28 #include "../../ui/ui_main.h"
29 #include "../../ui/ui_data.h"
30 #include "cp_campaign.h"
31 #include "cp_messageoptions.h"
32 #include "cp_messageoptions_callbacks.h"
33
34 static msoMenuState_t msoMenuState = MSO_MSTATE_REINIT;
35 static int messageList_size = 0; /**< actual messageSettings list size */
36 static int messageList_scroll = 0; /**< actual messageSettings list begin index due to scrolling */
37 static int visibleMSOEntries = 0; /**< actual visible entry count */
38 messageSettings_t backupMessageSettings[NT_NUM_NOTIFYTYPE]; /**< array holding backup message settings (used for restore function in options popup) */
39
40 /**
41 * @brief Initializes menu texts for scrollable area
42 * @sa MSO_Init_f
43 */
MSO_InitList(void)44 static void MSO_InitList (void)
45 {
46 uiNode_t* messageSetting = nullptr;
47 uiNode_t* lastCategory = nullptr;
48 int idx;
49
50 /* option already allocated, nothing to do */
51 if (cgi->UI_GetOption(TEXT_MESSAGEOPTIONS) != nullptr)
52 return;
53
54 cgi->UI_ResetData(TEXT_MESSAGEOPTIONS);
55 for (idx = 0; idx < ccs.numMsgCategoryEntries; idx++) {
56 const msgCategoryEntry_t* entry = &ccs.msgCategoryEntries[idx];
57 const char* id = va("%d", idx);
58
59 if (entry->isCategory) {
60 lastCategory = cgi->UI_AddOption(&messageSetting, id, va("_%s", entry->notifyType), id);
61 } else {
62 if (!lastCategory)
63 Sys_Error("MSO_InitList: The first entry must be a category");
64 cgi->UI_AddOption(&lastCategory->firstChild, id, va("_%s", entry->notifyType), id);
65 }
66 }
67 cgi->UI_RegisterOption(TEXT_MESSAGEOPTIONS, messageSetting);
68 MSO_SetMenuState(MSO_MSTATE_PREPARED, false, true);
69 }
70
71 /**
72 * @brief Executes confuncs to update visible message options lines.
73 * @sa MSO_Init_f
74 * @todo move this into scripts
75 */
MSO_UpdateVisibleButtons(void)76 static void MSO_UpdateVisibleButtons (void)
77 {
78 int visible;/* current line */
79 uiOptionIterator_t iterator;
80 uiNode_t* messageSetting = cgi->UI_GetOption(TEXT_MESSAGEOPTIONS);
81
82 UI_InitOptionIteratorAtIndex(messageList_scroll, messageSetting, &iterator);
83
84 /* update visible button lines based on current displayed values */
85 for (visible = 0; visible < messageList_size; visible++) {
86 const uiNode_t* option = iterator.option;
87 int idx;
88 msgCategoryEntry_t* entry;
89
90 if (!option)
91 break;
92 idx = atoi(OPTIONEXTRADATACONST(option).value);
93
94 entry = &ccs.msgCategoryEntries[idx];
95 if (!entry)
96 break;
97 if (entry->isCategory) {
98 /* category is visible anyway*/
99 cgi->UI_ExecuteConfunc("ms_disable %i", visible);
100
101 } else {
102 assert(entry->category);
103 cgi->UI_ExecuteConfunc("ms_enable %i", visible);
104 cgi->UI_ExecuteConfunc("ms_btnstate %i %i %i %i", visible, entry->settings->doPause,
105 entry->settings->doNotify, entry->settings->doSound);
106 }
107
108 UI_OptionIteratorNextOption(&iterator);
109 }
110
111 for (; visible < messageList_size; visible++)
112 cgi->UI_ExecuteConfunc("ms_disable %i", visible);
113 }
114
115 /**
116 * @brief initializes message options menu by showing as much button lines as needed.
117 * @note This must only be done once as long as settings are changed in menu, so
118 * messageOptionsInitialized is checked whether this is done yet. This function will be
119 * reenabled if settings are changed via MSO_Set_f. If text list is not initialized
120 * after parsing, MSO_InitTextList will be called first.
121 */
MSOCB_Init(void)122 static void MSOCB_Init (void)
123 {
124 if (msoMenuState < MSO_MSTATE_PREPARED) {
125 MSO_InitList();
126 msoMenuState = MSO_MSTATE_PREPARED;
127 }
128
129 if (msoMenuState < MSO_MSTATE_INITIALIZED) {
130 MSO_UpdateVisibleButtons();
131 msoMenuState = MSO_MSTATE_INITIALIZED;
132 }
133 }
134
135 /**
136 * @brief initializes message options menu by showing as much button lines as needed.
137 * @note First facultative param (from cgi->Cmd_Arg) init messageList_size (the number of rows of button)
138 */
MSO_Init_f(void)139 static void MSO_Init_f (void)
140 {
141 if (cgi->Cmd_Argc() == 2) {
142 messageList_size = atoi(cgi->Cmd_Argv(1));
143 }
144
145 MSOCB_Init();
146 }
147
148 /**
149 * @brief Function for menu buttons to update message settings.
150 * @sa MSO_Set
151 * @todo move this into scripts
152 */
MSO_Toggle_f(void)153 static void MSO_Toggle_f (void)
154 {
155 if (cgi->Cmd_Argc() != 3)
156 Com_Printf("Usage: %s <listId> <pause|notify|sound>\n", cgi->Cmd_Argv(0));
157 else {
158 uiOptionIterator_t iterator;
159 const int listIndex = atoi(cgi->Cmd_Argv(1));
160 int idx;
161 const msgCategoryEntry_t* selectedEntry;
162 int optionType;
163 bool activate;
164 int type;
165 uiNode_t* messageSetting = cgi->UI_GetOption(TEXT_MESSAGEOPTIONS);
166
167 UI_InitOptionIteratorAtIndex(messageList_scroll + listIndex, messageSetting, &iterator);
168 if (!iterator.option)
169 return;
170
171 idx = atoi(OPTIONEXTRADATA(iterator.option).value);
172 selectedEntry = &ccs.msgCategoryEntries[idx];
173 if (!selectedEntry)
174 return;
175 if (selectedEntry->isCategory) {
176 Com_Printf("Toggle command with selected category entry ignored.\n");
177 return;
178 }
179 for (type = 0; type < NT_NUM_NOTIFYTYPE; type++) {
180 if (Q_streq(nt_strings[type], selectedEntry->notifyType))
181 break;
182 }
183 if (type == NT_NUM_NOTIFYTYPE) {
184 Com_Printf("Unrecognized messagetype during toggle '%s' ignored\n", selectedEntry->notifyType);
185 return;
186 }
187
188 if (Q_streq(cgi->Cmd_Argv(2), "pause")) {
189 optionType = MSO_PAUSE;
190 activate = !selectedEntry->settings->doPause;
191 } else if (Q_streq(cgi->Cmd_Argv(2), "notify")) {
192 optionType = MSO_NOTIFY;
193 activate = !selectedEntry->settings->doNotify;
194 } else {
195 optionType = MSO_SOUND;
196 activate = !selectedEntry->settings->doSound;
197 }
198 MSO_Set(listIndex, (notify_t)type, optionType, activate, true);
199 }
200 }
201
202 /**
203 * @brief Function to update message options menu after scrolling.
204 * Updates all visible button lines based on configuration.
205 */
MSO_Scroll_f(void)206 static void MSO_Scroll_f (void)
207 {
208 if (cgi->Cmd_Argc() < 2)
209 return;
210
211 /* no scrolling if visible entry count is less than max on page (due to folding) */
212 messageList_scroll = atoi(cgi->Cmd_Argv(1));
213
214 MSO_UpdateVisibleButtons();
215 }
216
217 /**
218 * @brief Saves actual settings into backup settings variable.
219 */
MSO_BackupSettings_f(void)220 static void MSO_BackupSettings_f (void)
221 {
222 memcpy(backupMessageSettings, messageSettings, sizeof(backupMessageSettings));
223 }
224
225 /**
226 * @brief Restores actual settings from backup settings variable.
227 * @note message options are caused to be re-initialized (for menu display)
228 * @sa MSO_Init_f
229 */
MSO_RestoreSettings_f(void)230 static void MSO_RestoreSettings_f (void)
231 {
232 memcpy(messageSettings, backupMessageSettings, sizeof(messageSettings));
233 MSO_SetMenuState(MSO_MSTATE_REINIT,false,true);
234 }
235
MSO_SetMenuState(const msoMenuState_t newState,const bool callInit,const bool preserveIndex)236 void MSO_SetMenuState (const msoMenuState_t newState, const bool callInit, const bool preserveIndex)
237 {
238 msoMenuState = newState;
239 if (newState == MSO_MSTATE_REINIT && !preserveIndex) {
240 visibleMSOEntries = 0;
241 messageList_scroll = 0;
242 }
243 if (callInit)
244 MSOCB_Init();
245 }
246
MSO_InitCallbacks(void)247 void MSO_InitCallbacks (void)
248 {
249 OBJSET(backupMessageSettings, 1);
250 cgi->Cmd_AddCommand("msgoptions_toggle", MSO_Toggle_f, "Toggles pause, notification or sound setting for a message category");
251 cgi->Cmd_AddCommand("msgoptions_scroll", MSO_Scroll_f, "Scroll callback function for message options menu text");
252 cgi->Cmd_AddCommand("msgoptions_init", MSO_Init_f, "Initializes message options menu");
253 cgi->Cmd_AddCommand("msgoptions_backup", MSO_BackupSettings_f, "Backup message settings");
254 cgi->Cmd_AddCommand("msgoptions_restore",MSO_RestoreSettings_f, "Restore message settings from backup");
255
256 }
257
MSO_ShutdownCallbacks(void)258 void MSO_ShutdownCallbacks (void)
259 {
260 cgi->Cmd_RemoveCommand("msgoptions_toggle");
261 cgi->Cmd_RemoveCommand("msgoptions_scroll");
262 cgi->Cmd_RemoveCommand("msgoptions_init");
263 cgi->Cmd_RemoveCommand("msgoptions_backup");
264 cgi->Cmd_RemoveCommand("msgoptions_restore");
265 cgi->UI_ResetData(TEXT_MESSAGEOPTIONS);
266 }
267