]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/snazzyui.cpp
The Great Newline Fix
[taylor/freespace2.git] / src / menuui / snazzyui.cpp
1 /*
2  * $Logfile: /Freespace2/code/MenuUI/SnazzyUI.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  *  Code to drive the Snazzy User Interface
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:46  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:09  root
14  * Initial import.
15  *
16  * 
17  * 7     7/16/99 1:49p Dave
18  * 8 bit aabitmaps. yay.
19  * 
20  * 6     12/18/98 1:13a Dave
21  * Rough 1024x768 support for Direct3D. Proper detection and usage through
22  * the launcher.
23  * 
24  * 5     11/30/98 1:07p Dave
25  * 16 bit conversion, first run.
26  * 
27  * 4     10/23/98 3:51p Dave
28  * Full support for tstrings.tbl and foreign languages. All that remains
29  * is to make it active in Fred.
30  * 
31  * 3     10/13/98 9:28a Dave
32  * Started neatening up freespace.h. Many variables renamed and
33  * reorganized. Added AlphaColors.[h,cpp]
34  * 
35  * 2     10/07/98 10:53a Dave
36  * Initial checkin.
37  * 
38  * 1     10/07/98 10:49a Dave
39  * 
40  * 57    4/09/98 5:51p Lawrance
41  * Be able to disable sounds for certain menus
42  * 
43  * 56    4/08/98 10:18a John
44  * Made version and snazzy info all render as white in all screen modes.
45  * 
46  * 55    3/18/98 12:11p John
47  * redid some string externalization
48  * 
49  * 54    3/05/98 11:15p Hoffoss
50  * Changed non-game key checking to use game_check_key() instead of
51  * game_poll().
52  * 
53  * 53    2/22/98 4:17p John
54  * More string externalization classification... 190 left to go!
55  * 
56  * 52    2/03/98 11:52p Lawrance
57  * call snazzy_flush() from game_flush()
58  * 
59  * 51    1/20/98 2:23p Dave
60  * Removed optimized build warnings. 99% done with ingame join fixes.
61  * 
62  * 50    1/10/98 12:47a Lawrance
63  * rip out hud config text drawing
64  * 
65  * 49    12/23/97 5:28p Hoffoss
66  * Made enter key act the same as clicking the mouse button in main hall
67  * screen.
68  * 
69  * 48    11/19/97 8:36p Dave
70  * Removed references to MainMenu.h
71  * 
72  * 47    11/11/97 4:57p Dave
73  * Put in support for single vs. multiplayer pilots. Began work on
74  * multiplayer campaign saving. Put in initial player select screen
75  * 
76  * 46    9/07/97 10:06p Lawrance
77  * let snazzy code keep track of mouse status
78  * 
79  * 45    8/11/97 9:48p Lawrance
80  * don't poll keyboard if not requested 
81  * 
82  * 44    6/11/97 1:13p John
83  * Started fixing all the text colors in the game.
84  * 
85  * 43    6/05/97 10:19a Lawrance
86  * before playing a sound, ensure it is valid
87  * 
88  * 42    6/05/97 1:07a Lawrance
89  * changes to support sound interface
90  * 
91  * 41    4/23/97 5:19p Lawrance
92  * split up misc sounds into: gamewide, ingame, and interface
93  * 
94  * 40    4/18/97 2:54p Lawrance
95  * sounds now have a default volume, when playing, pass a scaling factor
96  * not the actual volume
97  * 
98  * 39    3/31/97 5:45p Lawrance
99  * supporting changes to allow multiple streamed audio files
100  * 
101  * 38    3/19/97 5:53p Lawrance
102  * integrating new Misc_sounds[] array (replaces old Game_sounds
103  * structure)
104  * 
105  * 37    3/01/97 2:13p Lawrance
106  * made to work with new cfile changes
107  * 
108  * 36    2/25/97 11:11a Lawrance
109  * adding more functionality needed for ship selection screen
110  * 
111  * 35    2/05/97 10:35a Lawrance
112  * supporting spooled music at menus, briefings, credits etc.
113  * 
114  * 34    1/22/97 11:01a John
115  * Added code to stream wav files in during menus.
116  * 
117  * 33    1/20/97 7:58p John
118  * Fixed some link errors with testcode.
119  * 
120  * 32    1/13/97 5:36p Lawrance
121  * integrating new Game_sounds structure for general game sounds
122  * 
123  * 31    1/07/97 6:56p Lawrance
124  * adding sound hooks
125  * 
126  * 30    12/10/96 4:18p Lawrance
127  * added snazzy_menu_close() call and integrated with existing menus
128  * 
129  * 29    12/09/96 2:53p Lawrance
130  * fixed bug where both the snazzy code and ui code were reading the
131  * keyboard, and the keypress from the snazzy code was being lost
132  * 
133  * 28    12/08/96 1:57a Lawrance
134  * integrating hud configuration
135  * 
136  * 27    11/26/96 10:13a Allender
137  * fixed code to properly get text from the region
138  * 
139  * 26    11/21/96 7:14p Lawrance
140  * converted menu code to use a file (menu.tbl) to get the data for the
141  * menu
142  * 
143  * 25    11/15/96 2:14p Lawrance
144  * improved comments, removed some unnecssary #includes and code
145  * 
146  * 24    11/15/96 12:09p John
147  * Added new UI code.  Made mouse not return Enter when you click it.
148  * Changed the doSnazzyUI function and names to be snazzy_menu_xxx.   
149  * 
150  * 23    11/13/96 4:02p Lawrance
151  * complete over-haul of the menu system and the states associated with
152  * them
153  * 
154  * 22    11/13/96 10:30a John
155  * Added code to call game_poll instead of key_inkey.
156  * 
157  * 21    11/13/96 8:32a Lawrance
158  * streamlined menu code
159  * 
160  * 20    11/12/96 12:20p John
161  * 
162  * 19    11/12/96 12:20p John
163  * added game pol
164  * 
165  * 18    11/11/96 4:03p Lawrance
166  * 
167  * 17    11/08/96 10:00a Lawrance
168  * 
169  * 16    11/06/96 8:54a Lawrance
170  * added revision templates, made more efficient
171  *
172  * $NoKeywords: $
173  *
174 */
175
176
177 #include <stdlib.h>
178
179 #include "pstypes.h"
180 #include "2d.h"
181 #include "pcxutils.h"
182 #include "key.h"
183 #include "optionsmenu.h"        // need the #defines for the menu choices
184 #include "techmenu.h"           // need the #defines for the menu choices
185 #include "trainingmenu.h"       // need the #defines for the menu choices
186 #include "font.h"
187 #include "mouse.h"
188 #include "snazzyui.h"
189 #include "cfile.h"
190 #include "hudconfig.h"
191 #include "gamesequence.h"
192 #include "hud.h"
193 #include "sound.h"
194 #include "gamesnd.h"
195 #include "freespace.h"
196 #include "alphacolors.h"
197 #include "localize.h"
198
199
200 extern int ascii_table[];
201 extern int shifted_ascii_table[];
202
203 static int Snazzy_mouse_left_was_down;
204
205 void snazzy_flush()
206 {
207         Snazzy_mouse_left_was_down = 0;
208 }
209
210 void snazzy_menu_init()
211 {
212         game_flush();
213 }
214
215 // snazzy_menu_do()
216 //
217 // This function will return an identifier that matches the region of the
218 // image the mouse pointer is currently over.  The function works by working
219 // with two images
220 //
221 // 1. An image that is displayed to the player
222 // 2. A second image, not seen, which has masks for certain areas of image 1
223 //
224 // The idea is to read the mouse, and determine if the mouse pointer is currently
225 // over one of these regions.  Since these regions may be many different colors,
226 // the mask is checked instead, since the regions are always a uniform color
227 //
228 //      The action parameter is used to return whether the region is clicked on or simply
229 // has the mouse over it.  The #defines SNAZZY_OVER and SNAZZY_CLICKED are used.
230 //
231 // The purpose of the key_in parameter is to allow the caller to determine if any
232 // keys are pressed while within the snazzy_menu_do().  It is an optional parameter.
233 // 
234
235 int snazzy_menu_do(ubyte *data, int mask_w, int mask_h, int num_regions, MENU_REGION *regions, int *action, int poll_key, int *key)
236 {
237         int i, k, x, y, offset;
238         int choice = -1, mouse_on_choice = -1;
239         ubyte pixel_value;
240
241         Assert(data != NULL);
242         Assert(num_regions > 0);
243         Assert(regions != NULL);
244         
245         gr_reset_clip();  // don't remove
246         mouse_get_pos( &x, &y );
247
248         // boundary conditions
249         if((y > mask_h - 1) || (x > mask_w - 1)){
250                 pixel_value = 0;
251         } else {
252                 // check the pixel value under the mouse
253                 offset = y * mask_w + x;
254                 pixel_value = *(data + (offset));
255         }
256
257         *action = -1;
258
259         k = 0;
260         if ( poll_key ) {
261                 k = game_check_key();
262                 if (key)
263                         *key = k;  // pass keypress back to caller
264         }
265
266 //      if (mouse_down_count(MOUSE_LEFT_BUTTON) )       {
267         if ( !mouse_down(MOUSE_LEFT_BUTTON) && Snazzy_mouse_left_was_down ) {
268                 if (pixel_value >= 0)
269                         //nprintf(("Alan", "pixel val: %d\n", pixel_value));
270                         for (i=0; i < num_regions; i++) {
271                                 if (pixel_value == regions[i].mask) {
272                                         choice = regions[i].mask;
273                                         if ( regions[i].click_sound != -1 ) {
274                                                 snd_play( &Snds_iface[regions[i].click_sound], 0.0f );
275                                         }
276                                 }
277                         }       // end for
278         }
279
280         switch ( k ) {
281                 case KEY_ESC:
282                         choice = ESC_PRESSED;
283                         break;
284
285                 default:
286                         if ( k )
287                                 for (i=0; i<num_regions; i++) {
288                                         if ( !regions[i].key )
289                                                 continue;
290                                         if (ascii_table[k] == regions[i].key || shifted_ascii_table[k] == regions[i].key) {
291                                                 choice = regions[i].mask;
292                                                 if ( regions[i].click_sound != -1 ) {
293                                                         snd_play( &Snds_iface[regions[i].click_sound], 0.0f );
294                                                 }
295                                         }
296                         }       // end for
297
298                         break;
299
300         } // end switch
301
302         i = -1;
303         if (pixel_value >= 0) {
304                 for (i=0; i<num_regions; i++) {
305                         if (pixel_value == regions[i].mask) {
306                                 mouse_on_choice = regions[i].mask;      
307                                 break;
308                         }
309                 }       // end for
310         }
311
312         gr_set_color_fast(&Color_white);
313         gr_set_font( FONT1 );
314
315         if ((mouse_on_choice >= 0) && (mouse_on_choice <= (num_regions)) && (i >=0)) {
316                 gr_printf( 0x8000, 450, regions[i].text );
317         }
318
319         if ( mouse_down(MOUSE_LEFT_BUTTON) ){
320                 Snazzy_mouse_left_was_down = 1;
321         } else {
322                 Snazzy_mouse_left_was_down = 0;
323         }
324         
325         if ( choice > -1 || choice == ESC_PRESSED ) {
326                 *action = SNAZZY_CLICKED;
327                 return choice;
328         }
329
330         if ( mouse_on_choice > -1 ) {
331                 *action = SNAZZY_OVER;
332                 return mouse_on_choice;
333         }
334
335         return -1;
336 }
337
338 // add_region() will set up a menu region
339 //
340 //
341 //
342
343 void snazzy_menu_add_region(MENU_REGION* region, char* text, int mask, int key, int click_sound)
344 {
345         region->mask = mask;
346         region->key = key;
347         strcpy(region->text, text);
348         region->click_sound = click_sound;
349 }
350  
351
352
353 // read_menu_tbl() will parse through menu.tbl and store the different menu region data
354 //
355 //
356 //
357
358 void read_menu_tbl(char* menu_name, char* bkg_filename, char* mask_filename, MENU_REGION* regions, int* num_regions, int play_sound)
359 {
360         CFILE* fp;
361         int state=0;
362         char* p1, *p2, *p3;
363         //char music_filename[128];
364
365         char seps[]   = NOX(" ,\t");
366         char *token;
367         char tmp_line[132];
368
369         *num_regions=0;
370
371         // open localization
372         lcl_ext_open();
373
374         fp = cfopen( NOX("menu.tbl"), "rt" );
375         if (fp == NULL) {
376                 Error(LOCATION, "menu.tbl could not be opened\n");
377
378                 // close localization
379                 lcl_ext_close();
380
381                 return;
382         }
383
384
385         while (cfgets(tmp_line, 132, fp)) {
386                 p1 = strchr(tmp_line,'\n'); if (p1) *p1 = '\0';
387                 p1 = strchr(tmp_line,';'); if (p1) *p1 = '\0';
388                 p1 = p3 = strchr( tmp_line, '[' );
389
390                 if (p3 && state == 1) { 
391                         // close localization
392                         lcl_ext_close();
393
394                         cfclose(fp);
395                         return;
396                 }
397                 
398                 if ( p1 || p3)  {
399                         if (!state)     {
400                                 p2 = strchr( tmp_line, ']' );
401                                 if (p2) *p2 = 0;
402                                 if (!stricmp( ++p1, menu_name )) state = 1;
403                         } else {
404                                 cfclose(fp);
405                                 break;
406                         }
407                 } else if (state) {
408                         
409                 
410                         // parse a region line
411                         p1 = strchr( tmp_line, '\"' );
412                         if (p1) {
413                                 p2 = strchr( tmp_line+1, '\"' );
414                                 if (!p2) {
415                                         nprintf(("Warning","Error parsing menu file\n"));
416
417                                         // close localization
418                                         lcl_ext_close();
419
420                                         return;
421                                 }
422                                 *p2 = 0;
423                                 strcpy(regions[*num_regions].text,++p1);
424                                 p2++;
425
426                                 // get the tokens mask number
427                                 token = strtok( p2, seps );
428                                 regions[*num_regions].mask = atoi(token);
429                                 
430                                 // get the hot key character
431                                 token = strtok( NULL, seps );
432                                 regions[*num_regions].key = token[0];
433
434                                 // stuff default click sound (not in menu.tbl)
435                                 if ( play_sound ) {
436                                         regions[*num_regions].click_sound = SND_IFACE_MOUSE_CLICK;
437                                 } else {
438                                         regions[*num_regions].click_sound = -1;
439                                 }
440
441                                 *num_regions = *num_regions + 1;
442
443                         }
444                                 else {
445                                 // get the menu filenames
446
447                                 // Establish string and get the first token
448                                 token = strtok( tmp_line, seps );
449                                 if ( token != NULL )
450                                 {
451                                         // store the background filename
452                                         strcpy(bkg_filename, token);
453
454                                         // get the mask filename
455                                         token = strtok( NULL, seps );
456                                         strcpy(mask_filename, token);
457                                 }
458                         }
459                 }
460         }       
461         cfclose(fp);
462         
463         // close localization
464         lcl_ext_close();
465 }
466
467 // snazzy_menu_close() is called when the menu using a snazzy interface is exited
468 //
469 //
470
471 void snazzy_menu_close()
472 {
473         game_flush();
474 }
475