1 /*
2 Copyright (C) 2004 by James Gregory
3 Part of the GalaxyHack project
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY.
9
10 See the COPYING file for more details.
11 */
12
13 #include "GenWindow.h"
14 #include "Globals.h"
15 #include "MainMenu.h"
16 #include "ForceSelect.h"
17 #include "SetupBattle.h"
18 #include "RTS.h"
19 #include "Score.h"
20
21 #include <string>
22 #include <list>
23
24 using std::string;
25 using std::list;
26
27 /*IMPORTANT NOTE:
28 WinMouseD() and WinKeyboard() rely upon windows returning true if they are going to do anything. The fact that a window can create another window in the same list as itself can otherwise cause issues. It would seem adding a window mid loop moves the reverse iterator back one somehow, meaning a window can accidently get input twice.
29
30 For mouse input this is automatically handled by GenWindow_Base::MouseD(), which will always return true if the mouse is over a given window.
31
32 Another way of doing this would be to make a copy of the myWindows list each frame, make it so windows only push back new windows on to this copy, and then at the end of each frame have the copied (and maybe altered) list assigned back to the real list. The fact that GenWindows are a handle class means this wouldn't actually literally copy the entire contents of the window list twice each frame, but it would seem rather inefficient to me, nonetheless.
33 */
34
35 /*ANOTHER NOTE:
36 Any pushing back of keyboard-reading windows must come after WinKeyboard(), or the new window will get the keyboard input too
37 */
38
UpdateWindows()39 void UpdateWindows() {
40 if (globalSettings.batch)
41 return;
42
43 //altering list whilst iterating through it, dodgy, see note above, some hackery here
44 list<GenWindow>::iterator endIter = myWindows.end();
45
46 for (list<GenWindow>::iterator iter = myWindows.begin(); iter != endIter; ) {
47 if (iter->TakeActivate()) {
48 myWindows.splice(myWindows.end(), myWindows, iter);
49 iter = myWindows.begin();
50 endIter = myWindows.end();
51 }
52 else
53 ++iter;
54 }
55
56 for (list<GenWindow>::iterator iter = myWindows.begin(); iter != myWindows.end();) {
57 if (iter->GetClosed())
58 iter = myWindows.erase(iter);
59 else
60 ++iter;
61 }
62
63 for (list<GenWindow>::reverse_iterator iter = myWindows.rbegin(); iter != myWindows.rend(); ++iter)
64 iter->Update();
65 }
66
WinMouseD(Uint8 button,Uint16 x,Uint16 y)67 bool WinMouseD(Uint8 button, Uint16 x, Uint16 y) {
68 //means no windowed input
69 bool ret = false;
70
71 //break as soon as the front most window returns true
72 for (list<GenWindow>::reverse_iterator iter = myWindows.rbegin(); iter != myWindows.rend(); ++iter) {
73 if (iter->MouseD(button, x, y)) {
74 ret = true;
75 break;
76 }
77 }
78
79 return ret;
80 }
81
WinMouseM(Uint8 state,Uint16 x,Uint16 y)82 void WinMouseM(Uint8 state, Uint16 x, Uint16 y) {
83 //break as soon as the front most window deals with motion
84 for (list<GenWindow>::reverse_iterator iter = myWindows.rbegin(); iter != myWindows.rend(); ++iter) {
85 if (iter->MouseM(state, x, y))
86 return;
87 }
88 }
89
WinKeyboard(SDL_keysym & keysym)90 bool WinKeyboard(SDL_keysym& keysym) {
91 bool ret = false;
92
93 //break as soon as the front most window has some keyboard input
94 for (list<GenWindow>::reverse_iterator iter = myWindows.rbegin(); iter != myWindows.rend(); ++iter) {
95 if (iter->Keyboard(keysym)) {
96 ret = true;
97 break;
98 }
99 }
100
101 return ret;
102 }
103
MessageWindows(WindowChoice theMessage,int paremOne,int paremTwo,int targetID,int sourceID)104 void MessageWindows(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
105 for (list<GenWindow>::iterator iter = myWindows.begin(); iter != myWindows.end(); ++iter)
106 iter->WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);
107 }
108
CreateInfoString(const string & iTheString,bool force)109 void CreateInfoString(const string& iTheString, bool force) {
110 if (!anInfoString || force)
111 myWindows.push_back(GenWindow(iTheString));
112 }
113
DrawAllWindows()114 void DrawAllWindows() {
115 if (globalSettings.batch)
116 return;
117
118 for (list<GenWindow>::iterator iter = myWindows.begin(); iter != myWindows.end(); ++iter)
119 iter->DrawSelf();
120 }
121
KillAllWindows()122 void KillAllWindows() {
123 //we can't use clear because with clear the size of the list
124 //isn't set to 0 until the clearing has finished, yet
125 //the base window destructor has to find the size
126 for (list<GenWindow>::iterator iter = myWindows.begin(); iter != myWindows.end();)
127 iter = myWindows.erase(iter);
128 }
129
LocateWindow(int findID)130 GenWindow_Base* LocateWindow(int findID) {
131 for (list<GenWindow>::iterator iter = myWindows.begin(); iter != myWindows.end(); ++iter) {
132 GenWindow_Base* winPointer = iter->GetPointer();
133 if (winPointer->myID == findID)
134 return winPointer;
135 }
136
137 char output[80];
138 sprintf(output, "Unable to find window with ID %d", findID);
139 throw runtime_error(output);
140
141 return 0;
142 }
143
GenWindow(int ix,int iy,WindowChoice iType,int paremOne,int paremTwo,int flags)144 GenWindow::GenWindow(int ix, int iy, WindowChoice iType, int paremOne, int paremTwo, int flags) {
145 switch (iType) {
146 case MM_MainSM:
147 hWindow = new MainMenu::MainSM();
148 break;
149
150 case MM_Options:
151 hWindow = new MainMenu::MainOptions(ix, iy);
152 break;
153
154 case Opt_StandardOptions:
155 hWindow = new StandardOptions(ix, iy, none_constant, flags);
156 break;
157
158 case Opt_SetResolution:
159 hWindow = new ChooseResolution();
160 break;
161
162 case Opt_SetWindowColor:
163 hWindow = new WindowColorSlider(ix, iy, flags);
164 break;
165
166 case FS_LoadSideDW:
167 hWindow = new ForceSelect::LoadSideDW();
168 break;
169
170 case FS_LoadSideMenu:
171 hWindow = new ForceSelect::LoadSideSM(paremOne);
172 break;
173
174 case FS_NewSideName:
175 hWindow = new ForceSelect::NewSideName();
176 break;
177
178 case FS_Commander:
179 hWindow = new ForceSelect::ChangeCommanderName();
180 break;
181
182 case FS_WhichSaveGroup:
183 hWindow = new ForceSelect::WhichSaveGroup(paremOne, static_cast<bool>(paremTwo));
184 break;
185
186 case FS_BasePU:
187 hWindow = new ForceSelect::BasePU(ix, iy);
188 break;
189
190 case FS_AddGroupMenu:
191 hWindow = new ForceSelect::AddGroupMenu(paremOne);
192 break;
193
194 case FS_CapShipTypeSlider:
195 hWindow = new ForceSelect::CapShipTypeSlider(ix, iy, paremOne, flags);
196 break;
197
198 case FS_SideOptions:
199 hWindow = new ForceSelect::SideOptions(ix, iy, flags);
200 break;
201
202 case FS_SideOptionsPU:
203 hWindow = new ForceSelect::SideOptionsPU(ix, iy);
204 break;
205
206 case FS_ExitNoSaveQ:
207 hWindow = new ForceSelect::ExitNoSaveQ();
208 break;
209
210 case FS_EditGroup:
211 hWindow = new ForceSelect::EditGroup(ix, iy, paremOne, flags & WFLAG_TILED);
212 break;
213
214 case FS_EditGroupPU:
215 hWindow = new ForceSelect::EditGroupPU(ix, iy, paremOne);
216 break;
217
218 case FS_AIScriptMenu:
219 hWindow = new ForceSelect::SetAIScriptMenu(paremOne, paremTwo);
220 break;
221
222 case FS_EditUnit:
223 hWindow = new ForceSelect::EditUnit(ix, iy, paremOne);
224 break;
225
226 case FS_EditUnitPU:
227 hWindow = new ForceSelect::EditUnitPU(ix, iy, paremOne);
228 break;
229
230 case FS_PictureMenu:
231 hWindow = new ForceSelect::SetUnitPicMenu(paremOne, paremTwo);
232 break;
233
234 //0 is small weapons, 1 is big weapons
235 case FS_WeaponsDW:
236 hWindow = new ForceSelect::WeaponsDW(ix, ix, paremOne, paremTwo);
237 break;
238
239 case FS_SmallWeaponsMenu:
240 hWindow = new ForceSelect::SmallWeaponsMenu(ix, ix, paremOne, paremTwo);
241 break;
242
243 case FS_BigWeaponsMenu:
244 hWindow = new ForceSelect::BigWeaponsMenu(ix, ix, paremOne, paremTwo);
245 break;
246
247 case FS_EquipmentDW:
248 hWindow = new ForceSelect::EquipmentDW(ix, ix, paremOne, paremTwo);
249 break;
250
251 case FS_EngineMenu:
252 hWindow = new ForceSelect::EngineMenu(ix, ix, paremOne, paremTwo);
253 break;
254
255 case FS_ArmourMenu:
256 hWindow = new ForceSelect::ArmourMenu(ix, ix, paremOne, paremTwo);
257 break;
258
259 case FS_ShieldMenu:
260 hWindow = new ForceSelect::ShieldMenu(ix, ix, paremOne, paremTwo);
261 break;
262
263 case FS_CSType:
264 hWindow = new ForceSelect::CSTypeMenu(ix, ix, paremOne);
265 break;
266
267 case SB_BasePU:
268 hWindow = new SetupBattle::BasePU(ix, iy);
269 break;
270
271 case SB_LoadSideMenu:
272 hWindow = new SetupBattle::LoadSideMenu(paremOne, paremTwo);
273 break;
274
275 case SB_PlayerList:
276 hWindow = new SetupBattle::PlayerList(ix, iy, flags);
277 break;
278
279 case SB_RandomSeed:
280 hWindow = new SetupBattle::RandomSeed(ix, iy, flags);
281 break;
282
283 case RTS_BasePU:
284 hWindow = new RTS::BasePU(ix, iy);
285 break;
286
287 case RTS_OptPU:
288 hWindow = new RTS::OptPU(ix, iy);
289 break;
290
291 case RTS_GameInfo:
292 hWindow = new RTS::GameInfo(ix, iy, flags);
293 break;
294
295 case RTS_SideStats:
296 hWindow = new RTS::SideStatsInfo(ix, iy, paremOne);
297 break;
298
299 case RTS_SideVars:
300 hWindow = new RTS::SideVarsInfo(ix, iy, paremOne);
301 break;
302
303 case RTS_SideSaveGroups:
304 hWindow = new RTS::SideSaveGroupsInfo(ix, iy, paremOne);
305 break;
306
307 case RTS_SideAIDebug:
308 hWindow = new RTS::SideAIErrors(ix, iy, paremOne);
309 break;
310
311 case RTS_InfoChoicePU:
312 hWindow = new RTS::InfoChoicePU(ix, iy, paremOne, paremTwo);
313 break;
314
315 case RTS_GroupStats:
316 hWindow = new RTS::GroupStatsInfo(ix, iy, paremOne, paremTwo, flags);
317 break;
318
319 case RTS_GroupShieldsInfo:
320 hWindow = new RTS::GroupShieldsInfo(ix, iy, paremOne, paremTwo, flags);
321 break;
322
323 case RTS_GroupStatusReport:
324 hWindow = new RTS::GroupStatusReport(ix, iy, paremOne, paremTwo, flags);
325 break;
326
327 case RTS_GroupAIReport:
328 hWindow = new RTS::GroupAIReport(ix, iy, paremOne, paremTwo, flags);
329 break;
330
331 case RTS_GroupVars:
332 hWindow = new RTS::GroupVarsInfo(ix, iy, paremOne, paremTwo, flags);
333 break;
334
335 case RTS_GroupSaveGroups:
336 hWindow = new RTS::GroupSaveGroupsInfo(ix, iy, paremOne, paremTwo, flags);
337 break;
338
339 case RTS_GroupTimers:
340 hWindow = new RTS::GroupTimersInfo(ix, iy, paremOne, paremTwo, flags);
341 break;
342
343 case RTS_RestartQ:
344 hWindow = new RTS::RestartQ();
345 break;
346
347 case RTS_SetGameSpeed:
348 hWindow = new RTS::GameSpeedSlider(ix, iy, flags);
349 break;
350
351 case RTS_SetScrollSpeed:
352 hWindow = new RTS::ScrollSpeedSlider(ix, iy, flags);
353 break;
354
355 case Score_BasePU:
356 hWindow = new Score::BasePU(ix, iy);
357 break;
358
359 default:
360 throw runtime_error("GenWindow standard constructor didn't recognise window type");
361 break;
362 }
363 }
364
GenWindow(int ix,int iy,WindowChoice iType,int paremOne,int paremTwo,int paremThree,int paremFour,int flags)365 GenWindow::GenWindow(int ix, int iy, WindowChoice iType, int paremOne, int paremTwo, int paremThree, int paremFour, int flags) {
366 switch (iType) {
367 case RTS_InfoChoicePU:
368 hWindow = new RTS::InfoChoicePU(ix, iy, paremOne, paremTwo, paremThree, paremFour);
369 break;
370
371 default:
372 throw runtime_error("GenWindow four parems constructor didn't recognise window type");
373 break;
374 }
375 }
376
GenWindow(WindowChoice iType,int iMySide,int iMyGroup,WindowChoice iChoiceType)377 GenWindow::GenWindow(WindowChoice iType, int iMySide, int iMyGroup, WindowChoice iChoiceType) {
378 hWindow = new SidePU(iMySide, iMyGroup, iChoiceType);
379 }
380
GenWindow(WindowChoice iType,int iMySide,int iMyGroup,WindowChoice iChoiceType,int iWhichSaveGroup)381 GenWindow::GenWindow(WindowChoice iType, int iMySide, int iMyGroup, WindowChoice iChoiceType, int iWhichSaveGroup) {
382 hWindow = new SidePU(iMySide, iMyGroup, iChoiceType, iWhichSaveGroup);
383 }
384
385
GenWindow(int ix,int iy,WindowChoice iType,const string & iString,int paremOne,int paremTwo)386 GenWindow::GenWindow(int ix, int iy, WindowChoice iType, const string& iString, int paremOne, int paremTwo) {
387 switch (iType) {
388 case WC_LargeBlankDW:
389 hWindow = new LargeBlankDW(iString);
390 break;
391
392 case FS_LoadSidePU:
393 hWindow = new ForceSelect::LoadSidePU(ix, iy, iString, paremOne);
394 break;
395
396 case FS_DeleteFleet:
397 hWindow = new ForceSelect::DeleteFleet(iString, paremOne);
398 break;
399
400 case FS_CopyFleet:
401 hWindow = new ForceSelect::CopyFleet(iString, paremOne);
402 break;
403
404 case FS_AddGroupPU:
405 hWindow = new ForceSelect::AddGroupPU(ix, iy, iString, paremOne);
406 break;
407
408 case FS_ForceExitQ:
409 hWindow = new ForceSelect::ForceExitQ(iString);
410 break;
411
412 case FS_ChangeAIScriptPU:
413 hWindow = new ForceSelect::SetAIScriptPU(iString, paremOne, paremTwo);
414 break;
415
416 default:
417 throw runtime_error("GenWindow int, int, WC, string, int constructor didn't recognise window type");
418 break;
419 }
420 }
421
GenWindow(int ix,int iy,WindowChoice iType,const string & iString,UnitType iUnitType,int paremOne,int paremTwo,int paremThree)422 GenWindow::GenWindow(int ix, int iy, WindowChoice iType, const string& iString, UnitType iUnitType, int paremOne, int paremTwo, int paremThree) {
423 switch (iType) {
424 case FS_NewGroupChoicesOK:
425 hWindow = new ForceSelect::NewGroupChoicesOK(ix, iy, iString, iUnitType, paremOne, paremTwo, paremThree);
426 break;
427
428 case FS_NewGroupParentPU:
429 hWindow = new ForceSelect::NewGroupParentPU(iString, iUnitType, paremOne);
430 break;
431
432 default:
433 throw runtime_error("int, int, WC, string, UT, int, int, int windows constructor didn't recognise window type");
434 break;
435 }
436 }
437
GenWindow(int ix,int iy,WindowChoice iType,int iSliderVar,int iVarMin,int iVarMax,const string & iVarName,const string & iVarUnits,int iParentID,int flags)438 GenWindow::GenWindow(int ix, int iy, WindowChoice iType, int iSliderVar, int iVarMin, int iVarMax, const string& iVarName, const string& iVarUnits, int iParentID, int flags) {
439 hWindow = new SliderWithUnits(ix, iy, iSliderVar, iVarMin, iVarMax, iVarName, iVarUnits, iParentID, flags);
440 }
441
GenWindow(int ix,int iy,WindowChoice iType,int * iVarPointer,int iVarMin,int iVarMax,const string & iVarName,const string & iVarUnits,int iParentID,int flags)442 GenWindow::GenWindow(int ix, int iy, WindowChoice iType, int* iVarPointer, int iVarMin, int iVarMax, const string& iVarName, const string& iVarUnits, int iParentID, int flags) {
443 hWindow = new SliderWithUnits(ix, iy, iVarPointer, iVarMin, iVarMax, iVarName, iVarUnits, iParentID, flags);
444 }
445
GenWindow(const string & iTheString)446 GenWindow::GenWindow(const string& iTheString) {
447 hWindow = new InfoString(iTheString);
448 }
449
GenWindow(WindowChoice iType,UnitType iUnitType,int paremOne)450 GenWindow::GenWindow(WindowChoice iType, UnitType iUnitType, int paremOne) {
451 switch (iType) {
452 case FS_NewUnitName:
453 hWindow = new ForceSelect::NewUnitName(iUnitType, paremOne);
454 break;
455
456 default:
457 throw runtime_error("GenWindow WC, UT, int constructor didn't recognise window type");
458 break;
459 }
460 }
461
GenWindow(WindowChoice iType,const string & stringOne,const string & stringTwo,int iParentID)462 GenWindow::GenWindow(WindowChoice iType, const string& stringOne, const string& stringTwo, int iParentID) {
463 switch (iType) {
464 case WC_DeleteBox:
465 hWindow = new DeleteBox(stringOne, stringTwo, iParentID);
466 break;
467
468 case WC_CopyBox:
469 hWindow = new CopyBox(stringOne, stringTwo, iParentID);
470 break;
471
472 default:
473 throw runtime_error("GenWindow Copy/DeleteBox constructor didn't recognise window type");
474 break;
475 }
476 }
477
478 ////
479
TakeActivate()480 bool GenWindow::TakeActivate() {
481 bool ret = hWindow->activate;
482 hWindow->activate = 0;
483 return ret;
484 }
485
WinMessage(WindowChoice theMessage,int paremOne,int paremTwo,int targetID,int sourceID)486 void GenWindow::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
487 if (sourceID != hWindow->myID)
488 hWindow->WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);
489 }
490
491