]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/optionsmenu.cpp
Initial revision
[taylor/freespace2.git] / src / menuui / optionsmenu.cpp
1 /*
2  * $Logfile: /Freespace2/code/MenuUI/OptionsMenu.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * C module that contains functions to drive the Options user interface
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:09  root
11  * Initial revision
12  *
13  * 
14  * 31    10/25/99 5:47p Jefff
15  * reassigned some xstr ids
16  * 
17  * 30    10/14/99 2:50p Jefff
18  * localization fixes
19  * 
20  * 29    9/13/99 6:07p Jefff
21  * took out audiostream pausing to allow for correct volume adjustments
22  * 
23  * 28    9/09/99 2:28p Jefff
24  * some detail slider #defines were switched around
25  * 
26  * 27    9/08/99 2:38p Jefff
27  * sound pausing going to menu from game
28  * 
29  * 26    8/05/99 3:40p Jefff
30  * hi-res text adjustments
31  * 
32  * 25    8/04/99 4:06p Jefff
33  * fixed volume sliders blacking out at master volume of 1.0
34  * 
35  * 24    8/02/99 6:05p Jefff
36  * failure sound on skill slider when disabled in game
37  * 
38  * 23    7/19/99 3:29p Dave
39  * Fixed gamma bitmap in the options screen.
40  * 
41  * 22    7/19/99 2:13p Dave
42  * Added some new strings for Heiko.
43  * 
44  * 21    7/18/99 9:54p Andsager
45  * Demo build clean up
46  * 
47  * 20    7/15/99 7:15p Jefff
48  * Added sounds for skill select
49  * 
50  * 19    7/15/99 4:10p Andsager
51  * Disable control_config hud_config in FS2_DEMO
52  * 
53  * 18    7/15/99 9:20a Andsager
54  * FS2_DEMO initial checkin
55  * 
56  * 17    7/13/99 1:15p Dave
57  * 32 bit support. Whee!
58  * 
59  * 16    7/09/99 5:54p Dave
60  * Seperated cruiser types into individual types. Added tons of new
61  * briefing icons. Campaign screen.
62  * 
63  * 15    6/25/99 11:59a Dave
64  * Multi options screen.
65  * 
66  * 14    6/24/99 12:34a Dave
67  * Main options screen.
68  * 
69  * 13    6/22/99 7:03p Dave
70  * New detail options screen.
71  * 
72  * 12    6/16/99 4:06p Dave
73  * New pilot info popup. Added new draw-bitmap-as-poly function.
74  * 
75  * 11    5/24/99 5:45p Dave
76  * Added detail levels to the nebula, with a decent speedup. Split nebula
77  * lightning into its own section.
78  * 
79  * 10    4/02/99 4:44p Jasenw
80  * 
81  * 9     2/05/99 7:22p Neilk
82  * Fixed gamma bitmap and converted coordinates for multiple resolutions
83  * 
84  * 8     1/30/99 5:08p Dave
85  * More new hi-res stuff.Support for nice D3D textures.
86  * 
87  * 7     12/18/98 1:13a Dave
88  * Rough 1024x768 support for Direct3D. Proper detection and usage through
89  * the launcher.
90  * 
91  * 6     11/30/98 1:07p Dave
92  * 16 bit conversion, first run.
93  * 
94  * 5     11/05/98 5:55p Dave
95  * Big pass at reducing #includes
96  * 
97  * 4     10/13/98 9:28a Dave
98  * Started neatening up freespace.h. Many variables renamed and
99  * reorganized. Added AlphaColors.[h,cpp]
100  * 
101  * 3     10/09/98 2:57p Dave
102  * Starting splitting up OS stuff.
103  * 
104  * 2     10/07/98 10:53a Dave
105  * Initial checkin.
106  * 
107  * 1     10/07/98 10:49a Dave
108  * 
109  * 123   6/12/98 7:13p Hoffoss
110  * Fixed options screen problem where it wasn't showing tooltips.
111  * 
112  * 122   6/12/98 4:52p Hoffoss
113  * Added support for special characters in in forgeign languages.
114  * 
115  * 121   6/09/98 10:31a Hoffoss
116  * Created index numbers for all xstr() references.  Any new xstr() stuff
117  * added from here on out should be added to the end if the list.  The
118  * current list count can be found in FreeSpace.cpp (search for
119  * XSTR_SIZE).
120  * 
121  * 120   6/05/98 9:50a Lawrance
122  * OEM changes
123  * 
124  * 119   6/01/98 11:43a John
125  * JAS & MK:  Classified all strings for localization.
126  * 
127  * 118   5/24/98 4:42p Dan
128  * AL: Fix several bugs related to pausing and enabling/disabling event
129  * music
130  * 
131  * 117   5/20/98 5:18p John
132  * Made the gamma box draw as a bitmap, not a bunch of pixels.  Speeds up
133  * the menu dramatically.
134  * 
135  * 116   5/19/98 1:21p Duncan
136  * Use 'InterfacePalette' instad of 'OptionsMainPalette'
137  * 
138  * 115   5/18/98 9:14p Dave
139  * Put in network config files support.
140  * 
141  * 114   5/18/98 5:16p Hoffoss
142  * Changed code to use new palette Jasen told me to use.
143  * 
144  * 113   5/16/98 3:40p Lawrance
145  * Don't restore the original details unless they've been stored!
146  * 
147  * 112   5/13/98 10:03a Mitri
148  * AL: Fix some bugs as a result of recent rearranging of code
149  * 
150  * 111   5/13/98 12:24a Lawrance
151  * Only load required bitmaps and masks for the options screen
152  * 
153  * 110   5/08/98 3:52p Hoffoss
154  * Fixed placement of gamma graphic.
155  * 
156  * 109   5/07/98 12:41p Hoffoss
157  * Added joystick deadzone slider support and mouse on/off support.
158  * 
159  * 108   5/06/98 8:06p Dave
160  * Made standalone reset properly under weird conditions. Tweak
161  * optionsmulti screen. Upped MAX_WEAPONS to 350. Put in new launch
162  * countdown anim. Minro ui fixes/tweaks.
163  * 
164  * 107   5/05/98 8:38p Hoffoss
165  * Added sensitivity adjustment to options menu and made it save to pilot
166  * file.
167  * 
168  * 106   4/27/98 9:00a Jasen
169  * Updated coords for button change.
170  * 
171  * 105   4/25/98 3:33p Allender
172  * do exit confirmation
173  * 
174  * 104   4/22/98 12:34a Dave
175  * Make sure hud config and control config buttons draw properly in all
176  * tab modes. Make small tab buttons light up correctly in multi options
177  * screen.
178  * 
179  * 103   4/21/98 12:14a Allender
180  * disable skill level buttons for multiplayer games
181  * 
182  * 102   4/20/98 6:04p Dave
183  * Implement multidata cache flushing and xferring mission files to
184  * multidata. Make sure observers can't change hud config. Fix pilot image
185  * viewing in popup. Put in game status field. Tweaked multi options. 
186  * 
187  * 101   4/18/98 12:45p Dave
188  * Aesthetic changes to multi options screen. Put in missing exit button.
189  * oops.
190  * 
191  * 100   4/17/98 5:27p Dave
192  * More work on the multi options screen. Fixed many minor ui todo bugs.
193  *  
194  *
195  * $NoKeywords: $
196  *
197 */
198
199 #include "grinternal.h"
200 #include "ui.h"
201 #include "missionscreencommon.h"
202 #include "bmpman.h"
203 #include "gamesequence.h"
204 #include "key.h"
205 #include "managepilot.h"
206 #include "freespace.h"
207 #include "gamesnd.h"
208 #include "sound.h"
209 #include "eventmusic.h"
210 #include "mainhallmenu.h"
211 #include "audiostr.h"
212 #include "multi.h"
213 #include "psnet.h"
214 #include "popup.h"
215 #include "popupdead.h"
216 #include "missionbriefcommon.h"
217 #include "optionsmenu.h"
218 #include "optionsmenumulti.h"
219 #include "joy.h"
220 #include "mouse.h"
221 #include "osregistry.h"
222 #include "alphacolors.h"
223 #include "timer.h"
224 #include "neb.h"
225 #include "beam.h"
226
227
228 // will display a notification warning message
229 #define OPTIONS_NOTIFY_TIME                     3500
230 #define OPTIONS_NOTIFY_Y            450
231
232 #define NUM_BUTTONS     24
233 #define NUM_ANIS                4
234 #define NUM_TABS                3
235 #define NUM_COMMONS     10
236
237 #define TABLESS                                                 999
238
239 #define OPTIONS_TAB                                             0
240 #define MULTIPLAYER_TAB                                 1
241 #define DETAIL_LEVELS_TAB                               2
242 #define ABORT_GAME_BUTTON                               3
243 #define CONTROL_CONFIG_BUTTON                   4
244 #define HUD_CONFIG_BUTTON                               5
245 #define ACCEPT_BUTTON                                   6
246
247 #define BRIEF_VOICE_OFF                                 7
248 #define BRIEF_VOICE_ON                                  8
249 #define MOUSE_OFF                                                       9
250 #define MOUSE_ON                                                        10
251 #define GAMMA_DOWN                                              11
252 #define GAMMA_UP                                                        12
253
254 // detail level screen buttons
255 #define PLANETS_ON                                              13
256 #define PLANETS_OFF                                             14
257 #define HUD_TARGETVIEW_RENDER_ON                15
258 #define HUD_TARGETVIEW_RENDER_OFF       16
259 #define WEAPON_EXTRAS_ON                                17
260 #define WEAPON_EXTRAS_OFF                               18
261
262 #define LOW_DETAIL_N                                            19
263 #define MEDIUM_DETAIL_N                                 20
264 #define HIGH_DETAIL_N                                   21
265 #define VERY_HIGH_DETAIL_N                              22
266 #define CUSTOM_DETAIL_N                                 23
267
268 #define REPEAT                                          (1<<0)
269 #define NO_MOUSE_OVER_SOUND     (1<<1)
270
271 // indicies for options coordinates
272 #define OPTIONS_X_COORD 0
273 #define OPTIONS_Y_COORD 1
274 #define OPTIONS_W_COORD 2
275 #define OPTIONS_H_COORD 3
276
277 struct options_buttons {
278         char *filename;
279         int x, y;
280         int hotspot;
281         int tab;
282         int flags;
283         UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..
284
285         options_buttons(char *name, int x1, int y1, int h, int t, int f = 0) : filename(name), x(x1), y(y1), hotspot(h), tab(t), flags(f) {}
286 };
287
288 options_buttons Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
289         {       // GR_640
290                 options_buttons("OPT_00",       17,     2,              0,              -1),                                                    // options tab
291                 options_buttons("OPT_01",       102,    2,              1,              -1),                                                    // multiplayer tab
292                 options_buttons("OPT_02",       170,    2,              2,              -1),                                                    // detail levels tab
293                 options_buttons("OPT_03",       10,     444,    3,              -1),                                                    // abort game button
294                 options_buttons("OPT_04",       411,    444,    4,              -1),                                                    // control config button
295                 options_buttons("OPT_05",       506,    444,    5,              -1),                                                    // hud config
296                 options_buttons("OPT_06",       576,    434,    6,              -1),                                                    // accept button                                
297
298                 options_buttons("OMB_07",       51,     74,     7,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle off
299                 options_buttons("OMB_08",       106,    74,     8,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle on
300                 options_buttons("OMB_18",       51,     266,    18,     OPTIONS_TAB, 2),                        // Mouse off
301                 options_buttons("OMB_19",       106,    266,    19,     OPTIONS_TAB, 2),                        // Mouse on
302                 options_buttons("OMB_26",       578,    149,    26,     OPTIONS_TAB, 1),                        // Gamma Down
303                 options_buttons("OMB_27",       607,    149,    27,     OPTIONS_TAB, 1),                        // Gamma Up
304                 
305                 options_buttons("ODB_21",       597,    261,    21,     DETAIL_LEVELS_TAB, 2),  // Planets On
306                 options_buttons("ODB_20",       539,    261,    20,     DETAIL_LEVELS_TAB, 2),  // Planets Off
307                 options_buttons("ODB_23",       597,    307,    23,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering On
308                 options_buttons("ODB_22",       539,    307,    22,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering Off
309                 options_buttons("ODB_25",       597,    354,    25,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras On
310                 options_buttons("ODB_24",       539,    354,    24,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras Off
311
312                 options_buttons("ODB_14",       614,    76,     14,     DETAIL_LEVELS_TAB, 2),  // Low Preset Detail
313                 options_buttons("ODB_15",       614,    96,     15,     DETAIL_LEVELS_TAB, 2),  // Medium Preset Detail
314                 options_buttons("ODB_16",       614,    114,    16,     DETAIL_LEVELS_TAB, 2),  // High Preset Detail
315                 options_buttons("ODB_17",       614,    133,    17,     DETAIL_LEVELS_TAB, 2),  // Highest Preset Detail
316                 options_buttons("ODB_18",       614,    152,    18,     DETAIL_LEVELS_TAB, 2),  // Custom Detail
317         },
318         {       // GR_1024
319                 options_buttons("2_OPT_00",     27,     4,              0,              -1),                                            // options tab
320                 options_buttons("2_OPT_01",     164,    4,              1,              -1),                                            // multiplayer tab
321                 options_buttons("2_OPT_02",     272,    4,              2,              -1),                                            // detail levels tab
322                 options_buttons("2_OPT_03",     16,     711,    3,              -1),                                            // abort game
323                 options_buttons("2_OPT_04",     657,    711,    4,              -1),                                            // control config button
324                 options_buttons("2_OPT_05",     809,    711,    5,              -1),                                            // hud config button
325                 options_buttons("2_OPT_06",     922,    694,    6,              -1),                                            // accept button                
326
327                 options_buttons("2_OMB_07",     81,     118,    7,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle off
328                 options_buttons("2_OMB_08",     170,    118,    8,              OPTIONS_TAB, 2),                        // Briefing / debriefing voice toggle on
329                 options_buttons("2_OMB_18",     81,     425,    18,     OPTIONS_TAB, 2),                        // Mouse off
330                 options_buttons("2_OMB_19",     170,    425,    19,     OPTIONS_TAB, 2),                        // Mouse on
331                 options_buttons("2_OMB_26",     925,    238,    26,     OPTIONS_TAB, 1),                        // Gamma Down
332                 options_buttons("2_OMB_27",     971,    238,    27,     OPTIONS_TAB, 1),                        // Gamma Up
333                 
334                 options_buttons("2_ODB_21",     956,    417,    21,     DETAIL_LEVELS_TAB, 2),  // Planets On
335                 options_buttons("2_ODB_20",     863,    417,    20,     DETAIL_LEVELS_TAB, 2),  // Planets Off
336                 options_buttons("2_ODB_23",     956,    492,    23,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering On
337                 options_buttons("2_ODB_22",     863,    492,    22,     DETAIL_LEVELS_TAB, 2),  // Target View Rendering Off
338                 options_buttons("2_ODB_25",     956,    567,    25,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras On
339                 options_buttons("2_ODB_24",     863,    567,    24,     DETAIL_LEVELS_TAB, 2),  // Weapon Extras Off
340
341                 options_buttons("2_ODB_14",     983,    122,    14,     DETAIL_LEVELS_TAB, 2),  // Low Preset Detail
342                 options_buttons("2_ODB_15",     983,    153,    15,     DETAIL_LEVELS_TAB, 2),  // Medium Preset Detail
343                 options_buttons("2_ODB_16",     983,    183,    16,     DETAIL_LEVELS_TAB, 2),  // High Preset Detail
344                 options_buttons("2_ODB_17",     983,    213,    17,     DETAIL_LEVELS_TAB, 2),  // Highest Preset Detail
345                 options_buttons("2_ODB_18",     983,    243,    18,     DETAIL_LEVELS_TAB, 2),  // Custom Detail
346         }       
347 };
348
349 #define NUM_OPTIONS_SLIDERS                     7
350 #define OPT_SOUND_VOLUME_SLIDER         0
351 #define OPT_MUSIC_VOLUME_SLIDER         1
352 #define OPT_VOICE_VOLUME_SLIDER         2
353 #define OPT_MOUSE_SENS_SLIDER                   3
354 #define OPT_JOY_SENS_SLIDER                     4
355 #define OPT_JOY_DEADZONE_SLIDER         5
356 #define OPT_SKILL_SLIDER                                6
357
358 op_sliders Options_sliders[GR_NUM_RESOLUTIONS][NUM_OPTIONS_SLIDERS] = {
359         { // GR_640             
360                 op_sliders("OMB_10",            31,     139,    -1,     -1,     10,     20,     10,
361                                           "OMB_11",             11,     226,    137,
362                                           "OMB_09",             9,              4,              137 ),                                                          // sound fx volume slider
363                 op_sliders("OMB_13",            31,     174,    -1,     -1,     13,     20,     10,
364                                           "OMB_14",             14,     226,    172,
365                                           "OMB_12",             12,     4,              172 ),                                                          // music volume slider
366                 op_sliders("OMB_16",            31,     209,    -1,     -1,     16,     20,     10,
367                                           "OMB_17",             17,     226,    206,
368                                           "OMB_15",             15,     4,              206 ),                                                          // voice volume slider
369                 op_sliders("OMB_20",            6,              316,    -1,     -1,     20,     20,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // mouse sensitivity    
370                 op_sliders("OMB_28",            440,    259,    -1,     -1,     28,     20,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick sensitivity
371                 op_sliders("OMB_29",            440,    290,    -1,     -1,     29,     20,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick deadzone
372                 op_sliders("OMB_21",            440,    75,     -1,     -1,     21,     36,     5,      NULL, -1, -1, -1, NULL, -1, -1, -1)
373         },      
374         { // GR_1024            
375                 op_sliders("2_OMB_10",          50,     223,    -1,     -1,     10,     32,     10,
376                                           "2_OMB_11",           11,     361,    219,
377                                           "2_OMB_09",           9,              7,              219 ),                                                          // sound fx volume slider
378                 op_sliders("2_OMB_13",          50,     281,    -1,     -1,     13,     32,     10,
379                                           "2_OMB_14",           14,     361,    275,
380                                           "2_OMB_12",           12,     7,              275 ),                                                          // music volume slider
381                 op_sliders("2_OMB_16",          50,     335,    -1,     -1,     16,     32,     10,
382                                           "2_OMB_17",           17,     361,    330,
383                                           "2_OMB_15",           15,     7,              330 ),                                                          // voice volume slider
384                 op_sliders("2_OMB_20",          9,              505,    -1,     -1,     20,     32,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // mouse sensitivity    
385                 op_sliders("2_OMB_28",          704,    414,    -1,     -1,     28,     32,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick sensitivity
386                 op_sliders("2_OMB_29",          704,    464,    -1,     -1,     29,     32,     10, NULL, -1, -1, -1, NULL, -1, -1, -1),        // joystick deadzone
387                 op_sliders("2_OMB_21",          704,    120,    -1,     -1,     21,     60,     5,      NULL, -1, -1, -1, NULL, -1, -1, -1)
388         }
389 };
390
391 static struct {
392         char *filename;
393         char *mask_filename;
394         int bitmap;
395         int mask;
396         
397 } Backgrounds[GR_NUM_RESOLUTIONS][NUM_TABS] = {
398 //XSTR:OFF
399         {       // GR_640
400                 { "OptionsMain", "OptionsMain-M"},
401                 { "OptionsMulti", "OptionsMulti-M"},
402                 { "OptionsDetail", "OptionsDetail-M"},
403         },
404         {       // GR_1024
405                 { "2_OptionsMain", "2_OptionsMain-M"},
406                 { "2_OptionsMulti", "2_OptionsMulti-M"},
407                 { "2_OptionsDetail", "2_OptionsDetail-M"},
408         }
409 //XSTR:ON
410 };
411
412 static int Tab = 0;
413 static int Options_menu_inited = 0;
414 static int Options_multi_inited = 0;
415 static int Options_detail_inited = 0;
416 static int Button_bms[NUM_COMMONS][MAX_BMAPS_PER_GADGET];
417
418 static UI_WINDOW Ui_window;
419 UI_GADGET Options_bogus;
420
421 static int Backup_skill_level;
422 static float Backup_sound_volume;
423 static float Backup_music_volume;
424 static float Backup_voice_volume;
425
426 static int Backup_briefing_voice_enabled;
427 static int Backup_use_mouse_to_fly;
428
429 static int Sound_volume_int;
430 static int Music_volume_int;
431 static int Voice_volume_int;
432
433 static int Voice_vol_handle = -1;
434 int Options_notify_stamp = -1;
435 char Options_notify_string[200];
436
437 // called whenever accept is hit
438 // do any processing, etc in here.
439 void options_accept();
440 void options_force_button_frame(int n, int frame_num);
441
442 extern float Freespace_gamma;
443
444 void options_add_notify(char *str);
445 void options_notify_do_frame();
446
447 int Options_gamma_coords[GR_NUM_RESOLUTIONS][4] = {
448         {
449                 435, 179, 195,  28      // GR_640
450         },
451         {
452                 692, 287, 308, 44               // GR_1024
453         }
454 };
455
456 #define MAX_GAMMA_BITMAP_SIZE 17500
457
458 int Options_gamma_num_coords[GR_NUM_RESOLUTIONS][4] = {
459         {
460                 489, 159, 65, 17                // GR_640
461         },
462         {
463                 779, 254, 65, 17                // GR_1024
464         }
465 };
466
467 int Options_skills_text_coords[GR_NUM_RESOLUTIONS][4] = {
468         {
469                 468, 104, 155, 10               // GR_640
470         },
471         {
472                 750, 169, 246, 21               // GR_1024
473         }
474 };
475
476
477 // ---------------------------------------------------------------------------------------------------------
478 // DETAIL LEVEL OPTIONS definitions  BEGIN
479 //
480
481 #define NUM_DETAIL_SLIDERS                      8
482
483 /*
484 #define DETAIL_DISTANCE_SLIDER  0
485 #define NEBULA_DETAIL_SLIDER            1
486 #define HARDWARE_TEXTURES_SLIDER        2
487 #define NUM_PARTICLES_SLIDER            6
488 #define SHARD_CULLING_SLIDER            3
489 #define SHIELD_DETAIL_SLIDER            4
490 #define NUM_STARS_SLIDER                        5
491 #define LIGHTING_SLIDER                         7
492 */
493 #define DETAIL_DISTANCE_SLIDER  0
494 #define NEBULA_DETAIL_SLIDER            1
495 #define HARDWARE_TEXTURES_SLIDER        2
496 #define NUM_PARTICLES_SLIDER            3
497 #define SHARD_CULLING_SLIDER            4
498 #define SHIELD_DETAIL_SLIDER            5
499 #define NUM_STARS_SLIDER                        6
500 #define LIGHTING_SLIDER                         7
501 op_sliders Detail_sliders[GR_NUM_RESOLUTIONS][NUM_DETAIL_SLIDERS] = {
502         { // GR_640
503                 op_sliders("ODB_07",    21,     71,     -1,     -1,     7,              20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // model detail
504                 op_sliders("ODB_08",    21,     119,    -1,     -1,     8,              20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // nebula detail
505                 op_sliders("ODB_09",    21,     166,    -1,     -1,     9,              20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // textures
506                 op_sliders("ODB_10",    21,     212,    -1,     -1,     10,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // particles
507                 op_sliders("ODB_11",    21,     260,    -1,     -1,     11,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // debris
508                 op_sliders("ODB_12",    21,     307,    -1,     -1,     12,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // shield hit
509                 op_sliders("ODB_13",    21,     354,    -1,     -1,     13,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // stars
510                 op_sliders("ODB_19",    518,    212,    -1,     -1,     19,     20,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),                 // lighting             
511         },      
512         { // GR_1024
513                 op_sliders("2_ODB_07",  34,     114,    -1,     -1,     7,              32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // model detail
514                 op_sliders("2_ODB_08",  34,     190,    -1,     -1,     8,              32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // nebula detail
515                 op_sliders("2_ODB_09",  34,     265,    -1,     -1,     9,              32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // textures
516                 op_sliders("2_ODB_10",  34,     340,    -1,     -1,     10,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // particles
517                 op_sliders("2_ODB_11",  34,     416,    -1,     -1,     11,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // debris
518                 op_sliders("2_ODB_12",  34,     492,    -1,     -1,     12,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // shield hit
519                 op_sliders("2_ODB_13",  34,     567,    -1,     -1,     13,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // stars
520                 op_sliders("2_ODB_19",  829,    340,    -1,     -1,     19,     32,     5, NULL, -1, -1, -1, NULL, -1, -1, -1),         // lighting
521         }
522 };
523 int Detail_slider_pos[NUM_DETAIL_SLIDERS];
524 detail_levels Detail_original;  // backup of Detail settings when screen is first entered
525 UI_GADGET Detail_bogus;
526 void options_detail_init();
527 void options_detail_hide_stuff();
528 void options_detail_unhide_stuff();
529 void options_detail_do_frame();
530 void options_detail_set_level(int level);
531
532 // text
533 #define OPTIONS_NUM_TEXT                                49
534 UI_XSTR Options_text[GR_NUM_RESOLUTIONS][OPTIONS_NUM_TEXT] = {
535         { // GR_640
536                 // common text
537                 { "Options",    1036,           10,     35,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][OPTIONS_TAB].button },
538                 { "Multi",              1042,           97,     35,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][MULTIPLAYER_TAB].button },
539                 { "Detail",             1351,           166,    35,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][DETAIL_LEVELS_TAB].button },
540                 { "Exit",               1059,           8,              417,    UI_XSTR_COLOR_PINK,     -1, &Buttons[0][ABORT_GAME_BUTTON].button },
541                 { "Game",               1412,           8,              430,    UI_XSTR_COLOR_PINK,     -1, &Buttons[0][ABORT_GAME_BUTTON].button },
542                 { "Control",    1352,           409,    418,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][CONTROL_CONFIG_BUTTON].button },
543                 { "Config",             1353,           409,    430,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][CONTROL_CONFIG_BUTTON].button },
544                 { "HUD",                        1354,           504,    418,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_CONFIG_BUTTON].button },
545                 { "Config",             1415,           504,    430,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_CONFIG_BUTTON].button },
546                 { "Accept",             1035,           573,    412,    UI_XSTR_COLOR_PINK,     -1, &Buttons[0][ACCEPT_BUTTON].button },
547
548                 // text for the detail level screen 
549                 { "Preset Detail Levels",       1355,   455,    56,     UI_XSTR_COLOR_GREEN,    -1, &Detail_bogus },
550                 { "Low",                        1160,           570,    82,     UI_XSTR_COLOR_GREEN, -1, &Buttons[0][LOW_DETAIL_N].button },
551                 { "Medium",             1161,           550,    100,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][MEDIUM_DETAIL_N].button },
552                 { "High",               1162,           568,    120,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][HIGH_DETAIL_N].button },
553                 { "Very High",  1163,           530,    139,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][VERY_HIGH_DETAIL_N].button },
554                 { "Custom",             1356,           546,    158,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CUSTOM_DETAIL_N].button },         
555                 { "Off",                        1286,           509,    267,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][PLANETS_OFF].button },
556                 { "On",                 1285,           573,    267,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][PLANETS_ON].button },
557                 { "Off",                        1286,           509,    314,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_TARGETVIEW_RENDER_OFF].button },
558                 { "On",                 1285,           573,    314,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][HUD_TARGETVIEW_RENDER_ON].button },
559                 { "Off",                        1286,           509,    361,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][WEAPON_EXTRAS_OFF].button },
560                 { "On",                 1285,           573,    361,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][WEAPON_EXTRAS_ON].button },
561                 { "Planets/Backgrounds",                1357,   455,    244, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
562                 { "Target View Rendering",              1358,   446,    291, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
563                 { "Weapon Extras",                              1359,   497,    338, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
564                 { "Model Detail",                                       1360,   27,     56,     UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
565                 { "Nebula Detail",                              1361,   27,     103,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
566                 { "3D Hardware Textures",               1362,   27,     150,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
567                 { "Particles",                                          1363,   27,     197,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
568                 { "Impact Effects",                             1364,   27,     244,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
569                 { "Shield Hit Effects",                 1365,   27,     291,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
570                 { "Stars",                                                      1366,   27,     338,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
571                 { "Lighting",                                           1367, 549,      197,    UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
572
573                 // main options screen text
574                 { "Briefing Voice",     1368,   14,     58,     UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
575                 { "Off",                                        1286,   20,     81,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][BRIEF_VOICE_OFF].button },
576                 { "On",                                 1285,   83,     81,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][BRIEF_VOICE_ON].button },
577                 { "Volume",                             1369,   14,     111,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
578                 { "Effects",                    1370,   20,     130,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
579                 { "Music",                              1371,   20,     165,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
580                 { "Voice",                              1372,   20,     199,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
581                 { "Mouse",                              1373,   14,     249,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
582                 { "Off",                                        1286,   20,     273,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][MOUSE_OFF].button },
583                 { "On",                                 1285,   83,     273,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[0][MOUSE_ON].button },
584                 { "Sensitivity",                1529,   20,     297,    UI_XSTR_COLOR_GREEN,    -1, &Options_sliders[0][OPT_MOUSE_SENS_SLIDER].slider },
585                 { "Skill Level",                1509,   533,    58,     UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
586                 { "Brightness",         1375,   532,    133,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
587                 { "Joystick",                   1376,   556,    231,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
588                 { "Sensitivity",                1374,   538,    250,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
589                 { "Deadzone",                   1377,   538,    281,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
590         },
591         { // GR_1024
592                         // common text
593                 { "Options",    1036,           16,     57,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][OPTIONS_TAB].button },
594                 { "Multi",              1042,           172,    57,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][MULTIPLAYER_TAB].button },
595                 { "Detail",             1351,           283,    57,     UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][DETAIL_LEVELS_TAB].button },
596                 { "Exit",               1059,           13,     685,    UI_XSTR_COLOR_PINK,     -1, &Buttons[1][ABORT_GAME_BUTTON].button },
597                 { "Game",               1412,           13,     696,    UI_XSTR_COLOR_PINK,     -1, &Buttons[1][ABORT_GAME_BUTTON].button },
598                 { "Control",    1352,           655,    685,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][CONTROL_CONFIG_BUTTON].button },
599                 { "Config",             1353,           655,    696,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][CONTROL_CONFIG_BUTTON].button },
600                 { "HUD",                        1354,           806,    685,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][HUD_CONFIG_BUTTON].button },
601                 { "Config",             1415,           806,    696,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][HUD_CONFIG_BUTTON].button },
602                 { "Accept",             1035,           927,    672,    UI_XSTR_COLOR_PINK,     -1, &Buttons[1][ACCEPT_BUTTON].button },
603
604                 // text for the detail level screen 
605                 { "Preset Detail Levels",       1355,   809,    90,     UI_XSTR_COLOR_GREEN,    -1, &Detail_bogus },
606                 { "Low",                        1160,           944,    131,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][LOW_DETAIL_N].button },
607                 { "Medium",             1161,           924,    161,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][MEDIUM_DETAIL_N].button },
608                 { "High",               1162,           942,    192,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][HIGH_DETAIL_N].button },
609                 { "Very High",  1163,           903,    222,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][VERY_HIGH_DETAIL_N].button },
610                 { "Custom",             1356,           922,    252,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][CUSTOM_DETAIL_N].button },         
611                 { "Off",                        1286,           835,    427,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][PLANETS_OFF].button },
612                 { "On",                 1285,           936,    427,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][PLANETS_ON].button },
613                 { "Off",                        1286,           835,    503,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][HUD_TARGETVIEW_RENDER_OFF].button },
614                 { "On",                 1285,           936,    503,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][HUD_TARGETVIEW_RENDER_ON].button },
615                 { "Off",                        1286,           835,    578,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][WEAPON_EXTRAS_OFF].button },
616                 { "On",                 1285,           936,    578,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][WEAPON_EXTRAS_ON].button },
617                 { "Planets/Backgrounds",        1357,   808,    391, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
618                 { "Target View Rendering",      1358,   799,    466, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },
619                 { "Weapon Extras",                      1359,   850,    542, UI_XSTR_COLOR_GREEN, -1, &Detail_bogus },                          
620                 { "Model Detail",                                       1360,   44,     99,     UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][DETAIL_DISTANCE_SLIDER].slider },
621                 { "Nebula Detail",                              1361,   44,     175,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][NEBULA_DETAIL_SLIDER].slider },
622                 { "3D Hardware Textures",               1362,   44,     250,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][HARDWARE_TEXTURES_SLIDER].slider },
623                 { "Particles",                                          1363,   44,     325,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][NUM_PARTICLES_SLIDER].slider },
624                 { "Impact Effects",                             1364,   44,     401,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][SHARD_CULLING_SLIDER].slider },
625                 { "Shield Hit Effects",                 1365,   44,     476,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][SHIELD_DETAIL_SLIDER].slider },
626                 { "Stars",                                                      1366, 44,       552,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][NUM_STARS_SLIDER].slider },
627                 { "Lighting",                                           1367, 903,      326,    UI_XSTR_COLOR_GREEN, -1, &Detail_sliders[1][LIGHTING_SLIDER].slider },
628
629                 // main options screen text
630                 { "Briefing Voice",     1368,   23,     93,     UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
631                 { "Off",                                        1286,   32,     130,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][BRIEF_VOICE_OFF].button },
632                 { "On",                                 1285,   134,    130,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][BRIEF_VOICE_ON].button },
633                 { "Volume",                             1369,   23,     178,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
634                 { "Effects",                    1370,   33,     209,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
635                 { "Music",                              1371,   33,     264,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
636                 { "Voice",                              1372,   33,     319,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
637                 { "Mouse",                              1373,   23,     399,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
638                 { "Off",                                        1286,   32,     437,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][MOUSE_OFF].button },
639                 { "On",                                 1285,   134,    437,    UI_XSTR_COLOR_GREEN,    -1, &Buttons[1][MOUSE_ON].button },
640                 { "Sensitivity",                1529,   34,     477,    UI_XSTR_COLOR_GREEN,    -1, &Options_sliders[1][OPT_MOUSE_SENS_SLIDER].slider },
641                 { "Skill Level",                1509,   854,    93,     UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
642                 { "Brightness",         1375,   852,    214,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
643                 { "Joystick",                   1376,   891,    370,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
644                 { "Sensitivity",                1374,   861,    400,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
645                 { "Deadzone",                   1377,   861,    451,    UI_XSTR_COLOR_GREEN,    -1, &Options_bogus },
646         }
647 };
648
649
650 //
651 // DETAIL LEVEL tab definitions END
652 // ---------------------------------------------------------------------------------------------------------
653
654 void options_play_voice_clip()
655 {
656         int snd_id;
657
658         if ( snd_is_playing(Voice_vol_handle) ) {
659                 snd_stop(Voice_vol_handle);
660                 Voice_vol_handle=-1;
661         }
662
663         snd_id = snd_load(&Snds_iface[SND_VOICE_SLIDER_CLIP]);
664         Voice_vol_handle = snd_play_raw( snd_id, 0.0f, 1.0f, SND_PRIORITY_SINGLE_INSTANCE );
665 }
666
667 void options_add_notify(char *str)
668 {
669         strcpy(Options_notify_string, str);
670         Options_notify_stamp = timestamp(OPTIONS_NOTIFY_TIME);
671 }
672
673 void options_notify_do_frame()
674 {
675         int w,h;
676
677         if (Options_notify_stamp != -1) {
678                 if (timestamp_elapsed(Options_notify_stamp)) {
679                         Options_notify_stamp = -1;
680
681                 } else {
682                         gr_get_string_size(&w, &h, Options_notify_string);
683                         gr_printf((gr_screen.max_w - w) / 2, OPTIONS_NOTIFY_Y, Options_notify_string);
684                 }
685         }
686 }
687
688 /*
689 void options_set_bmaps(int btn, int bm_index)
690 {
691         int j;
692
693         for (j=0; j<MAX_BMAPS_PER_GADGET; j++){
694                 Buttons[gr_screen.res][btn].button.bmap_ids[j] = Button_bms[bm_index][j];
695         }
696 }
697 */
698
699 void options_tab_setup(int set_palette)
700 {
701         // char *pal;
702         int i;
703         int flags[256];
704
705         if (Tab != MULTIPLAYER_TAB) {
706                 Assert(Backgrounds[gr_screen.res][Tab].mask >= 0);
707                 Ui_window.set_mask_bmap(Backgrounds[gr_screen.res][Tab].mask, Backgrounds[gr_screen.res][Tab].mask_filename);
708         }
709
710         for (i=0; i<256; i++){
711                 flags[i] = 0;
712         }
713
714         // activate, deactivate any necessary controls
715         for (i=0; i<NUM_BUTTONS; i++) {
716                 if ( ((Buttons[gr_screen.res][i].tab == Tab) || (Buttons[gr_screen.res][i].tab == -1)) && !flags[Buttons[gr_screen.res][i].hotspot] ) {
717                         flags[Buttons[gr_screen.res][i].hotspot] = 1;
718                         Buttons[gr_screen.res][i].button.enable();
719                         if (Buttons[gr_screen.res][i].filename)
720                                 Buttons[gr_screen.res][i].button.unhide();
721
722                 } else {
723                         Buttons[gr_screen.res][i].button.disable();
724                         Buttons[gr_screen.res][i].button.hide();
725                 }
726         }
727
728         // maybe enable/disable controls based upon current tab
729         if (Tab == OPTIONS_TAB) {
730                 for(i=0; i<NUM_OPTIONS_SLIDERS; i++){
731                         Options_sliders[gr_screen.res][i].slider.enable();
732                         Options_sliders[gr_screen.res][i].slider.unhide();
733                 }               
734         } else {
735                 for(i=0; i<NUM_OPTIONS_SLIDERS; i++){
736                         Options_sliders[gr_screen.res][i].slider.hide();
737                         Options_sliders[gr_screen.res][i].slider.disable();
738                 }               
739         }       
740
741         if( ((Game_mode & GM_IN_MISSION) && (!popupdead_is_active())) || (Game_mode & GM_MULTIPLAYER) ){
742                 Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.disable();
743                 Ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
744         }
745
746         // do other special processing
747         switch (Tab) {
748                 case MULTIPLAYER_TAB:
749 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
750                         options_multi_select();
751                         
752                         // need to hide the hud config and control config buttons
753                         // Buttons[gr_screen.res][CONTROL_CONFIG_BUTTON].button.hide();
754                         // Buttons[gr_screen.res][HUD_CONFIG_BUTTON].button.hide();
755 #endif // DEMO
756                         break;
757
758                 case DETAIL_LEVELS_TAB:
759                         options_detail_unhide_stuff();  
760                         break;
761         }
762 }
763
764 // call this function to close down, do other processing of data in the tab that's being left
765 void options_tab_close()
766 {
767         switch (Tab) {
768                 case MULTIPLAYER_TAB:
769 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
770                         options_multi_unselect();               
771 #endif
772                         break;
773
774                 case DETAIL_LEVELS_TAB:
775                         options_detail_hide_stuff();
776                         break;
777         }
778 }
779
780 void options_change_tab(int n)
781 {
782         int idx;
783
784 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
785         if (n == MULTIPLAYER_TAB) {
786                 game_feature_not_in_demo_popup();
787                 return;
788         }
789 #endif
790
791         switch (n) {
792                 case MULTIPLAYER_TAB:
793                         if ( !Options_multi_inited ) {
794                                 // init multiplayer
795 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
796                                 options_multi_init(&Ui_window);
797                                 options_multi_unselect();
798 #endif
799                                 Options_multi_inited = 1;
800                         }
801
802                         break;
803
804                 case DETAIL_LEVELS_TAB:
805                         if (!Options_detail_inited) {
806                                 // init detail levels
807                                 options_detail_init();
808                                 options_detail_hide_stuff();
809                                 Options_detail_inited = 1;
810                         }
811
812                         break;
813         }
814
815         // if we're going into the main screen
816         if(n == OPTIONS_TAB){
817                 Options_bogus.enable();
818                 Options_bogus.unhide();
819                 for(idx=0; idx<NUM_OPTIONS_SLIDERS; idx++){
820                         Options_sliders[gr_screen.res][idx].slider.enable();
821                         Options_sliders[gr_screen.res][idx].slider.unhide();
822                 }
823         } else {
824                 Options_bogus.hide();
825                 Options_bogus.disable();
826                 for(idx=0; idx<NUM_OPTIONS_SLIDERS; idx++){
827                         Options_sliders[gr_screen.res][idx].slider.hide();
828                         Options_sliders[gr_screen.res][idx].slider.disable();
829                 }
830         }
831
832         if (n != MULTIPLAYER_TAB) {
833                 if (Backgrounds[gr_screen.res][n].mask < 0) {
834                         gamesnd_play_iface(SND_GENERAL_FAIL);
835                         return;
836                 }
837         }
838
839         options_tab_close();
840
841         Tab = n;
842         options_tab_setup(1);
843         gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
844 }
845
846 void set_sound_volume()
847 {
848         main_hall_reset_ambient_vol();
849 }
850
851 void set_music_volume()
852 {
853         event_music_set_volume_all(Master_event_music_volume);
854 }
855
856 void set_voice_volume()
857 {
858         audiostream_set_volume_all(Master_voice_volume, ASF_VOICE);
859 }
860
861 void options_cancel_exit()
862 {
863         Master_sound_volume = Backup_sound_volume;
864         set_sound_volume();
865         Master_event_music_volume = Backup_music_volume;
866         set_music_volume();
867         Master_voice_volume = Backup_voice_volume;
868         set_voice_volume();
869
870         if(!(Game_mode & GM_MULTIPLAYER)){
871                 Game_skill_level = Backup_skill_level;
872         }
873
874         Briefing_voice_enabled = Backup_briefing_voice_enabled;
875         Use_mouse_to_fly = Backup_use_mouse_to_fly;
876
877         if ( Options_detail_inited ) {
878                 Detail = Detail_original;
879         }
880
881         gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
882 }
883
884 void options_change_gamma(float delta)
885 {
886         char tmp_gamma_string[32];
887
888         Freespace_gamma += delta;
889         if (Freespace_gamma < 0.1f) {
890                 Freespace_gamma = 0.1f;
891                 gamesnd_play_iface(SND_GENERAL_FAIL);
892
893         } else if (Freespace_gamma > 5.0f) {
894                 Freespace_gamma = 5.0f;
895                 gamesnd_play_iface(SND_GENERAL_FAIL);
896
897         } else {
898                 gamesnd_play_iface(SND_USER_SELECT);
899         }
900
901         gr_set_gamma(Freespace_gamma);
902         sprintf(tmp_gamma_string, NOX("%.2f"), Freespace_gamma);
903         os_config_write_string(NULL, NOX("Gamma"), tmp_gamma_string);
904 }
905
906 void options_button_pressed(int n)
907 {
908         int choice;     
909
910         switch (n) {            
911                 case OPTIONS_TAB:
912                 case MULTIPLAYER_TAB:
913                 case DETAIL_LEVELS_TAB: 
914                         if (Tab != n)
915                                 options_change_tab(n);
916
917                         break;
918
919                 case ABORT_GAME_BUTTON:
920                         gamesnd_play_iface(SND_USER_SELECT);
921                         choice = popup( PF_NO_NETWORKING | PF_BODY_BIG, 2, POPUP_NO, POPUP_YES, XSTR( "Exit Game?", 374));
922                         if ( choice == 1 )
923                                 gameseq_post_event(GS_EVENT_QUIT_GAME);
924                         break;
925
926                 case CONTROL_CONFIG_BUTTON:
927                         gamesnd_play_iface(SND_SWITCH_SCREENS);
928                         gameseq_post_event(GS_EVENT_CONTROL_CONFIG);
929                         break;                          
930
931                 case HUD_CONFIG_BUTTON:
932 #ifdef FS2_DEMO
933                         game_feature_not_in_demo_popup();
934 #else
935                         // can't go to the hud config screen when a multiplayer observer
936                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
937                                 gamesnd_play_iface(SND_GENERAL_FAIL);
938                                 options_add_notify(XSTR( "Cannot use HUD config when an observer!", 375));
939                                 break;
940                         }
941
942                         gamesnd_play_iface(SND_SWITCH_SCREENS);
943                         gameseq_post_event(GS_EVENT_HUD_CONFIG);
944 #endif
945                         break;
946
947                 case ACCEPT_BUTTON:
948                         options_accept();
949                         break;          
950
951                         // BEGIN - detail level tab buttons
952
953                 case HUD_TARGETVIEW_RENDER_ON:
954                         Detail.targetview_model = 1;
955                         gamesnd_play_iface(SND_USER_SELECT);
956                         break;
957
958                 case HUD_TARGETVIEW_RENDER_OFF:
959                         Detail.targetview_model = 0;
960                         gamesnd_play_iface(SND_USER_SELECT);
961                         break;
962
963                 case PLANETS_ON:
964                         Detail.planets_suns = 1;
965                         gamesnd_play_iface(SND_USER_SELECT);
966                         break;
967
968                 case PLANETS_OFF:
969                         Detail.planets_suns = 0;
970                         gamesnd_play_iface(SND_USER_SELECT);
971                         break;
972
973                 case WEAPON_EXTRAS_ON:
974                         Detail.weapon_extras = 1;
975                         gamesnd_play_iface(SND_USER_SELECT);
976                         break;
977
978                 case WEAPON_EXTRAS_OFF:
979                         Detail.weapon_extras = 0;
980                         gamesnd_play_iface(SND_USER_SELECT);
981                         break;          
982
983                 case LOW_DETAIL_N:
984                         options_detail_set_level(0);
985                         gamesnd_play_iface(SND_USER_SELECT);
986                         break;
987
988                 case MEDIUM_DETAIL_N:
989                         options_detail_set_level(1);
990                         gamesnd_play_iface(SND_USER_SELECT);
991                         break;
992
993                 case HIGH_DETAIL_N:
994                         options_detail_set_level(2);
995                         gamesnd_play_iface(SND_USER_SELECT);
996                         break;
997
998                 case VERY_HIGH_DETAIL_N:
999                         options_detail_set_level(3);
1000                         gamesnd_play_iface(SND_USER_SELECT);
1001                         break;
1002
1003                 case CUSTOM_DETAIL_N:
1004                         options_detail_set_level(-1);
1005                         gamesnd_play_iface(SND_USER_SELECT);
1006                         break;
1007                         // END - detail level tab buttons
1008
1009                 case GAMMA_DOWN:
1010                         options_change_gamma(-0.05f);
1011                         break;
1012
1013                 case GAMMA_UP:
1014                         options_change_gamma(0.05f);
1015                         break;
1016
1017                 case BRIEF_VOICE_ON:
1018                         Briefing_voice_enabled = 1;
1019                         gamesnd_play_iface(SND_USER_SELECT);
1020                         break;
1021
1022                 case BRIEF_VOICE_OFF:
1023                         Briefing_voice_enabled = 0;
1024                         gamesnd_play_iface(SND_USER_SELECT);
1025                         break;
1026
1027                 case MOUSE_ON:
1028                         Use_mouse_to_fly = 1;
1029                         gamesnd_play_iface(SND_USER_SELECT);
1030                         break;
1031
1032                 case MOUSE_OFF:
1033                         Use_mouse_to_fly = 0;
1034                         gamesnd_play_iface(SND_USER_SELECT);
1035                         break;
1036         }
1037 }
1038
1039 void options_sliders_update()
1040 {
1041         // sound slider
1042         if (Options_sliders[gr_screen.res][OPT_SOUND_VOLUME_SLIDER].slider.pos != Sound_volume_int) {
1043                 Sound_volume_int = Options_sliders[gr_screen.res][OPT_SOUND_VOLUME_SLIDER].slider.pos;
1044                 Master_sound_volume = ((float) (Sound_volume_int) / 9.0f);
1045                 set_sound_volume();
1046                 gamesnd_play_iface(SND_USER_SELECT);
1047         }
1048
1049         // music slider
1050         if (Options_sliders[gr_screen.res][OPT_MUSIC_VOLUME_SLIDER].slider.pos != Music_volume_int) {
1051                 Music_volume_int = Options_sliders[gr_screen.res][OPT_MUSIC_VOLUME_SLIDER].slider.pos;
1052                 Master_event_music_volume = ((float) (Music_volume_int) / 9.0f);
1053                 if (Master_event_music_volume > 0.0f) {
1054                         event_music_enable();
1055                 }
1056
1057                 set_music_volume();
1058                 gamesnd_play_iface(SND_USER_SELECT);
1059         }
1060
1061         // voice slider
1062         if (Options_sliders[gr_screen.res][OPT_VOICE_VOLUME_SLIDER].slider.pos != Voice_volume_int) {
1063                 Voice_volume_int = Options_sliders[gr_screen.res][OPT_VOICE_VOLUME_SLIDER].slider.pos;
1064                 Master_voice_volume = ((float) (Voice_volume_int) / 9.0f);
1065                 set_voice_volume();
1066                 options_play_voice_clip();
1067         }
1068
1069         if (Mouse_sensitivity != Options_sliders[gr_screen.res][OPT_MOUSE_SENS_SLIDER].slider.pos) {
1070                 Mouse_sensitivity = Options_sliders[gr_screen.res][OPT_MOUSE_SENS_SLIDER].slider.pos;
1071                 gamesnd_play_iface(SND_USER_SELECT);
1072         }
1073
1074         if (Joy_sensitivity != Options_sliders[gr_screen.res][OPT_JOY_SENS_SLIDER].slider.pos) {
1075                 Joy_sensitivity = Options_sliders[gr_screen.res][OPT_JOY_SENS_SLIDER].slider.pos;
1076                 gamesnd_play_iface(SND_USER_SELECT);
1077         }
1078
1079         if (Dead_zone_size != Options_sliders[gr_screen.res][OPT_JOY_DEADZONE_SLIDER].slider.pos * 5) {
1080                 Dead_zone_size = Options_sliders[gr_screen.res][OPT_JOY_DEADZONE_SLIDER].slider.pos * 5;
1081                 gamesnd_play_iface(SND_USER_SELECT);
1082         }
1083
1084         if (Game_skill_level != Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos) {
1085                 Game_skill_level = Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos;
1086                 gamesnd_play_iface(SND_USER_SELECT);
1087         }
1088 }
1089
1090 void options_accept()
1091 {
1092         // apply the selected multiplayer options
1093         if ( Options_multi_inited ) {
1094                 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
1095                 options_multi_accept();
1096                 #endif
1097         }
1098
1099         // If music is zero volume, disable
1100         if ( Master_event_music_volume <= 0.0f ) {
1101 //              event_music_disable();
1102                 event_music_level_close();
1103         }
1104
1105         // apply other options (display options, etc)
1106         // note: return in here (and play failed sound) if they can't accept yet for some reason
1107
1108         gamesnd_play_iface(SND_COMMIT_PRESSED);
1109         gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
1110 }
1111
1112 void options_load_background_and_mask(int tab)
1113 {
1114         Assert(tab == OPTIONS_TAB || tab == DETAIL_LEVELS_TAB );
1115         Backgrounds[gr_screen.res][tab].bitmap = bm_load(Backgrounds[gr_screen.res][tab].filename);
1116         Backgrounds[gr_screen.res][tab].mask = bm_load(Backgrounds[gr_screen.res][tab].mask_filename);
1117 }
1118
1119 int Gamma_last_set = -1;
1120 int Gamma_colors_inited = 0;
1121
1122 void options_menu_init()
1123 {
1124         int i, j;
1125         options_buttons *b;
1126
1127         Assert(!Options_menu_inited);
1128
1129         // pause all sounds, since we could get here through the game
1130         beam_pause_sounds();
1131         //audiostream_pause_all();
1132
1133         Tab = 0;
1134         Gamma_last_set = -1;
1135
1136         common_set_interface_palette("InterfacePalette");  // set the interface palette
1137         Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1138
1139         for (i=0; i<PLANETS_ON; i++) {
1140                 b = &Buttons[gr_screen.res][i];
1141
1142                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1143                 // set up callback for when a mouse first goes over a button
1144                 if (b->filename) {
1145                         b->button.set_bmaps(b->filename);
1146                         if ( !(b->flags & NO_MOUSE_OVER_SOUND) ) {
1147                                 b->button.set_highlight_action(common_play_highlight_sound);
1148                         }
1149
1150                 } else {
1151                         b->button.hide();
1152                 }
1153
1154                 b->button.link_hotspot(b->hotspot);
1155                 if (i < NUM_COMMONS) {
1156                         for (j=0; j<MAX_BMAPS_PER_GADGET; j++){
1157                                 Button_bms[i][j] = b->button.bmap_ids[j];
1158                         }
1159                 }
1160         }
1161
1162         // add all xstr text
1163         for(i=0; i<OPTIONS_NUM_TEXT; i++){
1164                 Ui_window.add_XSTR(&Options_text[gr_screen.res][i]);
1165         }
1166
1167         // bogus controls
1168         Detail_bogus.base_create(&Ui_window, UI_KIND_ICON, 0, 0, 0, 0);
1169         Options_bogus.base_create(&Ui_window, UI_KIND_ICON, 0, 0, 0, 0);
1170
1171         Buttons[gr_screen.res][GAMMA_DOWN].button.set_hotkey(KEY_COMMA);
1172         Buttons[gr_screen.res][GAMMA_UP].button.set_hotkey(KEY_PERIOD);
1173
1174         /*
1175         Skill_control.first_frame = bm_load_animation("OPa_11", &Skill_control.total_frames);
1176         if (Skill_control.first_frame < 0) {
1177                 Error(LOCATION, "Could not load OPa_11.ani\n");
1178                 return;
1179         }
1180         */
1181
1182         for (i=0; i<NUM_TABS; i++) {
1183                 Backgrounds[gr_screen.res][i].bitmap = -1;
1184                 Backgrounds[gr_screen.res][i].mask = -1;
1185         }
1186
1187         options_load_background_and_mask(OPTIONS_TAB);
1188         options_tab_setup(0);
1189
1190         Backup_skill_level = Game_skill_level;
1191         Backup_sound_volume = Master_sound_volume;
1192         Backup_music_volume = Master_event_music_volume;
1193         Backup_voice_volume = Master_voice_volume;
1194         Backup_briefing_voice_enabled = Briefing_voice_enabled;
1195         Backup_use_mouse_to_fly = Use_mouse_to_fly;
1196         
1197         // create slider        
1198         for ( i = 0; i < NUM_OPTIONS_SLIDERS; i++ ) {
1199                  Options_sliders[gr_screen.res][i].slider.create(&Ui_window, Options_sliders[gr_screen.res][i].x, Options_sliders[gr_screen.res][i].y,
1200                                                                                                                                                 Options_sliders[gr_screen.res][i].dots, Options_sliders[gr_screen.res][i].filename,
1201                                                                                                                                                 Options_sliders[gr_screen.res][i].hotspot, Options_sliders[gr_screen.res][i].right_filename, Options_sliders[gr_screen.res][i].right_mask, Options_sliders[gr_screen.res][i].right_x, Options_sliders[gr_screen.res][i].right_y,
1202                                                                                                                                                 Options_sliders[gr_screen.res][i].left_filename, Options_sliders[gr_screen.res][i].left_mask, Options_sliders[gr_screen.res][i].left_x, Options_sliders[gr_screen.res][i].left_y,
1203                                                                                                                                                 Options_sliders[gr_screen.res][i].dot_w);
1204         }       
1205
1206         // maybe disable the skill slider
1207         if( ((Game_mode & GM_IN_MISSION) && (!popupdead_is_active())) || (Game_mode & GM_MULTIPLAYER) ) {
1208                 Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.disable();
1209                 Ui_window.use_hack_to_get_around_stupid_problem_flag = 0;
1210         }
1211         
1212         // setup slider values 
1213         // note slider scale is 0-9, while Master_ values calc with 1-10 scale (hence the -1)
1214         Sound_volume_int = Options_sliders[gr_screen.res][OPT_SOUND_VOLUME_SLIDER].slider.pos = (int) (Master_sound_volume * 9.0f + 0.5f);
1215         Music_volume_int = Options_sliders[gr_screen.res][OPT_MUSIC_VOLUME_SLIDER].slider.pos = (int) (Master_event_music_volume * 9.0f + 0.5f);        
1216         Voice_volume_int = Options_sliders[gr_screen.res][OPT_VOICE_VOLUME_SLIDER].slider.pos = (int) (Master_voice_volume * 9.0f + 0.5f);
1217         Options_sliders[gr_screen.res][OPT_JOY_SENS_SLIDER].slider.pos = Joy_sensitivity;       
1218         Options_sliders[gr_screen.res][OPT_JOY_DEADZONE_SLIDER].slider.pos = Dead_zone_size / 5;        
1219         Options_sliders[gr_screen.res][OPT_MOUSE_SENS_SLIDER].slider.pos = Mouse_sensitivity;
1220         Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos = Game_skill_level;
1221
1222         Gamma_colors_inited = 0;
1223
1224         // used to allow all keystrokes, even when called from a demo playback
1225         key_clear_filter();
1226         Options_menu_inited = 1;
1227
1228         // hide options crap
1229         options_detail_hide_stuff();
1230 }
1231
1232 void options_menu_close()
1233 {
1234         int i;  
1235
1236         Assert(Options_menu_inited);    
1237
1238         for (i=0; i<NUM_TABS; i++) {
1239                 if (Backgrounds[gr_screen.res][i].bitmap >= 0){
1240                         bm_unload(Backgrounds[gr_screen.res][i].bitmap);
1241                 }
1242                 if ((Backgrounds[gr_screen.res][i].mask >= 0) && (i != Tab)){  // Ui_window.destroy() expects to release current tab's mask.
1243                         bm_unload(Backgrounds[gr_screen.res][i].mask);
1244                 }
1245         }
1246
1247         if ( Voice_vol_handle >= 0 ) {
1248                 snd_stop(Voice_vol_handle);
1249                 Voice_vol_handle = -1;
1250         }
1251
1252 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
1253         options_multi_close();
1254 #endif
1255
1256         Ui_window.destroy();
1257         common_free_interface_palette();                // restore game palette
1258         write_pilot_file();
1259         game_flush();
1260         
1261         // unpause all sounds, since we could be headed back to the game
1262         beam_unpause_sounds();
1263         //audiostream_unpause_all();
1264         
1265         Options_menu_inited = 0;
1266         Options_multi_inited = 0;
1267         Options_detail_inited = 0;
1268
1269
1270 }
1271
1272
1273 void draw_gamma_box()
1274 {
1275         int x, y, v;
1276
1277 // NEILK: i had to change this declaration because the size is determined dynamically. I just picked an arbitrary large number to data size (although we should always be using less)
1278 // TODO: change MAX size to maximum size for a 1024x768 bitmap
1279 //      ushort Gamma_data[Options_gamma_coords[gr_screen.res][OPTIONS_W_COORD]*Options_gamma_coords[gr_screen.res][OPTIONS_H_COORD]*2];
1280         ushort Gamma_data[MAX_GAMMA_BITMAP_SIZE];
1281
1282         v = fl2i( pow(0.5f, 1.0f / Freespace_gamma) * 255.0f );
1283         if (v > 255){
1284                 v = 255;
1285         } else if (v < 0){
1286                 v = 0;
1287         }
1288
1289         int Gamma_changed = 0;
1290         if ( v != Gamma_last_set )      {
1291                 Gamma_changed = 1;
1292         } else {
1293                 Gamma_changed = 0;
1294         }
1295         Gamma_last_set = v;
1296
1297         {
1298                 ushort clr_full_white = 0;
1299                 ushort clr_half_white = 0;
1300                 ubyte r, g, b, a;
1301
1302                 // if we're in bitmap poly mode
1303                 if(Gr_bitmap_poly){
1304                         BM_SELECT_TEX_FORMAT();
1305                 } else {
1306                         BM_SELECT_SCREEN_FORMAT();
1307                 }
1308
1309                 // set full white
1310                 r = g = b = a = 255;            
1311                 bm_set_components((ubyte*)&clr_full_white, &r, &g, &b, &a);
1312
1313                 // set half white
1314                 r = g = b = (ubyte)v;
1315                 bm_set_components((ubyte*)&clr_half_white, &r, &g, &b, &a);
1316
1317                 ushort *dptr = Gamma_data;
1318                 for (y=0; y<Options_gamma_coords[gr_screen.res][OPTIONS_H_COORD]; y++) {
1319                         for (x=0; x<Options_gamma_coords[gr_screen.res][OPTIONS_W_COORD]; x++) {
1320                                 if ((x / 20) & 1) {
1321                                         *dptr = clr_half_white;
1322                                 } else {
1323                                         if ((x & 1) == (y & 1)) {
1324                                                 *dptr = clr_full_white;
1325                                         } else {
1326                                                 *dptr = 0;
1327                                         }
1328                                 }
1329                                 dptr++;
1330                         }
1331                 }
1332
1333                 // always go back to screen format
1334                 BM_SELECT_SCREEN_FORMAT();
1335
1336                 // if we're in bitmap poly mode         
1337                 int Gamma_bitmap = bm_create( 16, Options_gamma_coords[gr_screen.res][OPTIONS_W_COORD], Options_gamma_coords[gr_screen.res][OPTIONS_H_COORD], Gamma_data );
1338                 gr_set_bitmap(Gamma_bitmap);
1339                 gr_bitmap( Options_gamma_coords[gr_screen.res][OPTIONS_X_COORD], Options_gamma_coords[gr_screen.res][OPTIONS_Y_COORD] );
1340
1341                 bm_release( Gamma_bitmap );
1342
1343         }
1344 }
1345
1346
1347 void options_menu_do_frame(float frametime)
1348 {
1349         int i, k, x, y; 
1350
1351         Assert(Options_menu_inited);
1352         k = Ui_window.process() & ~KEY_DEBUGGED;
1353         switch (k) {
1354                 case KEY_SHIFTED | KEY_TAB:
1355                 case KEY_LEFT:  // activate previous tab
1356                         i = Tab - 1;
1357                         if (i < 0)
1358                                 i = NUM_TABS - 1;
1359
1360                         options_change_tab(i);
1361                         break;
1362
1363                 case KEY_TAB:
1364                 case KEY_RIGHT:  // activate next tab
1365                         // check to see if the multiplayer options screen wants to eat the tab kay
1366                         if ((k == KEY_TAB) && (Tab == MULTIPLAYER_TAB)) {
1367                                 if (options_multi_eat_tab()) {
1368                                         break;
1369                                 }
1370                         }
1371
1372                         i = Tab + 1;
1373                         if (i >= NUM_TABS)
1374                                 i = 0;
1375
1376                         options_change_tab(i);
1377                         break;
1378
1379                 case KEY_C:
1380                         if (Tab == OPTIONS_TAB) {
1381                                 gamesnd_play_iface(SND_SWITCH_SCREENS);
1382                                 gameseq_post_event(GS_EVENT_CONTROL_CONFIG);
1383                         }
1384
1385                         break;
1386
1387                 case KEY_H:
1388                         if (Tab == OPTIONS_TAB) {
1389                                 gamesnd_play_iface(SND_SWITCH_SCREENS);
1390                                 gameseq_post_event(GS_EVENT_HUD_CONFIG);
1391                         }
1392
1393                         break;
1394
1395                 case KEY_ESC:
1396                         // if(Tab != MULTIPLAYER_TAB){
1397                                 options_cancel_exit();
1398                         // }
1399                         break;
1400
1401                 case KEY_CTRLED | KEY_ENTER:
1402                         options_accept();
1403                         break;
1404
1405                 case KEY_DELETE:
1406                         break;
1407
1408                 case KEY_ENTER:                 
1409                         break;
1410         }       
1411
1412         for (i=0; i<NUM_BUTTONS; i++) {
1413                 if (Buttons[gr_screen.res][i].button.pressed())
1414                         options_button_pressed(i);
1415         }
1416
1417         options_sliders_update();
1418
1419         // if we're in the multiplayer options tab, get the background bitmap from the options multi module
1420         if(Tab == MULTIPLAYER_TAB){
1421                 i = options_multi_background_bitmap();
1422         } else {
1423                 i = Backgrounds[gr_screen.res][Tab].bitmap;
1424         }
1425
1426         GR_MAYBE_CLEAR_RES(i);
1427         if (i >= 0) {
1428                 gr_set_bitmap(i);
1429                 gr_bitmap(0, 0);
1430         } 
1431
1432         Ui_window.draw();
1433
1434         // NOTE : this must be done here so that any special drawing crap we do is not overwritten by the UI_WINDOW::draw() call
1435         // do specific processing for the multiplayer tab
1436         switch (Tab) {
1437                 case MULTIPLAYER_TAB:
1438 #if !defined(DEMO) && !defined(OEM_BUILD) // not for FS2_DEMO
1439                         options_multi_do(k);
1440 #endif
1441                         break;
1442
1443                 case DETAIL_LEVELS_TAB:
1444                         options_detail_do_frame();
1445                         break;
1446
1447                 default:
1448                         Game_skill_level = Options_sliders[gr_screen.res][OPT_SKILL_SLIDER].slider.pos;
1449                         break;
1450         }
1451
1452         // handle the displaying of any notification messages
1453         options_notify_do_frame();
1454
1455         for (i=0; i<NUM_TABS; i++){
1456                 if (Buttons[gr_screen.res][i].button.button_down()){
1457                         break;
1458                 }
1459         }
1460
1461         if ((i == NUM_TABS) /*&& (Tab != MULTIPLAYER_TAB)*/ ){
1462                 Buttons[gr_screen.res][Tab].button.draw_forced(2);
1463         }
1464
1465         if (Tab == OPTIONS_TAB) {
1466                 // draw correct frame for briefing voice radio buttons
1467                 if (Briefing_voice_enabled) {
1468                         options_force_button_frame(BRIEF_VOICE_ON, 2);
1469                         options_force_button_frame(BRIEF_VOICE_OFF, 0);
1470
1471                 } else {
1472                         options_force_button_frame(BRIEF_VOICE_OFF, 2);
1473                         options_force_button_frame(BRIEF_VOICE_ON, 0);
1474                 }
1475
1476                 if (Use_mouse_to_fly) {
1477                         options_force_button_frame(MOUSE_ON, 2);
1478                         options_force_button_frame(MOUSE_OFF, 0);
1479
1480                 } else {
1481                         options_force_button_frame(MOUSE_OFF, 2);
1482                         options_force_button_frame(MOUSE_ON, 0);
1483                 }               
1484
1485                 int w;
1486                 gr_get_string_size(&w, NULL, Skill_level_names(Game_skill_level));
1487                 x = Options_skills_text_coords[gr_screen.res][OPTIONS_X_COORD];
1488                 y = Options_skills_text_coords[gr_screen.res][OPTIONS_Y_COORD];
1489                 gr_set_color_fast(&Color_bright_white);
1490                 gr_string(x + (Options_skills_text_coords[gr_screen.res][OPTIONS_W_COORD] / 2) - (w/2), y, Skill_level_names(Game_skill_level));
1491         }
1492
1493         
1494         //==============================================================================
1495         // Draw the gamma adjustment grid.
1496         if (Tab == OPTIONS_TAB) {
1497
1498                 draw_gamma_box();
1499                 
1500                 gr_set_color_fast(&Color_white);
1501                 x = Options_gamma_num_coords[gr_screen.res][OPTIONS_X_COORD]; //  + Options_gamma_num_coords[gr_screen.res][OPTIONS_W_COORD] / 2 - 12;
1502                 y = Options_gamma_num_coords[gr_screen.res][OPTIONS_Y_COORD]; // + Options_gamma_num_coords[gr_screen.res][OPTIONS_H_COORD] / 2 - gr_get_font_height() / 2;
1503
1504                 gr_printf(x, y, NOX("%.2f"), Freespace_gamma);
1505                 //gr_printf(GAMMA_TEXT_X, GAMMA_TEXT_Y, "Squint and try to make the above\nbar appear to be one solid color.\nThere are more 'ranges' to see\nif you set this in Glide mode.");
1506         }
1507         //==============================================================================
1508
1509         // maybe blit a waveform
1510         if(Tab == MULTIPLAYER_TAB){
1511                 options_multi_vox_process_waveform();
1512         }
1513         
1514 /*  Debug code: Graphs the joystick range scaling
1515 {
1516 int joy_get_scaled_reading(int raw, int axn);
1517         int x, y;
1518
1519         gr_set_color_fast(&Color_white);
1520         for (x=0; x<256; x+=16) {
1521                 gr_line(x + 15, 0, x + 15, 255);
1522                 gr_line(0, x + 15, 255, x + 15);
1523         }
1524
1525         gr_set_color_fast(&Color_bright_white);
1526         for (x=0; x<256; x++) {
1527                 y = joy_get_scaled_reading(x * 256, 0) / 512;
1528                 gr_line(x, 128, x, 128 + y);
1529         }
1530 }*/     
1531
1532         gr_flip();
1533 }
1534
1535
1536 // ---------------------------------------------------------------------------------------------------------
1537 // DETAIL LEVEL OPTIONS definitions  BEGIN
1538 //
1539
1540 void options_detail_synch_sliders()
1541 {
1542         Detail_slider_pos[DETAIL_DISTANCE_SLIDER] = Detail_sliders[gr_screen.res][DETAIL_DISTANCE_SLIDER].slider.pos = Detail.detail_distance;
1543         Detail_slider_pos[NEBULA_DETAIL_SLIDER] = Detail_sliders[gr_screen.res][NEBULA_DETAIL_SLIDER].slider.pos = Detail.nebula_detail;
1544         Detail_slider_pos[HARDWARE_TEXTURES_SLIDER] = Detail_sliders[gr_screen.res][HARDWARE_TEXTURES_SLIDER].slider.pos = Detail.hardware_textures;    
1545         Detail_slider_pos[SHARD_CULLING_SLIDER] = Detail_sliders[gr_screen.res][SHARD_CULLING_SLIDER].slider.pos = Detail.num_small_debris;
1546         Detail_slider_pos[SHIELD_DETAIL_SLIDER] = Detail_sliders[gr_screen.res][SHIELD_DETAIL_SLIDER].slider.pos = Detail.shield_effects;
1547         Detail_slider_pos[NUM_STARS_SLIDER] = Detail_sliders[gr_screen.res][NUM_STARS_SLIDER].slider.pos = Detail.num_stars;
1548         Detail_slider_pos[NUM_PARTICLES_SLIDER] = Detail_sliders[gr_screen.res][NUM_PARTICLES_SLIDER].slider.pos = Detail.num_particles;
1549         Detail_slider_pos[LIGHTING_SLIDER] = Detail_sliders[gr_screen.res][LIGHTING_SLIDER].slider.pos = Detail.lighting;
1550 }
1551
1552 void options_detail_init()
1553 {
1554         int i;
1555         options_buttons *b;
1556
1557         Detail_original = Detail;
1558
1559         options_load_background_and_mask(DETAIL_LEVELS_TAB);
1560
1561         for (i=PLANETS_ON; i<NUM_BUTTONS; i++) {
1562                 b = &Buttons[gr_screen.res][i];
1563
1564                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
1565                 // set up callback for when a mouse first goes over a button
1566                 if (b->filename) {
1567                         b->button.set_bmaps(b->filename);
1568                         if ( !(b->flags & NO_MOUSE_OVER_SOUND) ) {
1569                                 b->button.set_highlight_action(common_play_highlight_sound);
1570                         }
1571
1572                 } else {
1573                         b->button.hide();
1574                 }
1575
1576                 b->button.link_hotspot(b->hotspot);
1577         }
1578
1579         // create detail level sliders  
1580         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1581                 Detail_sliders[gr_screen.res][i].slider.create(&Ui_window, Detail_sliders[gr_screen.res][i].x, Detail_sliders[gr_screen.res][i].y,
1582                                                                                                                                                 Detail_sliders[gr_screen.res][i].dots, Detail_sliders[gr_screen.res][i].filename,
1583                                                                                                                                                 Detail_sliders[gr_screen.res][i].hotspot, Detail_sliders[gr_screen.res][i].right_filename, Detail_sliders[gr_screen.res][i].right_mask, Detail_sliders[gr_screen.res][i].right_x, Detail_sliders[gr_screen.res][i].right_y,
1584                                                                                                                                                 Detail_sliders[gr_screen.res][i].left_filename, Detail_sliders[gr_screen.res][i].left_mask, Detail_sliders[gr_screen.res][i].left_x, Detail_sliders[gr_screen.res][i].left_y,
1585                                                                                                                                                 Detail_sliders[gr_screen.res][i].dot_w);
1586         }
1587
1588         // init the actual slider positions and our internal positions
1589         options_detail_synch_sliders();
1590 }
1591
1592 void options_detail_sliders_update()
1593 {
1594         int i;
1595
1596         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1597                 if ( Detail_sliders[gr_screen.res][i].slider.pos != Detail_slider_pos[i] ) {
1598                         Detail_slider_pos[i] = Detail_sliders[gr_screen.res][i].slider.pos;
1599                         gamesnd_play_iface(SND_USER_SELECT);
1600                 }
1601         }
1602
1603         // set Detail based on slider positions
1604         Detail.detail_distance = Detail_sliders[gr_screen.res][DETAIL_DISTANCE_SLIDER].slider.pos;
1605
1606         // modify nebula stuff
1607         Detail.nebula_detail = Detail_sliders[gr_screen.res][NEBULA_DETAIL_SLIDER].slider.pos;
1608         neb2_set_detail_level(Detail.nebula_detail);
1609
1610         Detail.hardware_textures = Detail_sliders[gr_screen.res][HARDWARE_TEXTURES_SLIDER].slider.pos;  
1611         Detail.num_small_debris = Detail_sliders[gr_screen.res][SHARD_CULLING_SLIDER].slider.pos;
1612         Detail.shield_effects = Detail_sliders[gr_screen.res][SHIELD_DETAIL_SLIDER].slider.pos;
1613         Detail.num_stars = Detail_sliders[gr_screen.res][NUM_STARS_SLIDER].slider.pos;
1614         Detail.num_particles = Detail_sliders[gr_screen.res][NUM_PARTICLES_SLIDER].slider.pos;
1615         Detail.lighting = Detail_sliders[gr_screen.res][LIGHTING_SLIDER].slider.pos;
1616 }
1617
1618 void options_detail_hide_stuff()
1619 {
1620         int i;
1621
1622         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1623                 Detail_sliders[gr_screen.res][i].slider.disable();
1624                 Detail_sliders[gr_screen.res][i].slider.hide();
1625         }
1626
1627         // this will hide text unassociated with any real control
1628         Detail_bogus.hide();
1629 }
1630
1631 void options_detail_unhide_stuff()
1632 {
1633         int i;
1634
1635         for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1636                 Detail_sliders[gr_screen.res][i].slider.enable();
1637                 Detail_sliders[gr_screen.res][i].slider.unhide();
1638         }
1639
1640         // this will hide text unassociated with any real control
1641         Detail_bogus.unhide();
1642 }
1643
1644 void options_force_button_frame(int n, int frame_num)
1645 {
1646         if ( !Buttons[gr_screen.res][n].button.button_down() ) {
1647                 Buttons[gr_screen.res][n].button.draw_forced(frame_num);
1648         }
1649 }
1650
1651 // called once per frame to set lit buttons
1652 void options_detail_do_frame()
1653 {
1654         options_detail_sliders_update();        
1655
1656         // force on/off buttons to draw their correct setting
1657
1658         if ( Detail.targetview_model ) {
1659                 options_force_button_frame(HUD_TARGETVIEW_RENDER_ON, 2);
1660                 options_force_button_frame(HUD_TARGETVIEW_RENDER_OFF, 0);
1661         } else {
1662                 options_force_button_frame(HUD_TARGETVIEW_RENDER_OFF, 2);
1663                 options_force_button_frame(HUD_TARGETVIEW_RENDER_ON, 0);
1664         }
1665
1666         if ( Detail.planets_suns == 1 ) {
1667                 options_force_button_frame(PLANETS_ON, 2);
1668                 options_force_button_frame(PLANETS_OFF, 0);
1669         } else {
1670                 options_force_button_frame(PLANETS_OFF, 2);
1671                 options_force_button_frame(PLANETS_ON, 0);
1672         }
1673
1674         if ( Detail.weapon_extras) {
1675                 options_force_button_frame(WEAPON_EXTRAS_ON, 2);
1676                 options_force_button_frame(WEAPON_EXTRAS_OFF, 0);
1677         } else {
1678                 options_force_button_frame(WEAPON_EXTRAS_OFF, 2);
1679                 options_force_button_frame(WEAPON_EXTRAS_ON, 0);
1680         }       
1681
1682         int current_detail;
1683
1684         if ( Detail.setting >= 0 ) {
1685                 current_detail = current_detail_level();
1686                 Detail.setting = current_detail;
1687         } else {
1688                 current_detail = -1;
1689         }
1690
1691         options_force_button_frame(LOW_DETAIL_N, 0);
1692         options_force_button_frame(MEDIUM_DETAIL_N, 0);
1693         options_force_button_frame(HIGH_DETAIL_N, 0);
1694         options_force_button_frame(VERY_HIGH_DETAIL_N, 0);
1695         options_force_button_frame(CUSTOM_DETAIL_N, 0);
1696
1697         switch ( current_detail ) {
1698         case -1:
1699                 options_force_button_frame(CUSTOM_DETAIL_N, 2);
1700                 break;
1701         case 0:
1702                 options_force_button_frame(LOW_DETAIL_N, 2);
1703                 break;
1704         case 1:
1705                 options_force_button_frame(MEDIUM_DETAIL_N, 2);
1706                 break;
1707         case 2:
1708                 options_force_button_frame(HIGH_DETAIL_N, 2);
1709                 break;
1710         case 3:
1711                 options_force_button_frame(VERY_HIGH_DETAIL_N, 2);
1712                 break;
1713         }
1714 }
1715
1716 // Set all the detail settings to a predefined level
1717 void options_detail_set_level(int level)
1718 {
1719         detail_level_set(level);
1720         options_detail_synch_sliders();
1721 }
1722
1723 //
1724 // DETAIL LEVEL tab definitions END
1725 // ---------------------------------------------------------------------------------------------------------
1726
1727