Linux makefiles
[canaan.git] / prj / cam / src / shock / shkoptmn.cpp
blob2c90b567f2a5420f1ec3f5878f718f9cd4e14fcc
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 // $Header: r:/t2repos/thief2/src/shock/shkoptmn.cpp,v 1.20 1999/08/27 13:04:56 mahk Exp $
7 #include <shkoptmn.h>
8 #include <string.h>
9 #include <dev2d.h>
10 #include <keydefs.h>
12 #include <shkmenu.h>
13 #include <shksvbnd.h>
14 #include <appagg.h>
15 #include <drkpanl.h>
17 #include <appsfx.h>
18 #include <gamescrn.h>
19 #include <scrnmode.h>
21 #include <resapi.h>
22 #include <imgrstyp.h>
23 #include <strrstyp.h>
25 #include <gcompose.h>
26 #include <questapi.h>
27 #include <drkdiff.h>
28 #include <config.h>
29 #include <uigame.h>
31 #include <panltool.h>
32 #include <appapi.h>
33 #include <mprintf.h>
34 #include <campaign.h>
36 #include <gadslide.h>
37 #include <gen_bind.h>
38 #include <lgd3d.h>
40 #include <command.h>
41 #include <gamma.h>
42 #include <objmodel.h>
43 #include <metasnd.h>
45 #include <simman.h>
46 #include <simdef.h>
47 #include <netman.h>
49 #include <volconv.h>
51 #include <shkdiff.h>
53 #include <math.h>
55 // Include this last.
56 #include <dbmem.h>
59 #define kVolumeSliderNotches 25
60 #define kOneOverVolumeSliderNotches ((1.0)/(float)kVolumeSliderNotches)
62 static void TouchGamma (float gamma)
64 g_gamma = gamma;
65 gamma_update();
69 //is the difficulty setting greyed out or not?
70 static BOOL g_diff_active = TRUE;
72 //starting difficulty
73 extern int g_diff;
75 #define MIN_DIFF 1
77 inline int DIFF2BUTT(int x)
79 // boundary cases
80 if (x < kShockFirstDiff)
81 x = kShockFirstDiff;
82 if (x >= kShockLimDiff)
83 x = kShockDiffNormal;
85 return x - 1;
88 #define BUTT2DIFF(x) ((x) + 1)
91 EXTERN BOOL g_zbuffer_toggle;
92 extern int sfx_use_channels;
95 /////////////////
97 #define MAX_NUM_BINDABLE 64
98 #define QUICKCONFIG_BINDNUM 15 /*number of quick configurable commands*/
99 #define NUM_BIND_SLOTS 13
100 //max cmds we will display per a given cmd
101 #define MAX_BINDS_PER_CMD 3
103 /////////////////
105 #define SLIDER_BMPRES 0
106 #define BINDUP_BMPRES 1
107 #define BINDDN_BMPRES 2
109 #define NUM_LIST 13
110 #define FILL_SUBPANEL 666
112 #define LRMOD(x) (!strcmp (x, "lalt") || !strcmp (x, "ralt") || \
113 !strcmp (x, "lctrl") || !strcmp (x, "rctrl") || \
114 !strcmp (x, "lshift") || !strcmp (x, "rshift"))
118 #define MIN_RES_X 640
119 #define MIN_RES_Y 480
120 #define MAX_RES_Y 768
122 //all 8-bit for software
123 static short soft_modes[] = {
124 GRM_400x300x8,
125 GRM_512x384x8,
126 GRM_640x400x8,
127 GRM_640x480x8,
128 GRM_800x600x8,
132 //#define CanChangeEAX() (SFX_Is_EAX_Available())
133 #define CanChangeEAX() (SFX_Is_EAX_Available() && (SFX_GetSoundDevice () == SFXDEVICE_A3D))
135 static BOOL InSim()
137 AutoAppIPtr(SimManager);
138 return (pSimManager->LastMsg() & (kSimInit | kSimResume)) != 0;
141 #define CanChangeSoundDeviceNow() (!InSim())
144 BOOL CanChangeDifficultyNow()
146 AutoAppIPtr(NetManager);
147 return !pNetManager->IsNetworkGame();
151 static const DrawElement def_draw_elem =
153 0, 0, 0, // type, data, data2
154 0, 0, // fcolor bcolor
155 INTERNAL(DRAWFLAG_INT_TRANSP), // flags
158 static void InitDrawElem(DrawElement* elem)
160 *elem = def_draw_elem;
164 //------------------------------------------------------------
165 // OPTIONS MENU
167 class cShockOptions;
168 typedef class cShockOptions cOptions;
170 static cOptions *gpOptions = NULL;
173 class cShockOptions: public cDarkPanel
175 static sDarkPanelDesc gDesc;
177 public:
178 cOptions() : cDarkPanel(&gDesc)
180 memset(&mTabButtons,0,sizeof(mTabButtons));
181 memset(mSubPanelButtons,0,sizeof(mSubPanelButtons));
182 memset(&mListButtons,0,sizeof(mListButtons));
183 memset(&mBindButtons,0,sizeof(mBindButtons));
184 memset(&mBindScrollers,0,sizeof(mBindScrollers));
185 memset(mSliders,0,sizeof(mSliders));
189 void SetInitialSub ()
191 mCurSub = kSubControls;
194 //Will stuff retrieve_num many controls bound to cmd into the dest
195 //string array, and will return how many actually got stuff
196 int GetCmdBinds (const char *cmd, cStr *dest, int retrieve_num, cStr* raw_dest = NULL)
198 char control_buf[64];
199 char controls[4][32];
200 long num_controls, i, cur_control;
202 g_pInputBinder->GetControlFromCmdStart ((char *)cmd, control_buf);
205 for (cur_control = 0; *control_buf != '\0' && cur_control < retrieve_num;) {
206 g_pInputBinder->DecomposeControl (control_buf, controls, &num_controls);
207 //we don't want to throw in the l/r mods
208 for (i = 0; i < num_controls && !LRMOD (controls[i]); i++);
210 //no l/r's, this control is cool. fetch names
211 if (i == num_controls)
213 cStr& cur_dest = dest[cur_control];
215 cStr temp_raw; // We might not have a raw_dest
216 cStr& cur_raw = (raw_dest) ? raw_dest[cur_control] : temp_raw;
218 cur_dest = "";
219 cur_raw = "";
220 for (i = 0; i < num_controls; i++)
222 if (i)
224 cur_dest += "+";
225 cur_raw += "+";
228 cStr str = FetchUIString ("controls", controls[i], mResPath);
230 //does this key have a translated string?
231 cur_dest += (*str) ? str : controls[i];
232 cur_raw += controls[i];
235 cur_control++;
238 g_pInputBinder->GetControlFromCmdNext (control_buf);
241 return cur_control;
244 enum
246 kDone,
247 kNumButts,
248 kSubFillRect = kNumButts,
249 kNumRects
252 enum
254 kTab0,
255 kTab1,
256 kTab2,
257 kTab3,
258 kNumTabs
261 enum {
262 //control buttons
263 kFirstControlButt,
264 kCustomize = kFirstControlButt,
265 kLookspring,
266 kMouseInvert,
267 kFreelook,
268 kJoyRotate,
270 kFirstControlRect,
271 kMouseSensSliderRect = kFirstControlRect,
272 kMouseSensTextRect,
273 kLimControlRect,
274 kNumControlButts = kFirstControlRect - kFirstControlButt,
275 kNumControlRects = kLimControlRect - kFirstControlButt,
277 //video buttons
278 kFirstBasicVideoButt = kLimControlRect,
279 kScreenRes = kFirstBasicVideoButt,
280 kHardwareDriver,
282 kFirstBasicVideoRect,
283 kGammaSliderRect = kFirstBasicVideoRect,
284 kGammaSliderText,
285 kLimBasicVideoRect,
286 kNumBasicVideoButts = kFirstBasicVideoRect - kFirstBasicVideoButt,
287 kNumBasicVideoRects = kLimBasicVideoRect - kFirstBasicVideoRect,
289 kFirstAdvancedVideoButt = kLimBasicVideoRect,
290 kHardwareDriverOld = kFirstAdvancedVideoButt,
291 kZBufferToggle,
292 kBasicVidOptions,
293 kLimAdvancedVideoRect,
294 kNumAdvancedVideoRects = kLimAdvancedVideoRect - kFirstAdvancedVideoButt,
296 //audio buttons/rects
297 kFirstAudioButt = kLimAdvancedVideoRect,
298 kSpeakerTest = kFirstAudioButt,
299 kStereoToggle,
300 kA3DToggle,
301 kAudioChannels,
302 kAudioEAXToggle,
304 kFirstAudioRect,
305 kVolumeSliderRect = kFirstAudioRect,
306 kVolumeSliderText,
307 k3dVolumeSliderRect,
308 k3dVolumeSliderText,
309 kMusicSliderRect,
310 kMusicSliderText,
312 kLimAudioRect,
313 kNumAudioButts = kFirstAudioRect - kFirstAudioButt,
314 kNumAudioRects = kLimAudioRect - kFirstAudioButt,
316 //game buttons (Note irregularity)
317 kFirstGameRect = kLimAudioRect,
318 kDiffTextRect = kFirstGameRect,
319 kFirstGameButt,
320 kDiff0 = kFirstGameButt,
321 kDiff1,
322 kDiff2,
323 kDiff3,
324 kLimGameRect,
325 kNumGameButts = kLimGameRect - kFirstGameButt,
326 kNumGameRects = kLimGameRect - kFirstGameRect,
328 //bind buttons
329 kFirstBindButt = kLimGameRect,
330 kBindLoad = kFirstBindButt,
331 kBindBack,
332 kBindSave,
333 kQuickConfigure,
334 kBind,
335 kBindClear,
336 kBindButt0,//0 to NUM_BIND_SLOTS - 1
338 kBindScrollUp = kBindButt0 + NUM_BIND_SLOTS,
339 kBindScrollDown,
340 kLimBindRects,
341 kNumBindButts = kBindButt0 - kFirstBindButt,
342 kNumBindRects = kLimBindRects - kFirstBindButt,
344 kFirstListButt = kLimBindRects,
345 kListBack = kFirstListButt,
346 kList0,//13 of these, just add what is needed.
347 kNumListButts = kList0 - kFirstListButt,
348 kNumListRects = NUM_LIST + kNumListButts,
351 kNumSubPanelRects = kNumControlRects + kNumBasicVideoRects + kNumAdvancedVideoRects
352 + kNumAudioRects + kNumGameRects + kNumBindRects + kNumListRects,
355 enum {
356 kVolumeSlider,
357 k3dVolumeSlider,
358 kMusicSlider,
359 kNumVolumeSliders,
360 kMouseSensSlider = kNumVolumeSliders,
361 kGammaSlider,
362 kNumSubPanelSlides
366 enum {
367 kSubControls,
368 kSubBasicVideo,
369 kSubAdvancedVideo,
370 kSubAudio,
371 kSubGame,
372 kSubBind,
373 kSubList,
374 kNumSubs
377 enum {
378 kMiscStrOn,
379 kMiscStrOff,
380 kMiscStrEmpty,
381 kMiscStrLow,
382 kMiscStrHigh,
383 kMiscStrLeftRight,
384 kMiscStrForwardBackward,
385 kNumMiscStrs
390 static int gFirstSubRect[];
393 protected:
394 guiStyle mTextStyle;
395 guiStyle mGreyStyle;
397 cStr mMiscStrs[kNumMiscStrs];
399 IRes *mButtBmpRes[3][4];//4 button draw states
400 DrawElement mButtDrawElem[3];
403 LGadButtonList mTabButtons;
404 LGadButtonListDesc mTabDesc;
405 cRectArray mTabRects;
406 DrawElement mTabElems[kNumTabs];
407 cStr mTabStrs[kNumTabs];
409 int mCurSub;
410 int mSwap;
411 LGadButtonList mSubPanelButtons[kNumSubs];
412 LGadButtonListDesc mSubPanelDesc[kNumSubs];
413 cRectArray mSubPanelRects;
414 DrawElement mSubPanelElems[kNumSubPanelRects];
415 cStr mSubPanelStrs[kNumSubPanelRects];
417 //list
418 int mListSub;
419 int mListPrevPick;
420 int mTopList;
421 int mNumListTotal;
422 LGadButtonList mListButtons;
423 LGadButtonListDesc mListButtonDesc;
424 DrawElement mListButtonElems[NUM_LIST];
425 cStr mListButtonStrs[NUM_LIST];
427 //video-related data
428 BOOL mNumVidDevices;
429 int mSelectedRes;
430 int m3dDriver;
432 //binding-related data
433 int mTopBind;
434 int mNumBindable;
435 guiStyle mBindStyle;
437 LGadButtonList mBindButtons;
438 LGadButtonListDesc mBindButtonDesc;
439 DrawElement mBindButtonElems[NUM_BIND_SLOTS];
440 cStr mBindButtonStrs[MAX_NUM_BINDABLE];
441 cStr mBindCmd[MAX_NUM_BINDABLE];
442 bool mBindButtsFilled[MAX_NUM_BINDABLE];
444 LGadButtonList mBindScrollers;
445 LGadButtonListDesc mBindScrollerDesc;
447 int m_cookie;
450 //slider stuff
451 LGadSlider mSliders[kNumSubPanelSlides];
452 bool mSlidersOn[kNumSubPanelSlides];
453 DrawElement mSliderBaseBmp;
455 ulong m_old_context;
457 //slider variables
458 int m_sens;
459 int m_volume[kNumVolumeSliders];
460 int m_gamma;
463 typedef bool (*ButtListCB)(ushort, int, void *, LGadBox *);
466 //////////////////////////////////////////////////////
468 void SetBoxData(LGadBox* box)
470 LGadBoxSetUserData (box, this);
472 int flags = LGadBoxFlags(box);
473 LGadBoxSetFlags(box, flags | BOXFLAG_CLEAR);
476 typedef int (*vol_get_func)(void);
478 uint MillibelToSlider(int vol)
480 uint retval = (uint) ( VolMillibelToLinear((float)vol) * kVolumeSliderNotches);
481 if (retval >= kVolumeSliderNotches)
482 retval = kVolumeSliderNotches - 1;
483 return retval;
487 // get slider volume, in slider notches
488 uint GetVolume(uint which)
490 static vol_get_func funcs[] =
492 SFX_GetMasterVolume,
493 SFX_Get3dVolume,
494 SFX_GetMusicVolume,
497 if (which == k3dVolumeSlider)
499 uint vol3d = MillibelToSlider(SFX_Get3dVolume());
500 uint vol2d = MillibelToSlider(SFX_Get2dVolume());
501 if (vol3d > vol2d)
503 vol2d = kVolumeSliderNotches - vol2d;
504 return (kVolumeSliderNotches + vol2d)/2;
506 else
507 return vol3d/2;
510 int vol = funcs[which]();
511 return MillibelToSlider(vol);
515 typedef void (*vol_set_func)(int);
517 // set volume, in slider notches
518 void SetVolume(int which, int vol)
520 static vol_set_func funcs[] =
522 SFX_SetMasterVolume,
523 SFX_Set3dVolume,
524 SFX_SetMusicVolume,
527 vol_set_func func = funcs[which];
528 // the 3d volume slider is really a "mix" between 2d and 3d
529 if (which == k3dVolumeSlider)
531 int half = (kVolumeSliderNotches + 1)/2;
532 if (vol < half)
534 SFX_Set2dVolume(0);
535 func = SFX_Set3dVolume;
536 vol *= 2;
538 else
540 SFX_Set3dVolume(0);
541 func = SFX_Set2dVolume;
542 vol = (kVolumeSliderNotches - vol)*2;
546 Assert_(which < kNumVolumeSliders);
548 float fvol = VolLinearToMillibel((float)vol * kOneOverVolumeSliderNotches);
550 func((int)fvol);
554 static int gVolSliderRects[];
557 void InitUI()
559 cDarkPanel::InitUI();
561 //load in the tab and subpanel rectangles
562 AppendRects ("optiontr", mTabRects);//tabs
563 AppendRects ("optioncr", mSubPanelRects);//controls
564 AppendRects ("optnbvr", mSubPanelRects);//basic video
565 AppendRects ("optnavr", mSubPanelRects);//advanced video
566 AppendRects ("optionar", mSubPanelRects);//audio
567 AppendRects ("optiongr", mSubPanelRects);//game
568 AppendRects ("optionbr", mSubPanelRects);//bindings
569 AppendRects ("optionlr", mSubPanelRects);//list
571 //load miscellaneous strings
572 char buf[16];
573 for (long i = 0; i < kNumMiscStrs; i++) {
574 sprintf (buf, "misc_%d", i);
575 mMiscStrs[i] = FetchUIString (panel_name, buf, mResPath);
578 //create our "tabs" at the top of the menu for the different major categories
579 InitButtonList (&mTabDesc, &mTabRects[0], mTabElems, OnTabButton, mTabStrs, "tab_", kNumTabs, BUTTONLIST_RADIO_FLAG);
580 LGadCreateButtonListDesc (&mTabButtons, LGadCurrentRoot(), &mTabDesc);
581 SetBoxData(VB(&mTabButtons));
582 //muy sucky
583 int sub_tabs[] = {0, 1, 1, 2, 3, 0, 1};
584 LGadRadioButtonSelect (&mTabButtons, sub_tabs[mCurSub]);
586 // default to current style colors
587 AssertMsg (GetCurrentStyle (), "No current style for diff defaults");
588 memset (&mTextStyle, 0, sizeof (guiStyle));
589 memcpy (mTextStyle.colors, GetCurrentStyle ()->colors, sizeof(mTextStyle.colors));
590 uiGameLoadStyle ("opttext_", &mTextStyle, mResPath);
592 // style for greyed area
593 AssertMsg (GetCurrentStyle (), "No current style for diff defaults");
594 memcpy (&mGreyStyle, GetCurrentStyle (), sizeof(guiStyle));
595 uiGameLoadStyle ("grey_", &mGreyStyle, mResPath);
597 //get our slider button bitmap
598 AutoAppIPtr (ResMan);
599 for (i = 0; i < 4; i++) {
600 mButtBmpRes[SLIDER_BMPRES][i] = pResMan->Bind ("slidbutt", RESTYPE_IMAGE, NULL, mResPath);
601 if (!mButtBmpRes[SLIDER_BMPRES][i])
602 AssertMsg (0, "Error loading button bitmap");
604 InitDrawElem(&mButtDrawElem[SLIDER_BMPRES]);
605 mButtDrawElem[SLIDER_BMPRES].draw_data = (void *)mButtBmpRes[SLIDER_BMPRES];
606 mButtDrawElem[SLIDER_BMPRES].draw_type = DRAWTYPE_RESOFFSET;
608 InitDrawElem(&mSliderBaseBmp);
609 mSliderBaseBmp.draw_type = DRAWTYPE_RES;
610 mSliderBaseBmp.draw_data = (void *)pResMan->Bind ("slidbase", RESTYPE_IMAGE, NULL, mResPath);
612 for (i = 0; i < kNumSubPanelSlides; i++)
613 mSlidersOn[i] = FALSE;
615 //set sliders initial vals
616 m_sens = int((atof (g_pInputBinder->ProcessCmd ("echo $mouse_sensitivity")) - 0.5) * 2.0);
618 for (int v = 0; v < kNumVolumeSliders; v++)
619 m_volume[v] = GetVolume(v);
620 m_gamma = 20-(20.0 / (MAX_GAMMA - MIN_GAMMA)) * (g_gamma - MIN_GAMMA);
622 m3dDriver = 0;
623 if (config_is_defined("d3d_driver_index"))
624 config_get_int("d3d_driver_index", &m3dDriver);
626 //initialize our subpanels
627 mSwap = mCurSub;
628 mCurSub = -1;
629 InitControlOptions ();
630 InitVideoOptions ();
631 InitAudioOptions ();
632 InitGameOptions ();
633 InitBindOptions ();
634 InitListOptions ();
636 //our handler for handling keyboard arrows and enter in the binding menu
637 uiSlab *slab;
638 uiGetCurrentSlab (&slab);
640 uiInstallRegionHandler (slab->creg, UI_EVENT_KBD_COOKED, StaticBindKeyHandler, NULL, &m_cookie);
643 //////////////////////////////////////////////////////
645 void TermUI()
647 LGadDestroyButtonList(&mTabButtons);
649 memset(&mTabElems,0,sizeof(mTabElems));
650 for (int i = 0, j; i < kNumTabs; i++)
651 mTabStrs[i] = "";
653 TermSubPanel ();
654 uiGameUnloadStyle (&mBindStyle);
655 uiGameUnloadStyle (&mTextStyle);
657 for (i = 0; i < 3; i++)
658 for (j = 0; j < 4; j++)
659 mButtBmpRes[i][j]->Release ();
661 ((IRes *)(mSliderBaseBmp.draw_data))->Release ();
663 //save the current bindings upon exit of the options menu
664 //change to game context
665 ulong old_context;
666 g_pInputBinder->GetContext (&old_context);
667 g_pInputBinder->SetContext (HK_GAME_MODE,FALSE);
668 cStr header = FetchUIString (panel_name, "bnd_header", mResPath);
669 g_pInputBinder->SaveBndFile ("user.bnd", (char *)(const char *)header);
670 //plop in input variable control settings
671 BndAppendControls ();
673 g_pInputBinder->SetContext (HK_GAME2_MODE,FALSE);
674 g_pInputBinder->SaveBndFile ("user2.bnd", (char *)(const char *)header);
675 g_pInputBinder->SetContext (old_context,FALSE);
677 //remove the binding keyboard handler
678 uiSlab *slab;
679 uiGetCurrentSlab (&slab);
680 uiRemoveRegionHandler (LGadBoxRegion (slab->creg), m_cookie);
682 cDarkPanel::TermUI();
686 //////////////////////////////////////////////////////
688 void TermSubPanel ()
690 LGadDestroyButtonList (&mSubPanelButtons[mCurSub]);
692 if (mCurSub == kSubBind) {
693 LGadDestroyButtonList (&mBindButtons);
694 LGadDestroyButtonList (&mBindScrollers);
697 memset (mSubPanelElems, 0, kNumSubPanelRects * sizeof(DrawElement));
698 for (int i = 0; i < kNumSubPanelRects; i++)
699 mSubPanelStrs[i] = "";
701 //if there are any sliders, kill them
702 DestroyAllSliders ();
704 mTabRects.SetSize (0);
705 mSubPanelRects.SetSize (0);
708 //////////////////////////////////////////////////////
710 void TermSpecial ()
712 if (mCurSub == kSubBind) {
713 LGadDestroyButtonList (&mBindButtons);
714 LGadDestroyButtonList (&mBindScrollers);
717 else if (mCurSub == kSubList) {
718 if (mListSub == kSubBasicVideo) {
719 SetVidRes ();
722 LGadDestroyButtonList (&mListButtons);
726 //////////////////////////////////////////////////////
728 void OnLoopMsg (eLoopMessage msg, tLoopMessageData msg_data)
730 if (SFX_GetSoundDevice () == SFXDEVICE_A3D) {
731 mxs_vector origin = {0.0, 0.0, 0.0};
732 SFX_Frame (&origin, (mxs_angvec *)&origin);
734 else
735 SFX_Frame (NULL, NULL);
737 if (mSwap != -1) {
738 SwapSubPanel (mSwap);
739 mSwap = -1;
742 //check slider data
743 //volume
745 switch (mCurSub)
747 case kSubAudio:
749 for (int i = 0; i < kNumVolumeSliders; i++)
750 SetVolume(i,m_volume[i]);
752 break;
754 case kSubControls:
756 char buf[32];
757 sprintf (buf, "mouse_sensitivity %8.8f", ((double)m_sens / 2.0) + 0.5);//slide goes from 0.5 (slow) to 10.5 (fast)
758 g_pInputBinder->ProcessCmd (buf);
760 break;
763 case kSubBasicVideo:
765 //gamma
766 static int prev_gamma;
767 if (prev_gamma != m_gamma) {
768 TouchGamma ((((MAX_GAMMA - MIN_GAMMA) / 20.0) * (float)(20-m_gamma)) + MIN_GAMMA);
769 prev_gamma = m_gamma;
772 break;
777 //////////////////////////////////////////////////////
779 void InitControlOptions ()
781 InitButtonList(&mSubPanelDesc[kSubControls], &mSubPanelRects[(int)kCustomize], &mSubPanelElems[(int)kCustomize], OnSubPanelButton,
782 &mSubPanelStrs[(int)kCustomize], "control_", kNumControlButts, 0);
784 //set starting button strings
786 // watch me factor code like the dickens.
787 static const char* cmds[] =
790 "echo $lookspring",
791 "echo $mouse_invert",
792 "echo $freelook",
793 "echo $joy_rotate",
796 for (int i = kLookspring; i < kFirstControlRect; i++)
798 int idx = i - kFirstControlButt;
800 char *str = g_pInputBinder->ProcessCmd((char*)cmds[idx]); // command value
801 cStr& substr = mSubPanelStrs[i]; // button string
802 DrawElement& elem = mSubPanelElems[i]; // button elem
803 char res_str[16];
804 sprintf(res_str,"control_%d",i);
806 BOOL state = atof(str) != 0.0;
807 const char* state_str;
809 if (i == kJoyRotate) // exception
811 if (g_joystickActive)
812 state_str = mMiscStrs[(state) ? kMiscStrLeftRight : kMiscStrForwardBackward ];
813 else
815 *res_str = '\0';
816 state_str = NULL;
819 else
820 state_str = mMiscStrs[(state) ? kMiscStrOn : kMiscStrOff ];
822 SetUIString(substr,elem,res_str,(char*)state_str);
828 //////////////////////////////////////////////////////
830 void BndAppendControls ()
832 FILE *fp = fopen ("user.bnd", "at");
833 if (fp)
835 fprintf (fp, "\n");
837 char *controls[] = {"lookspring", "mouse_invert", "freelook", "mouse_sensitivity", "\0"};
838 char str[32];
839 char **p_control = controls;
841 while (**p_control) {
842 sprintf (str, "echo $%s", *p_control);
843 fprintf (fp, "%s %s\r\n", *p_control, g_pInputBinder->ProcessCmd (str));
844 p_control++;
847 fclose (fp);
851 //////////////////////////////////////////////////////
853 void InitVideoOptions ()
855 InitButtonList (&mSubPanelDesc[kSubBasicVideo], &mSubPanelRects[(int)kFirstBasicVideoButt], &mSubPanelElems[(int)kFirstBasicVideoButt],
856 OnSubPanelButton, &mSubPanelStrs[(int)kFirstBasicVideoButt], "videob_", kNumBasicVideoButts, 0);
858 int first = kFirstAdvancedVideoButt;
859 InitButtonList (&mSubPanelDesc[kSubAdvancedVideo], &mSubPanelRects[first], &mSubPanelElems[first],
860 OnSubPanelButton, &mSubPanelStrs[(int)first], "videoa_", kNumAdvancedVideoRects, 0);
863 SetVidResStr();
865 //let's get some info about the video card
866 mNumVidDevices = lgd3d_enumerate_devices ();
868 sScrnMode mode = *GetGameScreenMode();
870 if (mNumVidDevices > 0 && (mode.flags & kScrnMode3dDriver)) {
871 g_zbuffer_toggle = TRUE;
872 mode.flags |= kScrnMode3dDriver;
873 SetUIString (mSubPanelStrs[(int)kZBufferToggle], mSubPanelElems[(int)kZBufferToggle], "videoa_1",
874 (char *)(const char *)mMiscStrs[(g_zbuffer_toggle && (mode.flags & kScrnMode3dDriver) != 0) ? kMiscStrOn : kMiscStrOff]);
877 else {
878 g_zbuffer_toggle = FALSE;
879 mode.flags &= ~kScrnMode3dDriver;
880 SetUIString (mSubPanelStrs[(int)kZBufferToggle], mSubPanelElems[(int)kZBufferToggle], "videoa_1",
881 (char *)(const char *)mMiscStrs[kMiscStrOff]);
884 SetGameScreenMode (&mode);
888 //////////////////////////////////////////////////////
890 void InitAudioOptions ()
892 InitButtonList (&mSubPanelDesc[kSubAudio], &mSubPanelRects[(int)kSpeakerTest], &mSubPanelElems[(int)kSpeakerTest], OnSubPanelButton,
893 &mSubPanelStrs[(int)kSpeakerTest], "audio_", kNumAudioButts, 0);
895 SetUIString (mSubPanelStrs[(int)kStereoToggle], mSubPanelElems[(int)kStereoToggle], "audio_1",
896 (char *)(const char *)mMiscStrs[(SFX_StereoReversed ()) ? kMiscStrOn : kMiscStrOff]);
898 SetUIString (mSubPanelStrs[(int)kA3DToggle], mSubPanelElems[(int)kA3DToggle], "audio_2",
899 (char *)(const char *)mMiscStrs[(SFX_GetSoundDevice () == SFXDEVICE_A3D) ? kMiscStrOn : kMiscStrOff]);
901 char buf[8];
902 sprintf (buf, "%d", sfx_use_channels);
903 mSubPanelStrs[(int)kAudioChannels] += buf;
904 SetUIString (mSubPanelStrs[(int)kAudioChannels], mSubPanelElems[(int)kAudioChannels], "audio_3", buf);
906 BOOL isEAXOn = SFX_Is_EAX_Enabled();
907 SetUIString (mSubPanelStrs[(int)kAudioEAXToggle], mSubPanelElems[(int)kAudioEAXToggle], "audio_4",
908 (char *)(const char *)mMiscStrs[isEAXOn ? kMiscStrOn : kMiscStrOff]);
911 //////////////////////////////////////////////////////
913 void InitGameOptions ()
915 int first = kFirstGameButt;
916 InitButtonList (&mSubPanelDesc[kSubGame], &mSubPanelRects[first], &mSubPanelElems[first], OnSubPanelButton,
917 &mSubPanelStrs[first], "game_", kNumGameButts, BUTTONLIST_RADIO_FLAG);
920 //////////////////////////////////////////////////////
922 void InitBindOptions ()
924 InitButtonList (&mSubPanelDesc[kSubBind], &mSubPanelRects[(int)kBindLoad], &mSubPanelElems[(int)kBindLoad], OnSubPanelButton,
925 &mSubPanelStrs[(int)kBindLoad], "bind_", kNumBindButts, 0);
927 //set up description for binding buttons. joy.
928 //rearrange a few rects
929 mTopBind = 0;
930 cRectArray tmp_rects;
931 tmp_rects.SetSize (NUM_BIND_SLOTS);
932 for (long i = 0; i < (NUM_BIND_SLOTS - 2); i++)
933 tmp_rects[i] = mSubPanelRects[(int)kBindButt0 + 2 + i];
934 tmp_rects[NUM_BIND_SLOTS - 2] = mSubPanelRects[(int)kBindScrollUp];
935 tmp_rects[NUM_BIND_SLOTS - 1] = mSubPanelRects[(int)kBindButt0 + 1];
936 for (i = 0; i < NUM_BIND_SLOTS; i++)
938 mSubPanelRects[(int)kBindButt0 + 1 + i] = tmp_rects[i];
939 InitDrawElem(&mBindButtonElems[i]);
940 mBindButtonElems[i].draw_type = DRAWTYPE_TEXT;
942 //description of binding radio buttons
944 LGadButtonListDesc tmp_desc = {NUM_BIND_SLOTS, (Rect *)&mSubPanelRects[(int)kBindButt0],
945 mBindButtonElems, OnBindButton, 0, BUTTONLIST_RADIO_FLAG};
946 memcpy (&mBindButtonDesc, &tmp_desc, sizeof (LGadButtonListDesc));
949 // default to current style colors
950 AssertMsg (GetCurrentStyle (), "No current style for diff defaults");
951 memset (&mBindStyle, 0, sizeof (mBindStyle));
952 memcpy (mBindStyle.colors, GetCurrentStyle()->colors, sizeof (mBindStyle.colors));
953 uiGameLoadStyle("bind_", &mBindStyle, mResPath);
955 //load bind cmds
956 cStr bind_cmd;
957 char buf[16];
958 mNumBindable = 0;
959 while (1) {
960 sprintf (buf, "bindcmd_%d", mNumBindable);
961 bind_cmd = FetchUIString ("bindcmds", buf, mResPath);
963 if (bind_cmd == "" || mNumBindable >= MAX_NUM_BINDABLE)
964 break;
966 mBindCmd[mNumBindable] = bind_cmd;
967 mBindButtsFilled[mNumBindable] = FALSE;
968 mNumBindable++;
971 FillBindStrs ();
974 //load bitmaps for up/down scroll arrows
975 LoadButtBmp (mButtBmpRes[BINDUP_BMPRES], &mButtDrawElem[BINDUP_BMPRES], "bup_");
976 LoadButtBmp (mButtBmpRes[BINDDN_BMPRES], &mButtDrawElem[BINDDN_BMPRES], "bdn_");
978 //description of binding scroll buttons
980 LGadButtonListDesc tmp_desc = {2, (Rect *)&mSubPanelRects[(int)kBindScrollUp],
981 &mButtDrawElem[BINDUP_BMPRES], OnScrollButton, 0, 0};
982 memcpy (&mBindScrollerDesc, &tmp_desc, sizeof (LGadButtonListDesc));
987 //////////////////////////////////////////////////////
989 void InitListOptions ()
991 //description of back button
993 LGadButtonListDesc tmp_desc = {kNumListButts, (Rect *)&mSubPanelRects[(int)kListBack],
994 &mSubPanelElems[(int)kListBack], OnSubPanelButton, 0, 0};
995 mSubPanelDesc[kSubList] = tmp_desc;
998 mSubPanelStrs[(int)kListBack] = FetchUIString (panel_name, "bind_1", mResPath);
1000 DrawElement& backelem = mSubPanelElems[(int)kListBack];
1001 InitDrawElem(&backelem);
1002 backelem.draw_data = (void *)(const char *)mSubPanelStrs[(int)kListBack];
1003 backelem.draw_type = DRAWTYPE_TEXT;
1005 //description of list buttons
1007 LGadButtonListDesc tmp_desc = {NUM_LIST, (Rect *)&mSubPanelRects[(int)kList0],
1008 mListButtonElems, OnListButton, 0, BUTTONLIST_RADIO_FLAG};
1009 mListButtonDesc = tmp_desc;
1012 mTopList = 0;
1017 //////////////////////////////////////////////////////
1019 void FillBindStr (long bind_num, long butt_num)
1021 if (bind_num >= mNumBindable) {
1022 static char *dummy = "";
1023 mBindButtonElems[butt_num].draw_data = dummy;
1024 return;
1027 if (mBindButtsFilled[bind_num]) {
1028 mBindButtonElems[butt_num].draw_data = (void*)(const char*)mBindButtonStrs[bind_num];
1029 return;
1031 mBindButtsFilled[bind_num] = TRUE;
1033 ulong old_context;
1034 g_pInputBinder->GetContext (&old_context);
1035 if (old_context != HK_GAME_MODE)
1036 g_pInputBinder->SetContext (HK_GAME_MODE,FALSE);
1038 //get our bindings
1039 char buf[64];
1040 sprintf (buf, "bindname_%d", bind_num);
1042 mBindButtonStrs[bind_num] = FetchUIString (panel_name, buf, mResPath);
1043 mBindButtonStrs[bind_num] += " = ";
1045 cStr controls[MAX_BINDS_PER_CMD];
1046 cStr raw_controls[MAX_BINDS_PER_CMD];
1047 int num = GetCmdBinds (mBindCmd[bind_num], controls, MAX_BINDS_PER_CMD, raw_controls);
1049 for (long i = 0; i < num; i++) {
1050 if (i != 0)
1051 mBindButtonStrs[bind_num] += ", ";
1052 mBindButtonStrs[bind_num] += controls[i];
1055 //there were no controls
1056 if (i == 0)
1057 mBindButtonStrs[bind_num] += mMiscStrs[kMiscStrEmpty];
1058 else
1060 // Copy the controls over to game2
1061 g_pInputBinder->SetContext(HK_GAME2_MODE,FALSE);
1062 for (int i = 0; i < num; i++)
1064 const char* cmd = mBindCmd[bind_num];
1065 const char* ctrl = raw_controls[i];
1067 // if cmd has a space, we have to quote it, because the binder is stupid
1068 cStr newcmd = "";
1069 if (strchr(cmd,' ') != NULL)
1071 newcmd += "\"";
1072 newcmd += cmd;
1073 newcmd += "\"";
1074 cmd = newcmd;
1077 // Check the config to make sure we can bind this stuff in game2
1078 BOOL can_bind = TRUE;
1079 char varbuf[80];
1080 sprintf(varbuf,"%s_bind_game2",ctrl);
1081 config_get_int(varbuf,&can_bind);
1083 if (can_bind)
1084 g_pInputBinder->Bind((char*)ctrl,(char*)cmd);
1088 if (old_context != HK_GAME2_MODE)
1089 g_pInputBinder->SetContext (old_context,FALSE);
1091 mBindButtonElems[butt_num].draw_data = (void*)(const char*)mBindButtonStrs[bind_num];
1094 //////////////////////////////////////////////////////
1096 void FillBindStrs ()
1098 AutoAppIPtr(ResMan);
1099 IRes* ctrls = pResMan->Bind("controls",RESTYPE_STRING,NULL,mResPath);
1100 ctrls->Lock();
1102 IRes* panel = pResMan->Bind(panel_name,RESTYPE_STRING,NULL,mResPath);
1103 panel->Lock();
1105 ulong old_context;
1106 g_pInputBinder->GetContext (&old_context);
1107 g_pInputBinder->SetContext (HK_GAME_MODE,TRUE);
1110 for (long i = 0, j = mTopBind; i < NUM_BIND_SLOTS; i++, j++) {
1112 FillBindStr (j, i);
1115 ctrls->Unlock();
1116 panel->Unlock();
1117 SafeRelease(ctrls);
1118 SafeRelease(panel);
1120 //change back to previous mode
1121 g_pInputBinder->SetContext (old_context,TRUE);
1125 //////////////////////////////////////////////////////
1127 static bool StaticBindKeyHandler (uiEvent *p_event, Region *p_reg, void *state)
1129 bool ret = FALSE;
1130 if (gpOptions->mCurSub == gpOptions->kSubBind && p_event->type == UI_EVENT_KBD_COOKED)
1131 ret = gpOptions->BindKeyHandler ((uiCookedKeyEvent *)p_event);
1132 return ret;
1135 bool BindKeyHandler (uiCookedKeyEvent *event)
1137 //only use up actions
1138 if (event->code & KB_FLAG_DOWN)
1139 return FALSE;
1142 BOOL redraw = TRUE;
1143 int cur_selected = LGadRadioButtonSelection (&mBindButtons);
1145 switch (event->code) {
1146 case KEY_UP:
1147 case KEY_PAD_UP:
1148 if (cur_selected > 0)
1149 LGadRadioButtonSelect (&mBindButtons, cur_selected - 1);
1150 else if (mTopBind > 0) {
1151 mTopBind--;
1152 FillBindStrs ();
1154 else
1155 redraw = FALSE;
1157 break;
1160 case KEY_DOWN:
1161 case KEY_PAD_DOWN:
1162 if (cur_selected < (NUM_BIND_SLOTS - 1))
1163 LGadRadioButtonSelect (&mBindButtons, cur_selected + 1);
1164 else if (mTopBind < mNumBindable - NUM_BIND_SLOTS) {
1165 mTopBind++;
1166 FillBindStrs ();
1168 else
1169 redraw = FALSE;
1171 break;
1173 case KEY_PGUP:
1174 case KEY_PAD_PGUP:
1175 mTopBind -= NUM_BIND_SLOTS;
1176 if (mTopBind < 0) {
1177 mTopBind = 0;
1178 LGadRadioButtonSelect (&mBindButtons, 0);
1181 FillBindStrs ();
1183 break;
1185 case KEY_PGDN:
1186 case KEY_PAD_PGDN:
1187 mTopBind += NUM_BIND_SLOTS;
1188 if (mTopBind >= (mNumBindable - NUM_BIND_SLOTS)) {
1189 mTopBind = mNumBindable - NUM_BIND_SLOTS;
1190 LGadRadioButtonSelect (&mBindButtons, NUM_BIND_SLOTS - 1);
1193 FillBindStrs ();
1195 break;
1198 case KEY_HOME:
1199 case KEY_PAD_HOME:
1200 LGadRadioButtonSelect (&mBindButtons, 0);
1201 if (mTopBind != 0) {
1202 mTopBind = 0;
1203 FillBindStrs ();
1205 break;
1208 case KEY_END:
1209 case KEY_PAD_END:
1210 LGadRadioButtonSelect (&mBindButtons, NUM_BIND_SLOTS - 1);
1211 if (mTopBind != (mNumBindable - NUM_BIND_SLOTS)) {
1212 mTopBind = mNumBindable - NUM_BIND_SLOTS;
1213 FillBindStrs ();
1215 break;
1218 case KEY_ENTER:
1219 case KEY_GREY_ENTER:
1220 OnSubPanelButtonList (BUTTONGADG_LCLICK, kBind - kBindLoad);
1222 break;
1224 default:
1225 redraw = FALSE;
1228 if (redraw) {
1229 FillBlack (FILL_SUBPANEL);
1230 RedrawDisplay ();
1233 return TRUE;
1237 //////////////////////////////////////////////////////
1239 void SetVidRes ()
1241 //has not changed
1242 if (mSelectedRes == -1)
1243 return;
1245 sScrnMode mode = *GetGameScreenMode();
1247 char *mode_desc = (char *)(const char *)mListButtonStrs[mSelectedRes];
1248 sscanf (mode_desc, "%dx%dx%d", &mode.w, &mode.h, &mode.bitdepth);
1250 SetGameScreenMode (&mode);
1252 SetVidResStr();
1255 // Set the resolution string
1256 void SetVidResStr()
1258 int residx = kScreenRes;
1259 cStr& resstr = mSubPanelStrs[residx];
1260 DrawElement& elem = mSubPanelElems[residx];
1262 char buf[64];
1263 const sScrnMode& mode = *GetGameScreenMode();
1264 sprintf(buf,"%dx%dx%d",mode.w,mode.h,mode.bitdepth);
1266 SetUIString(resstr,elem,"videob_0",buf);
1270 //////////////////////////////////////////////////////
1272 void FillVidResStrs ()
1274 //int mTopList;
1275 const sScrnMode *mode = GetGameScreenMode ();
1276 lgd3ds_device_info *info;
1278 int idx = mNumVidDevices - 1;
1279 if (config_is_defined("d3d_driver_index"))
1280 config_get_int("d3d_driver_index", &idx);
1281 info = lgd3d_get_device_info (idx);
1283 int bpp;
1284 short *cur_mode;
1285 char buf[32], mode_str[32];
1287 if (mNumVidDevices > 0 && (mode->flags & kScrnMode3dDriver)) {
1288 cur_mode = &info->supported_modes[mTopList];
1289 bpp = 16;
1291 else {
1292 cur_mode = &soft_modes[mTopList];
1293 bpp = 8;
1296 //get current mode string so we know what to select
1297 sprintf (mode_str, "%dx%dx%d", mode->w, mode->h, mode->bitdepth);
1298 //dunny button will be default selection if we dont have a matching res for some reason
1299 LGadRadioButtonSelect (&mListButtons, mListPrevPick = NUM_LIST - 1);
1301 mNumListTotal = 0;
1302 for (long i = 0, inc = 0; i < NUM_LIST; i += inc) {
1303 inc = 0;
1304 if (*cur_mode != -1 && i < NUM_LIST - 1)
1306 grs_mode_info& info = grd_mode_info[*cur_mode];
1308 if (info.bitDepth == bpp
1309 && info.w >= MIN_RES_X
1310 && info.h >= MIN_RES_Y
1311 && info.h <= MAX_RES_Y)
1315 sprintf (buf, "%dx%dx%d", grd_mode_info[*cur_mode].w,
1316 grd_mode_info[*cur_mode].h, grd_mode_info[*cur_mode].bitDepth);
1318 mListButtonStrs[i] = buf;
1320 if (!strcmp (buf, mode_str))
1321 LGadRadioButtonSelect (&mListButtons, mListPrevPick = i);
1323 inc = 1;
1324 mNumListTotal++;
1326 cur_mode++;
1328 else {
1329 mListButtonStrs[i] = "";
1330 inc = 1;
1333 DrawElement& elem = mListButtonElems[i];
1334 InitDrawElem(&elem);
1335 elem.draw_data = (void *)(const char *)mListButtonStrs[i];
1336 elem.draw_type = DRAWTYPE_TEXT;
1342 //////////////////////////////////////////////////////
1344 void FillVidDevStrs ()
1346 lgd3ds_device_info *info;
1348 for (long i = 0; i < NUM_LIST; i++) {
1349 if (i < mNumVidDevices) {
1350 info = lgd3d_get_device_info (i);
1351 mListButtonStrs[i] = info->p_ddraw_desc;
1353 else
1354 mListButtonStrs[i] = "";
1356 DrawElement& elem = mListButtonElems[i];
1357 InitDrawElem(&elem);
1358 elem.draw_data = (void *)(const char *)mListButtonStrs[i];
1359 elem.draw_type = DRAWTYPE_TEXT;
1362 int idx = mNumVidDevices - 1;
1363 if (config_is_defined("d3d_driver_index"))
1364 config_get_int("d3d_driver_index", &idx);
1365 LGadRadioButtonSelect (&mListButtons, mListPrevPick = idx);
1368 //////////////////////////////////////////////////////
1370 static BOOL BindFilter (char *control, char *cmd, void *data)
1372 //we'll reserve ESC for breaking from a bind query
1373 if (!strcmp (control, "esc"))
1374 return FALSE;
1376 //don't bind joystick movement
1377 if (!strcmp (control, "joy_move"))
1378 return FALSE;
1380 //scroll lock doesnt have up/down events like a normal key
1381 if (!strcmp (control, "scroll_lock"))
1382 return FALSE;
1384 // don't bind the F keys since the game needs them for psi powers
1385 int i;
1386 for (i=1; i <= 12; i++)
1388 char fkey[32];
1389 sprintf(fkey,"F%d",i);
1390 if (!stricmp(control, fkey))
1391 return(FALSE);
1394 // otherwise, it's legal
1395 return TRUE;
1398 //////////////////////////////////////////////////////
1400 static void PostBindFunc (BOOL bound)
1402 for (long i = 0; i < gpOptions->mNumBindable; i++)
1403 gpOptions->mBindButtsFilled[i] = FALSE;
1404 gpOptions->FillBindStrs ();
1405 gpOptions->FillBlack (FILL_SUBPANEL);
1406 gpOptions->RedrawDisplay ();
1408 g_pInputBinder->SetContext (gpOptions->m_old_context,TRUE);
1411 //////////////////////////////////////////////////////
1413 static void QuickConfigPostBindFunc (BOOL bound)
1415 int bind_num = gpOptions->mTopBind + LGadRadioButtonSelection (&gpOptions->mBindButtons) + 1;
1416 if (bind_num < QUICKCONFIG_BINDNUM && bound) {
1417 if (bind_num > NUM_BIND_SLOTS - 1) {
1418 gpOptions->mTopBind++;
1420 LGadRadioButtonSelect (&gpOptions->mBindButtons, bind_num - gpOptions->mTopBind);
1421 char buf[16];
1422 sprintf (buf, "bindname_%d", bind_num);
1423 gpOptions->mBindButtonStrs[bind_num] = FetchUIString (gpOptions->panel_name, buf, gpOptions->mResPath);
1424 gpOptions->mBindButtonStrs[bind_num] += " = ?";
1426 g_pInputBinder->TrapBind ((char *)(const char *)gpOptions->mBindCmd[bind_num],
1427 gpOptions->BindFilter, gpOptions->QuickConfigPostBindFunc, NULL);
1430 else
1431 g_pInputBinder->SetContext (gpOptions->m_old_context,TRUE);
1433 for (long i = 0; i < gpOptions->mNumBindable; i++)
1434 gpOptions->mBindButtsFilled[i] = ((i != bind_num || !bound) || (bind_num == QUICKCONFIG_BINDNUM)) ? FALSE : TRUE;
1436 gpOptions->FillBindStrs ();
1437 gpOptions->FillBlack (FILL_SUBPANEL);
1438 gpOptions->RedrawDisplay ();
1442 //////////////////////////////////////////////////////
1444 void InitButtonList (LGadButtonListDesc *desc, Rect *rect_array, DrawElement *draw_elem,
1445 ButtListCB cb, cStr *strs, const char *prefix, int num, int flags)
1447 // set up drawlelems
1448 for (int i = 0; i < num; i++) {
1449 DrawElement *elem = &draw_elem[i];
1450 InitDrawElem(elem);
1452 char buf[16];
1453 sprintf(buf, "%s%d", prefix, i);
1454 strs[i] = FetchUIString (panel_name, buf, mResPath);
1455 elem->draw_type = DRAWTYPE_TEXT;
1456 elem->draw_data = (void*)(const char*)strs[i];
1460 LGadButtonListDesc tmp_desc = {
1461 num,
1462 rect_array,
1463 draw_elem,
1466 flags,
1469 memcpy (desc, &tmp_desc, sizeof (LGadButtonListDesc));
1473 //////////////////////////////////////////////////////
1475 void DrawButtonList (LGadButtonListDesc *blist)
1477 Rect rect = {{0, 0}, {640, 480}};
1478 uiHideMouse (&rect);
1480 int num = blist->num_buttons;
1481 for (int i = 0; i < num; i++) {
1482 ElementDraw (&blist->button_elems[i], dsNORMAL, blist->button_rects[i].ul.x, blist->button_rects[i].ul.y,
1483 blist->button_rects[i].lr.x - blist->button_rects[i].ul.x, blist->button_rects[i].lr.y - blist->button_rects[i].ul.y);
1486 uiShowMouse (&rect);
1489 //////////////////////////////////////////////////////
1491 void DrawSlider (int num, int rect_num, BOOL draw_slide = TRUE)
1493 Rect rect = {{0, 0}, {640, 480}};
1494 uiHideMouse (&rect);
1496 Rect *slide_rect = (Rect *)&mSubPanelRects[rect_num];
1497 ElementDraw (&mSliderBaseBmp, dsNORMAL, slide_rect->ul.x, slide_rect->ul.y,
1498 slide_rect->lr.x - slide_rect->ul.x, slide_rect->lr.y - slide_rect->ul.y);
1500 uiShowMouse (&rect);
1501 if (draw_slide)
1502 LGadDrawBox ((LGadBox*)&mSliders[num], NULL);
1505 //////////////////////////////////////////////////////
1507 void LoadButtBmp (IRes *butt_res[4], DrawElement *draw_elem, char *prefix)
1509 char *sffx [] = {"norm", "down", "hlit", "hlit"}, str[128];
1510 AutoAppIPtr (ResMan);
1511 for (int i = 0; i < 4; i++) {
1512 butt_res[i] = pResMan->Bind (strcat (strcpy (str, prefix), sffx[i]), RESTYPE_IMAGE, NULL, mResPath);
1513 if (!butt_res[i])
1514 AssertMsg (0, "Error loading button bitmap");
1517 InitDrawElem(draw_elem);
1518 draw_elem->draw_data = (void *)butt_res;
1519 draw_elem->draw_type = DRAWTYPE_RESOFFSET;
1522 //////////////////////////////////////////////////////
1524 void SetUIString (cStr &str, DrawElement &draw_elem, char *name, char *suffix)
1526 str = FetchUIString (panel_name, name, mResPath);
1527 if (suffix)
1528 str += suffix;
1529 draw_elem.draw_data = (void*)(const char*)str;
1532 //////////////////////////////////////////////////////
1534 void AppendRects (char *rect_file, cRectArray &old_rects)
1536 long old_sz, tmp_sz;
1537 cRectArray tmp_rects;
1538 FetchUIRects(rect_file, tmp_rects, mResPath);
1539 old_rects.SetSize ((old_sz = old_rects.Size ()) + (tmp_sz = tmp_rects.Size ()));
1541 for (long i = 0, j = old_sz; i < tmp_sz; i++, j++)
1542 old_rects[j] = tmp_rects[i];
1545 //////////////////////////////////////////////////////
1547 void CreateSlider (int slider_num, int rect_num, int *val_ptr, int num_notches, int inc)
1549 LGadSlider *slider = &mSliders[slider_num];
1550 Rect *rect = (Rect *)&mSubPanelRects[rect_num];
1551 memset (slider, 0, sizeof (LGadSlider));
1552 slider->gadg.draw = mButtDrawElem[SLIDER_BMPRES];
1554 //this is absolutely a hack.
1555 //make the slider's range of motion smaller since the slider's base art
1556 //presents the slide as having a more confined range. 12 pixels will do the trick.
1557 short x, w;
1558 x = rect->ul.x + 12;
1559 w = rect->lr.x - rect->ul.x - 24;
1561 LGadCreateSliderArgs (slider, LGadCurrentRoot (), x, rect->ul.y + ((rect->lr.y - rect->ul.y)>>1), 0, 0, NULL,
1562 val_ptr, num_notches, inc, w, LGSLIDER_HORIZONTAL, 0);
1564 mSlidersOn[slider_num] = TRUE;
1566 LGadDrawBox ((LGadBox*)slider, NULL);
1569 //////////////////////////////////////////////////////
1571 void DestroySlider (int slider_num)
1573 if (mSlidersOn[slider_num]) {
1574 LGadDestroySlider (&mSliders[slider_num], FALSE);
1575 mSlidersOn[slider_num] = FALSE;
1579 //////////////////////////////////////////////////////
1581 void DestroyAllSliders ()
1583 for (int i = 0; i < (int)kNumSubPanelSlides; i++)
1584 DestroySlider (i);
1587 //////////////////////////////////////////////////////
1589 void DrawString (char *strname, int rect_num)
1591 cStr str = FetchUIString (panel_name, strname, mResPath);//copy the string
1592 char *s = (char*)(const char*)str;//get a mutable pointer
1594 Rect &r = mSubPanelRects[rect_num];
1596 DrawElement draw;
1597 InitDrawElem(&draw);
1598 draw.draw_type = DRAWTYPE_TEXT;
1599 draw.draw_data = s;
1600 ElementSetStyle(&mTextStyle);
1601 ElementDraw (&draw, dsNORMAL, r.ul.x, r.ul.y, r.lr.x - r.ul.x, r.lr.y - r.ul.y);
1604 //////////////////////////////////////////////////////
1606 void RedrawDisplay ()
1608 // draw buttonlist
1609 region_expose (LGadBoxRegion (&mTabButtons), LGadBoxRect (&mTabButtons));
1610 DrawButtonList (&mSubPanelDesc[mCurSub]);
1612 //any sub-specific stuff
1613 switch (mCurSub) {
1614 case kSubControls:
1615 DrawSlider ((int)kMouseSensSlider, (int)kMouseSensSliderRect);
1616 DrawString ("mouse_sens", kMouseSensTextRect);
1617 break;
1619 case kSubBasicVideo:
1620 DrawSlider ((int)kGammaSlider, (int)kGammaSliderRect);
1621 DrawString ("gamma", kGammaSliderText);
1622 break;
1624 case kSubAudio:
1626 for (int i = 0; i < kNumVolumeSliders; i++)
1628 DrawSlider (i, gVolSliderRects[i]);
1629 char name[16];
1630 sprintf(name,"volume_%d",i);
1631 DrawString (name,gVolSliderRects[i] + 1); // plus one to get from rect to text rect
1634 break;
1636 case kSubGame:
1637 region_expose (LGadBoxRegion (&mSubPanelButtons[kSubGame]), LGadBoxRect (&mSubPanelButtons[kSubGame]));
1638 DrawString ("diff", kDiffTextRect);
1639 break;
1641 case kSubBind:
1642 DrawButtonList (&mBindScrollerDesc);
1643 region_expose (LGadBoxRegion (&mBindButtons), LGadBoxRect (&mBindButtons));
1644 break;
1646 case kSubList:
1647 region_expose (LGadBoxRegion (&mListButtons), LGadBoxRect (&mListButtons));
1648 // DrawButtonList (&mBindScrollerDesc);
1649 break;
1653 //////////////////////////////////////////////////////
1655 void FillBlack (int rect_num)
1657 Rect *rect;
1658 if (rect_num == FILL_SUBPANEL)
1659 rect = (Rect *)&mRects[(int)kSubFillRect];
1660 else
1661 rect = (Rect *)&mSubPanelRects[rect_num];
1663 GUIErase(rect);
1666 //////////////////////////////////////////////////////
1668 void SwapSubPanel (int new_sub)
1670 if (mCurSub != -1) {
1671 LGadDestroyButtonList (&mSubPanelButtons[mCurSub]);
1672 TermSpecial ();
1675 if (new_sub!=kSubAudio)
1676 metaSndEnterPanel(kMetaSndPanelOptions);
1677 else
1678 metaSndExitPanel(TRUE);
1680 LGadCreateButtonListDesc (&mSubPanelButtons[new_sub], LGadCurrentRoot (), &mSubPanelDesc[new_sub]);
1681 SetBoxData(VB(&mSubPanelButtons[new_sub]));
1683 switch (new_sub)
1685 case kSubControls:
1687 DrawSlider ((int)kMouseSensSlider, (int)kMouseSensSliderRect, FALSE);
1688 CreateSlider ((int)kMouseSensSlider, (int)kMouseSensSliderRect, &m_sens, 20, 1);
1690 break;
1692 case kSubBasicVideo:
1694 DrawSlider ((int)kGammaSlider, (int)kGammaSliderRect, FALSE);
1695 CreateSlider ((int)kGammaSlider, (int)kGammaSliderRect, &m_gamma, 20, 1);
1697 break;
1699 case kSubAudio:
1701 for (int i = 0; i < kNumVolumeSliders; i++)
1703 DrawSlider(i,gVolSliderRects[i],FALSE);
1704 CreateSlider(i,gVolSliderRects[i],&m_volume[i],kVolumeSliderNotches - 1, 1);
1707 if (! CanChangeSoundDeviceNow ()) {
1708 mSubPanelDesc[kSubAudio].button_elems[kAudioChannels - kFirstAudioButt].fcolor = guiStyleGetColor(&mGreyStyle,StyleColorText);
1709 mSubPanelDesc[kSubAudio].button_elems[kA3DToggle - kFirstAudioButt].fcolor = guiStyleGetColor(&mGreyStyle,StyleColorText);
1712 if (!CanChangeEAX())
1713 mSubPanelDesc[kSubAudio].button_elems[kAudioEAXToggle - kSpeakerTest].fcolor = guiStyleGetColor(&mGreyStyle,StyleColorText);
1715 break;
1717 case kSubGame:
1719 g_diff_active = CanChangeDifficultyNow();
1720 if (InSim())
1722 AutoAppIPtr(QuestData);
1723 if (pQuestData->Exists(DIFF_QVAR))
1724 g_diff = pQuestData->Get(DIFF_QVAR);
1727 if (!g_diff_active)
1728 LGadBoxSetStyle (&mSubPanelButtons[kSubGame], &mGreyStyle);
1730 //set the current difficulty setting
1731 LGadRadioButtonSelect (&mSubPanelButtons[kSubGame], DIFF2BUTT(g_diff));
1733 break;
1735 case kSubBind:
1737 LGadCreateButtonListDesc (&mBindButtons, LGadCurrentRoot (), &mBindButtonDesc);
1738 SetBoxData(VB(&mBindButtons));
1739 LGadRadioButtonSelect (&mBindButtons,0);
1740 LGadBoxSetStyle (&mBindButtons, &mBindStyle);
1742 LGadCreateButtonListDesc (&mBindScrollers, LGadCurrentRoot (), &mBindScrollerDesc);
1743 SetBoxData(VB(&mBindScrollers));
1745 break;
1747 case kSubList:
1749 LGadCreateButtonListDesc (&mListButtons, LGadCurrentRoot (), &mListButtonDesc);
1750 SetBoxData(VB(&mListButtons));
1751 LGadBoxSetStyle (&mListButtons, &mBindStyle);
1753 // LGadCreateButtonListDesc (&mBindScrollers, LGadCurrentRoot (), &mBindScrollerDesc);
1754 // SetBoxData(VB(&mBindScrollers));
1756 if (mListSub == kSubAdvancedVideo)
1757 FillVidDevStrs ();
1758 else if (mListSub == kSubBasicVideo)
1759 FillVidResStrs ();
1760 mTopList = 0;
1762 break;
1765 FillBlack (FILL_SUBPANEL);
1767 mCurSub = new_sub;
1768 RedrawDisplay ();
1771 //////////////////////////////////////////////////////
1773 static void PlayRightTest (int, void *)
1775 sfx_parm parm;
1776 memset (&parm, 0, sizeof (sfx_parm));
1777 parm.pan = SFX_StereoReversed() ? -10000 : 10000;
1778 cStr snd_name = FetchUIString (gpOptions->panel_name, "rightsound", gpOptions->mResPath);
1780 if (SFX_GetSoundDevice () == SFXDEVICE_A3D) {
1781 //@TODO: make the a3d speaker test sound crisper, clearer, more refreshed
1782 mxs_vector pos = {0.0, SFX_StereoReversed() ? 10.0 : -10.0, 0.0};
1783 SFX_Play_Vec (SFX_3D, &parm, (char *)(const char *)snd_name, &pos);
1785 else
1786 SFX_Play_Raw (SFX_STATIC, &parm, (char *)(const char *)snd_name);
1789 //////////////////////////////////////////////////////
1791 static bool OnTabButton (ushort action, int button, void *data, LGadBox *)
1793 cOptions *panel = (cOptions*)data;
1795 panel->OnTabButtonList (action, button);
1796 return FALSE;
1799 //////////////////////////////////////////////////////
1801 void OnTabButtonList (ushort action, int button)
1803 if (!(action & BUTTONGADG_LCLICK))
1804 return;
1806 switch (button)
1808 //controls
1809 case kTab0:
1811 if (mCurSub != kSubControls) {
1812 mSwap = kSubControls;
1813 DestroyAllSliders ();
1816 break;
1818 //video
1819 case kTab1:
1821 if (mCurSub != kSubBasicVideo && mCurSub != kSubAdvancedVideo) {
1822 DestroyAllSliders ();
1823 mSwap = kSubBasicVideo;
1826 break;
1828 //audio
1829 case kTab2:
1831 if (mCurSub != kSubAudio) {
1832 DestroyAllSliders ();
1833 mSwap = kSubAudio;
1836 break;
1838 //game
1839 case kTab3:
1841 if (mCurSub != kSubGame) {
1842 DestroyAllSliders ();
1843 mSwap = kSubGame;
1846 break;
1851 //////////////////////////////////////////////////////
1853 static bool OnSubPanelButton (ushort action, int button, void *data, LGadBox *)
1855 cOptions *panel = (cOptions*)data;
1857 panel->OnSubPanelButtonList (action, button);
1858 return FALSE;
1861 //////////////////////////////////////////////////////
1863 void OnSubPanelButtonList (ushort action, int button)
1865 if (!(action & BUTTONGADG_LCLICK))
1866 return;
1868 int idx = button + gFirstSubRect[mCurSub];
1871 switch (idx)
1874 case kScreenRes:
1875 mSwap = kSubList;
1876 mListSub = kSubBasicVideo;
1877 mSelectedRes = -1;
1878 mTopList = 0;
1879 break;
1882 #ifdef ADVANDED_VID_PANEL
1883 case kAdvancedVidOptions:
1884 DestroyAllSliders ();
1885 mSwap = kSubAdvancedVideo;
1886 break;
1887 #endif
1889 case kHardwareDriver:
1890 mSwap = kSubList;
1891 mListSub = kSubAdvancedVideo;
1892 mTopList = 0;
1893 break;
1895 case kZBufferToggle:
1897 const sScrnMode *old_mode = GetGameScreenMode ();
1898 if (mNumVidDevices > 0 && old_mode->flags & kScrnMode3dDriver) {
1899 if (!g_zbuffer_toggle) {
1900 SetUIString (mSubPanelStrs[(int)kZBufferToggle], mSubPanelElems[(int)kZBufferToggle], "videoa_1",
1901 (char *)(const char *)mMiscStrs[kMiscStrOn]);
1902 g_zbuffer_toggle = TRUE;
1904 else {
1905 SetUIString (mSubPanelStrs[(int)kZBufferToggle], mSubPanelElems[(int)kZBufferToggle], "videoa_1",
1906 (char *)(const char *)mMiscStrs[kMiscStrOff]);
1907 g_zbuffer_toggle = FALSE;
1909 FillBlack ((int)kZBufferToggle);
1910 RedrawDisplay ();
1913 break;
1915 case kBasicVidOptions:
1916 DestroyAllSliders ();
1917 mSwap = kSubBasicVideo;
1918 break;
1921 case kSpeakerTest:
1923 sfx_parm parm;
1924 memset (&parm, 0, sizeof (sfx_parm));
1925 parm.pan = SFX_StereoReversed() ? 10000 : -10000;
1926 parm.end_callback = PlayRightTest;
1927 cStr snd_name = FetchUIString (panel_name, "leftsound", mResPath);
1929 if (SFX_GetSoundDevice () == SFXDEVICE_A3D) {
1930 mxs_vector pos = {0.0, SFX_StereoReversed() ? -10.0 : 10.0, 0.0};
1931 //@TODO: make the a3d speaker test sound crisper, clearer, more refreshed
1932 SFX_Play_Vec (SFX_3D, &parm, (char *)(const char *)snd_name, &pos);
1934 else
1935 SFX_Play_Raw (SFX_STATIC, &parm, (char *)(const char *)snd_name);
1937 break;
1939 case kStereoToggle:
1940 SFX_SetReverseStereo (!SFX_StereoReversed ());
1941 SetUIString (mSubPanelStrs[(int)kStereoToggle], mSubPanelElems[(int)kStereoToggle], "audio_1",
1942 (char *)(const char *)mMiscStrs[(SFX_StereoReversed ()) ? kMiscStrOn : kMiscStrOff]);
1943 FillBlack (kStereoToggle);
1944 RedrawDisplay ();
1945 break;
1947 case kA3DToggle:
1948 if (CanChangeSoundDeviceNow()) {
1949 if (SFX_GetSoundDevice () != SFXDEVICE_A3D)
1951 // Try to use 3D sound hardware
1952 if (! SFX_SetSoundDevice (SFXDEVICE_A3D, TRUE))
1954 // If no 3D sound hardware, turn back on software.
1955 SFX_SetSoundDevice (SFXDEVICE_Software, TRUE);
1958 else
1959 SFX_SetSoundDevice (SFXDEVICE_Software, TRUE);
1961 SetUIString (mSubPanelStrs[(int)kA3DToggle], mSubPanelElems[(int)kA3DToggle], "audio_2",
1962 (char *)(const char *)mMiscStrs[(SFX_GetSoundDevice () == SFXDEVICE_A3D) ? kMiscStrOn : kMiscStrOff]);
1963 FillBlack (kA3DToggle);
1964 // RedrawDisplay ();
1966 // EAX settings may have changed.
1967 BOOL newEAXState = SFX_Is_EAX_Enabled();
1968 SetUIString (mSubPanelStrs[(int)kAudioEAXToggle], mSubPanelElems[(int)kAudioEAXToggle], "audio_4",
1969 (char *)(const char *)mMiscStrs[newEAXState ? kMiscStrOn : kMiscStrOff]);
1971 // Set EAX button color as appropriate.
1972 if ( CanChangeEAX() )
1973 // Hack: This takes the "green" color from the "speaker test" button..... there must be a better way...
1974 mSubPanelDesc[kSubAudio].button_elems[kAudioEAXToggle - kSpeakerTest].fcolor = mSubPanelDesc[kSubAudio].button_elems[0].fcolor;
1975 else
1976 mSubPanelDesc[kSubAudio].button_elems[kAudioEAXToggle - kSpeakerTest].fcolor = guiStyleGetColor(&mGreyStyle,StyleColorText);
1977 FillBlack (kAudioEAXToggle);
1979 RedrawDisplay();
1981 break;
1983 case kAudioChannels:
1984 if (CanChangeSoundDeviceNow())
1986 // List of valid selections
1987 static int selections[] = { 4, 8, 12, 16, 0 };
1988 int chan = sfx_use_channels;
1989 for (int* sel = selections; *sel != 0 && *sel <= chan; sel++)
1991 if (*sel == 0)
1992 chan = selections[0];
1993 else
1994 chan = *sel;
1996 SFXClose ();
1997 sfx_use_channels = chan;
1998 config_set_int("sfx_channels", chan);
1999 SFXInit ();
2001 char buf[8];
2002 sprintf (buf, "%d", chan);
2003 mSubPanelStrs[(int)kAudioChannels] += buf;
2004 SetUIString (mSubPanelStrs[(int)kAudioChannels], mSubPanelElems[(int)kAudioChannels], "audio_3", buf);
2006 break;
2008 case kAudioEAXToggle:
2009 if (CanChangeEAX())
2011 // Toggle EAX state.
2012 BOOL newEAXState = !SFX_Is_EAX_Enabled();
2013 if (newEAXState)
2014 SFX_Enable_EAX();
2015 else
2016 SFX_Disable_EAX();
2018 // Double-check to make sure state actually toggled.
2019 newEAXState = SFX_Is_EAX_Enabled();
2020 config_set_int ("sfx_eax", (int) newEAXState);
2021 SetUIString (mSubPanelStrs[(int)kAudioEAXToggle], mSubPanelElems[(int)kAudioEAXToggle], "audio_4",
2022 (char *)(const char *)mMiscStrs[newEAXState ? kMiscStrOn : kMiscStrOff]);
2024 break;
2026 case kCustomize:
2027 DestroyAllSliders ();
2028 mSwap = kSubBind;
2029 break;
2032 // I may weep openly
2033 case kDiff0:
2034 case kDiff1:
2035 case kDiff2:
2036 case kDiff3:
2038 if (g_diff_active)
2040 // Set the difficulty
2041 g_diff = BUTT2DIFF(button);
2042 if (InSim())
2044 AutoAppIPtr(QuestData);
2045 if (pQuestData->Exists(DIFF_QVAR))
2046 pQuestData->Set(DIFF_QVAR,g_diff);
2049 //not active, don't let them change buttons
2050 else
2051 LGadRadioButtonSelect (&mSubPanelButtons[kSubGame], DIFF2BUTT(g_diff));
2053 break;
2056 case kBindLoad:
2057 SwitchToShockLoadBndMode (TRUE);
2058 break;
2061 case kBindSave:
2062 SwitchToShockSaveBndMode (TRUE);
2063 break;
2065 case kBindBack:
2066 DestroyAllSliders ();
2067 mSwap = kSubControls;
2068 break;
2071 case kQuickConfigure:
2072 LGadRadioButtonSelect (&mBindButtons, mTopBind = 0);
2073 mBindButtonStrs[0] = FetchUIString (panel_name, "bindname_0", mResPath);
2074 mBindButtonStrs[0] += " = ?";
2076 //change to game context
2077 g_pInputBinder->GetContext (&m_old_context);
2078 g_pInputBinder->SetContext (HK_GAME_MODE,TRUE);
2079 g_pInputBinder->TrapBind ((char *)(const char *)mBindCmd[0], BindFilter, QuickConfigPostBindFunc, NULL);
2081 FillBindStrs ();
2082 FillBlack (FILL_SUBPANEL);
2083 RedrawDisplay ();
2084 break;
2087 case kBind:
2089 int bind_num = mTopBind + LGadRadioButtonSelection (&mBindButtons);
2090 char buf[16];
2091 sprintf (buf, "bindname_%d", bind_num);
2092 mBindButtonStrs[bind_num] = FetchUIString (panel_name, buf, mResPath);
2093 mBindButtonStrs[bind_num] += " = ?";
2095 //change to game context
2096 g_pInputBinder->GetContext (&m_old_context);
2097 g_pInputBinder->SetContext (HK_GAME_MODE,TRUE);
2098 g_pInputBinder->TrapBind ((char *)(const char *)mBindCmd[bind_num], BindFilter, PostBindFunc, NULL);
2100 FillBindStrs ();
2101 FillBlack (FILL_SUBPANEL);
2102 RedrawDisplay ();
2104 break;
2107 case kBindClear:
2109 //change to game context
2110 g_pInputBinder->GetContext (&m_old_context);
2111 g_pInputBinder->SetContext (HK_GAME_MODE,TRUE);
2113 char str[128], control_buf[64];
2114 int bind_num = mTopBind + LGadRadioButtonSelection (&mBindButtons);
2116 g_pInputBinder->GetControlFromCmdStart ((char *)(const char *)mBindCmd[bind_num], control_buf);
2117 while (*control_buf != '\0') {
2118 strcpy (str, "unbind ");
2119 strcat (str, control_buf);
2120 g_pInputBinder->ProcessCmd (str);
2121 g_pInputBinder->GetControlFromCmdStart ((char *)(const char *)mBindCmd[bind_num], control_buf);
2124 g_pInputBinder->SetContext (m_old_context,TRUE);
2126 for (int i = 0; i < mNumBindable; i++)
2127 mBindButtsFilled[i] = FALSE;
2128 FillBindStrs ();
2129 FillBlack (FILL_SUBPANEL);
2130 RedrawDisplay ();
2132 break;
2134 case kLookspring:
2136 char *inverted = g_pInputBinder->ProcessCmd ("echo $lookspring"), buf[16];
2137 sprintf (buf, "control_%d", button);
2138 if (atof (inverted) == 0.0) {
2139 g_pInputBinder->ProcessCmd ("lookspring 1");
2140 SetUIString (mSubPanelStrs[(int)kLookspring], mSubPanelElems[(int)kLookspring], buf, (char *)(const char *)mMiscStrs[kMiscStrOn]);
2142 //when lookspring is turned on, turn off freelook if it is on
2143 if (atof (g_pInputBinder->ProcessCmd ("echo $freelook")) != 0.0)
2144 OnSubPanelButtonList (action, kFreelook - kCustomize);
2146 else {
2147 g_pInputBinder->ProcessCmd ("lookspring 0");
2148 SetUIString (mSubPanelStrs[(int)kLookspring], mSubPanelElems[(int)kLookspring], buf, (char *)(const char *)mMiscStrs[kMiscStrOff]);
2150 FillBlack ((int)kLookspring);
2151 RedrawDisplay ();
2153 break;
2155 case kJoyRotate:
2157 if (g_joystickActive)
2159 char *rotate = g_pInputBinder->ProcessCmd ("echo $joy_rotate"), buf[16];
2160 sprintf (buf, "control_%d", button);
2161 if (atof (rotate) == 0.0) {
2162 g_pInputBinder->ProcessCmd ("joy_rotate 1");
2163 SetUIString (mSubPanelStrs[(int)kJoyRotate], mSubPanelElems[(int)kJoyRotate], buf, (char *)(const char *)mMiscStrs[kMiscStrLeftRight]);
2165 else {
2166 g_pInputBinder->ProcessCmd ("joy_rotate 0");
2167 SetUIString (mSubPanelStrs[(int)kJoyRotate], mSubPanelElems[(int)kJoyRotate], buf, (char *)(const char *)mMiscStrs[kMiscStrForwardBackward]);
2169 FillBlack ((int)kJoyRotate);
2170 RedrawDisplay ();
2173 break;
2175 case kMouseInvert:
2177 char *inverted = g_pInputBinder->ProcessCmd ("echo $mouse_invert"), buf[16];
2178 sprintf (buf, "control_%d", button);
2179 if (atof (inverted) == 0.0) {
2180 g_pInputBinder->ProcessCmd ("mouse_invert 1");
2181 SetUIString (mSubPanelStrs[(int)kMouseInvert], mSubPanelElems[(int)kMouseInvert], buf, (char *)(const char *)mMiscStrs[kMiscStrOn]);
2183 else {
2184 g_pInputBinder->ProcessCmd ("mouse_invert 0");
2185 SetUIString (mSubPanelStrs[(int)kMouseInvert], mSubPanelElems[(int)kMouseInvert], buf, (char *)(const char *)mMiscStrs[kMiscStrOff]);
2187 FillBlack ((int)kMouseInvert);
2188 RedrawDisplay ();
2190 break;
2193 case kFreelook:
2195 char *inverted = g_pInputBinder->ProcessCmd ("echo $freelook"), buf[16];
2196 sprintf (buf, "control_%d", button);
2197 if (atof (inverted) == 0.0) {
2198 g_pInputBinder->ProcessCmd ("freelook 1");
2199 SetUIString (mSubPanelStrs[(int)kFreelook], mSubPanelElems[(int)kFreelook], buf, (char *)(const char *)mMiscStrs[kMiscStrOn]);
2201 //when freelook is turned on, turn off lookspring if it is on
2202 if (atof (g_pInputBinder->ProcessCmd ("echo $lookspring")) != 0.0)
2203 OnSubPanelButtonList (action, kLookspring - kCustomize);
2205 else {
2206 g_pInputBinder->ProcessCmd ("freelook 0");
2207 SetUIString (mSubPanelStrs[(int)kFreelook], mSubPanelElems[(int)kFreelook], buf, (char *)(const char *)mMiscStrs[kMiscStrOff]);
2209 FillBlack ((int)kFreelook);
2210 RedrawDisplay ();
2212 break;
2215 case kListBack:
2216 mSwap = mListSub;
2217 DestroyAllSliders ();
2219 if (mListSub == kSubAdvancedVideo) {
2220 config_set_int ("d3d_driver_index", m3dDriver = LGadRadioButtonSelection (&mListButtons));
2221 // Go back to basic video instead of advanced
2222 mSwap = kSubBasicVideo;
2225 //resolution choice
2226 else if (mListSub == kSubBasicVideo) {
2227 SetVidRes ();
2229 break;
2234 //////////////////////////////////////////////////////
2236 static bool OnScrollButton (ushort action, int button, void *data, LGadBox *)
2238 cOptions *panel = (cOptions*)data;
2240 panel->OnScrollList (action, button);
2241 return FALSE;
2244 //////////////////////////////////////////////////////
2246 void OnScrollList (ushort action, int button)
2248 if (!(action & BUTTONGADG_LCLICK))
2249 return;
2251 BOOL redraw = TRUE;
2253 switch (button)
2255 //scroll up
2256 case 0:
2257 switch (mCurSub) {
2258 case kSubBind:
2259 if (mTopBind > 0) {
2260 mTopBind--;
2261 FillBindStrs ();
2263 else
2264 redraw = FALSE;
2265 break;
2267 //scrolling through resolutions
2268 case kSubList:
2269 if (mTopList > 0) {
2270 mTopList--;
2271 FillVidResStrs ();
2273 else
2274 redraw = FALSE;
2275 break;
2278 break;
2280 //scroll down
2281 case 1:
2282 switch (mCurSub) {
2283 case kSubBind:
2284 if (mTopBind <= mNumBindable - NUM_BIND_SLOTS) {
2285 mTopBind++;
2286 FillBindStrs ();
2288 if (mTopBind == mNumBindable - (NUM_BIND_SLOTS - 1) && LGadRadioButtonSelection (&mBindButtons) == (NUM_BIND_SLOTS - 1))
2289 LGadRadioButtonSelect (&mBindButtons, 8);
2291 else
2292 redraw = FALSE;
2293 break;
2295 //resolutions
2296 case kSubList:
2297 if (mNumListTotal >= NUM_LIST - 1) {
2298 mTopList++;
2299 FillVidResStrs ();
2301 else
2302 redraw = FALSE;
2303 break;
2306 break;
2309 if (redraw) {
2310 FillBlack (FILL_SUBPANEL);
2311 RedrawDisplay ();
2316 //////////////////////////////////////////////////////
2318 static bool OnBindButton (ushort action, int button, void *data, LGadBox *)
2320 cOptions *panel = (cOptions*)data;
2322 panel->OnBind (action, button);
2323 return FALSE;
2326 //////////////////////////////////////////////////////
2328 void OnBind (ushort action, int button)
2330 if (!(action & BUTTONGADG_LCLICK))
2331 return;
2333 static int prev_pick;
2334 if (!strcmp ((const char *)mBindButtonElems[button].draw_data, "")) {
2335 LGadRadioButtonSelect (&mBindButtons, prev_pick);
2337 else
2338 prev_pick = button;
2341 //////////////////////////////////////////////////////
2343 static bool OnListButton (ushort action, int button, void *data, LGadBox *)
2345 cOptions *panel = (cOptions*)data;
2347 panel->OnList (action, button);
2348 return FALSE;
2351 //////////////////////////////////////////////////////
2353 void OnList (ushort action, int button)
2355 if (!(action & BUTTONGADG_LCLICK))
2356 return;
2358 BOOL valid_butt = TRUE;
2360 //display device choice
2361 if (mListSub == kSubAdvancedVideo) {
2362 //the button clicked was not filled
2363 if (button >= mNumVidDevices) {
2364 LGadRadioButtonSelect (&mListButtons, mListPrevPick);
2365 valid_butt = FALSE;
2368 //there was something there
2369 else {
2370 config_set_int ("d3d_driver_index", button);
2371 m3dDriver = button;
2375 //resolution choice
2376 else if (mListSub == kSubBasicVideo) {
2377 //the button clicked was not filled
2378 if (button >= mNumListTotal) {
2379 LGadRadioButtonSelect (&mListButtons, mListPrevPick);
2380 valid_butt = FALSE;
2382 else {
2383 mSelectedRes = mTopList + button;
2384 SetVidRes ();
2388 if (valid_butt)
2389 mListPrevPick = button;
2392 //////////////////////////////////////////////////////
2394 void OnButtonList(ushort action, int button)
2396 if (!(action & BUTTONGADG_LCLICK))
2397 return;
2399 switch (button)
2401 case kDone:
2403 if (mCurSub == kSubList)
2404 OnSubPanelButtonList (action, 0);
2406 cAutoIPtr<IPanelMode> mode = GetPanelMode();
2407 mode->Exit();
2409 break;
2416 int cShockOptions::gFirstSubRect[] =
2418 cShockOptions::kFirstControlButt,
2419 cShockOptions::kFirstBasicVideoButt,
2420 cShockOptions::kFirstAdvancedVideoButt,
2421 cShockOptions::kFirstAudioButt,
2422 cShockOptions::kFirstGameButt,
2423 cShockOptions::kFirstBindButt,
2424 cShockOptions::kFirstListButt,
2427 int cShockOptions::gVolSliderRects[] =
2429 cShockOptions::kVolumeSliderRect,
2430 cShockOptions::k3dVolumeSliderRect,
2431 cShockOptions::kMusicSliderRect,
2436 // Options Menu descriptor
2439 static const char* options_button_names[] =
2441 "done"
2444 sDarkPanelDesc cOptions::gDesc =
2446 "options",
2447 cOptions::kNumButts,
2448 cOptions::kNumRects,
2449 cOptions::kNumButts,
2450 options_button_names,
2451 NULL,
2453 kMetaSndPanelOptions
2458 EXTERN void SwitchToShockOptionsMode(BOOL push)
2460 if (gpOptions)
2462 cAutoIPtr<IPanelMode> panel = gpOptions->GetPanelMode();
2463 panel->Switch((push) ? kLoopModePush : kLoopModeSwitch);
2468 const sLoopInstantiator* DescribeShockOptionsMode(void)
2470 if (gpOptions)
2472 cAutoIPtr<IPanelMode> panel = gpOptions->GetPanelMode();
2473 return panel->Instantiator();
2475 return NULL;
2479 //Wrapper so that others can use this easier..
2480 //Will stuff retrieve_num many controls bound to cmd into the dest
2481 //string array, and will return how many actually got stuff
2482 #ifdef WE_NEED_THIS
2483 int GetCmdBinds (const char *cmd, cStr *dest, int retrieve_num)
2485 return gpOptions->GetCmdBinds (cmd, dest, retrieve_num);
2487 #endif
2492 // Init and term stuff
2495 void ShockOptionsMenuInit ()
2497 gpOptions = new cOptions;
2498 gpOptions->SetInitialSub ();
2499 ShockInitBindSaveLoad();
2502 void ShockOptionsMenuTerm ()
2504 delete gpOptions;
2505 ShockTermBindSaveLoad();