1 /*
2
3 *************************************************************************
4
5 ArmageTron -- Just another Tron Lightcycle Game in 3D.
6 Copyright (C) 2000 Manuel Moos (manuel@moosnet.de)
7 Copyright (C) 2004 Armagetron Advanced Team (http://sourceforge.net/projects/armagetronad/)
8
9 **************************************************************************
10
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25 ***************************************************************************
26
27 */
28
29 #ifndef ArmageTron_MENU_H
30 #define ArmageTron_MENU_H
31
32 #include "rFont.h"
33 #include "tList.h"
34 #include "tString.h"
35 #include "tCallback.h"
36 #include "tLocale.h"
37
38 #include "rSDL.h"
39 #ifndef DEDICATED
40 #include <SDL_events.h>
41 #endif
42
43 #include <deque>
44
45 #include "defs.h"
46
47 class uMenuItem;
48
49 class uMenu{
50 friend class uMenuItem;
51
52 protected:
53 tList<uMenuItem> items;
54 static FUNCPTR idle;
55
56 REAL menuTop;
57 REAL menuBot;
58 REAL yOffset;
59
60 bool exitFlag;
61
62 REAL spaceBelow;
63 REAL center;
64
65 int selected;
66
67 REAL YPos(int num);
68 public:
69 static bool wrap;
70
71 // different quick exit types
72 enum QuickExit
73 {
74 QuickExit_Off = 0, // no quick exit, keep going
75 QuickExit_Game = 1, // quit to game selection menu
76 QuickExit_Total = 2 // quit the program
77 };
78
79 static QuickExit quickexit;
80 static bool exitToMain;
81
82 tOutput title;
83
IdleFunc()84 FUNCPTR IdleFunc(){return idle;}
SetIdle(FUNCPTR idle_func)85 static void SetIdle(FUNCPTR idle_func) {idle=idle_func;}
86
87 // poll input, return true if ESC was pressed
88 static bool IdleInput();
89
SetCenter(REAL c)90 void SetCenter(REAL c) {center=c;}
SetTop(REAL t)91 void SetTop(REAL t) {menuTop=t;}
SetBot(REAL b)92 void SetBot(REAL b) {menuBot=b;spaceBelow=1+menuBot;}
SetSelected(int s)93 void SetSelected(int s) {selected = s;}
NumItems()94 int NumItems() {return items.Len();}
Item(int i)95 uMenuItem* Item(int i) { return items[i]; }
96 void AddItem(uMenuItem* item);
97 void RemoveItem(uMenuItem* item);
98
99 #ifdef SLOPPYLOCALE
100 uMenu(const char *t,bool exit_item=true);
101 #endif
102 uMenu(const tOutput &t,bool exit_item=true);
103 virtual ~uMenu();
104
105 //! enters the menu; calls idle_func before rendering every frame
Enter()106 inline void Enter(){OnEnter();}
107
108 void ReverseItems();
109
110 // paints a nice background
111 static void GenericBackground();
112
113 // marks the menu for exit
Exit()114 inline void Exit(){OnExit();}
115
RequestSpaceBelow(REAL x)116 void RequestSpaceBelow(REAL x){
117 if (spaceBelow<x)
118 spaceBelow=x;
119 }
120
121 // print a big message and a small interpretation
122 static bool Message(const tOutput& message, const tOutput& interpretation, REAL timeout = -1);
123
124 //! returns whether there is currently an active menu
125 static bool MenuActive();
126 protected:
127 //! handles a key press
128 virtual void HandleEvent( SDL_Event event );
129
130 //! enters the menu; calls idle_func before rendering every frame
131 virtual void OnEnter();
132
133 //! marks the menu for exit
134 virtual void OnExit();
135
136 //! called every frame before the menu is rendered
137 virtual void OnRender();
138 };
139
140
141 // *****************************************************
142
143 class uMenuItem{
144 friend class uMenu;
145
146 int idnum;
uMenuItem()147 uMenuItem(){}
148 protected:
149 uMenu *menu;
150 tOutput helpText;
151
152 void DisplayText(REAL x,REAL y,const char *text,bool selected,
153 REAL alpha=1,int center=0,int cursor=0,int cursorPos=0, rTextField::ColorMode colorMode = rTextField::COLOR_USE );
154 void DisplayTextSpecial(REAL x,REAL y,const char *text,bool selected,
155 REAL alpha=1,int center=0);
156 public:
uMenuItem(uMenu * M,const tOutput & help)157 uMenuItem(uMenu *M,const tOutput &help)
158 :idnum(-1),menu(M),helpText(help){
159 menu->items.Add(this,idnum);
160 }
161
162 #ifdef SLOPPYLOCALE
uMenuItem(uMenu * M,const char * help)163 uMenuItem(uMenu *M,const char *help)
164 :idnum(-1),menu(M),helpText(help){
165 menu->items.Add(this,idnum);
166 }
167 #endif
168
~uMenuItem()169 virtual ~uMenuItem()
170 {
171 if (menu && idnum >= 0)
172 menu->items.Remove(this,idnum);
173 }
174
Help()175 virtual tString Help(){return tString(helpText);}
176 // displays the menuitem at position x,y. set selected to true
177 // if the item is currently under the cursor
178 virtual void Render(REAL ,REAL ,REAL =1,bool =0){}
179
RenderBackground()180 virtual void RenderBackground(){
181 menu->GenericBackground();
182 }
183
184 // if the user presses left/right on menuitem
LeftRight(int)185 virtual void LeftRight(int ){} //lr=-1:left lr=+1: right
LeftRightRelease()186 virtual void LeftRightRelease(){}
187
Enter()188 virtual void Enter(){} // if the user presses enter/space on menu
189
Event(SDL_Event &)190 virtual bool Event(SDL_Event &){return false;} // if the key c is
191 // pressed,mouse moved ...
192 // while menuitem is active; return value: key was used
193
SpaceRight()194 virtual REAL SpaceRight(){return 0;}
195
GetID()196 int GetID(){return idnum;}
197
198 protected:
199 void SetColor( bool selected, REAL alpha ); //!< Sets the color of text output for this menuitem
200 };
201
202
203 // *****************************************************
204 // Menu Exit
205 // *****************************************************
206
207 class uMenuItemExit:public uMenuItem{
208 tOutput t;
209
210 static const tOutput& ExitText();
211 static const tOutput& ExitHelp();
212
213 public:
214 uMenuItemExit(uMenu *M,
215 const tOutput &text = ExitText(),
216 const tOutput &help = ExitHelp())
uMenuItem(M,help)217 :uMenuItem(M,help)
218 ,t(text){}
219
220 // displays the menuitem at position x,y. set selected to true
221 // if the item is currently under the cursor
222 virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0){
223 DisplayTextSpecial(x,y,tString(t),selected,alpha);
224 }
225
Enter()226 virtual void Enter(){menu->Exit();}
227 // if the user presses enter/space on menu
228 };
229
230 // *****************************************************
231 // Selection
232 // *****************************************************
233
234 template<class T> class uSelectItem{
235 public:
236 int idnum;
237
238 tOutput description;
239 tOutput helpText;
240 T value;
241
uSelectItem(const tOutput & desc,const tOutput & help,T val)242 uSelectItem(const tOutput& desc,const tOutput& help,T val)
243 :idnum(-1),description(desc),helpText(help),value(val){}
244 };
245
246 template<class T> class uMenuItemSelection:public uMenuItem{
247 protected:
248 tList<uSelectItem<T> > choices;
249 tOutput title;
250 int select;
251 T * target;
252 public:
253 #ifdef SLOPPYLOCALE
uMenuItemSelection(uMenu * m,const char * tit,const char * help,T & targ)254 uMenuItemSelection(uMenu *m,
255 const char* tit,const char *help,
256 T &targ)
257 :uMenuItem(m,help),title(tit),select(0),target(&targ){}
258 #endif
259
uMenuItemSelection(uMenu * m,const tOutput & tit,const tOutput & help,T & targ)260 uMenuItemSelection(uMenu *m,
261 const tOutput &tit,const tOutput &help,
262 T &targ)
263 :uMenuItem(m,help),title(tit),select(0),target(&targ){}
264
~uMenuItemSelection()265 ~uMenuItemSelection(){
266 Clear();
267 }
268
Clear()269 void Clear(){
270 for(int i=choices.Len()-1;i>=0;i--){
271 uSelectItem<T> *x=choices(i);
272 choices.Remove(x,x->idnum);
273 delete x;
274 }
275 select=0;
276 }
277
NewChoice(uSelectItem<T> * c)278 void NewChoice(uSelectItem<T> *c){
279 choices.Add(c,c->idnum);
280 }
281
NewChoice(const tOutput & desc,const tOutput & help,T val)282 void NewChoice(const tOutput& desc,const tOutput& help,T val){
283 uSelectItem<T> *x=new uSelectItem<T>(desc,help,val);
284 NewChoice(x);
285 }
286
LeftRight(int lr)287 virtual void LeftRight(int lr){
288 select+=lr;
289 if(select>=choices.Len())
290 select=choices.Len()-1;
291 if(select<0)
292 select=0;
293 if (choices.Len())
294 *target=choices(select)->value;
295 }
296
297 virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0){
298 for(int i=choices.Len()-1;i>=0;i--)
299 if (choices(i)->value==*target)
300 select=i;
301
302 DisplayText(REAL(x-.02),y,title,selected,alpha,1);
303 if (choices.Len()>0)
304 DisplayText(REAL(x+.02),y,choices(select)->description,selected,alpha,-1);
305 }
306
Help()307 virtual tString Help(){
308 tString ret;
309 ret << helpText;
310 ret << "\n";
311 ret << choices(select)->helpText;
312 return ret;
313 }
314
315 };
316
317 template<class T> class uSelectEntry{
318 public:
uSelectEntry(uMenuItemSelection<T> & sel,const char * desc,const char * help,T val)319 uSelectEntry(uMenuItemSelection<T> &sel,
320 const char *desc,
321 const char *help,T val){
322 sel.NewChoice(desc,help,val);
323 }
324 };
325
326 // *****************************************
327 // Toggle
328 // *****************************************
329
330 class uMenuItemToggle: public uMenuItemSelection<bool>{
331 void NewChoice(uSelectItem<bool> *c);
332 void NewChoice(const char *desc,bool val);
333 public:
334 #ifdef SLOPPYLOCALE
335 uMenuItemToggle(uMenu *m,const char *tit,
336 const char *help,bool &targ);
337 #endif
338 uMenuItemToggle(uMenu *m,const tOutput& title,
339 const tOutput& help,bool &targ);
340 ~uMenuItemToggle();
341
342 virtual void LeftRight(int);
343 virtual void Enter();
344 };
345
346
347 // *****************************************
348 // Integer Choose
349 // *****************************************
350
351 class uMenuItemInt:public uMenuItem{
352 protected:
353 tOutput title;
354 int ⌖
355 int Min,Max;
356 int Step;
357 public:
358 /*
359 uMenuItemInt(uMenu *m,const char *tit,
360 const char *help,int &targ,
361 int mi,int ma,int step=1);
362 */
363 uMenuItemInt(uMenu *m,const tOutput &title,
364 const tOutput &help,int &targ,
365 int mi,int ma,int step=1);
366
~uMenuItemInt()367 ~uMenuItemInt(){}
368
369 virtual void LeftRight(int);
370
371 virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0);
372 };
373
374 // *****************************************
375 // Float Choose
376 // *****************************************
377
378 class uMenuItemReal:public uMenuItem{
379 protected:
380 tOutput title;
381 REAL ⌖
382 REAL Min,Max;
383 REAL Step;
384 public:
385 /*
386 uMenuItemInt(uMenu *m,const char *tit,
387 const char *help,int &targ,
388 int mi,int ma,int step=1);
389 */
390 uMenuItemReal(uMenu *m,const tOutput &title,
391 const tOutput &help,REAL &targ,
392 REAL mi,REAL ma,REAL step=1);
393
~uMenuItemReal()394 ~uMenuItemReal(){}
395
396 virtual void LeftRight(int);
397
398 virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0);
399 };
400
401 // *****************************************************
402 // String query
403 // *****************************************************
404
405
406 class uMenuItemString: public uMenuItem{
407 protected:
408 tOutput description;
409 tString *content;
410 int cursorPos;
411 int maxLength_;
412
413 // color mode used for rendering
414 rTextField::ColorMode colorMode_;
415 public:
416 uMenuItemString(uMenu *M,const tOutput& desc,
417 const tOutput& help,tString &c, int maxLength = 1024 );
~uMenuItemString()418 virtual ~uMenuItemString(){}
419
420 virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0);
421
422 virtual bool Event(SDL_Event &e);
423
MyMenu()424 uMenu *MyMenu(){return menu;}
425
SetColorMode(rTextField::ColorMode colorMode)426 void SetColorMode( rTextField::ColorMode colorMode )
427 {
428 colorMode_ = colorMode;
429 }
430
GetColorMode()431 rTextField::ColorMode GetColorMode() const
432 {
433 return colorMode_;
434 }
435 };
436
437 class uMenuItemStringWithHistory : protected uMenuItemString {
438 protected:
439 std::deque<tString> &m_History;
440 unsigned int m_HistoryPos;
441 unsigned int m_HistoryLimit;
442 public:
443 uMenuItemStringWithHistory(uMenu *M,const tOutput& desc, const tOutput& help,tString &c, int maxLength, std::deque<tString> &history, int limit );
444
445 ~uMenuItemStringWithHistory();
446
447 virtual bool Event(SDL_Event &e);
448 };
449
450
451 // *****************************************************
452 // Submenu
453 // *****************************************************
454
455
456 class uMenuItemSubmenu: public uMenuItem{
457 uMenu *submenu;
458 public:
459 uMenuItemSubmenu(uMenu *M,uMenu *s,
460 const tOutput& help);
~uMenuItemSubmenu()461 virtual ~uMenuItemSubmenu(){}
462
463 virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0);
464
465 virtual void Enter();
466 };
467
468
469 // *****************************************************
470 // generic action
471 // *****************************************************
472
473 class uMenuItemAction: public uMenuItem{
474 public:
475 uMenuItemAction(uMenu *M,const tOutput& name,
476 const tOutput& help );
477
~uMenuItemAction()478 virtual ~uMenuItemAction(){}
479
480 virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0);
481
482 virtual void Enter() = 0;
483 protected:
484 tOutput name_;
485 };
486
487 // *****************************************************
488 // Execute function
489 // *****************************************************
490
491
492 class uMenuItemFunction: public uMenuItemAction{
493 FUNCPTR func;
494 public:
495 uMenuItemFunction(uMenu *M,const tOutput& name,
496 const tOutput& help,FUNCPTR f);
497
~uMenuItemFunction()498 virtual ~uMenuItemFunction(){}
499
500 virtual void Enter();
501 };
502
503
504 class uMenuItemFunctionInt: public uMenuItemAction{
505 INTFUNCPTR func;
506 int arg;
507 public:
508 uMenuItemFunctionInt(uMenu *M,const tOutput& name,
509 const tOutput& help,INTFUNCPTR f,int arg);
510
~uMenuItemFunctionInt()511 virtual ~uMenuItemFunctionInt(){}
512
513 virtual void Enter();
514 };
515
516 // *****************************************************
517 // File Selection (added by k)
518 // *****************************************************
519
520 class uMenuItemFileSelection: public uMenuItemSelection<tString>
521 {
522 void NewChoice( uSelectItem<bool> * );
523 void NewChoice( char *, bool );
524 protected:
525 tString dir_;
526 tString fileSpec_;
527 int getFilesFlag_;
528 bool formatName_;
529 tString defaultFileName_;
530 tString defaultFilePath_;
531 public:
532 uMenuItemFileSelection( uMenu *m, char *tit, const char *help, tString& targ,
533 const char *dir, const char *fileSpec, int getFilesFlag = 0, bool formatName = true )
534 :uMenuItemSelection<tString>( m, tit, help, targ )
535 {
536 SetParams( dir, fileSpec, getFilesFlag, formatName, "", "" );
537 Reload();
538 }
539
540 uMenuItemFileSelection( uMenu *m, char *tit, const char *help, tString& targ,
541 const char *dir, const char *fileSpec,
542 const char *defaultFileName, const char *defaultFilePath,
543 int getFilesFlag = 0, bool formatName = true )
544 :uMenuItemSelection<tString>( m, tit, help, targ )
545 {
546 SetParams( dir, fileSpec, getFilesFlag, formatName, defaultFileName, defaultFilePath );
547 Reload();
548 }
549
~uMenuItemFileSelection()550 virtual ~uMenuItemFileSelection() {}
551
SetDir(const char * dir)552 void SetDir( const char *dir ) { dir_ = dir; }
SetFileSpec(const char * fileSpec)553 void SetFileSpec( const char *fileSpec ) { fileSpec_ = fileSpec; }
SetFormatName(bool formatName)554 void SetFormatName( bool formatName ) { formatName_ = formatName; }
SetGetFilesFlag(int getFilesFlag)555 void SetGetFilesFlag( int getFilesFlag ) { getFilesFlag_ = getFilesFlag; }
SetDefaultFileName(const char * defaultFileName)556 void SetDefaultFileName( const char *defaultFileName ) { defaultFileName_ = defaultFileName; }
SetDefaultFilePath(const char * defaultFilePath)557 void SetDefaultFilePath( const char *defaultFilePath ) { defaultFilePath_ = defaultFilePath; }
558
SetParams(const char * dir,const char * fileSpec,int getFilesFlag,bool formatName,const char * defaultFileName,const char * defaultFilePath)559 void SetParams( const char *dir, const char *fileSpec, int getFilesFlag,
560 bool formatName, const char *defaultFileName, const char *defaultFilePath )
561 {
562 SetDir( dir );
563 SetFileSpec( fileSpec );
564 SetGetFilesFlag( getFilesFlag );
565 SetFormatName( formatName );
566 SetDefaultFileName( defaultFileName );
567 SetDefaultFilePath( defaultFilePath );
568 }
569
570 void Reload();
571
572 void LoadDirectory( const char *dir, const char *fileSpec, bool formatName = true );
573
574 void AddFile( const char *fileName, const char *filePath, bool formatName = true );
575 };
576
577 // *****************************************************
578 // Menu Enter/Leave-Callback
579 // *****************************************************
580
581 class uCallbackMenuEnter: public tCallback{
582 public:
583 uCallbackMenuEnter(VOIDFUNC *f);
584 static void MenuEnter();
585 };
586
587 class uCallbackMenuLeave: public tCallback{
588 public:
589 uCallbackMenuLeave(VOIDFUNC *f);
590 static void MenuLeave();
591 };
592
593 class uCallbackMenuBackground: public tCallback{
594 public:
595 uCallbackMenuBackground(VOIDFUNC *f);
596 static void MenuBackground();
597 };
598
599
AddItem(uMenuItem * item)600 inline void uMenu::AddItem(uMenuItem* item) { items.Add(item, item->idnum); }
RemoveItem(uMenuItem * item)601 inline void uMenu::RemoveItem(uMenuItem* item) { items.Remove(item, item->idnum); }
602
603 #endif
604
605