convert line ends
[canaan.git] / prj / cam / src / deepc / ui / dpcoptmn.cpp
blob7c205e333a4dbf6d9cd4bea50cd747de8f941981
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 #include <dpcoptmn.h>
7 #include <string.h>
8 #include <dev2d.h>
9 #include <keydefs.h>
11 #include <dpcmenu.h>
12 #include <dpcsvbnd.h>
13 #include <appagg.h>
14 #include <drkpanl.h>
16 #include <appsfx.h>
17 #include <gamescrn.h>
18 #include <scrnmode.h>
20 #include <resapi.h>
21 #include <imgrstyp.h>
22 #include <strrstyp.h>
24 #include <gcompose.h>
25 #include <questapi.h>
26 #include <drkdiff.h>
27 #include <config.h>
28 #include <uigame.h>
30 #include <panltool.h>
31 #include <appapi.h>
32 #include <mprintf.h>
33 #include <campaign.h>
35 #include <gadslide.h>
36 #include <gen_bind.h>
37 #include <lgd3d.h>
39 #include <command.h>
40 #include <gamma.h>
41 #include <objmodel.h>
42 #include <metasnd.h>
44 #include <simman.h>
45 #include <simdef.h>
46 #include <netman.h>
48 #include <volconv.h>
50 #include <dpcdiff.h>
52 #include <math.h>
54 // Include this last.
55 #include <dbmem.h>
58 #define kVolumeSliderNotches 25
59 #define kOneOverVolumeSliderNotches ((1.0)/(float)kVolumeSliderNotches)
61 static void TouchGamma (float gamma)
63 g_gamma = gamma;
64 gamma_update();
68 //is the difficulty setting greyed out or not?
69 static BOOL g_diff_active = TRUE;
71 //starting difficulty
72 extern int g_diff;
74 #define MIN_DIFF 1
76 inline int DIFF2BUTT(int x)
78 // boundary cases
79 if (x < kDPCFirstDiff)
80 x = kDPCFirstDiff;
81 if (x >= kDPCLimDiff)
82 x = kDPCDiffNormal;
84 return x - 1;
87 #define BUTT2DIFF(x) ((x) + 1)
90 EXTERN BOOL g_zbuffer_toggle;
91 extern int sfx_use_channels;
94 /////////////////
96 #define MAX_NUM_BINDABLE 64
97 #define QUICKCONFIG_BINDNUM 15 /*number of quick configurable commands*/
98 #define NUM_BIND_SLOTS 13
99 //max cmds we will display per a given cmd
100 #define MAX_BINDS_PER_CMD 3
102 /////////////////
104 #define SLIDER_BMPRES 0
105 #define BINDUP_BMPRES 1
106 #define BINDDN_BMPRES 2
108 #define NUM_LIST 13
109 #define FILL_SUBPANEL 666
111 #define LRMOD(x) (!strcmp (x, "lalt") || !strcmp (x, "ralt") || \
112 !strcmp (x, "lctrl") || !strcmp (x, "rctrl") || \
113 !strcmp (x, "lshift") || !strcmp (x, "rshift"))
117 #define MIN_RES_X 640
118 #define MIN_RES_Y 480
119 #define MAX_RES_Y 768
121 //all 8-bit for software
122 static short soft_modes[] = {
123 GRM_400x300x8,
124 GRM_512x384x8,
125 GRM_640x400x8,
126 GRM_640x480x8,
127 GRM_800x600x8,
131 //#define CanChangeEAX() (SFX_Is_EAX_Available())
132 #define CanChangeEAX() (SFX_Is_EAX_Available() && (SFX_GetSoundDevice () == SFXDEVICE_A3D))
134 static BOOL InSim()
136 AutoAppIPtr(SimManager);
137 return (pSimManager->LastMsg() & (kSimInit | kSimResume)) != 0;
140 #define CanChangeSoundDeviceNow() (!InSim())
143 BOOL CanChangeDifficultyNow()
145 AutoAppIPtr(NetManager);
146 return !pNetManager->IsNetworkGame();
150 static const DrawElement def_draw_elem =
152 0, 0, 0, // type, data, data2
153 0, 0, // fcolor bcolor
154 INTERNAL(DRAWFLAG_INT_TRANSP), // flags
157 static void InitDrawElem(DrawElement* elem)
159 *elem = def_draw_elem;
163 //------------------------------------------------------------
164 // OPTIONS MENU
166 class cDPCOptions;
167 typedef class cDPCOptions cOptions;
169 static cOptions *gpOptions = NULL;
172 class cDPCOptions: public cDarkPanel
174 static sDarkPanelDesc gDesc;
176 public:
177 cOptions() : cDarkPanel(&gDesc)
179 memset(&mTabButtons,0,sizeof(mTabButtons));
180 memset(mSubPanelButtons,0,sizeof(mSubPanelButtons));
181 memset(&mListButtons,0,sizeof(mListButtons));
182 memset(&mBindButtons,0,sizeof(mBindButtons));
183 memset(&mBindScrollers,0,sizeof(mBindScrollers));
184 memset(mSliders,0,sizeof(mSliders));
188 void SetInitialSub ()
190 mCurSub = kSubControls;
193 //Will stuff retrieve_num many controls bound to cmd into the dest
194 //string array, and will return how many actually got stuff
195 int GetCmdBinds (const char *cmd, cStr *dest, int retrieve_num, cStr* raw_dest = NULL)
197 char control_buf[64];
198 char controls[4][32];
199 long num_controls, i, cur_control;
201 g_pInputBinder->GetControlFromCmdStart ((char *)cmd, control_buf);
204 for (cur_control = 0; *control_buf != '\0' && cur_control < retrieve_num;) {
205 g_pInputBinder->DecomposeControl (control_buf, controls, &num_controls);
206 //we don't want to throw in the l/r mods
207 for (i = 0; i < num_controls && !LRMOD (controls[i]); i++);
209 //no l/r's, this control is cool. fetch names
210 if (i == num_controls)
212 cStr& cur_dest = dest[cur_control];
214 cStr temp_raw; // We might not have a raw_dest
215 cStr& cur_raw = (raw_dest) ? raw_dest[cur_control] : temp_raw;
217 cur_dest = "";
218 cur_raw = "";
219 for (i = 0; i < num_controls; i++)
221 if (i)
223 cur_dest += "+";
224 cur_raw += "+";
227 cStr str = FetchUIString ("controls", controls[i], mResPath);
229 //does this key have a translated string?
230 cur_dest += (*str) ? str : controls[i];
231 cur_raw += controls[i];
234 cur_control++;
237 g_pInputBinder->GetControlFromCmdNext (control_buf);
240 return cur_control;
243 enum
245 kDone,
246 kNumButts,
247 kSubFillRect = kNumButts,
248 kNumRects
251 enum
253 kTab0,
254 kTab1,
255 kTab2,
256 kTab3,
257 kNumTabs
260 enum {
261 //control buttons
262 kFirstControlButt,
263 kCustomize = kFirstControlButt,
264 kLookspring,
265 kMouseInvert,
266 kFreelook,
267 kJoyRotate,
269 kFirstControlRect,
270 kMouseSensSliderRect = kFirstControlRect,
271 kMouseSensTextRect,
272 kLimControlRect,
273 kNumControlButts = kFirstControlRect - kFirstControlButt,
274 kNumControlRects = kLimControlRect - kFirstControlButt,
276 //video buttons
277 kFirstBasicVideoButt = kLimControlRect,
278 kScreenRes = kFirstBasicVideoButt,
279 kHardwareDriver,
281 kFirstBasicVideoRect,
282 kGammaSliderRect = kFirstBasicVideoRect,
283 kGammaSliderText,
284 kLimBasicVideoRect,
285 kNumBasicVideoButts = kFirstBasicVideoRect - kFirstBasicVideoButt,
286 kNumBasicVideoRects = kLimBasicVideoRect - kFirstBasicVideoRect,
288 kFirstAdvancedVideoButt = kLimBasicVideoRect,
289 kHardwareDriverOld = kFirstAdvancedVideoButt,
290 kZBufferToggle,
291 kBasicVidOptions,
292 kLimAdvancedVideoRect,
293 kNumAdvancedVideoRects = kLimAdvancedVideoRect - kFirstAdvancedVideoButt,
295 //audio buttons/rects
296 kFirstAudioButt = kLimAdvancedVideoRect,
297 kSpeakerTest = kFirstAudioButt,
298 kStereoToggle,
299 kA3DToggle,
300 kAudioChannels,
301 kAudioEAXToggle,
303 kFirstAudioRect,
304 kVolumeSliderRect = kFirstAudioRect,
305 kVolumeSliderText,
306 k3dVolumeSliderRect,
307 k3dVolumeSliderText,
308 kMusicSliderRect,
309 kMusicSliderText,
311 kLimAudioRect,
312 kNumAudioButts = kFirstAudioRect - kFirstAudioButt,
313 kNumAudioRects = kLimAudioRect - kFirstAudioButt,
315 //game buttons (Note irregularity)
316 kFirstGameRect = kLimAudioRect,
317 kDiffTextRect = kFirstGameRect,
318 kFirstGameButt,
319 kDiff0 = kFirstGameButt,
320 kDiff1,
321 kDiff2,
322 kDiff3,
323 kLimGameRect,
324 kNumGameButts = kLimGameRect - kFirstGameButt,
325 kNumGameRects = kLimGameRect - kFirstGameRect,
327 //bind buttons
328 kFirstBindButt = kLimGameRect,
329 kBindLoad = kFirstBindButt,
330 kBindBack,
331 kBindSave,
332 kQuickConfigure,
333 kBind,
334 kBindClear,
335 kBindButt0,//0 to NUM_BIND_SLOTS - 1
337 kBindScrollUp = kBindButt0 + NUM_BIND_SLOTS,
338 kBindScrollDown,
339 kLimBindRects,
340 kNumBindButts = kBindButt0 - kFirstBindButt,
341 kNumBindRects = kLimBindRects - kFirstBindButt,
343 kFirstListButt = kLimBindRects,
344 kListBack = kFirstListButt,
345 kList0,//13 of these, just add what is needed.
346 kNumListButts = kList0 - kFirstListButt,
347 kNumListRects = NUM_LIST + kNumListButts,
350 kNumSubPanelRects = kNumControlRects + kNumBasicVideoRects + kNumAdvancedVideoRects
351 + kNumAudioRects + kNumGameRects + kNumBindRects + kNumListRects,
354 enum {
355 kVolumeSlider,
356 k3dVolumeSlider,
357 kMusicSlider,
358 kNumVolumeSliders,
359 kMouseSensSlider = kNumVolumeSliders,
360 kGammaSlider,
361 kNumSubPanelSlides
365 enum {
366 kSubControls,
367 kSubBasicVideo,
368 kSubAdvancedVideo,
369 kSubAudio,
370 kSubGame,
371 kSubBind,
372 kSubList,
373 kNumSubs
376 enum {
377 kMiscStrOn,
378 kMiscStrOff,
379 kMiscStrEmpty,
380 kMiscStrLow,
381 kMiscStrHigh,
382 kMiscStrLeftRight,
383 kMiscStrForwardBackward,
384 kNumMiscStrs
389 static int gFirstSubRect[];
392 protected:
393 guiStyle mTextStyle;
394 guiStyle mGreyStyle;
396 cStr mMiscStrs[kNumMiscStrs];
398 IRes *mButtBmpRes[3][4];//4 button draw states
399 DrawElement mButtDrawElem[3];
402 LGadButtonList mTabButtons;
403 LGadButtonListDesc mTabDesc;
404 cRectArray mTabRects;
405 DrawElement mTabElems[kNumTabs];
406 cStr mTabStrs[kNumTabs];
408 int mCurSub;
409 int mSwap;
410 LGadButtonList mSubPanelButtons[kNumSubs];
411 LGadButtonListDesc mSubPanelDesc[kNumSubs];
412 cRectArray mSubPanelRects;
413 DrawElement mSubPanelElems[kNumSubPanelRects];
414 cStr mSubPanelStrs[kNumSubPanelRects];
416 //list
417 int mListSub;
418 int mListPrevPick;
419 int mTopList;
420 int mNumListTotal;
421 LGadButtonList mListButtons;
422 LGadButtonListDesc mListButtonDesc;
423 DrawElement mListButtonElems[NUM_LIST];
424 cStr mListButtonStrs[NUM_LIST];
426 //video-related data
427 BOOL mNumVidDevices;
428 int mSelectedRes;
429 int m3dDriver;
431 //binding-related data
432 int mTopBind;
433 int mNumBindable;
434 guiStyle mBindStyle;
436 LGadButtonList mBindButtons;
437 LGadButtonListDesc mBindButtonDesc;
438 DrawElement mBindButtonElems[NUM_BIND_SLOTS];
439 cStr mBindButtonStrs[MAX_NUM_BINDABLE];
440 cStr mBindCmd[MAX_NUM_BINDABLE];
441 bool mBindButtsFilled[MAX_NUM_BINDABLE];
443 LGadButtonList mBindScrollers;
444 LGadButtonListDesc mBindScrollerDesc;
446 int m_cookie;
449 //slider stuff
450 LGadSlider mSliders[kNumSubPanelSlides];
451 bool mSlidersOn[kNumSubPanelSlides];
452 DrawElement mSliderBaseBmp;
454 ulong m_old_context;
456 //slider variables
457 int m_sens;
458 int m_volume[kNumVolumeSliders];
459 int m_gamma;
462 typedef bool (*ButtListCB)(ushort, int, void *, LGadBox *);
465 //////////////////////////////////////////////////////
467 void SetBoxData(LGadBox* box)
469 LGadBoxSetUserData (box, this);
471 int flags = LGadBoxFlags(box);
472 LGadBoxSetFlags(box, flags | BOXFLAG_CLEAR);
475 typedef int (*vol_get_func)(void);
477 uint MillibelToSlider(int vol)
479 uint retval = (uint) ( VolMillibelToLinear((float)vol) * kVolumeSliderNotches);
480 if (retval >= kVolumeSliderNotches)
481 retval = kVolumeSliderNotches - 1;
482 return retval;
486 // get slider volume, in slider notches
487 uint GetVolume(uint which)
489 static vol_get_func funcs[] =
491 SFX_GetMasterVolume,
492 SFX_Get3dVolume,
493 SFX_GetMusicVolume,
496 if (which == k3dVolumeSlider)
498 uint vol3d = MillibelToSlider(SFX_Get3dVolume());
499 uint vol2d = MillibelToSlider(SFX_Get2dVolume());
500 if (vol3d > vol2d)
502 vol2d = kVolumeSliderNotches - vol2d;
503 return (kVolumeSliderNotches + vol2d)/2;
505 else
506 return vol3d/2;
509 int vol = funcs[which]();
510 return MillibelToSlider(vol);
514 typedef void (*vol_set_func)(int);
516 // set volume, in slider notches
517 void SetVolume(int which, int vol)
519 static vol_set_func funcs[] =
521 SFX_SetMasterVolume,
522 SFX_Set3dVolume,
523 SFX_SetMusicVolume,
526 vol_set_func func = funcs[which];
527 // the 3d volume slider is really a "mix" between 2d and 3d
528 if (which == k3dVolumeSlider)
530 int half = (kVolumeSliderNotches + 1)/2;
531 if (vol < half)
533 SFX_Set2dVolume(0);
534 func = SFX_Set3dVolume;
535 vol *= 2;
537 else
539 SFX_Set3dVolume(0);
540 func = SFX_Set2dVolume;
541 vol = (kVolumeSliderNotches - vol)*2;
545 Assert_(which < kNumVolumeSliders);
547 float fvol = VolLinearToMillibel((float)vol * kOneOverVolumeSliderNotches);
549 func((int)fvol);
553 static int gVolSliderRects[];
556 void InitUI()
558 cDarkPanel::InitUI();
560 //load in the tab and subpanel rectangles
561 AppendRects ("optiontr", mTabRects);//tabs
562 AppendRects ("optioncr", mSubPanelRects);//controls
563 AppendRects ("optnbvr", mSubPanelRects);//basic video
564 AppendRects ("optnavr", mSubPanelRects);//advanced video
565 AppendRects ("optionar", mSubPanelRects);//audio
566 AppendRects ("optiongr", mSubPanelRects);//game
567 AppendRects ("optionbr", mSubPanelRects);//bindings
568 AppendRects ("optionlr", mSubPanelRects);//list
570 //load miscellaneous strings
571 char buf[16];
572 for (long i = 0; i < kNumMiscStrs; i++) {
573 sprintf (buf, "misc_%d", i);
574 mMiscStrs[i] = FetchUIString (panel_name, buf, mResPath);
577 //create our "tabs" at the top of the menu for the different major categories
578 InitButtonList (&mTabDesc, &mTabRects[0], mTabElems, OnTabButton, mTabStrs, "tab_", kNumTabs, BUTTONLIST_RADIO_FLAG);
579 LGadCreateButtonListDesc (&mTabButtons, LGadCurrentRoot(), &mTabDesc);
580 SetBoxData(VB(&mTabButtons));
581 //muy sucky
582 int sub_tabs[] = {0, 1, 1, 2, 3, 0, 1};
583 LGadRadioButtonSelect (&mTabButtons, sub_tabs[mCurSub]);
585 // default to current style colors
586 AssertMsg (GetCurrentStyle (), "No current style for diff defaults");
587 memset (&mTextStyle, 0, sizeof (guiStyle));
588 memcpy (mTextStyle.colors, GetCurrentStyle ()->colors, sizeof(mTextStyle.colors));
589 uiGameLoadStyle ("opttext_", &mTextStyle, mResPath);
591 // style for greyed area
592 AssertMsg (GetCurrentStyle (), "No current style for diff defaults");
593 memcpy (&mGreyStyle, GetCurrentStyle (), sizeof(guiStyle));
594 uiGameLoadStyle ("grey_", &mGreyStyle, mResPath);
596 //get our slider button bitmap
597 AutoAppIPtr (ResMan);
598 for (i = 0; i < 4; i++) {
599 mButtBmpRes[SLIDER_BMPRES][i] = pResMan->Bind ("slidbutt", RESTYPE_IMAGE, NULL, mResPath);
600 if (!mButtBmpRes[SLIDER_BMPRES][i])
601 AssertMsg (0, "Error loading button bitmap");
603 InitDrawElem(&mButtDrawElem[SLIDER_BMPRES]);
604 mButtDrawElem[SLIDER_BMPRES].draw_data = (void *)mButtBmpRes[SLIDER_BMPRES];
605 mButtDrawElem[SLIDER_BMPRES].draw_type = DRAWTYPE_RESOFFSET;
607 InitDrawElem(&mSliderBaseBmp);
608 mSliderBaseBmp.draw_type = DRAWTYPE_RES;
609 mSliderBaseBmp.draw_data = (void *)pResMan->Bind ("slidbase", RESTYPE_IMAGE, NULL, mResPath);
611 for (i = 0; i < kNumSubPanelSlides; i++)
612 mSlidersOn[i] = FALSE;
614 //set sliders initial vals
615 m_sens = int((atof (g_pInputBinder->ProcessCmd ("echo $mouse_sensitivity")) - 0.5) * 2.0);
617 for (int v = 0; v < kNumVolumeSliders; v++)
618 m_volume[v] = GetVolume(v);
619 m_gamma = 20-(20.0 / (MAX_GAMMA - MIN_GAMMA)) * (g_gamma - MIN_GAMMA);
621 m3dDriver = 0;
622 if (config_is_defined("d3d_driver_index"))
623 config_get_int("d3d_driver_index", &m3dDriver);
625 //initialize our subpanels
626 mSwap = mCurSub;
627 mCurSub = -1;
628 InitControlOptions ();
629 InitVideoOptions ();
630 InitAudioOptions ();
631 InitGameOptions ();
632 InitBindOptions ();
633 InitListOptions ();
635 //our handler for handling keyboard arrows and enter in the binding menu
636 uiSlab *slab;
637 uiGetCurrentSlab (&slab);
639 uiInstallRegionHandler (slab->creg, UI_EVENT_KBD_COOKED, StaticBindKeyHandler, NULL, &m_cookie);
642 //////////////////////////////////////////////////////
644 void TermUI()
646 LGadDestroyButtonList(&mTabButtons);
648 memset(&mTabElems,0,sizeof(mTabElems));
649 for (int i = 0, j; i < kNumTabs; i++)
650 mTabStrs[i] = "";
652 TermSubPanel ();
653 uiGameUnloadStyle (&mBindStyle);
654 uiGameUnloadStyle (&mTextStyle);
656 for (i = 0; i < 3; i++)
657 for (j = 0; j < 4; j++)
658 mButtBmpRes[i][j]->Release ();
660 ((IRes *)(mSliderBaseBmp.draw_data))->Release ();
662 //save the current bindings upon exit of the options menu
663 //change to game context
664 ulong old_context;
665 g_pInputBinder->GetContext (&old_context);
666 g_pInputBinder->SetContext (HK_GAME_MODE,FALSE);
667 cStr header = FetchUIString (panel_name, "bnd_header", mResPath);
668 g_pInputBinder->SaveBndFile ("user.bnd", (char *)(const char *)header);
669 //plop in input variable control settings
670 BndAppendControls ();
672 g_pInputBinder->SetContext (HK_GAME2_MODE,FALSE);
673 g_pInputBinder->SaveBndFile ("user2.bnd", (char *)(const char *)header);
674 g_pInputBinder->SetContext (old_context,FALSE);
676 //remove the binding keyboard handler
677 uiSlab *slab;
678 uiGetCurrentSlab (&slab);
679 uiRemoveRegionHandler (LGadBoxRegion (slab->creg), m_cookie);
681 cDarkPanel::TermUI();
685 //////////////////////////////////////////////////////
687 void TermSubPanel ()
689 LGadDestroyButtonList (&mSubPanelButtons[mCurSub]);
691 if (mCurSub == kSubBind) {
692 LGadDestroyButtonList (&mBindButtons);
693 LGadDestroyButtonList (&mBindScrollers);
696 memset (mSubPanelElems, 0, kNumSubPanelRects * sizeof(DrawElement));
697 for (int i = 0; i < kNumSubPanelRects; i++)
698 mSubPanelStrs[i] = "";
700 //if there are any sliders, kill them
701 DestroyAllSliders ();
703 mTabRects.SetSize (0);
704 mSubPanelRects.SetSize (0);
707 //////////////////////////////////////////////////////
709 void TermSpecial ()
711 if (mCurSub == kSubBind) {
712 LGadDestroyButtonList (&mBindButtons);
713 LGadDestroyButtonList (&mBindScrollers);
716 else if (mCurSub == kSubList) {
717 if (mListSub == kSubBasicVideo) {
718 SetVidRes ();
721 LGadDestroyButtonList (&mListButtons);
725 //////////////////////////////////////////////////////
727 void OnLoopMsg (eLoopMessage msg, tLoopMessageData msg_data)
729 if (SFX_GetSoundDevice () == SFXDEVICE_A3D) {
730 mxs_vector origin = {0.0, 0.0, 0.0};
731 SFX_Frame (&origin, (mxs_angvec *)&origin);
733 else
734 SFX_Frame (NULL, NULL);
736 if (mSwap != -1) {
737 SwapSubPanel (mSwap);
738 mSwap = -1;
741 //check slider data
742 //volume
744 switch (mCurSub)
746 case kSubAudio:
748 for (int i = 0; i < kNumVolumeSliders; i++)
749 SetVolume(i,m_volume[i]);
751 break;
753 case kSubControls:
755 char buf[32];
756 sprintf (buf, "mouse_sensitivity %8.8f", ((double)m_sens / 2.0) + 0.5);//slide goes from 0.5 (slow) to 10.5 (fast)
757 g_pInputBinder->ProcessCmd (buf);
759 break;
762 case kSubBasicVideo:
764 //gamma
765 static int prev_gamma;
766 if (prev_gamma != m_gamma) {
767 TouchGamma ((((MAX_GAMMA - MIN_GAMMA) / 20.0) * (float)(20-m_gamma)) + MIN_GAMMA);
768 prev_gamma = m_gamma;
771 break;
776 //////////////////////////////////////////////////////
778 void InitControlOptions ()
780 InitButtonList(&mSubPanelDesc[kSubControls], &mSubPanelRects[(int)kCustomize], &mSubPanelElems[(int)kCustomize], OnSubPanelButton,
781 &mSubPanelStrs[(int)kCustomize], "control_", kNumControlButts, 0);
783 //set starting button strings
785 // watch me factor code like the dickens.
786 static const char* cmds[] =
789 "echo $lookspring",
790 "echo $mouse_invert",
791 "echo $freelook",
792 "echo $joy_rotate",
795 for (int i = kLookspring; i < kFirstControlRect; i++)
797 int idx = i - kFirstControlButt;
799 char *str = g_pInputBinder->ProcessCmd((char*)cmds[idx]); // command value
800 cStr& substr = mSubPanelStrs[i]; // button string
801 DrawElement& elem = mSubPanelElems[i]; // button elem
802 char res_str[16];
803 sprintf(res_str,"control_%d",i);
805 BOOL state = atof(str) != 0.0;
806 const char* state_str;
808 if (i == kJoyRotate) // exception
810 if (g_joystickActive)
811 state_str = mMiscStrs[(state) ? kMiscStrLeftRight : kMiscStrForwardBackward ];
812 else
814 *res_str = '\0';
815 state_str = NULL;
818 else
819 state_str = mMiscStrs[(state) ? kMiscStrOn : kMiscStrOff ];
821 SetUIString(substr,elem,res_str,(char*)state_str);
827 //////////////////////////////////////////////////////
829 void BndAppendControls ()
831 FILE *fp = fopen ("user.bnd", "at");
832 if (fp)
834 fprintf (fp, "\n");
836 char *controls[] = {"lookspring", "mouse_invert", "freelook", "mouse_sensitivity", "\0"};
837 char str[32];
838 char **p_control = controls;
840 while (**p_control) {
841 sprintf (str, "echo $%s", *p_control);
842 fprintf (fp, "%s %s\r\n", *p_control, g_pInputBinder->ProcessCmd (str));
843 p_control++;
846 fclose (fp);
850 //////////////////////////////////////////////////////
852 void InitVideoOptions ()
854 InitButtonList (&mSubPanelDesc[kSubBasicVideo], &mSubPanelRects[(int)kFirstBasicVideoButt], &mSubPanelElems[(int)kFirstBasicVideoButt],
855 OnSubPanelButton, &mSubPanelStrs[(int)kFirstBasicVideoButt], "videob_", kNumBasicVideoButts, 0);
857 int first = kFirstAdvancedVideoButt;
858 InitButtonList (&mSubPanelDesc[kSubAdvancedVideo], &mSubPanelRects[first], &mSubPanelElems[first],
859 OnSubPanelButton, &mSubPanelStrs[(int)first], "videoa_", kNumAdvancedVideoRects, 0);
862 SetVidResStr();
864 //let's get some info about the video card
865 mNumVidDevices = lgd3d_enumerate_devices ();
867 sScrnMode mode = *GetGameScreenMode();
869 if (mNumVidDevices > 0 && (mode.flags & kScrnMode3dDriver)) {
870 g_zbuffer_toggle = TRUE;
871 mode.flags |= kScrnMode3dDriver;
872 SetUIString (mSubPanelStrs[(int)kZBufferToggle], mSubPanelElems[(int)kZBufferToggle], "videoa_1",
873 (char *)(const char *)mMiscStrs[(g_zbuffer_toggle && (mode.flags & kScrnMode3dDriver) != 0) ? kMiscStrOn : kMiscStrOff]);
876 else {
877 g_zbuffer_toggle = FALSE;
878 mode.flags &= ~kScrnMode3dDriver;
879 SetUIString (mSubPanelStrs[(int)kZBufferToggle], mSubPanelElems[(int)kZBufferToggle], "videoa_1",
880 (char *)(const char *)mMiscStrs[kMiscStrOff]);
883 SetGameScreenMode (&mode);
887 //////////////////////////////////////////////////////
889 void InitAudioOptions ()
891 InitButtonList (&mSubPanelDesc[kSubAudio], &mSubPanelRects[(int)kSpeakerTest], &mSubPanelElems[(int)kSpeakerTest], OnSubPanelButton,
892 &mSubPanelStrs[(int)kSpeakerTest], "audio_", kNumAudioButts, 0);
894 SetUIString (mSubPanelStrs[(int)kStereoToggle], mSubPanelElems[(int)kStereoToggle], "audio_1",
895 (char *)(const char *)mMiscStrs[(SFX_StereoReversed ()) ? kMiscStrOn : kMiscStrOff]);
897 SetUIString (mSubPanelStrs[(int)kA3DToggle], mSubPanelElems[(int)kA3DToggle], "audio_2",
898 (char *)(const char *)mMiscStrs[(SFX_GetSoundDevice () == SFXDEVICE_A3D) ? kMiscStrOn : kMiscStrOff]);
900 char buf[8];
901 sprintf (buf, "%d", sfx_use_channels);
902 mSubPanelStrs[(int)kAudioChannels] += buf;
903 SetUIString (mSubPanelStrs[(int)kAudioChannels], mSubPanelElems[(int)kAudioChannels], "audio_3", buf);
905 BOOL isEAXOn = SFX_Is_EAX_Enabled();
906 SetUIString (mSubPanelStrs[(int)kAudioEAXToggle], mSubPanelElems[(int)kAudioEAXToggle], "audio_4",
907 (char *)(const char *)mMiscStrs[isEAXOn ? kMiscStrOn : kMiscStrOff]);
910 //////////////////////////////////////////////////////
912 void InitGameOptions ()
914 int first = kFirstGameButt;
915 InitButtonList (&mSubPanelDesc[kSubGame], &mSubPanelRects[first], &mSubPanelElems[first], OnSubPanelButton,
916 &mSubPanelStrs[first], "game_", kNumGameButts, BUTTONLIST_RADIO_FLAG);
919 //////////////////////////////////////////////////////
921 void InitBindOptions ()
923 InitButtonList (&mSubPanelDesc[kSubBind], &mSubPanelRects[(int)kBindLoad], &mSubPanelElems[(int)kBindLoad], OnSubPanelButton,
924 &mSubPanelStrs[(int)kBindLoad], "bind_", kNumBindButts, 0);
926 //set up description for binding buttons. joy.
927 //rearrange a few rects
928 mTopBind = 0;
929 cRectArray tmp_rects;
930 tmp_rects.SetSize (NUM_BIND_SLOTS);
931 for (long i = 0; i < (NUM_BIND_SLOTS - 2); i++)
932 tmp_rects[i] = mSubPanelRects[(int)kBindButt0 + 2 + i];
933 tmp_rects[NUM_BIND_SLOTS - 2] = mSubPanelRects[(int)kBindScrollUp];
934 tmp_rects[NUM_BIND_SLOTS - 1] = mSubPanelRects[(int)kBindButt0 + 1];
935 for (i = 0; i < NUM_BIND_SLOTS; i++)
937 mSubPanelRects[(int)kBindButt0 + 1 + i] = tmp_rects[i];
938 InitDrawElem(&mBindButtonElems[i]);
939 mBindButtonElems[i].draw_type = DRAWTYPE_TEXT;
941 //description of binding radio buttons
943 LGadButtonListDesc tmp_desc = {NUM_BIND_SLOTS, (Rect *)&mSubPanelRects[(int)kBindButt0],
944 mBindButtonElems, OnBindButton, 0, BUTTONLIST_RADIO_FLAG};
945 memcpy (&mBindButtonDesc, &tmp_desc, sizeof (LGadButtonListDesc));
948 // default to current style colors
949 AssertMsg (GetCurrentStyle (), "No current style for diff defaults");
950 memset (&mBindStyle, 0, sizeof (mBindStyle));
951 memcpy (mBindStyle.colors, GetCurrentStyle()->colors, sizeof (mBindStyle.colors));
952 uiGameLoadStyle("bind_", &mBindStyle, mResPath);
954 //load bind cmds
955 cStr bind_cmd;
956 char buf[16];
957 mNumBindable = 0;
958 while (1) {
959 sprintf (buf, "bindcmd_%d", mNumBindable);
960 bind_cmd = FetchUIString ("bindcmds", buf, mResPath);
962 if (bind_cmd == "" || mNumBindable >= MAX_NUM_BINDABLE)
963 break;
965 mBindCmd[mNumBindable] = bind_cmd;
966 mBindButtsFilled[mNumBindable] = FALSE;
967 mNumBindable++;
970 FillBindStrs ();
973 //load bitmaps for up/down scroll arrows
974 LoadButtBmp (mButtBmpRes[BINDUP_BMPRES], &mButtDrawElem[BINDUP_BMPRES], "bup_");
975 LoadButtBmp (mButtBmpRes[BINDDN_BMPRES], &mButtDrawElem[BINDDN_BMPRES], "bdn_");
977 //description of binding scroll buttons
979 LGadButtonListDesc tmp_desc = {2, (Rect *)&mSubPanelRects[(int)kBindScrollUp],
980 &mButtDrawElem[BINDUP_BMPRES], OnScrollButton, 0, 0};
981 memcpy (&mBindScrollerDesc, &tmp_desc, sizeof (LGadButtonListDesc));
986 //////////////////////////////////////////////////////
988 void InitListOptions ()
990 //description of back button
992 LGadButtonListDesc tmp_desc = {kNumListButts, (Rect *)&mSubPanelRects[(int)kListBack],
993 &mSubPanelElems[(int)kListBack], OnSubPanelButton, 0, 0};
994 mSubPanelDesc[kSubList] = tmp_desc;
997 mSubPanelStrs[(int)kListBack] = FetchUIString (panel_name, "bind_1", mResPath);
999 DrawElement& backelem = mSubPanelElems[(int)kListBack];
1000 InitDrawElem(&backelem);
1001 backelem.draw_data = (void *)(const char *)mSubPanelStrs[(int)kListBack];
1002 backelem.draw_type = DRAWTYPE_TEXT;
1004 //description of list buttons
1006 LGadButtonListDesc tmp_desc = {NUM_LIST, (Rect *)&mSubPanelRects[(int)kList0],
1007 mListButtonElems, OnListButton, 0, BUTTONLIST_RADIO_FLAG};
1008 mListButtonDesc = tmp_desc;
1011 mTopList = 0;
1016 //////////////////////////////////////////////////////
1018 void FillBindStr (long bind_num, long butt_num)
1020 if (bind_num >= mNumBindable) {
1021 static char *dummy = "";
1022 mBindButtonElems[butt_num].draw_data = dummy;
1023 return;
1026 if (mBindButtsFilled[bind_num]) {
1027 mBindButtonElems[butt_num].draw_data = (void*)(const char*)mBindButtonStrs[bind_num];
1028 return;
1030 mBindButtsFilled[bind_num] = TRUE;
1032 ulong old_context;
1033 g_pInputBinder->GetContext (&old_context);
1034 if (old_context != HK_GAME_MODE)
1035 g_pInputBinder->SetContext (HK_GAME_MODE,FALSE);
1037 //get our bindings
1038 char buf[64];
1039 sprintf (buf, "bindname_%d", bind_num);
1041 mBindButtonStrs[bind_num] = FetchUIString (panel_name, buf, mResPath);
1042 mBindButtonStrs[bind_num] += " = ";
1044 cStr controls[MAX_BINDS_PER_CMD];
1045 cStr raw_controls[MAX_BINDS_PER_CMD];
1046 int num = GetCmdBinds (mBindCmd[bind_num], controls, MAX_BINDS_PER_CMD, raw_controls);
1048 for (long i = 0; i < num; i++) {
1049 if (i != 0)
1050 mBindButtonStrs[bind_num] += ", ";
1051 mBindButtonStrs[bind_num] += controls[i];
1054 //there were no controls
1055 if (i == 0)
1056 mBindButtonStrs[bind_num] += mMiscStrs[kMiscStrEmpty];
1057 else
1059 // Copy the controls over to game2
1060 g_pInputBinder->SetContext(HK_GAME2_MODE,FALSE);
1061 for (int i = 0; i < num; i++)
1063 const char* cmd = mBindCmd[bind_num];
1064 const char* ctrl = raw_controls[i];
1066 // if cmd has a space, we have to quote it, because the binder is stupid
1067 cStr newcmd = "";
1068 if (strchr(cmd,' ') != NULL)
1070 newcmd += "\"";
1071 newcmd += cmd;
1072 newcmd += "\"";
1073 cmd = newcmd;
1076 // Check the config to make sure we can bind this stuff in game2
1077 BOOL can_bind = TRUE;
1078 char varbuf[80];
1079 sprintf(varbuf,"%s_bind_game2",ctrl);
1080 config_get_int(varbuf,&can_bind);
1082 if (can_bind)
1083 g_pInputBinder->Bind((char*)ctrl,(char*)cmd);
1087 if (old_context != HK_GAME2_MODE)
1088 g_pInputBinder->SetContext (old_context,FALSE);
1090 mBindButtonElems[butt_num].draw_data = (void*)(const char*)mBindButtonStrs[bind_num];
1093 //////////////////////////////////////////////////////
1095 void FillBindStrs ()
1097 AutoAppIPtr(ResMan);
1098 IRes* ctrls = pResMan->Bind("controls",RESTYPE_STRING,NULL,mResPath);
1099 ctrls->Lock();
1101 IRes* panel = pResMan->Bind(panel_name,RESTYPE_STRING,NULL,mResPath);
1102 panel->Lock();
1104 ulong old_context;
1105 g_pInputBinder->GetContext (&old_context);
1106 g_pInputBinder->SetContext (HK_GAME_MODE,TRUE);
1109 for (long i = 0, j = mTopBind; i < NUM_BIND_SLOTS; i++, j++) {
1111 FillBindStr (j, i);
1114 ctrls->Unlock();
1115 panel->Unlock();
1116 SafeRelease(ctrls);
1117 SafeRelease(panel);
1119 //change back to previous mode
1120 g_pInputBinder->SetContext (old_context,TRUE);
1124 //////////////////////////////////////////////////////
1126 static bool StaticBindKeyHandler (uiEvent *p_event, Region *p_reg, void *state)
1128 bool ret = FALSE;
1129 if (gpOptions->mCurSub == gpOptions->kSubBind && p_event->type == UI_EVENT_KBD_COOKED)
1130 ret = gpOptions->BindKeyHandler ((uiCookedKeyEvent *)p_event);
1131 return ret;
1134 bool BindKeyHandler (uiCookedKeyEvent *event)
1136 //only use up actions
1137 if (event->code & KB_FLAG_DOWN)
1138 return FALSE;
1141 BOOL redraw = TRUE;
1142 int cur_selected = LGadRadioButtonSelection (&mBindButtons);
1144 switch (event->code) {
1145 case KEY_UP:
1146 case KEY_PAD_UP:
1147 if (cur_selected > 0)
1148 LGadRadioButtonSelect (&mBindButtons, cur_selected - 1);
1149 else if (mTopBind > 0) {
1150 mTopBind--;
1151 FillBindStrs ();
1153 else
1154 redraw = FALSE;
1156 break;
1159 case KEY_DOWN:
1160 case KEY_PAD_DOWN:
1161 if (cur_selected < (NUM_BIND_SLOTS - 1))
1162 LGadRadioButtonSelect (&mBindButtons, cur_selected + 1);
1163 else if (mTopBind < mNumBindable - NUM_BIND_SLOTS) {
1164 mTopBind++;
1165 FillBindStrs ();
1167 else
1168 redraw = FALSE;
1170 break;
1172 case KEY_PGUP:
1173 case KEY_PAD_PGUP:
1174 mTopBind -= NUM_BIND_SLOTS;
1175 if (mTopBind < 0) {
1176 mTopBind = 0;
1177 LGadRadioButtonSelect (&mBindButtons, 0);
1180 FillBindStrs ();
1182 break;
1184 case KEY_PGDN:
1185 case KEY_PAD_PGDN:
1186 mTopBind += NUM_BIND_SLOTS;
1187 if (mTopBind >= (mNumBindable - NUM_BIND_SLOTS)) {
1188 mTopBind = mNumBindable - NUM_BIND_SLOTS;
1189 LGadRadioButtonSelect (&mBindButtons, NUM_BIND_SLOTS - 1);
1192 FillBindStrs ();
1194 break;
1197 case KEY_HOME:
1198 case KEY_PAD_HOME:
1199 LGadRadioButtonSelect (&mBindButtons, 0);
1200 if (mTopBind != 0) {
1201 mTopBind = 0;
1202 FillBindStrs ();
1204 break;
1207 case KEY_END:
1208 case KEY_PAD_END:
1209 LGadRadioButtonSelect (&mBindButtons, NUM_BIND_SLOTS - 1);
1210 if (mTopBind != (mNumBindable - NUM_BIND_SLOTS)) {
1211 mTopBind = mNumBindable - NUM_BIND_SLOTS;
1212 FillBindStrs ();
1214 break;
1217 case KEY_ENTER:
1218 case KEY_GREY_ENTER:
1219 OnSubPanelButtonList (BUTTONGADG_LCLICK, kBind - kBindLoad);
1221 break;
1223 default:
1224 redraw = FALSE;
1227 if (redraw) {
1228 FillBlack (FILL_SUBPANEL);
1229 RedrawDisplay ();
1232 return TRUE;
1236 //////////////////////////////////////////////////////
1238 void SetVidRes ()
1240 //has not changed
1241 if (mSelectedRes == -1)
1242 return;
1244 sScrnMode mode = *GetGameScreenMode();
1246 char *mode_desc = (char *)(const char *)mListButtonStrs[mSelectedRes];
1247 sscanf (mode_desc, "%dx%dx%d", &mode.w, &mode.h, &mode.bitdepth);
1249 SetGameScreenMode (&mode);
1251 SetVidResStr();
1254 // Set the resolution string
1255 void SetVidResStr()
1257 int residx = kScreenRes;
1258 cStr& resstr = mSubPanelStrs[residx];
1259 DrawElement& elem = mSubPanelElems[residx];
1261 char buf[64];
1262 const sScrnMode& mode = *GetGameScreenMode();
1263 sprintf(buf,"%dx%dx%d",mode.w,mode.h,mode.bitdepth);
1265 SetUIString(resstr,elem,"videob_0",buf);
1269 //////////////////////////////////////////////////////
1271 void FillVidResStrs ()
1273 //int mTopList;
1274 const sScrnMode *mode = GetGameScreenMode ();
1275 lgd3ds_device_info *info;
1277 int idx = mNumVidDevices - 1;
1278 if (config_is_defined("d3d_driver_index"))
1279 config_get_int("d3d_driver_index", &idx);
1280 info = lgd3d_get_device_info (idx);
1282 int bpp;
1283 short *cur_mode;
1284 char buf[32], mode_str[32];
1286 if (mNumVidDevices > 0 && (mode->flags & kScrnMode3dDriver)) {
1287 cur_mode = &info->supported_modes[mTopList];
1288 bpp = 16;
1290 else {
1291 cur_mode = &soft_modes[mTopList];
1292 bpp = 8;
1295 //get current mode string so we know what to select
1296 sprintf (mode_str, "%dx%dx%d", mode->w, mode->h, mode->bitdepth);
1297 //dunny button will be default selection if we dont have a matching res for some reason
1298 LGadRadioButtonSelect (&mListButtons, mListPrevPick = NUM_LIST - 1);
1300 mNumListTotal = 0;
1301 for (long i = 0, inc = 0; i < NUM_LIST; i += inc) {
1302 inc = 0;
1303 if (*cur_mode != -1 && i < NUM_LIST - 1)
1305 grs_mode_info& info = grd_mode_info[*cur_mode];
1307 if (info.bitDepth == bpp
1308 && info.w >= MIN_RES_X
1309 && info.h >= MIN_RES_Y
1310 && info.h <= MAX_RES_Y)
1314 sprintf (buf, "%dx%dx%d", grd_mode_info[*cur_mode].w,
1315 grd_mode_info[*cur_mode].h, grd_mode_info[*cur_mode].bitDepth);
1317 mListButtonStrs[i] = buf;
1319 if (!strcmp (buf, mode_str))
1320 LGadRadioButtonSelect (&mListButtons, mListPrevPick = i);
1322 inc = 1;
1323 mNumListTotal++;
1325 cur_mode++;
1327 else {
1328 mListButtonStrs[i] = "";
1329 inc = 1;
1332 DrawElement& elem = mListButtonElems[i];
1333 InitDrawElem(&elem);
1334 elem.draw_data = (void *)(const char *)mListButtonStrs[i];
1335 elem.draw_type = DRAWTYPE_TEXT;
1341 //////////////////////////////////////////////////////
1343 void FillVidDevStrs ()
1345 lgd3ds_device_info *info;
1347 for (long i = 0; i < NUM_LIST; i++) {
1348 if (i < mNumVidDevices) {
1349 info = lgd3d_get_device_info (i);
1350 mListButtonStrs[i] = info->p_ddraw_desc;
1352 else
1353 mListButtonStrs[i] = "";
1355 DrawElement& elem = mListButtonElems[i];
1356 InitDrawElem(&elem);
1357 elem.draw_data = (void *)(const char *)mListButtonStrs[i];
1358 elem.draw_type = DRAWTYPE_TEXT;
1361 int idx = mNumVidDevices - 1;
1362 if (config_is_defined("d3d_driver_index"))
1363 config_get_int("d3d_driver_index", &idx);
1364 LGadRadioButtonSelect (&mListButtons, mListPrevPick = idx);
1367 //////////////////////////////////////////////////////
1369 static BOOL BindFilter (char *control, char *cmd, void *data)
1371 //we'll reserve ESC for breaking from a bind query
1372 if (!strcmp (control, "esc"))
1373 return FALSE;
1375 //don't bind joystick movement
1376 if (!strcmp (control, "joy_move"))
1377 return FALSE;
1379 //scroll lock doesnt have up/down events like a normal key
1380 if (!strcmp (control, "scroll_lock"))
1381 return FALSE;
1383 // don't bind the F keys since the game needs them for psi powers
1384 int i;
1385 for (i=1; i <= 12; i++)
1387 char fkey[32];
1388 sprintf(fkey,"F%d",i);
1389 if (!stricmp(control, fkey))
1390 return(FALSE);
1393 // otherwise, it's legal
1394 return TRUE;
1397 //////////////////////////////////////////////////////
1399 static void PostBindFunc (BOOL bound)
1401 for (long i = 0; i < gpOptions->mNumBindable; i++)
1402 gpOptions->mBindButtsFilled[i] = FALSE;
1403 gpOptions->FillBindStrs ();
1404 gpOptions->FillBlack (FILL_SUBPANEL);
1405 gpOptions->RedrawDisplay ();
1407 g_pInputBinder->SetContext (gpOptions->m_old_context,TRUE);
1410 //////////////////////////////////////////////////////
1412 static void QuickConfigPostBindFunc (BOOL bound)
1414 int bind_num = gpOptions->mTopBind + LGadRadioButtonSelection (&gpOptions->mBindButtons) + 1;
1415 if (bind_num < QUICKCONFIG_BINDNUM && bound) {
1416 if (bind_num > NUM_BIND_SLOTS - 1) {
1417 gpOptions->mTopBind++;
1419 LGadRadioButtonSelect (&gpOptions->mBindButtons, bind_num - gpOptions->mTopBind);
1420 char buf[16];
1421 sprintf (buf, "bindname_%d", bind_num);
1422 gpOptions->mBindButtonStrs[bind_num] = FetchUIString (gpOptions->panel_name, buf, gpOptions->mResPath);
1423 gpOptions->mBindButtonStrs[bind_num] += " = ?";
1425 g_pInputBinder->TrapBind ((char *)(const char *)gpOptions->mBindCmd[bind_num],
1426 gpOptions->BindFilter, gpOptions->QuickConfigPostBindFunc, NULL);
1429 else
1430 g_pInputBinder->SetContext (gpOptions->m_old_context,TRUE);
1432 for (long i = 0; i < gpOptions->mNumBindable; i++)
1433 gpOptions->mBindButtsFilled[i] = ((i != bind_num || !bound) || (bind_num == QUICKCONFIG_BINDNUM)) ? FALSE : TRUE;
1435 gpOptions->FillBindStrs ();
1436 gpOptions->FillBlack (FILL_SUBPANEL);
1437 gpOptions->RedrawDisplay ();
1441 //////////////////////////////////////////////////////
1443 void InitButtonList (LGadButtonListDesc *desc, Rect *rect_array, DrawElement *draw_elem,
1444 ButtListCB cb, cStr *strs, const char *prefix, int num, int flags)
1446 // set up drawlelems
1447 for (int i = 0; i < num; i++) {
1448 DrawElement *elem = &draw_elem[i];
1449 InitDrawElem(elem);
1451 char buf[16];
1452 sprintf(buf, "%s%d", prefix, i);
1453 strs[i] = FetchUIString (panel_name, buf, mResPath);
1454 elem->draw_type = DRAWTYPE_TEXT;
1455 elem->draw_data = (void*)(const char*)strs[i];
1459 LGadButtonListDesc tmp_desc = {
1460 num,
1461 rect_array,
1462 draw_elem,
1465 flags,
1468 memcpy (desc, &tmp_desc, sizeof (LGadButtonListDesc));
1472 //////////////////////////////////////////////////////
1474 void DrawButtonList (LGadButtonListDesc *blist)
1476 Rect rect = {{0, 0}, {640, 480}};
1477 uiHideMouse (&rect);
1479 int num = blist->num_buttons;
1480 for (int i = 0; i < num; i++) {
1481 ElementDraw (&blist->button_elems[i], dsNORMAL, blist->button_rects[i].ul.x, blist->button_rects[i].ul.y,
1482 blist->button_rects[i].lr.x - blist->button_rects[i].ul.x, blist->button_rects[i].lr.y - blist->button_rects[i].ul.y);
1485 uiShowMouse (&rect);
1488 //////////////////////////////////////////////////////
1490 void DrawSlider (int num, int rect_num, BOOL draw_slide = TRUE)
1492 Rect rect = {{0, 0}, {640, 480}};
1493 uiHideMouse (&rect);
1495 Rect *slide_rect = (Rect *)&mSubPanelRects[rect_num];
1496 ElementDraw (&mSliderBaseBmp, dsNORMAL, slide_rect->ul.x, slide_rect->ul.y,
1497 slide_rect->lr.x - slide_rect->ul.x, slide_rect->lr.y - slide_rect->ul.y);
1499 uiShowMouse (&rect);
1500 if (draw_slide)
1501 LGadDrawBox ((LGadBox*)&mSliders[num], NULL);
1504 //////////////////////////////////////////////////////
1506 void LoadButtBmp (IRes *butt_res[4], DrawElement *draw_elem, char *prefix)
1508 char *sffx [] = {"norm", "down", "hlit", "hlit"}, str[128];
1509 AutoAppIPtr (ResMan);
1510 for (int i = 0; i < 4; i++) {
1511 butt_res[i] = pResMan->Bind (strcat (strcpy (str, prefix), sffx[i]), RESTYPE_IMAGE, NULL, mResPath);
1512 if (!butt_res[i])
1513 AssertMsg (0, "Error loading button bitmap");
1516 InitDrawElem(draw_elem);
1517 draw_elem->draw_data = (void *)butt_res;
1518 draw_elem->draw_type = DRAWTYPE_RESOFFSET;
1521 //////////////////////////////////////////////////////
1523 void SetUIString (cStr &str, DrawElement &draw_elem, char *name, char *suffix)
1525 str = FetchUIString (panel_name, name, mResPath);
1526 if (suffix)
1527 str += suffix;
1528 draw_elem.draw_data = (void*)(const char*)str;
1531 //////////////////////////////////////////////////////
1533 void AppendRects (char *rect_file, cRectArray &old_rects)
1535 long old_sz, tmp_sz;
1536 cRectArray tmp_rects;
1537 FetchUIRects(rect_file, tmp_rects, mResPath);
1538 old_rects.SetSize ((old_sz = old_rects.Size ()) + (tmp_sz = tmp_rects.Size ()));
1540 for (long i = 0, j = old_sz; i < tmp_sz; i++, j++)
1541 old_rects[j] = tmp_rects[i];
1544 //////////////////////////////////////////////////////
1546 void CreateSlider (int slider_num, int rect_num, int *val_ptr, int num_notches, int inc)
1548 LGadSlider *slider = &mSliders[slider_num];
1549 Rect *rect = (Rect *)&mSubPanelRects[rect_num];
1550 memset (slider, 0, sizeof (LGadSlider));
1551 slider->gadg.draw = mButtDrawElem[SLIDER_BMPRES];
1553 //this is absolutely a hack.
1554 //make the slider's range of motion smaller since the slider's base art
1555 //presents the slide as having a more confined range. 12 pixels will do the trick.
1556 short x, w;
1557 x = rect->ul.x + 12;
1558 w = rect->lr.x - rect->ul.x - 24;
1560 LGadCreateSliderArgs (slider, LGadCurrentRoot (), x, rect->ul.y + ((rect->lr.y - rect->ul.y)>>1), 0, 0, NULL,
1561 val_ptr, num_notches, inc, w, LGSLIDER_HORIZONTAL, 0);
1563 mSlidersOn[slider_num] = TRUE;
1565 LGadDrawBox ((LGadBox*)slider, NULL);
1568 //////////////////////////////////////////////////////
1570 void DestroySlider (int slider_num)
1572 if (mSlidersOn[slider_num]) {
1573 LGadDestroySlider (&mSliders[slider_num], FALSE);
1574 mSlidersOn[slider_num] = FALSE;
1578 //////////////////////////////////////////////////////
1580 void DestroyAllSliders ()
1582 for (int i = 0; i < (int)kNumSubPanelSlides; i++)
1583 DestroySlider (i);
1586 //////////////////////////////////////////////////////
1588 void DrawString (char *strname, int rect_num)
1590 cStr str = FetchUIString (panel_name, strname, mResPath);//copy the string
1591 char *s = (char*)(const char*)str;//get a mutable pointer
1593 Rect &r = mSubPanelRects[rect_num];
1595 DrawElement draw;
1596 InitDrawElem(&draw);
1597 draw.draw_type = DRAWTYPE_TEXT;
1598 draw.draw_data = s;
1599 ElementSetStyle(&mTextStyle);
1600 ElementDraw (&draw, dsNORMAL, r.ul.x, r.ul.y, r.lr.x - r.ul.x, r.lr.y - r.ul.y);
1603 //////////////////////////////////////////////////////
1605 void RedrawDisplay ()
1607 // draw buttonlist
1608 region_expose (LGadBoxRegion (&mTabButtons), LGadBoxRect (&mTabButtons));
1609 DrawButtonList (&mSubPanelDesc[mCurSub]);
1611 //any sub-specific stuff
1612 switch (mCurSub) {
1613 case kSubControls:
1614 DrawSlider ((int)kMouseSensSlider, (int)kMouseSensSliderRect);
1615 DrawString ("mouse_sens", kMouseSensTextRect);
1616 break;
1618 case kSubBasicVideo:
1619 DrawSlider ((int)kGammaSlider, (int)kGammaSliderRect);
1620 DrawString ("gamma", kGammaSliderText);
1621 break;
1623 case kSubAudio:
1625 for (int i = 0; i < kNumVolumeSliders; i++)
1627 DrawSlider (i, gVolSliderRects[i]);
1628 char name[16];
1629 sprintf(name,"volume_%d",i);
1630 DrawString (name,gVolSliderRects[i] + 1); // plus one to get from rect to text rect
1633 break;
1635 case kSubGame:
1636 region_expose (LGadBoxRegion (&mSubPanelButtons[kSubGame]), LGadBoxRect (&mSubPanelButtons[kSubGame]));
1637 DrawString ("diff", kDiffTextRect);
1638 break;
1640 case kSubBind:
1641 DrawButtonList (&mBindScrollerDesc);
1642 region_expose (LGadBoxRegion (&mBindButtons), LGadBoxRect (&mBindButtons));
1643 break;
1645 case kSubList:
1646 region_expose (LGadBoxRegion (&mListButtons), LGadBoxRect (&mListButtons));
1647 // DrawButtonList (&mBindScrollerDesc);
1648 break;
1652 //////////////////////////////////////////////////////
1654 void FillBlack (int rect_num)
1656 Rect *rect;
1657 if (rect_num == FILL_SUBPANEL)
1658 rect = (Rect *)&mRects[(int)kSubFillRect];
1659 else
1660 rect = (Rect *)&mSubPanelRects[rect_num];
1662 GUIErase(rect);
1665 //////////////////////////////////////////////////////
1667 void SwapSubPanel (int new_sub)
1669 if (mCurSub != -1) {
1670 LGadDestroyButtonList (&mSubPanelButtons[mCurSub]);
1671 TermSpecial ();
1674 if (new_sub!=kSubAudio)
1675 metaSndEnterPanel(kMetaSndPanelOptions);
1676 else
1677 metaSndExitPanel(TRUE);
1679 LGadCreateButtonListDesc (&mSubPanelButtons[new_sub], LGadCurrentRoot (), &mSubPanelDesc[new_sub]);
1680 SetBoxData(VB(&mSubPanelButtons[new_sub]));
1682 switch (new_sub)
1684 case kSubControls:
1686 DrawSlider ((int)kMouseSensSlider, (int)kMouseSensSliderRect, FALSE);
1687 CreateSlider ((int)kMouseSensSlider, (int)kMouseSensSliderRect, &m_sens, 20, 1);
1689 break;
1691 case kSubBasicVideo:
1693 DrawSlider ((int)kGammaSlider, (int)kGammaSliderRect, FALSE);
1694 CreateSlider ((int)kGammaSlider, (int)kGammaSliderRect, &m_gamma, 20, 1);
1696 break;
1698 case kSubAudio:
1700 for (int i = 0; i < kNumVolumeSliders; i++)
1702 DrawSlider(i,gVolSliderRects[i],FALSE);
1703 CreateSlider(i,gVolSliderRects[i],&m_volume[i],kVolumeSliderNotches - 1, 1);
1706 if (! CanChangeSoundDeviceNow ()) {
1707 mSubPanelDesc[kSubAudio].button_elems[kAudioChannels - kFirstAudioButt].fcolor = guiStyleGetColor(&mGreyStyle,StyleColorText);
1708 mSubPanelDesc[kSubAudio].button_elems[kA3DToggle - kFirstAudioButt].fcolor = guiStyleGetColor(&mGreyStyle,StyleColorText);
1711 if (!CanChangeEAX())
1712 mSubPanelDesc[kSubAudio].button_elems[kAudioEAXToggle - kSpeakerTest].fcolor = guiStyleGetColor(&mGreyStyle,StyleColorText);
1714 break;
1716 case kSubGame:
1718 g_diff_active = CanChangeDifficultyNow();
1719 if (InSim())
1721 AutoAppIPtr(QuestData);
1722 if (pQuestData->Exists(DIFF_QVAR))
1723 g_diff = pQuestData->Get(DIFF_QVAR);
1726 if (!g_diff_active)
1727 LGadBoxSetStyle (&mSubPanelButtons[kSubGame], &mGreyStyle);
1729 //set the current difficulty setting
1730 LGadRadioButtonSelect (&mSubPanelButtons[kSubGame], DIFF2BUTT(g_diff));
1732 break;
1734 case kSubBind:
1736 LGadCreateButtonListDesc (&mBindButtons, LGadCurrentRoot (), &mBindButtonDesc);
1737 SetBoxData(VB(&mBindButtons));
1738 LGadRadioButtonSelect (&mBindButtons,0);
1739 LGadBoxSetStyle (&mBindButtons, &mBindStyle);
1741 LGadCreateButtonListDesc (&mBindScrollers, LGadCurrentRoot (), &mBindScrollerDesc);
1742 SetBoxData(VB(&mBindScrollers));
1744 break;
1746 case kSubList:
1748 LGadCreateButtonListDesc (&mListButtons, LGadCurrentRoot (), &mListButtonDesc);
1749 SetBoxData(VB(&mListButtons));
1750 LGadBoxSetStyle (&mListButtons, &mBindStyle);
1752 // LGadCreateButtonListDesc (&mBindScrollers, LGadCurrentRoot (), &mBindScrollerDesc);
1753 // SetBoxData(VB(&mBindScrollers));
1755 if (mListSub == kSubAdvancedVideo)
1756 FillVidDevStrs ();
1757 else if (mListSub == kSubBasicVideo)
1758 FillVidResStrs ();
1759 mTopList = 0;
1761 break;
1764 FillBlack (FILL_SUBPANEL);
1766 mCurSub = new_sub;
1767 RedrawDisplay ();
1770 //////////////////////////////////////////////////////
1772 static void PlayRightTest (int, void *)
1774 sfx_parm parm;
1775 memset (&parm, 0, sizeof (sfx_parm));
1776 parm.pan = SFX_StereoReversed() ? -10000 : 10000;
1777 cStr snd_name = FetchUIString (gpOptions->panel_name, "rightsound", gpOptions->mResPath);
1779 if (SFX_GetSoundDevice () == SFXDEVICE_A3D) {
1780 //@TODO: make the a3d speaker test sound crisper, clearer, more refreshed
1781 mxs_vector pos = {0.0, SFX_StereoReversed() ? 10.0 : -10.0, 0.0};
1782 SFX_Play_Vec (SFX_3D, &parm, (char *)(const char *)snd_name, &pos);
1784 else
1785 SFX_Play_Raw (SFX_STATIC, &parm, (char *)(const char *)snd_name);
1788 //////////////////////////////////////////////////////
1790 static bool OnTabButton (ushort action, int button, void *data, LGadBox *)
1792 cOptions *panel = (cOptions*)data;
1794 panel->OnTabButtonList (action, button);
1795 return FALSE;
1798 //////////////////////////////////////////////////////
1800 void OnTabButtonList (ushort action, int button)
1802 if (!(action & BUTTONGADG_LCLICK))
1803 return;
1805 switch (button)
1807 //controls
1808 case kTab0:
1810 if (mCurSub != kSubControls) {
1811 mSwap = kSubControls;
1812 DestroyAllSliders ();
1815 break;
1817 //video
1818 case kTab1:
1820 if (mCurSub != kSubBasicVideo && mCurSub != kSubAdvancedVideo) {
1821 DestroyAllSliders ();
1822 mSwap = kSubBasicVideo;
1825 break;
1827 //audio
1828 case kTab2:
1830 if (mCurSub != kSubAudio) {
1831 DestroyAllSliders ();
1832 mSwap = kSubAudio;
1835 break;
1837 //game
1838 case kTab3:
1840 if (mCurSub != kSubGame) {
1841 DestroyAllSliders ();
1842 mSwap = kSubGame;
1845 break;
1850 //////////////////////////////////////////////////////
1852 static bool OnSubPanelButton (ushort action, int button, void *data, LGadBox *)
1854 cOptions *panel = (cOptions*)data;
1856 panel->OnSubPanelButtonList (action, button);
1857 return FALSE;
1860 //////////////////////////////////////////////////////
1862 void OnSubPanelButtonList (ushort action, int button)
1864 if (!(action & BUTTONGADG_LCLICK))
1865 return;
1867 int idx = button + gFirstSubRect[mCurSub];
1870 switch (idx)
1873 case kScreenRes:
1874 mSwap = kSubList;
1875 mListSub = kSubBasicVideo;
1876 mSelectedRes = -1;
1877 mTopList = 0;
1878 break;
1881 #ifdef ADVANDED_VID_PANEL
1882 case kAdvancedVidOptions:
1883 DestroyAllSliders ();
1884 mSwap = kSubAdvancedVideo;
1885 break;
1886 #endif
1888 case kHardwareDriver:
1889 mSwap = kSubList;
1890 mListSub = kSubAdvancedVideo;
1891 mTopList = 0;
1892 break;
1894 case kZBufferToggle:
1896 const sScrnMode *old_mode = GetGameScreenMode ();
1897 if (mNumVidDevices > 0 && old_mode->flags & kScrnMode3dDriver) {
1898 if (!g_zbuffer_toggle) {
1899 SetUIString (mSubPanelStrs[(int)kZBufferToggle], mSubPanelElems[(int)kZBufferToggle], "videoa_1",
1900 (char *)(const char *)mMiscStrs[kMiscStrOn]);
1901 g_zbuffer_toggle = TRUE;
1903 else {
1904 SetUIString (mSubPanelStrs[(int)kZBufferToggle], mSubPanelElems[(int)kZBufferToggle], "videoa_1",
1905 (char *)(const char *)mMiscStrs[kMiscStrOff]);
1906 g_zbuffer_toggle = FALSE;
1908 FillBlack ((int)kZBufferToggle);
1909 RedrawDisplay ();
1912 break;
1914 case kBasicVidOptions:
1915 DestroyAllSliders ();
1916 mSwap = kSubBasicVideo;
1917 break;
1920 case kSpeakerTest:
1922 sfx_parm parm;
1923 memset (&parm, 0, sizeof (sfx_parm));
1924 parm.pan = SFX_StereoReversed() ? 10000 : -10000;
1925 parm.end_callback = PlayRightTest;
1926 cStr snd_name = FetchUIString (panel_name, "leftsound", mResPath);
1928 if (SFX_GetSoundDevice () == SFXDEVICE_A3D) {
1929 mxs_vector pos = {0.0, SFX_StereoReversed() ? -10.0 : 10.0, 0.0};
1930 //@TODO: make the a3d speaker test sound crisper, clearer, more refreshed
1931 SFX_Play_Vec (SFX_3D, &parm, (char *)(const char *)snd_name, &pos);
1933 else
1934 SFX_Play_Raw (SFX_STATIC, &parm, (char *)(const char *)snd_name);
1936 break;
1938 case kStereoToggle:
1939 SFX_SetReverseStereo (!SFX_StereoReversed ());
1940 SetUIString (mSubPanelStrs[(int)kStereoToggle], mSubPanelElems[(int)kStereoToggle], "audio_1",
1941 (char *)(const char *)mMiscStrs[(SFX_StereoReversed ()) ? kMiscStrOn : kMiscStrOff]);
1942 FillBlack (kStereoToggle);
1943 RedrawDisplay ();
1944 break;
1946 case kA3DToggle:
1947 if (CanChangeSoundDeviceNow()) {
1948 if (SFX_GetSoundDevice () != SFXDEVICE_A3D)
1950 // Try to use 3D sound hardware
1951 if (! SFX_SetSoundDevice (SFXDEVICE_A3D, TRUE))
1953 // If no 3D sound hardware, turn back on software.
1954 SFX_SetSoundDevice (SFXDEVICE_Software, TRUE);
1957 else
1958 SFX_SetSoundDevice (SFXDEVICE_Software, TRUE);
1960 SetUIString (mSubPanelStrs[(int)kA3DToggle], mSubPanelElems[(int)kA3DToggle], "audio_2",
1961 (char *)(const char *)mMiscStrs[(SFX_GetSoundDevice () == SFXDEVICE_A3D) ? kMiscStrOn : kMiscStrOff]);
1962 FillBlack (kA3DToggle);
1963 // RedrawDisplay ();
1965 // EAX settings may have changed.
1966 BOOL newEAXState = SFX_Is_EAX_Enabled();
1967 SetUIString (mSubPanelStrs[(int)kAudioEAXToggle], mSubPanelElems[(int)kAudioEAXToggle], "audio_4",
1968 (char *)(const char *)mMiscStrs[newEAXState ? kMiscStrOn : kMiscStrOff]);
1970 // Set EAX button color as appropriate.
1971 if ( CanChangeEAX() )
1972 // Hack: This takes the "green" color from the "speaker test" button..... there must be a better way...
1973 mSubPanelDesc[kSubAudio].button_elems[kAudioEAXToggle - kSpeakerTest].fcolor = mSubPanelDesc[kSubAudio].button_elems[0].fcolor;
1974 else
1975 mSubPanelDesc[kSubAudio].button_elems[kAudioEAXToggle - kSpeakerTest].fcolor = guiStyleGetColor(&mGreyStyle,StyleColorText);
1976 FillBlack (kAudioEAXToggle);
1978 RedrawDisplay();
1980 break;
1982 case kAudioChannels:
1983 if (CanChangeSoundDeviceNow())
1985 // List of valid selections
1986 static int selections[] = { 4, 8, 12, 16, 0 };
1987 int chan = sfx_use_channels;
1988 for (int* sel = selections; *sel != 0 && *sel <= chan; sel++)
1990 if (*sel == 0)
1991 chan = selections[0];
1992 else
1993 chan = *sel;
1995 SFXClose ();
1996 sfx_use_channels = chan;
1997 config_set_int("sfx_channels", chan);
1998 SFXInit ();
2000 char buf[8];
2001 sprintf (buf, "%d", chan);
2002 mSubPanelStrs[(int)kAudioChannels] += buf;
2003 SetUIString (mSubPanelStrs[(int)kAudioChannels], mSubPanelElems[(int)kAudioChannels], "audio_3", buf);
2005 break;
2007 case kAudioEAXToggle:
2008 if (CanChangeEAX())
2010 // Toggle EAX state.
2011 BOOL newEAXState = !SFX_Is_EAX_Enabled();
2012 if (newEAXState)
2013 SFX_Enable_EAX();
2014 else
2015 SFX_Disable_EAX();
2017 // Double-check to make sure state actually toggled.
2018 newEAXState = SFX_Is_EAX_Enabled();
2019 config_set_int ("sfx_eax", (int) newEAXState);
2020 SetUIString (mSubPanelStrs[(int)kAudioEAXToggle], mSubPanelElems[(int)kAudioEAXToggle], "audio_4",
2021 (char *)(const char *)mMiscStrs[newEAXState ? kMiscStrOn : kMiscStrOff]);
2023 break;
2025 case kCustomize:
2026 DestroyAllSliders ();
2027 mSwap = kSubBind;
2028 break;
2031 // I may weep openly
2032 case kDiff0:
2033 case kDiff1:
2034 case kDiff2:
2035 case kDiff3:
2037 if (g_diff_active)
2039 // Set the difficulty
2040 g_diff = BUTT2DIFF(button);
2041 if (InSim())
2043 AutoAppIPtr(QuestData);
2044 if (pQuestData->Exists(DIFF_QVAR))
2045 pQuestData->Set(DIFF_QVAR,g_diff);
2048 //not active, don't let them change buttons
2049 else
2050 LGadRadioButtonSelect (&mSubPanelButtons[kSubGame], DIFF2BUTT(g_diff));
2052 break;
2055 case kBindLoad:
2056 SwitchToDPCLoadBndMode (TRUE);
2057 break;
2060 case kBindSave:
2061 SwitchToDPCSaveBndMode (TRUE);
2062 break;
2064 case kBindBack:
2065 DestroyAllSliders ();
2066 mSwap = kSubControls;
2067 break;
2070 case kQuickConfigure:
2071 LGadRadioButtonSelect (&mBindButtons, mTopBind = 0);
2072 mBindButtonStrs[0] = FetchUIString (panel_name, "bindname_0", mResPath);
2073 mBindButtonStrs[0] += " = ?";
2075 //change to game context
2076 g_pInputBinder->GetContext (&m_old_context);
2077 g_pInputBinder->SetContext (HK_GAME_MODE,TRUE);
2078 g_pInputBinder->TrapBind ((char *)(const char *)mBindCmd[0], BindFilter, QuickConfigPostBindFunc, NULL);
2080 FillBindStrs ();
2081 FillBlack (FILL_SUBPANEL);
2082 RedrawDisplay ();
2083 break;
2086 case kBind:
2088 int bind_num = mTopBind + LGadRadioButtonSelection (&mBindButtons);
2089 char buf[16];
2090 sprintf (buf, "bindname_%d", bind_num);
2091 mBindButtonStrs[bind_num] = FetchUIString (panel_name, buf, mResPath);
2092 mBindButtonStrs[bind_num] += " = ?";
2094 //change to game context
2095 g_pInputBinder->GetContext (&m_old_context);
2096 g_pInputBinder->SetContext (HK_GAME_MODE,TRUE);
2097 g_pInputBinder->TrapBind ((char *)(const char *)mBindCmd[bind_num], BindFilter, PostBindFunc, NULL);
2099 FillBindStrs ();
2100 FillBlack (FILL_SUBPANEL);
2101 RedrawDisplay ();
2103 break;
2106 case kBindClear:
2108 //change to game context
2109 g_pInputBinder->GetContext (&m_old_context);
2110 g_pInputBinder->SetContext (HK_GAME_MODE,TRUE);
2112 char str[128], control_buf[64];
2113 int bind_num = mTopBind + LGadRadioButtonSelection (&mBindButtons);
2115 g_pInputBinder->GetControlFromCmdStart ((char *)(const char *)mBindCmd[bind_num], control_buf);
2116 while (*control_buf != '\0') {
2117 strcpy (str, "unbind ");
2118 strcat (str, control_buf);
2119 g_pInputBinder->ProcessCmd (str);
2120 g_pInputBinder->GetControlFromCmdStart ((char *)(const char *)mBindCmd[bind_num], control_buf);
2123 g_pInputBinder->SetContext (m_old_context,TRUE);
2125 for (int i = 0; i < mNumBindable; i++)
2126 mBindButtsFilled[i] = FALSE;
2127 FillBindStrs ();
2128 FillBlack (FILL_SUBPANEL);
2129 RedrawDisplay ();
2131 break;
2133 case kLookspring:
2135 char *inverted = g_pInputBinder->ProcessCmd ("echo $lookspring"), buf[16];
2136 sprintf (buf, "control_%d", button);
2137 if (atof (inverted) == 0.0) {
2138 g_pInputBinder->ProcessCmd ("lookspring 1");
2139 SetUIString (mSubPanelStrs[(int)kLookspring], mSubPanelElems[(int)kLookspring], buf, (char *)(const char *)mMiscStrs[kMiscStrOn]);
2141 //when lookspring is turned on, turn off freelook if it is on
2142 if (atof (g_pInputBinder->ProcessCmd ("echo $freelook")) != 0.0)
2143 OnSubPanelButtonList (action, kFreelook - kCustomize);
2145 else {
2146 g_pInputBinder->ProcessCmd ("lookspring 0");
2147 SetUIString (mSubPanelStrs[(int)kLookspring], mSubPanelElems[(int)kLookspring], buf, (char *)(const char *)mMiscStrs[kMiscStrOff]);
2149 FillBlack ((int)kLookspring);
2150 RedrawDisplay ();
2152 break;
2154 case kJoyRotate:
2156 if (g_joystickActive)
2158 char *rotate = g_pInputBinder->ProcessCmd ("echo $joy_rotate"), buf[16];
2159 sprintf (buf, "control_%d", button);
2160 if (atof (rotate) == 0.0) {
2161 g_pInputBinder->ProcessCmd ("joy_rotate 1");
2162 SetUIString (mSubPanelStrs[(int)kJoyRotate], mSubPanelElems[(int)kJoyRotate], buf, (char *)(const char *)mMiscStrs[kMiscStrLeftRight]);
2164 else {
2165 g_pInputBinder->ProcessCmd ("joy_rotate 0");
2166 SetUIString (mSubPanelStrs[(int)kJoyRotate], mSubPanelElems[(int)kJoyRotate], buf, (char *)(const char *)mMiscStrs[kMiscStrForwardBackward]);
2168 FillBlack ((int)kJoyRotate);
2169 RedrawDisplay ();
2172 break;
2174 case kMouseInvert:
2176 char *inverted = g_pInputBinder->ProcessCmd ("echo $mouse_invert"), buf[16];
2177 sprintf (buf, "control_%d", button);
2178 if (atof (inverted) == 0.0) {
2179 g_pInputBinder->ProcessCmd ("mouse_invert 1");
2180 SetUIString (mSubPanelStrs[(int)kMouseInvert], mSubPanelElems[(int)kMouseInvert], buf, (char *)(const char *)mMiscStrs[kMiscStrOn]);
2182 else {
2183 g_pInputBinder->ProcessCmd ("mouse_invert 0");
2184 SetUIString (mSubPanelStrs[(int)kMouseInvert], mSubPanelElems[(int)kMouseInvert], buf, (char *)(const char *)mMiscStrs[kMiscStrOff]);
2186 FillBlack ((int)kMouseInvert);
2187 RedrawDisplay ();
2189 break;
2192 case kFreelook:
2194 char *inverted = g_pInputBinder->ProcessCmd ("echo $freelook"), buf[16];
2195 sprintf (buf, "control_%d", button);
2196 if (atof (inverted) == 0.0) {
2197 g_pInputBinder->ProcessCmd ("freelook 1");
2198 SetUIString (mSubPanelStrs[(int)kFreelook], mSubPanelElems[(int)kFreelook], buf, (char *)(const char *)mMiscStrs[kMiscStrOn]);
2200 //when freelook is turned on, turn off lookspring if it is on
2201 if (atof (g_pInputBinder->ProcessCmd ("echo $lookspring")) != 0.0)
2202 OnSubPanelButtonList (action, kLookspring - kCustomize);
2204 else {
2205 g_pInputBinder->ProcessCmd ("freelook 0");
2206 SetUIString (mSubPanelStrs[(int)kFreelook], mSubPanelElems[(int)kFreelook], buf, (char *)(const char *)mMiscStrs[kMiscStrOff]);
2208 FillBlack ((int)kFreelook);
2209 RedrawDisplay ();
2211 break;
2214 case kListBack:
2215 mSwap = mListSub;
2216 DestroyAllSliders ();
2218 if (mListSub == kSubAdvancedVideo) {
2219 config_set_int ("d3d_driver_index", m3dDriver = LGadRadioButtonSelection (&mListButtons));
2220 // Go back to basic video instead of advanced
2221 mSwap = kSubBasicVideo;
2224 //resolution choice
2225 else if (mListSub == kSubBasicVideo) {
2226 SetVidRes ();
2228 break;
2233 //////////////////////////////////////////////////////
2235 static bool OnScrollButton (ushort action, int button, void *data, LGadBox *)
2237 cOptions *panel = (cOptions*)data;
2239 panel->OnScrollList (action, button);
2240 return FALSE;
2243 //////////////////////////////////////////////////////
2245 void OnScrollList (ushort action, int button)
2247 if (!(action & BUTTONGADG_LCLICK))
2248 return;
2250 BOOL redraw = TRUE;
2252 switch (button)
2254 //scroll up
2255 case 0:
2256 switch (mCurSub) {
2257 case kSubBind:
2258 if (mTopBind > 0) {
2259 mTopBind--;
2260 FillBindStrs ();
2262 else
2263 redraw = FALSE;
2264 break;
2266 //scrolling through resolutions
2267 case kSubList:
2268 if (mTopList > 0) {
2269 mTopList--;
2270 FillVidResStrs ();
2272 else
2273 redraw = FALSE;
2274 break;
2277 break;
2279 //scroll down
2280 case 1:
2281 switch (mCurSub) {
2282 case kSubBind:
2283 if (mTopBind <= mNumBindable - NUM_BIND_SLOTS) {
2284 mTopBind++;
2285 FillBindStrs ();
2287 if (mTopBind == mNumBindable - (NUM_BIND_SLOTS - 1) && LGadRadioButtonSelection (&mBindButtons) == (NUM_BIND_SLOTS - 1))
2288 LGadRadioButtonSelect (&mBindButtons, 8);
2290 else
2291 redraw = FALSE;
2292 break;
2294 //resolutions
2295 case kSubList:
2296 if (mNumListTotal >= NUM_LIST - 1) {
2297 mTopList++;
2298 FillVidResStrs ();
2300 else
2301 redraw = FALSE;
2302 break;
2305 break;
2308 if (redraw) {
2309 FillBlack (FILL_SUBPANEL);
2310 RedrawDisplay ();
2315 //////////////////////////////////////////////////////
2317 static bool OnBindButton (ushort action, int button, void *data, LGadBox *)
2319 cOptions *panel = (cOptions*)data;
2321 panel->OnBind (action, button);
2322 return FALSE;
2325 //////////////////////////////////////////////////////
2327 void OnBind (ushort action, int button)
2329 if (!(action & BUTTONGADG_LCLICK))
2330 return;
2332 static int prev_pick;
2333 if (!strcmp ((const char *)mBindButtonElems[button].draw_data, "")) {
2334 LGadRadioButtonSelect (&mBindButtons, prev_pick);
2336 else
2337 prev_pick = button;
2340 //////////////////////////////////////////////////////
2342 static bool OnListButton (ushort action, int button, void *data, LGadBox *)
2344 cOptions *panel = (cOptions*)data;
2346 panel->OnList (action, button);
2347 return FALSE;
2350 //////////////////////////////////////////////////////
2352 void OnList (ushort action, int button)
2354 if (!(action & BUTTONGADG_LCLICK))
2355 return;
2357 BOOL valid_butt = TRUE;
2359 //display device choice
2360 if (mListSub == kSubAdvancedVideo) {
2361 //the button clicked was not filled
2362 if (button >= mNumVidDevices) {
2363 LGadRadioButtonSelect (&mListButtons, mListPrevPick);
2364 valid_butt = FALSE;
2367 //there was something there
2368 else {
2369 config_set_int ("d3d_driver_index", button);
2370 m3dDriver = button;
2374 //resolution choice
2375 else if (mListSub == kSubBasicVideo) {
2376 //the button clicked was not filled
2377 if (button >= mNumListTotal) {
2378 LGadRadioButtonSelect (&mListButtons, mListPrevPick);
2379 valid_butt = FALSE;
2381 else {
2382 mSelectedRes = mTopList + button;
2383 SetVidRes ();
2387 if (valid_butt)
2388 mListPrevPick = button;
2391 //////////////////////////////////////////////////////
2393 void OnButtonList(ushort action, int button)
2395 if (!(action & BUTTONGADG_LCLICK))
2396 return;
2398 switch (button)
2400 case kDone:
2402 if (mCurSub == kSubList)
2403 OnSubPanelButtonList (action, 0);
2405 cAutoIPtr<IPanelMode> mode = GetPanelMode();
2406 mode->Exit();
2408 break;
2415 int cDPCOptions::gFirstSubRect[] =
2417 cDPCOptions::kFirstControlButt,
2418 cDPCOptions::kFirstBasicVideoButt,
2419 cDPCOptions::kFirstAdvancedVideoButt,
2420 cDPCOptions::kFirstAudioButt,
2421 cDPCOptions::kFirstGameButt,
2422 cDPCOptions::kFirstBindButt,
2423 cDPCOptions::kFirstListButt,
2426 int cDPCOptions::gVolSliderRects[] =
2428 cDPCOptions::kVolumeSliderRect,
2429 cDPCOptions::k3dVolumeSliderRect,
2430 cDPCOptions::kMusicSliderRect,
2435 // Options Menu descriptor
2438 static const char* options_button_names[] =
2440 "done"
2443 sDarkPanelDesc cOptions::gDesc =
2445 "options",
2446 cOptions::kNumButts,
2447 cOptions::kNumRects,
2448 cOptions::kNumButts,
2449 options_button_names,
2450 NULL,
2452 kMetaSndPanelOptions
2457 EXTERN void SwitchToDPCOptionsMode(BOOL push)
2459 if (gpOptions)
2461 cAutoIPtr<IPanelMode> panel = gpOptions->GetPanelMode();
2462 panel->Switch((push) ? kLoopModePush : kLoopModeSwitch);
2467 const sLoopInstantiator* DescribeDPCOptionsMode(void)
2469 if (gpOptions)
2471 cAutoIPtr<IPanelMode> panel = gpOptions->GetPanelMode();
2472 return panel->Instantiator();
2474 return NULL;
2478 //Wrapper so that others can use this easier..
2479 //Will stuff retrieve_num many controls bound to cmd into the dest
2480 //string array, and will return how many actually got stuff
2481 #ifdef WE_NEED_THIS
2482 int GetCmdBinds (const char *cmd, cStr *dest, int retrieve_num)
2484 return gpOptions->GetCmdBinds (cmd, dest, retrieve_num);
2486 #endif
2491 // Init and term stuff
2494 void DPCOptionsMenuInit ()
2496 gpOptions = new cOptions;
2497 gpOptions->SetInitialSub ();
2498 DPCInitBindSaveLoad();
2501 void DPCOptionsMenuTerm ()
2503 delete gpOptions;
2504 DPCTermBindSaveLoad();