1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4
5 This file is part of Quake III Arena source code.
6
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22 //
23 /**********************************************************************
24 UI_QMENU.C
25
26 Quake's menu framework system.
27 **********************************************************************/
28 #include "ui_local.h"
29
30 sfxHandle_t menu_in_sound;
31 sfxHandle_t menu_move_sound;
32 sfxHandle_t menu_out_sound;
33 sfxHandle_t menu_buzz_sound;
34 sfxHandle_t menu_null_sound;
35 sfxHandle_t weaponChangeSound;
36
37 static qhandle_t sliderBar;
38 static qhandle_t sliderButton_0;
39 static qhandle_t sliderButton_1;
40
41 vec4_t menu_text_color = {1.0f, 1.0f, 1.0f, 1.0f};
42 vec4_t menu_dim_color = {0.0f, 0.0f, 0.0f, 0.75f};
43 vec4_t color_black = {0.00f, 0.00f, 0.00f, 1.00f};
44 vec4_t color_white = {1.00f, 1.00f, 1.00f, 1.00f};
45 vec4_t color_yellow = {1.00f, 1.00f, 0.00f, 1.00f};
46 vec4_t color_blue = {0.00f, 0.00f, 1.00f, 1.00f};
47 vec4_t color_lightOrange = {1.00f, 0.68f, 0.00f, 1.00f };
48 vec4_t color_orange = {1.00f, 0.43f, 0.00f, 1.00f};
49 vec4_t color_red = {1.00f, 0.00f, 0.00f, 1.00f};
50 vec4_t color_dim = {0.00f, 0.00f, 0.00f, 0.25f};
51
52 // current color scheme
53 vec4_t pulse_color = {1.00f, 1.00f, 1.00f, 1.00f};
54 vec4_t text_color_disabled = {0.50f, 0.50f, 0.50f, 1.00f}; // light gray
55 vec4_t text_color_normal = {1.00f, 0.43f, 0.00f, 1.00f}; // light orange
56 vec4_t text_color_highlight = {1.00f, 1.00f, 0.00f, 1.00f}; // bright yellow
57 vec4_t listbar_color = {1.00f, 0.43f, 0.00f, 0.30f}; // transluscent orange
58 vec4_t text_color_status = {1.00f, 1.00f, 1.00f, 1.00f}; // bright white
59
60 // action widget
61 static void Action_Init( menuaction_s *a );
62 static void Action_Draw( menuaction_s *a );
63
64 // radio button widget
65 static void RadioButton_Init( menuradiobutton_s *rb );
66 static void RadioButton_Draw( menuradiobutton_s *rb );
67 static sfxHandle_t RadioButton_Key( menuradiobutton_s *rb, int key );
68
69 // slider widget
70 static void Slider_Init( menuslider_s *s );
71 static sfxHandle_t Slider_Key( menuslider_s *s, int key );
72 static void Slider_Draw( menuslider_s *s );
73
74 // spin control widget
75 static void SpinControl_Init( menulist_s *s );
76 static void SpinControl_Draw( menulist_s *s );
77 static sfxHandle_t SpinControl_Key( menulist_s *l, int key );
78
79 // text widget
80 static void Text_Init( menutext_s *b );
81 static void Text_Draw( menutext_s *b );
82
83 // scrolllist widget
84 static void ScrollList_Init( menulist_s *l );
85 sfxHandle_t ScrollList_Key( menulist_s *l, int key );
86
87 // proportional text widget
88 static void PText_Init( menutext_s *b );
89 static void PText_Draw( menutext_s *b );
90
91 // proportional banner text widget
92 static void BText_Init( menutext_s *b );
93 static void BText_Draw( menutext_s *b );
94
95 /*
96 =================
97 Text_Init
98 =================
99 */
Text_Init(menutext_s * t)100 static void Text_Init( menutext_s *t )
101 {
102 t->generic.flags |= QMF_INACTIVE;
103 }
104
105 /*
106 =================
107 Text_Draw
108 =================
109 */
Text_Draw(menutext_s * t)110 static void Text_Draw( menutext_s *t )
111 {
112 int x;
113 int y;
114 char buff[512];
115 float* color;
116
117 x = t->generic.x;
118 y = t->generic.y;
119
120 buff[0] = '\0';
121
122 // possible label
123 if (t->generic.name)
124 strcpy(buff,t->generic.name);
125
126 // possible value
127 if (t->string)
128 strcat(buff,t->string);
129
130 if (t->generic.flags & QMF_GRAYED)
131 color = text_color_disabled;
132 else
133 color = t->color;
134
135 UI_DrawString( x, y, buff, t->style, color );
136 }
137
138 /*
139 =================
140 BText_Init
141 =================
142 */
BText_Init(menutext_s * t)143 static void BText_Init( menutext_s *t )
144 {
145 t->generic.flags |= QMF_INACTIVE;
146 }
147
148 /*
149 =================
150 BText_Draw
151 =================
152 */
BText_Draw(menutext_s * t)153 static void BText_Draw( menutext_s *t )
154 {
155 int x;
156 int y;
157 float* color;
158
159 x = t->generic.x;
160 y = t->generic.y;
161
162 if (t->generic.flags & QMF_GRAYED)
163 color = text_color_disabled;
164 else
165 color = t->color;
166
167 UI_DrawBannerString( x, y, t->string, t->style, color );
168 }
169
170 /*
171 =================
172 PText_Init
173 =================
174 */
PText_Init(menutext_s * t)175 static void PText_Init( menutext_s *t )
176 {
177 int x;
178 int y;
179 int w;
180 int h;
181 float sizeScale;
182
183 sizeScale = UI_ProportionalSizeScale( t->style );
184
185 x = t->generic.x;
186 y = t->generic.y;
187 w = UI_ProportionalStringWidth( t->string ) * sizeScale;
188 h = PROP_HEIGHT * sizeScale;
189
190 if( t->generic.flags & QMF_RIGHT_JUSTIFY ) {
191 x -= w;
192 }
193 else if( t->generic.flags & QMF_CENTER_JUSTIFY ) {
194 x -= w / 2;
195 }
196
197 t->generic.left = x - PROP_GAP_WIDTH * sizeScale;
198 t->generic.right = x + w + PROP_GAP_WIDTH * sizeScale;
199 t->generic.top = y;
200 t->generic.bottom = y + h;
201 }
202
203 /*
204 =================
205 PText_Draw
206 =================
207 */
PText_Draw(menutext_s * t)208 static void PText_Draw( menutext_s *t )
209 {
210 int x;
211 int y;
212 float * color;
213 int style;
214
215 x = t->generic.x;
216 y = t->generic.y;
217
218 if (t->generic.flags & QMF_GRAYED)
219 color = text_color_disabled;
220 else
221 color = t->color;
222
223 style = t->style;
224 if( t->generic.flags & QMF_PULSEIFFOCUS ) {
225 if( Menu_ItemAtCursor( t->generic.parent ) == t ) {
226 style |= UI_PULSE;
227 }
228 else {
229 style |= UI_INVERSE;
230 }
231 }
232
233 UI_DrawProportionalString( x, y, t->string, style, color );
234 }
235
236 /*
237 =================
238 Bitmap_Init
239 =================
240 */
Bitmap_Init(menubitmap_s * b)241 void Bitmap_Init( menubitmap_s *b )
242 {
243 int x;
244 int y;
245 int w;
246 int h;
247
248 x = b->generic.x;
249 y = b->generic.y;
250 w = b->width;
251 h = b->height;
252 if( w < 0 ) {
253 w = -w;
254 }
255 if( h < 0 ) {
256 h = -h;
257 }
258
259 if (b->generic.flags & QMF_RIGHT_JUSTIFY)
260 {
261 x = x - w;
262 }
263 else if (b->generic.flags & QMF_CENTER_JUSTIFY)
264 {
265 x = x - w/2;
266 }
267
268 b->generic.left = x;
269 b->generic.right = x + w;
270 b->generic.top = y;
271 b->generic.bottom = y + h;
272
273 b->shader = 0;
274 b->focusshader = 0;
275 }
276
277 /*
278 =================
279 Bitmap_Draw
280 =================
281 */
Bitmap_Draw(menubitmap_s * b)282 void Bitmap_Draw( menubitmap_s *b )
283 {
284 float x;
285 float y;
286 float w;
287 float h;
288 vec4_t tempcolor;
289 float* color;
290
291 x = b->generic.x;
292 y = b->generic.y;
293 w = b->width;
294 h = b->height;
295
296 if (b->generic.flags & QMF_RIGHT_JUSTIFY)
297 {
298 x = x - w;
299 }
300 else if (b->generic.flags & QMF_CENTER_JUSTIFY)
301 {
302 x = x - w/2;
303 }
304
305 // used to refresh shader
306 if (b->generic.name && !b->shader)
307 {
308 b->shader = trap_R_RegisterShaderNoMip( b->generic.name );
309 if (!b->shader && b->errorpic)
310 b->shader = trap_R_RegisterShaderNoMip( b->errorpic );
311 }
312
313 if (b->focuspic && !b->focusshader)
314 b->focusshader = trap_R_RegisterShaderNoMip( b->focuspic );
315
316 if (b->generic.flags & QMF_GRAYED)
317 {
318 if (b->shader)
319 {
320 trap_R_SetColor( colorMdGrey );
321 UI_DrawHandlePic( x, y, w, h, b->shader );
322 trap_R_SetColor( NULL );
323 }
324 }
325 else
326 {
327 if (b->shader)
328 UI_DrawHandlePic( x, y, w, h, b->shader );
329
330 if ( ( (b->generic.flags & QMF_PULSE)
331 || (b->generic.flags & QMF_PULSEIFFOCUS) )
332 && (Menu_ItemAtCursor( b->generic.parent ) == b))
333 {
334 if (b->focuscolor)
335 {
336 tempcolor[0] = b->focuscolor[0];
337 tempcolor[1] = b->focuscolor[1];
338 tempcolor[2] = b->focuscolor[2];
339 color = tempcolor;
340 }
341 else
342 color = pulse_color;
343 color[3] = 0.5+0.5*sin(uis.realtime/PULSE_DIVISOR);
344
345 trap_R_SetColor( color );
346 UI_DrawHandlePic( x, y, w, h, b->focusshader );
347 trap_R_SetColor( NULL );
348 }
349 else if ((b->generic.flags & QMF_HIGHLIGHT) || ((b->generic.flags & QMF_HIGHLIGHT_IF_FOCUS) && (Menu_ItemAtCursor( b->generic.parent ) == b)))
350 {
351 if (b->focuscolor)
352 {
353 trap_R_SetColor( b->focuscolor );
354 UI_DrawHandlePic( x, y, w, h, b->focusshader );
355 trap_R_SetColor( NULL );
356 }
357 else
358 UI_DrawHandlePic( x, y, w, h, b->focusshader );
359 }
360 }
361 }
362
363 /*
364 =================
365 Action_Init
366 =================
367 */
Action_Init(menuaction_s * a)368 static void Action_Init( menuaction_s *a )
369 {
370 int len;
371
372 // calculate bounds
373 if (a->generic.name)
374 len = strlen(a->generic.name);
375 else
376 len = 0;
377
378 // left justify text
379 a->generic.left = a->generic.x;
380 a->generic.right = a->generic.x + len*BIGCHAR_WIDTH;
381 a->generic.top = a->generic.y;
382 a->generic.bottom = a->generic.y + BIGCHAR_HEIGHT;
383 }
384
385 /*
386 =================
387 Action_Draw
388 =================
389 */
Action_Draw(menuaction_s * a)390 static void Action_Draw( menuaction_s *a )
391 {
392 int x, y;
393 int style;
394 float* color;
395
396 style = 0;
397 color = menu_text_color;
398 if ( a->generic.flags & QMF_GRAYED )
399 {
400 color = text_color_disabled;
401 }
402 else if (( a->generic.flags & QMF_PULSEIFFOCUS ) && ( a->generic.parent->cursor == a->generic.menuPosition ))
403 {
404 color = text_color_highlight;
405 style = UI_PULSE;
406 }
407 else if (( a->generic.flags & QMF_HIGHLIGHT_IF_FOCUS ) && ( a->generic.parent->cursor == a->generic.menuPosition ))
408 {
409 color = text_color_highlight;
410 }
411 else if ( a->generic.flags & QMF_BLINK )
412 {
413 style = UI_BLINK;
414 color = text_color_highlight;
415 }
416
417 x = a->generic.x;
418 y = a->generic.y;
419
420 UI_DrawString( x, y, a->generic.name, UI_LEFT|style, color );
421
422 if ( a->generic.parent->cursor == a->generic.menuPosition )
423 {
424 // draw cursor
425 UI_DrawChar( x - BIGCHAR_WIDTH, y, 13, UI_LEFT|UI_BLINK, color);
426 }
427 }
428
429 /*
430 =================
431 RadioButton_Init
432 =================
433 */
RadioButton_Init(menuradiobutton_s * rb)434 static void RadioButton_Init( menuradiobutton_s *rb )
435 {
436 int len;
437
438 // calculate bounds
439 if (rb->generic.name)
440 len = strlen(rb->generic.name);
441 else
442 len = 0;
443
444 rb->generic.left = rb->generic.x - (len+1)*SMALLCHAR_WIDTH;
445 rb->generic.right = rb->generic.x + 6*SMALLCHAR_WIDTH;
446 rb->generic.top = rb->generic.y;
447 rb->generic.bottom = rb->generic.y + SMALLCHAR_HEIGHT;
448 }
449
450 /*
451 =================
452 RadioButton_Key
453 =================
454 */
RadioButton_Key(menuradiobutton_s * rb,int key)455 static sfxHandle_t RadioButton_Key( menuradiobutton_s *rb, int key )
456 {
457 switch (key)
458 {
459 case K_MOUSE1:
460 if (!(rb->generic.flags & QMF_HASMOUSEFOCUS))
461 break;
462
463 case K_JOY1:
464 case K_JOY2:
465 case K_JOY3:
466 case K_JOY4:
467 case K_ENTER:
468 case K_KP_ENTER:
469 case K_KP_LEFTARROW:
470 case K_LEFTARROW:
471 case K_KP_RIGHTARROW:
472 case K_RIGHTARROW:
473 rb->curvalue = !rb->curvalue;
474 if ( rb->generic.callback )
475 rb->generic.callback( rb, QM_ACTIVATED );
476
477 return (menu_move_sound);
478 }
479
480 // key not handled
481 return 0;
482 }
483
484 /*
485 =================
486 RadioButton_Draw
487 =================
488 */
RadioButton_Draw(menuradiobutton_s * rb)489 static void RadioButton_Draw( menuradiobutton_s *rb )
490 {
491 int x;
492 int y;
493 float *color;
494 int style;
495 qboolean focus;
496
497 x = rb->generic.x;
498 y = rb->generic.y;
499
500 focus = (rb->generic.parent->cursor == rb->generic.menuPosition);
501
502 if ( rb->generic.flags & QMF_GRAYED )
503 {
504 color = text_color_disabled;
505 style = UI_LEFT|UI_SMALLFONT;
506 }
507 else if ( focus )
508 {
509 color = text_color_highlight;
510 style = UI_LEFT|UI_PULSE|UI_SMALLFONT;
511 }
512 else
513 {
514 color = text_color_normal;
515 style = UI_LEFT|UI_SMALLFONT;
516 }
517
518 if ( focus )
519 {
520 // draw cursor
521 UI_FillRect( rb->generic.left, rb->generic.top, rb->generic.right-rb->generic.left+1, rb->generic.bottom-rb->generic.top+1, listbar_color );
522 UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color);
523 }
524
525 if ( rb->generic.name )
526 UI_DrawString( x - SMALLCHAR_WIDTH, y, rb->generic.name, UI_RIGHT|UI_SMALLFONT, color );
527
528 if ( !rb->curvalue )
529 {
530 UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y + 2, 16, 16, uis.rb_off);
531 UI_DrawString( x + SMALLCHAR_WIDTH + 16, y, "off", style, color );
532 }
533 else
534 {
535 UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y + 2, 16, 16, uis.rb_on );
536 UI_DrawString( x + SMALLCHAR_WIDTH + 16, y, "on", style, color );
537 }
538 }
539
540 /*
541 =================
542 Slider_Init
543 =================
544 */
Slider_Init(menuslider_s * s)545 static void Slider_Init( menuslider_s *s )
546 {
547 int len;
548
549 // calculate bounds
550 if (s->generic.name)
551 len = strlen(s->generic.name);
552 else
553 len = 0;
554
555 s->generic.left = s->generic.x - (len+1)*SMALLCHAR_WIDTH;
556 s->generic.right = s->generic.x + (SLIDER_RANGE+2+1)*SMALLCHAR_WIDTH;
557 s->generic.top = s->generic.y;
558 s->generic.bottom = s->generic.y + SMALLCHAR_HEIGHT;
559 }
560
561 /*
562 =================
563 Slider_Key
564 =================
565 */
Slider_Key(menuslider_s * s,int key)566 static sfxHandle_t Slider_Key( menuslider_s *s, int key )
567 {
568 sfxHandle_t sound;
569 int x;
570 int oldvalue;
571
572 switch (key)
573 {
574 case K_MOUSE1:
575 x = uis.cursorx - s->generic.x - 2*SMALLCHAR_WIDTH;
576 oldvalue = s->curvalue;
577 s->curvalue = (x/(float)(SLIDER_RANGE*SMALLCHAR_WIDTH)) * (s->maxvalue-s->minvalue) + s->minvalue;
578
579 if (s->curvalue < s->minvalue)
580 s->curvalue = s->minvalue;
581 else if (s->curvalue > s->maxvalue)
582 s->curvalue = s->maxvalue;
583 if (s->curvalue != oldvalue)
584 sound = menu_move_sound;
585 else
586 sound = 0;
587 break;
588
589 case K_KP_LEFTARROW:
590 case K_LEFTARROW:
591 if (s->curvalue > s->minvalue)
592 {
593 s->curvalue--;
594 sound = menu_move_sound;
595 }
596 else
597 sound = menu_buzz_sound;
598 break;
599
600 case K_KP_RIGHTARROW:
601 case K_RIGHTARROW:
602 if (s->curvalue < s->maxvalue)
603 {
604 s->curvalue++;
605 sound = menu_move_sound;
606 }
607 else
608 sound = menu_buzz_sound;
609 break;
610
611 default:
612 // key not handled
613 sound = 0;
614 break;
615 }
616
617 if ( sound && s->generic.callback )
618 s->generic.callback( s, QM_ACTIVATED );
619
620 return (sound);
621 }
622
623 #if 1
624 /*
625 =================
626 Slider_Draw
627 =================
628 */
Slider_Draw(menuslider_s * s)629 static void Slider_Draw( menuslider_s *s ) {
630 int x;
631 int y;
632 int style;
633 float *color;
634 int button;
635 qboolean focus;
636
637 x = s->generic.x;
638 y = s->generic.y;
639 focus = (s->generic.parent->cursor == s->generic.menuPosition);
640
641 if( s->generic.flags & QMF_GRAYED ) {
642 color = text_color_disabled;
643 style = UI_SMALLFONT;
644 }
645 else if( focus ) {
646 color = text_color_highlight;
647 style = UI_SMALLFONT | UI_PULSE;
648 }
649 else {
650 color = text_color_normal;
651 style = UI_SMALLFONT;
652 }
653
654 // draw label
655 UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, UI_RIGHT|style, color );
656
657 // draw slider
658 UI_SetColor( color );
659 UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y, 96, 16, sliderBar );
660 UI_SetColor( NULL );
661
662 // clamp thumb
663 if( s->maxvalue > s->minvalue ) {
664 s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue );
665 if( s->range < 0 ) {
666 s->range = 0;
667 }
668 else if( s->range > 1) {
669 s->range = 1;
670 }
671 }
672 else {
673 s->range = 0;
674 }
675
676 // draw thumb
677 if( style & UI_PULSE) {
678 button = sliderButton_1;
679 }
680 else {
681 button = sliderButton_0;
682 }
683
684 UI_DrawHandlePic( (int)( x + 2*SMALLCHAR_WIDTH + (SLIDER_RANGE-1)*SMALLCHAR_WIDTH* s->range ) - 2, y - 2, 12, 20, button );
685 }
686 #else
687 /*
688 =================
689 Slider_Draw
690 =================
691 */
Slider_Draw(menuslider_s * s)692 static void Slider_Draw( menuslider_s *s )
693 {
694 float *color;
695 int style;
696 int i;
697 int x;
698 int y;
699 qboolean focus;
700
701 x = s->generic.x;
702 y = s->generic.y;
703 focus = (s->generic.parent->cursor == s->generic.menuPosition);
704
705 style = UI_SMALLFONT;
706 if ( s->generic.flags & QMF_GRAYED )
707 {
708 color = text_color_disabled;
709 }
710 else if (focus)
711 {
712 color = text_color_highlight;
713 style |= UI_PULSE;
714 }
715 else
716 {
717 color = text_color_normal;
718 }
719
720 if ( focus )
721 {
722 // draw cursor
723 UI_FillRect( s->generic.left, s->generic.top, s->generic.right-s->generic.left+1, s->generic.bottom-s->generic.top+1, listbar_color );
724 UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color);
725 }
726
727 // draw label
728 UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, UI_RIGHT|style, color );
729
730 // draw slider
731 UI_DrawChar( x + SMALLCHAR_WIDTH, y, 128, UI_LEFT|style, color);
732 for ( i = 0; i < SLIDER_RANGE; i++ )
733 UI_DrawChar( x + (i+2)*SMALLCHAR_WIDTH, y, 129, UI_LEFT|style, color);
734 UI_DrawChar( x + (i+2)*SMALLCHAR_WIDTH, y, 130, UI_LEFT|style, color);
735
736 // clamp thumb
737 if (s->maxvalue > s->minvalue)
738 {
739 s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue );
740 if ( s->range < 0)
741 s->range = 0;
742 else if ( s->range > 1)
743 s->range = 1;
744 }
745 else
746 s->range = 0;
747
748 // draw thumb
749 if (style & UI_PULSE) {
750 style &= ~UI_PULSE;
751 style |= UI_BLINK;
752 }
753 UI_DrawChar( (int)( x + 2*SMALLCHAR_WIDTH + (SLIDER_RANGE-1)*SMALLCHAR_WIDTH* s->range ), y, 131, UI_LEFT|style, color);
754 }
755 #endif
756
757 /*
758 =================
759 SpinControl_Init
760 =================
761 */
SpinControl_Init(menulist_s * s)762 static void SpinControl_Init( menulist_s *s ) {
763 int len;
764 int l;
765 const char* str;
766
767 if (s->generic.name)
768 len = strlen(s->generic.name) * SMALLCHAR_WIDTH;
769 else
770 len = 0;
771
772 s->generic.left = s->generic.x - SMALLCHAR_WIDTH - len;
773
774 len = s->numitems = 0;
775 while ( (str = s->itemnames[s->numitems]) != 0 )
776 {
777 l = strlen(str);
778 if (l > len)
779 len = l;
780
781 s->numitems++;
782 }
783
784 s->generic.top = s->generic.y;
785 s->generic.right = s->generic.x + (len+1)*SMALLCHAR_WIDTH;
786 s->generic.bottom = s->generic.y + SMALLCHAR_HEIGHT;
787 }
788
789 /*
790 =================
791 SpinControl_Key
792 =================
793 */
SpinControl_Key(menulist_s * s,int key)794 static sfxHandle_t SpinControl_Key( menulist_s *s, int key )
795 {
796 sfxHandle_t sound;
797
798 sound = 0;
799 switch (key)
800 {
801 case K_MOUSE1:
802 s->curvalue++;
803 if (s->curvalue >= s->numitems)
804 s->curvalue = 0;
805 sound = menu_move_sound;
806 break;
807
808 case K_KP_LEFTARROW:
809 case K_LEFTARROW:
810 if (s->curvalue > 0)
811 {
812 s->curvalue--;
813 sound = menu_move_sound;
814 }
815 else
816 sound = menu_buzz_sound;
817 break;
818
819 case K_KP_RIGHTARROW:
820 case K_RIGHTARROW:
821 if (s->curvalue < s->numitems-1)
822 {
823 s->curvalue++;
824 sound = menu_move_sound;
825 }
826 else
827 sound = menu_buzz_sound;
828 break;
829 }
830
831 if ( sound && s->generic.callback )
832 s->generic.callback( s, QM_ACTIVATED );
833
834 return (sound);
835 }
836
837 /*
838 =================
839 SpinControl_Draw
840 =================
841 */
SpinControl_Draw(menulist_s * s)842 static void SpinControl_Draw( menulist_s *s )
843 {
844 float *color;
845 int x,y;
846 int style;
847 qboolean focus;
848
849 x = s->generic.x;
850 y = s->generic.y;
851
852 style = UI_SMALLFONT;
853 focus = (s->generic.parent->cursor == s->generic.menuPosition);
854
855 if ( s->generic.flags & QMF_GRAYED )
856 color = text_color_disabled;
857 else if ( focus )
858 {
859 color = text_color_highlight;
860 style |= UI_PULSE;
861 }
862 else if ( s->generic.flags & QMF_BLINK )
863 {
864 color = text_color_highlight;
865 style |= UI_BLINK;
866 }
867 else
868 color = text_color_normal;
869
870 if ( focus )
871 {
872 // draw cursor
873 UI_FillRect( s->generic.left, s->generic.top, s->generic.right-s->generic.left+1, s->generic.bottom-s->generic.top+1, listbar_color );
874 UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color);
875 }
876
877 UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, style|UI_RIGHT, color );
878 UI_DrawString( x + SMALLCHAR_WIDTH, y, s->itemnames[s->curvalue], style|UI_LEFT, color );
879 }
880
881 /*
882 =================
883 ScrollList_Init
884 =================
885 */
ScrollList_Init(menulist_s * l)886 static void ScrollList_Init( menulist_s *l )
887 {
888 int w;
889
890 l->oldvalue = 0;
891 l->curvalue = 0;
892 l->top = 0;
893
894 if( !l->columns ) {
895 l->columns = 1;
896 l->seperation = 0;
897 }
898 else if( !l->seperation ) {
899 l->seperation = 3;
900 }
901
902 w = ( (l->width + l->seperation) * l->columns - l->seperation) * SMALLCHAR_WIDTH;
903
904 l->generic.left = l->generic.x;
905 l->generic.top = l->generic.y;
906 l->generic.right = l->generic.x + w;
907 l->generic.bottom = l->generic.y + l->height * SMALLCHAR_HEIGHT;
908
909 if( l->generic.flags & QMF_CENTER_JUSTIFY ) {
910 l->generic.left -= w / 2;
911 l->generic.right -= w / 2;
912 }
913 }
914
915 /*
916 =================
917 ScrollList_Key
918 =================
919 */
ScrollList_Key(menulist_s * l,int key)920 sfxHandle_t ScrollList_Key( menulist_s *l, int key )
921 {
922 int x;
923 int y;
924 int w;
925 int i;
926 int j;
927 int c;
928 int cursorx;
929 int cursory;
930 int column;
931 int index;
932
933 switch (key)
934 {
935 case K_MOUSE1:
936 if (l->generic.flags & QMF_HASMOUSEFOCUS)
937 {
938 // check scroll region
939 x = l->generic.x;
940 y = l->generic.y;
941 w = ( (l->width + l->seperation) * l->columns - l->seperation) * SMALLCHAR_WIDTH;
942 if( l->generic.flags & QMF_CENTER_JUSTIFY ) {
943 x -= w / 2;
944 }
945 if (UI_CursorInRect( x, y, w, l->height*SMALLCHAR_HEIGHT ))
946 {
947 cursorx = (uis.cursorx - x)/SMALLCHAR_WIDTH;
948 column = cursorx / (l->width + l->seperation);
949 cursory = (uis.cursory - y)/SMALLCHAR_HEIGHT;
950 index = column * l->height + cursory;
951 if (l->top + index < l->numitems)
952 {
953 l->oldvalue = l->curvalue;
954 l->curvalue = l->top + index;
955
956 if (l->oldvalue != l->curvalue && l->generic.callback)
957 {
958 l->generic.callback( l, QM_GOTFOCUS );
959 return (menu_move_sound);
960 }
961 }
962 }
963
964 // absorbed, silent sound effect
965 return (menu_null_sound);
966 }
967 break;
968
969 case K_KP_HOME:
970 case K_HOME:
971 l->oldvalue = l->curvalue;
972 l->curvalue = 0;
973 l->top = 0;
974
975 if (l->oldvalue != l->curvalue && l->generic.callback)
976 {
977 l->generic.callback( l, QM_GOTFOCUS );
978 return (menu_move_sound);
979 }
980 return (menu_buzz_sound);
981
982 case K_KP_END:
983 case K_END:
984 l->oldvalue = l->curvalue;
985 l->curvalue = l->numitems-1;
986 if( l->columns > 1 ) {
987 c = (l->curvalue / l->height + 1) * l->height;
988 l->top = c - (l->columns * l->height);
989 }
990 else {
991 l->top = l->curvalue - (l->height - 1);
992 }
993 if (l->top < 0)
994 l->top = 0;
995
996 if (l->oldvalue != l->curvalue && l->generic.callback)
997 {
998 l->generic.callback( l, QM_GOTFOCUS );
999 return (menu_move_sound);
1000 }
1001 return (menu_buzz_sound);
1002
1003 case K_PGUP:
1004 case K_KP_PGUP:
1005 if( l->columns > 1 ) {
1006 return menu_null_sound;
1007 }
1008
1009 if (l->curvalue > 0)
1010 {
1011 l->oldvalue = l->curvalue;
1012 l->curvalue -= l->height-1;
1013 if (l->curvalue < 0)
1014 l->curvalue = 0;
1015 l->top = l->curvalue;
1016 if (l->top < 0)
1017 l->top = 0;
1018
1019 if (l->generic.callback)
1020 l->generic.callback( l, QM_GOTFOCUS );
1021
1022 return (menu_move_sound);
1023 }
1024 return (menu_buzz_sound);
1025
1026 case K_PGDN:
1027 case K_KP_PGDN:
1028 if( l->columns > 1 ) {
1029 return menu_null_sound;
1030 }
1031
1032 if (l->curvalue < l->numitems-1)
1033 {
1034 l->oldvalue = l->curvalue;
1035 l->curvalue += l->height-1;
1036 if (l->curvalue > l->numitems-1)
1037 l->curvalue = l->numitems-1;
1038 l->top = l->curvalue - (l->height-1);
1039 if (l->top < 0)
1040 l->top = 0;
1041
1042 if (l->generic.callback)
1043 l->generic.callback( l, QM_GOTFOCUS );
1044
1045 return (menu_move_sound);
1046 }
1047 return (menu_buzz_sound);
1048
1049 case K_KP_UPARROW:
1050 case K_UPARROW:
1051 if( l->curvalue == 0 ) {
1052 return menu_buzz_sound;
1053 }
1054
1055 l->oldvalue = l->curvalue;
1056 l->curvalue--;
1057
1058 if( l->curvalue < l->top ) {
1059 if( l->columns == 1 ) {
1060 l->top--;
1061 }
1062 else {
1063 l->top -= l->height;
1064 }
1065 }
1066
1067 if( l->generic.callback ) {
1068 l->generic.callback( l, QM_GOTFOCUS );
1069 }
1070
1071 return (menu_move_sound);
1072
1073 case K_KP_DOWNARROW:
1074 case K_DOWNARROW:
1075 if( l->curvalue == l->numitems - 1 ) {
1076 return menu_buzz_sound;
1077 }
1078
1079 l->oldvalue = l->curvalue;
1080 l->curvalue++;
1081
1082 if( l->curvalue >= l->top + l->columns * l->height ) {
1083 if( l->columns == 1 ) {
1084 l->top++;
1085 }
1086 else {
1087 l->top += l->height;
1088 }
1089 }
1090
1091 if( l->generic.callback ) {
1092 l->generic.callback( l, QM_GOTFOCUS );
1093 }
1094
1095 return menu_move_sound;
1096
1097 case K_KP_LEFTARROW:
1098 case K_LEFTARROW:
1099 if( l->columns == 1 ) {
1100 return menu_null_sound;
1101 }
1102
1103 if( l->curvalue < l->height ) {
1104 return menu_buzz_sound;
1105 }
1106
1107 l->oldvalue = l->curvalue;
1108 l->curvalue -= l->height;
1109
1110 if( l->curvalue < l->top ) {
1111 l->top -= l->height;
1112 }
1113
1114 if( l->generic.callback ) {
1115 l->generic.callback( l, QM_GOTFOCUS );
1116 }
1117
1118 return menu_move_sound;
1119
1120 case K_KP_RIGHTARROW:
1121 case K_RIGHTARROW:
1122 if( l->columns == 1 ) {
1123 return menu_null_sound;
1124 }
1125
1126 c = l->curvalue + l->height;
1127
1128 if( c >= l->numitems ) {
1129 return menu_buzz_sound;
1130 }
1131
1132 l->oldvalue = l->curvalue;
1133 l->curvalue = c;
1134
1135 if( l->curvalue > l->top + l->columns * l->height - 1 ) {
1136 l->top += l->height;
1137 }
1138
1139 if( l->generic.callback ) {
1140 l->generic.callback( l, QM_GOTFOCUS );
1141 }
1142
1143 return menu_move_sound;
1144 }
1145
1146 // cycle look for ascii key inside list items
1147 if ( !Q_isprint( key ) )
1148 return (0);
1149
1150 // force to lower for case insensitive compare
1151 if ( Q_isupper( key ) )
1152 {
1153 key -= 'A' - 'a';
1154 }
1155
1156 // iterate list items
1157 for (i=1; i<=l->numitems; i++)
1158 {
1159 j = (l->curvalue + i) % l->numitems;
1160 c = l->itemnames[j][0];
1161 if ( Q_isupper( c ) )
1162 {
1163 c -= 'A' - 'a';
1164 }
1165
1166 if (c == key)
1167 {
1168 // set current item, mimic windows listbox scroll behavior
1169 if (j < l->top)
1170 {
1171 // behind top most item, set this as new top
1172 l->top = j;
1173 }
1174 else if (j > l->top+l->height-1)
1175 {
1176 // past end of list box, do page down
1177 l->top = (j+1) - l->height;
1178 }
1179
1180 if (l->curvalue != j)
1181 {
1182 l->oldvalue = l->curvalue;
1183 l->curvalue = j;
1184 if (l->generic.callback)
1185 l->generic.callback( l, QM_GOTFOCUS );
1186 return ( menu_move_sound );
1187 }
1188
1189 return (menu_buzz_sound);
1190 }
1191 }
1192
1193 return (menu_buzz_sound);
1194 }
1195
1196 /*
1197 =================
1198 ScrollList_Draw
1199 =================
1200 */
ScrollList_Draw(menulist_s * l)1201 void ScrollList_Draw( menulist_s *l )
1202 {
1203 int x;
1204 int u;
1205 int y;
1206 int i;
1207 int base;
1208 int column;
1209 float* color;
1210 qboolean hasfocus;
1211 int style;
1212
1213 hasfocus = (l->generic.parent->cursor == l->generic.menuPosition);
1214
1215 x = l->generic.x;
1216 for( column = 0; column < l->columns; column++ ) {
1217 y = l->generic.y;
1218 base = l->top + column * l->height;
1219 for( i = base; i < base + l->height; i++) {
1220 if (i >= l->numitems)
1221 break;
1222
1223 if (i == l->curvalue)
1224 {
1225 u = x - 2;
1226 if( l->generic.flags & QMF_CENTER_JUSTIFY ) {
1227 u -= (l->width * SMALLCHAR_WIDTH) / 2 + 1;
1228 }
1229
1230 UI_FillRect(u,y,l->width*SMALLCHAR_WIDTH,SMALLCHAR_HEIGHT+2,listbar_color);
1231 color = text_color_highlight;
1232
1233 if (hasfocus)
1234 style = UI_PULSE|UI_LEFT|UI_SMALLFONT;
1235 else
1236 style = UI_LEFT|UI_SMALLFONT;
1237 }
1238 else
1239 {
1240 color = text_color_normal;
1241 style = UI_LEFT|UI_SMALLFONT;
1242 }
1243 if( l->generic.flags & QMF_CENTER_JUSTIFY ) {
1244 style |= UI_CENTER;
1245 }
1246
1247 UI_DrawString(
1248 x,
1249 y,
1250 l->itemnames[i],
1251 style,
1252 color);
1253
1254 y += SMALLCHAR_HEIGHT;
1255 }
1256 x += (l->width + l->seperation) * SMALLCHAR_WIDTH;
1257 }
1258 }
1259
1260 /*
1261 =================
1262 Menu_AddItem
1263 =================
1264 */
Menu_AddItem(menuframework_s * menu,void * item)1265 void Menu_AddItem( menuframework_s *menu, void *item )
1266 {
1267 menucommon_s *itemptr;
1268
1269 if (menu->nitems >= MAX_MENUITEMS)
1270 trap_Error ("Menu_AddItem: excessive items");
1271
1272 menu->items[menu->nitems] = item;
1273 ((menucommon_s*)menu->items[menu->nitems])->parent = menu;
1274 ((menucommon_s*)menu->items[menu->nitems])->menuPosition = menu->nitems;
1275 ((menucommon_s*)menu->items[menu->nitems])->flags &= ~QMF_HASMOUSEFOCUS;
1276
1277 // perform any item specific initializations
1278 itemptr = (menucommon_s*)item;
1279 if (!(itemptr->flags & QMF_NODEFAULTINIT))
1280 {
1281 switch (itemptr->type)
1282 {
1283 case MTYPE_ACTION:
1284 Action_Init((menuaction_s*)item);
1285 break;
1286
1287 case MTYPE_FIELD:
1288 MenuField_Init((menufield_s*)item);
1289 break;
1290
1291 case MTYPE_SPINCONTROL:
1292 SpinControl_Init((menulist_s*)item);
1293 break;
1294
1295 case MTYPE_RADIOBUTTON:
1296 RadioButton_Init((menuradiobutton_s*)item);
1297 break;
1298
1299 case MTYPE_SLIDER:
1300 Slider_Init((menuslider_s*)item);
1301 break;
1302
1303 case MTYPE_BITMAP:
1304 Bitmap_Init((menubitmap_s*)item);
1305 break;
1306
1307 case MTYPE_TEXT:
1308 Text_Init((menutext_s*)item);
1309 break;
1310
1311 case MTYPE_SCROLLLIST:
1312 ScrollList_Init((menulist_s*)item);
1313 break;
1314
1315 case MTYPE_PTEXT:
1316 PText_Init((menutext_s*)item);
1317 break;
1318
1319 case MTYPE_BTEXT:
1320 BText_Init((menutext_s*)item);
1321 break;
1322
1323 default:
1324 trap_Error( va("Menu_Init: unknown type %d", itemptr->type) );
1325 }
1326 }
1327
1328 menu->nitems++;
1329 }
1330
1331 /*
1332 =================
1333 Menu_CursorMoved
1334 =================
1335 */
Menu_CursorMoved(menuframework_s * m)1336 void Menu_CursorMoved( menuframework_s *m )
1337 {
1338 void (*callback)( void *self, int notification );
1339
1340 if (m->cursor_prev == m->cursor)
1341 return;
1342
1343 if (m->cursor_prev >= 0 && m->cursor_prev < m->nitems)
1344 {
1345 callback = ((menucommon_s*)(m->items[m->cursor_prev]))->callback;
1346 if (callback)
1347 callback(m->items[m->cursor_prev],QM_LOSTFOCUS);
1348 }
1349
1350 if (m->cursor >= 0 && m->cursor < m->nitems)
1351 {
1352 callback = ((menucommon_s*)(m->items[m->cursor]))->callback;
1353 if (callback)
1354 callback(m->items[m->cursor],QM_GOTFOCUS);
1355 }
1356 }
1357
1358 /*
1359 =================
1360 Menu_SetCursor
1361 =================
1362 */
Menu_SetCursor(menuframework_s * m,int cursor)1363 void Menu_SetCursor( menuframework_s *m, int cursor )
1364 {
1365 if (((menucommon_s*)(m->items[cursor]))->flags & (QMF_GRAYED|QMF_INACTIVE))
1366 {
1367 // cursor can't go there
1368 return;
1369 }
1370
1371 m->cursor_prev = m->cursor;
1372 m->cursor = cursor;
1373
1374 Menu_CursorMoved( m );
1375 }
1376
1377 /*
1378 =================
1379 Menu_SetCursorToItem
1380 =================
1381 */
Menu_SetCursorToItem(menuframework_s * m,void * ptr)1382 void Menu_SetCursorToItem( menuframework_s *m, void* ptr )
1383 {
1384 int i;
1385
1386 for (i=0; i<m->nitems; i++)
1387 {
1388 if (m->items[i] == ptr)
1389 {
1390 Menu_SetCursor( m, i );
1391 return;
1392 }
1393 }
1394 }
1395
1396 /*
1397 ** Menu_AdjustCursor
1398 **
1399 ** This function takes the given menu, the direction, and attempts
1400 ** to adjust the menu's cursor so that it's at the next available
1401 ** slot.
1402 */
Menu_AdjustCursor(menuframework_s * m,int dir)1403 void Menu_AdjustCursor( menuframework_s *m, int dir ) {
1404 menucommon_s *item = NULL;
1405 qboolean wrapped = qfalse;
1406
1407 wrap:
1408 while ( m->cursor >= 0 && m->cursor < m->nitems ) {
1409 item = ( menucommon_s * ) m->items[m->cursor];
1410 if (( item->flags & (QMF_GRAYED|QMF_MOUSEONLY|QMF_INACTIVE) ) ) {
1411 m->cursor += dir;
1412 }
1413 else {
1414 break;
1415 }
1416 }
1417
1418 if ( dir == 1 ) {
1419 if ( m->cursor >= m->nitems ) {
1420 if ( m->wrapAround ) {
1421 if ( wrapped ) {
1422 m->cursor = m->cursor_prev;
1423 return;
1424 }
1425 m->cursor = 0;
1426 wrapped = qtrue;
1427 goto wrap;
1428 }
1429 m->cursor = m->cursor_prev;
1430 }
1431 }
1432 else {
1433 if ( m->cursor < 0 ) {
1434 if ( m->wrapAround ) {
1435 if ( wrapped ) {
1436 m->cursor = m->cursor_prev;
1437 return;
1438 }
1439 m->cursor = m->nitems - 1;
1440 wrapped = qtrue;
1441 goto wrap;
1442 }
1443 m->cursor = m->cursor_prev;
1444 }
1445 }
1446 }
1447
1448 /*
1449 =================
1450 Menu_Draw
1451 =================
1452 */
Menu_Draw(menuframework_s * menu)1453 void Menu_Draw( menuframework_s *menu )
1454 {
1455 int i;
1456 menucommon_s *itemptr;
1457
1458 // draw menu
1459 for (i=0; i<menu->nitems; i++)
1460 {
1461 itemptr = (menucommon_s*)menu->items[i];
1462
1463 if (itemptr->flags & QMF_HIDDEN)
1464 continue;
1465
1466 if (itemptr->ownerdraw)
1467 {
1468 // total subclassing, owner draws everything
1469 itemptr->ownerdraw( itemptr );
1470 }
1471 else
1472 {
1473 switch (itemptr->type)
1474 {
1475 case MTYPE_RADIOBUTTON:
1476 RadioButton_Draw( (menuradiobutton_s*)itemptr );
1477 break;
1478
1479 case MTYPE_FIELD:
1480 MenuField_Draw( (menufield_s*)itemptr );
1481 break;
1482
1483 case MTYPE_SLIDER:
1484 Slider_Draw( (menuslider_s*)itemptr );
1485 break;
1486
1487 case MTYPE_SPINCONTROL:
1488 SpinControl_Draw( (menulist_s*)itemptr );
1489 break;
1490
1491 case MTYPE_ACTION:
1492 Action_Draw( (menuaction_s*)itemptr );
1493 break;
1494
1495 case MTYPE_BITMAP:
1496 Bitmap_Draw( (menubitmap_s*)itemptr );
1497 break;
1498
1499 case MTYPE_TEXT:
1500 Text_Draw( (menutext_s*)itemptr );
1501 break;
1502
1503 case MTYPE_SCROLLLIST:
1504 ScrollList_Draw( (menulist_s*)itemptr );
1505 break;
1506
1507 case MTYPE_PTEXT:
1508 PText_Draw( (menutext_s*)itemptr );
1509 break;
1510
1511 case MTYPE_BTEXT:
1512 BText_Draw( (menutext_s*)itemptr );
1513 break;
1514
1515 default:
1516 trap_Error( va("Menu_Draw: unknown type %d", itemptr->type) );
1517 }
1518 }
1519 #ifndef NDEBUG
1520 if( uis.debug ) {
1521 int x;
1522 int y;
1523 int w;
1524 int h;
1525
1526 if( !( itemptr->flags & QMF_INACTIVE ) ) {
1527 x = itemptr->left;
1528 y = itemptr->top;
1529 w = itemptr->right - itemptr->left + 1;
1530 h = itemptr->bottom - itemptr->top + 1;
1531
1532 if (itemptr->flags & QMF_HASMOUSEFOCUS) {
1533 UI_DrawRect(x, y, w, h, colorYellow );
1534 }
1535 else {
1536 UI_DrawRect(x, y, w, h, colorWhite );
1537 }
1538 }
1539 }
1540 #endif
1541 }
1542
1543 itemptr = Menu_ItemAtCursor( menu );
1544 if ( itemptr && itemptr->statusbar)
1545 itemptr->statusbar( ( void * ) itemptr );
1546 }
1547
1548 /*
1549 =================
1550 Menu_ItemAtCursor
1551 =================
1552 */
Menu_ItemAtCursor(menuframework_s * m)1553 void *Menu_ItemAtCursor( menuframework_s *m )
1554 {
1555 if ( m->cursor < 0 || m->cursor >= m->nitems )
1556 return NULL;
1557
1558 return m->items[m->cursor];
1559 }
1560
1561 /*
1562 =================
1563 Menu_ActivateItem
1564 =================
1565 */
Menu_ActivateItem(menuframework_s * s,menucommon_s * item)1566 sfxHandle_t Menu_ActivateItem( menuframework_s *s, menucommon_s* item ) {
1567 if ( item->callback ) {
1568 item->callback( item, QM_ACTIVATED );
1569 if( !( item->flags & QMF_SILENT ) ) {
1570 return menu_move_sound;
1571 }
1572 }
1573
1574 return 0;
1575 }
1576
1577 /*
1578 =================
1579 Menu_DefaultKey
1580 =================
1581 */
Menu_DefaultKey(menuframework_s * m,int key)1582 sfxHandle_t Menu_DefaultKey( menuframework_s *m, int key )
1583 {
1584 sfxHandle_t sound = 0;
1585 menucommon_s *item;
1586 int cursor_prev;
1587
1588 // menu system keys
1589 switch ( key )
1590 {
1591 case K_MOUSE2:
1592 case K_ESCAPE:
1593 UI_PopMenu();
1594 return menu_out_sound;
1595 }
1596
1597 if (!m || !m->nitems)
1598 return 0;
1599
1600 // route key stimulus to widget
1601 item = Menu_ItemAtCursor( m );
1602 if (item && !(item->flags & (QMF_GRAYED|QMF_INACTIVE)))
1603 {
1604 switch (item->type)
1605 {
1606 case MTYPE_SPINCONTROL:
1607 sound = SpinControl_Key( (menulist_s*)item, key );
1608 break;
1609
1610 case MTYPE_RADIOBUTTON:
1611 sound = RadioButton_Key( (menuradiobutton_s*)item, key );
1612 break;
1613
1614 case MTYPE_SLIDER:
1615 sound = Slider_Key( (menuslider_s*)item, key );
1616 break;
1617
1618 case MTYPE_SCROLLLIST:
1619 sound = ScrollList_Key( (menulist_s*)item, key );
1620 break;
1621
1622 case MTYPE_FIELD:
1623 sound = MenuField_Key( (menufield_s*)item, &key );
1624 break;
1625 }
1626
1627 if (sound) {
1628 // key was handled
1629 return sound;
1630 }
1631 }
1632
1633 // default handling
1634 switch ( key )
1635 {
1636 #ifndef NDEBUG
1637 case K_F11:
1638 uis.debug ^= 1;
1639 break;
1640
1641 case K_F12:
1642 trap_Cmd_ExecuteText(EXEC_APPEND, "screenshot\n");
1643 break;
1644 #endif
1645 case K_KP_UPARROW:
1646 case K_UPARROW:
1647 cursor_prev = m->cursor;
1648 m->cursor_prev = m->cursor;
1649 m->cursor--;
1650 Menu_AdjustCursor( m, -1 );
1651 if ( cursor_prev != m->cursor ) {
1652 Menu_CursorMoved( m );
1653 sound = menu_move_sound;
1654 }
1655 break;
1656
1657 case K_TAB:
1658 case K_KP_DOWNARROW:
1659 case K_DOWNARROW:
1660 cursor_prev = m->cursor;
1661 m->cursor_prev = m->cursor;
1662 m->cursor++;
1663 Menu_AdjustCursor( m, 1 );
1664 if ( cursor_prev != m->cursor ) {
1665 Menu_CursorMoved( m );
1666 sound = menu_move_sound;
1667 }
1668 break;
1669
1670 case K_MOUSE1:
1671 case K_MOUSE3:
1672 if (item)
1673 if ((item->flags & QMF_HASMOUSEFOCUS) && !(item->flags & (QMF_GRAYED|QMF_INACTIVE)))
1674 return (Menu_ActivateItem( m, item ));
1675 break;
1676
1677 case K_JOY1:
1678 case K_JOY2:
1679 case K_JOY3:
1680 case K_JOY4:
1681 case K_AUX1:
1682 case K_AUX2:
1683 case K_AUX3:
1684 case K_AUX4:
1685 case K_AUX5:
1686 case K_AUX6:
1687 case K_AUX7:
1688 case K_AUX8:
1689 case K_AUX9:
1690 case K_AUX10:
1691 case K_AUX11:
1692 case K_AUX12:
1693 case K_AUX13:
1694 case K_AUX14:
1695 case K_AUX15:
1696 case K_AUX16:
1697 case K_KP_ENTER:
1698 case K_ENTER:
1699 if (item)
1700 if (!(item->flags & (QMF_MOUSEONLY|QMF_GRAYED|QMF_INACTIVE)))
1701 return (Menu_ActivateItem( m, item ));
1702 break;
1703 }
1704
1705 return sound;
1706 }
1707
1708 /*
1709 =================
1710 Menu_Cache
1711 =================
1712 */
Menu_Cache(void)1713 void Menu_Cache( void )
1714 {
1715 uis.charset = trap_R_RegisterShaderNoMip( "gfx/2d/bigchars" );
1716 uis.charsetProp = trap_R_RegisterShaderNoMip( "menu/art/font1_prop.tga" );
1717 uis.charsetPropGlow = trap_R_RegisterShaderNoMip( "menu/art/font1_prop_glo.tga" );
1718 uis.charsetPropB = trap_R_RegisterShaderNoMip( "menu/art/font2_prop.tga" );
1719 uis.cursor = trap_R_RegisterShaderNoMip( "menu/art/3_cursor2" );
1720 uis.rb_on = trap_R_RegisterShaderNoMip( "menu/art/switch_on" );
1721 uis.rb_off = trap_R_RegisterShaderNoMip( "menu/art/switch_off" );
1722
1723 uis.whiteShader = trap_R_RegisterShaderNoMip( "white" );
1724 if ( uis.glconfig.hardwareType == GLHW_RAGEPRO ) {
1725 // the blend effect turns to shit with the normal
1726 uis.menuBackShader = trap_R_RegisterShaderNoMip( "menubackRagePro" );
1727 } else {
1728 uis.menuBackShader = trap_R_RegisterShaderNoMip( "menuback" );
1729 }
1730 uis.menuBackNoLogoShader = trap_R_RegisterShaderNoMip( "menubacknologo" );
1731
1732 menu_in_sound = trap_S_RegisterSound( "sound/misc/menu1.wav", qfalse );
1733 menu_move_sound = trap_S_RegisterSound( "sound/misc/menu2.wav", qfalse );
1734 menu_out_sound = trap_S_RegisterSound( "sound/misc/menu3.wav", qfalse );
1735 menu_buzz_sound = trap_S_RegisterSound( "sound/misc/menu4.wav", qfalse );
1736 weaponChangeSound = trap_S_RegisterSound( "sound/weapons/change.wav", qfalse );
1737
1738 // need a nonzero sound, make an empty sound for this
1739 menu_null_sound = -1;
1740
1741 sliderBar = trap_R_RegisterShaderNoMip( "menu/art/slider2" );
1742 sliderButton_0 = trap_R_RegisterShaderNoMip( "menu/art/sliderbutt_0" );
1743 sliderButton_1 = trap_R_RegisterShaderNoMip( "menu/art/sliderbutt_1" );
1744 }
1745
1746