From 6bf20c78f5b69d40bcc4931df93d29198435ab67 Mon Sep 17 00:00:00 2001 From: zakk Date: Fri, 26 Aug 2005 17:39:27 +0000 Subject: newlines fixed git-svn-id: svn://svn.icculus.org/quake3/trunk@6 edf5b092-35ff-0310-97b2-ce42778d08ea --- code/q3_ui/ui_qmenu.c | 3492 ++++++++++++++++++++++++------------------------- 1 file changed, 1746 insertions(+), 1746 deletions(-) (limited to 'code/q3_ui/ui_qmenu.c') diff --git a/code/q3_ui/ui_qmenu.c b/code/q3_ui/ui_qmenu.c index 400448a..a6ec29e 100755 --- a/code/q3_ui/ui_qmenu.c +++ b/code/q3_ui/ui_qmenu.c @@ -1,1746 +1,1746 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// -/********************************************************************** - UI_QMENU.C - - Quake's menu framework system. -**********************************************************************/ -#include "ui_local.h" - -sfxHandle_t menu_in_sound; -sfxHandle_t menu_move_sound; -sfxHandle_t menu_out_sound; -sfxHandle_t menu_buzz_sound; -sfxHandle_t menu_null_sound; -sfxHandle_t weaponChangeSound; - -static qhandle_t sliderBar; -static qhandle_t sliderButton_0; -static qhandle_t sliderButton_1; - -vec4_t menu_text_color = {1.0f, 1.0f, 1.0f, 1.0f}; -vec4_t menu_dim_color = {0.0f, 0.0f, 0.0f, 0.75f}; -vec4_t color_black = {0.00f, 0.00f, 0.00f, 1.00f}; -vec4_t color_white = {1.00f, 1.00f, 1.00f, 1.00f}; -vec4_t color_yellow = {1.00f, 1.00f, 0.00f, 1.00f}; -vec4_t color_blue = {0.00f, 0.00f, 1.00f, 1.00f}; -vec4_t color_lightOrange = {1.00f, 0.68f, 0.00f, 1.00f }; -vec4_t color_orange = {1.00f, 0.43f, 0.00f, 1.00f}; -vec4_t color_red = {1.00f, 0.00f, 0.00f, 1.00f}; -vec4_t color_dim = {0.00f, 0.00f, 0.00f, 0.25f}; - -// current color scheme -vec4_t pulse_color = {1.00f, 1.00f, 1.00f, 1.00f}; -vec4_t text_color_disabled = {0.50f, 0.50f, 0.50f, 1.00f}; // light gray -vec4_t text_color_normal = {1.00f, 0.43f, 0.00f, 1.00f}; // light orange -vec4_t text_color_highlight = {1.00f, 1.00f, 0.00f, 1.00f}; // bright yellow -vec4_t listbar_color = {1.00f, 0.43f, 0.00f, 0.30f}; // transluscent orange -vec4_t text_color_status = {1.00f, 1.00f, 1.00f, 1.00f}; // bright white - -// action widget -static void Action_Init( menuaction_s *a ); -static void Action_Draw( menuaction_s *a ); - -// radio button widget -static void RadioButton_Init( menuradiobutton_s *rb ); -static void RadioButton_Draw( menuradiobutton_s *rb ); -static sfxHandle_t RadioButton_Key( menuradiobutton_s *rb, int key ); - -// slider widget -static void Slider_Init( menuslider_s *s ); -static sfxHandle_t Slider_Key( menuslider_s *s, int key ); -static void Slider_Draw( menuslider_s *s ); - -// spin control widget -static void SpinControl_Init( menulist_s *s ); -static void SpinControl_Draw( menulist_s *s ); -static sfxHandle_t SpinControl_Key( menulist_s *l, int key ); - -// text widget -static void Text_Init( menutext_s *b ); -static void Text_Draw( menutext_s *b ); - -// scrolllist widget -static void ScrollList_Init( menulist_s *l ); -sfxHandle_t ScrollList_Key( menulist_s *l, int key ); - -// proportional text widget -static void PText_Init( menutext_s *b ); -static void PText_Draw( menutext_s *b ); - -// proportional banner text widget -static void BText_Init( menutext_s *b ); -static void BText_Draw( menutext_s *b ); - -/* -================= -Text_Init -================= -*/ -static void Text_Init( menutext_s *t ) -{ - t->generic.flags |= QMF_INACTIVE; -} - -/* -================= -Text_Draw -================= -*/ -static void Text_Draw( menutext_s *t ) -{ - int x; - int y; - char buff[512]; - float* color; - - x = t->generic.x; - y = t->generic.y; - - buff[0] = '\0'; - - // possible label - if (t->generic.name) - strcpy(buff,t->generic.name); - - // possible value - if (t->string) - strcat(buff,t->string); - - if (t->generic.flags & QMF_GRAYED) - color = text_color_disabled; - else - color = t->color; - - UI_DrawString( x, y, buff, t->style, color ); -} - -/* -================= -BText_Init -================= -*/ -static void BText_Init( menutext_s *t ) -{ - t->generic.flags |= QMF_INACTIVE; -} - -/* -================= -BText_Draw -================= -*/ -static void BText_Draw( menutext_s *t ) -{ - int x; - int y; - float* color; - - x = t->generic.x; - y = t->generic.y; - - if (t->generic.flags & QMF_GRAYED) - color = text_color_disabled; - else - color = t->color; - - UI_DrawBannerString( x, y, t->string, t->style, color ); -} - -/* -================= -PText_Init -================= -*/ -static void PText_Init( menutext_s *t ) -{ - int x; - int y; - int w; - int h; - float sizeScale; - - sizeScale = UI_ProportionalSizeScale( t->style ); - - x = t->generic.x; - y = t->generic.y; - w = UI_ProportionalStringWidth( t->string ) * sizeScale; - h = PROP_HEIGHT * sizeScale; - - if( t->generic.flags & QMF_RIGHT_JUSTIFY ) { - x -= w; - } - else if( t->generic.flags & QMF_CENTER_JUSTIFY ) { - x -= w / 2; - } - - t->generic.left = x - PROP_GAP_WIDTH * sizeScale; - t->generic.right = x + w + PROP_GAP_WIDTH * sizeScale; - t->generic.top = y; - t->generic.bottom = y + h; -} - -/* -================= -PText_Draw -================= -*/ -static void PText_Draw( menutext_s *t ) -{ - int x; - int y; - float * color; - int style; - - x = t->generic.x; - y = t->generic.y; - - if (t->generic.flags & QMF_GRAYED) - color = text_color_disabled; - else - color = t->color; - - style = t->style; - if( t->generic.flags & QMF_PULSEIFFOCUS ) { - if( Menu_ItemAtCursor( t->generic.parent ) == t ) { - style |= UI_PULSE; - } - else { - style |= UI_INVERSE; - } - } - - UI_DrawProportionalString( x, y, t->string, style, color ); -} - -/* -================= -Bitmap_Init -================= -*/ -void Bitmap_Init( menubitmap_s *b ) -{ - int x; - int y; - int w; - int h; - - x = b->generic.x; - y = b->generic.y; - w = b->width; - h = b->height; - if( w < 0 ) { - w = -w; - } - if( h < 0 ) { - h = -h; - } - - if (b->generic.flags & QMF_RIGHT_JUSTIFY) - { - x = x - w; - } - else if (b->generic.flags & QMF_CENTER_JUSTIFY) - { - x = x - w/2; - } - - b->generic.left = x; - b->generic.right = x + w; - b->generic.top = y; - b->generic.bottom = y + h; - - b->shader = 0; - b->focusshader = 0; -} - -/* -================= -Bitmap_Draw -================= -*/ -void Bitmap_Draw( menubitmap_s *b ) -{ - float x; - float y; - float w; - float h; - vec4_t tempcolor; - float* color; - - x = b->generic.x; - y = b->generic.y; - w = b->width; - h = b->height; - - if (b->generic.flags & QMF_RIGHT_JUSTIFY) - { - x = x - w; - } - else if (b->generic.flags & QMF_CENTER_JUSTIFY) - { - x = x - w/2; - } - - // used to refresh shader - if (b->generic.name && !b->shader) - { - b->shader = trap_R_RegisterShaderNoMip( b->generic.name ); - if (!b->shader && b->errorpic) - b->shader = trap_R_RegisterShaderNoMip( b->errorpic ); - } - - if (b->focuspic && !b->focusshader) - b->focusshader = trap_R_RegisterShaderNoMip( b->focuspic ); - - if (b->generic.flags & QMF_GRAYED) - { - if (b->shader) - { - trap_R_SetColor( colorMdGrey ); - UI_DrawHandlePic( x, y, w, h, b->shader ); - trap_R_SetColor( NULL ); - } - } - else - { - if (b->shader) - UI_DrawHandlePic( x, y, w, h, b->shader ); - - // bk001204 - parentheses - if ( ( (b->generic.flags & QMF_PULSE) - || (b->generic.flags & QMF_PULSEIFFOCUS) ) - && (Menu_ItemAtCursor( b->generic.parent ) == b)) - { - if (b->focuscolor) - { - tempcolor[0] = b->focuscolor[0]; - tempcolor[1] = b->focuscolor[1]; - tempcolor[2] = b->focuscolor[2]; - color = tempcolor; - } - else - color = pulse_color; - color[3] = 0.5+0.5*sin(uis.realtime/PULSE_DIVISOR); - - trap_R_SetColor( color ); - UI_DrawHandlePic( x, y, w, h, b->focusshader ); - trap_R_SetColor( NULL ); - } - else if ((b->generic.flags & QMF_HIGHLIGHT) || ((b->generic.flags & QMF_HIGHLIGHT_IF_FOCUS) && (Menu_ItemAtCursor( b->generic.parent ) == b))) - { - if (b->focuscolor) - { - trap_R_SetColor( b->focuscolor ); - UI_DrawHandlePic( x, y, w, h, b->focusshader ); - trap_R_SetColor( NULL ); - } - else - UI_DrawHandlePic( x, y, w, h, b->focusshader ); - } - } -} - -/* -================= -Action_Init -================= -*/ -static void Action_Init( menuaction_s *a ) -{ - int len; - - // calculate bounds - if (a->generic.name) - len = strlen(a->generic.name); - else - len = 0; - - // left justify text - a->generic.left = a->generic.x; - a->generic.right = a->generic.x + len*BIGCHAR_WIDTH; - a->generic.top = a->generic.y; - a->generic.bottom = a->generic.y + BIGCHAR_HEIGHT; -} - -/* -================= -Action_Draw -================= -*/ -static void Action_Draw( menuaction_s *a ) -{ - int x, y; - int style; - float* color; - - style = 0; - color = menu_text_color; - if ( a->generic.flags & QMF_GRAYED ) - { - color = text_color_disabled; - } - else if (( a->generic.flags & QMF_PULSEIFFOCUS ) && ( a->generic.parent->cursor == a->generic.menuPosition )) - { - color = text_color_highlight; - style = UI_PULSE; - } - else if (( a->generic.flags & QMF_HIGHLIGHT_IF_FOCUS ) && ( a->generic.parent->cursor == a->generic.menuPosition )) - { - color = text_color_highlight; - } - else if ( a->generic.flags & QMF_BLINK ) - { - style = UI_BLINK; - color = text_color_highlight; - } - - x = a->generic.x; - y = a->generic.y; - - UI_DrawString( x, y, a->generic.name, UI_LEFT|style, color ); - - if ( a->generic.parent->cursor == a->generic.menuPosition ) - { - // draw cursor - UI_DrawChar( x - BIGCHAR_WIDTH, y, 13, UI_LEFT|UI_BLINK, color); - } -} - -/* -================= -RadioButton_Init -================= -*/ -static void RadioButton_Init( menuradiobutton_s *rb ) -{ - int len; - - // calculate bounds - if (rb->generic.name) - len = strlen(rb->generic.name); - else - len = 0; - - rb->generic.left = rb->generic.x - (len+1)*SMALLCHAR_WIDTH; - rb->generic.right = rb->generic.x + 6*SMALLCHAR_WIDTH; - rb->generic.top = rb->generic.y; - rb->generic.bottom = rb->generic.y + SMALLCHAR_HEIGHT; -} - -/* -================= -RadioButton_Key -================= -*/ -static sfxHandle_t RadioButton_Key( menuradiobutton_s *rb, int key ) -{ - switch (key) - { - case K_MOUSE1: - if (!(rb->generic.flags & QMF_HASMOUSEFOCUS)) - break; - - case K_JOY1: - case K_JOY2: - case K_JOY3: - case K_JOY4: - case K_ENTER: - case K_KP_ENTER: - case K_KP_LEFTARROW: - case K_LEFTARROW: - case K_KP_RIGHTARROW: - case K_RIGHTARROW: - rb->curvalue = !rb->curvalue; - if ( rb->generic.callback ) - rb->generic.callback( rb, QM_ACTIVATED ); - - return (menu_move_sound); - } - - // key not handled - return 0; -} - -/* -================= -RadioButton_Draw -================= -*/ -static void RadioButton_Draw( menuradiobutton_s *rb ) -{ - int x; - int y; - float *color; - int style; - qboolean focus; - - x = rb->generic.x; - y = rb->generic.y; - - focus = (rb->generic.parent->cursor == rb->generic.menuPosition); - - if ( rb->generic.flags & QMF_GRAYED ) - { - color = text_color_disabled; - style = UI_LEFT|UI_SMALLFONT; - } - else if ( focus ) - { - color = text_color_highlight; - style = UI_LEFT|UI_PULSE|UI_SMALLFONT; - } - else - { - color = text_color_normal; - style = UI_LEFT|UI_SMALLFONT; - } - - if ( focus ) - { - // draw cursor - UI_FillRect( rb->generic.left, rb->generic.top, rb->generic.right-rb->generic.left+1, rb->generic.bottom-rb->generic.top+1, listbar_color ); - UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color); - } - - if ( rb->generic.name ) - UI_DrawString( x - SMALLCHAR_WIDTH, y, rb->generic.name, UI_RIGHT|UI_SMALLFONT, color ); - - if ( !rb->curvalue ) - { - UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y + 2, 16, 16, uis.rb_off); - UI_DrawString( x + SMALLCHAR_WIDTH + 16, y, "off", style, color ); - } - else - { - UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y + 2, 16, 16, uis.rb_on ); - UI_DrawString( x + SMALLCHAR_WIDTH + 16, y, "on", style, color ); - } -} - -/* -================= -Slider_Init -================= -*/ -static void Slider_Init( menuslider_s *s ) -{ - int len; - - // calculate bounds - if (s->generic.name) - len = strlen(s->generic.name); - else - len = 0; - - s->generic.left = s->generic.x - (len+1)*SMALLCHAR_WIDTH; - s->generic.right = s->generic.x + (SLIDER_RANGE+2+1)*SMALLCHAR_WIDTH; - s->generic.top = s->generic.y; - s->generic.bottom = s->generic.y + SMALLCHAR_HEIGHT; -} - -/* -================= -Slider_Key -================= -*/ -static sfxHandle_t Slider_Key( menuslider_s *s, int key ) -{ - sfxHandle_t sound; - int x; - int oldvalue; - - switch (key) - { - case K_MOUSE1: - x = uis.cursorx - s->generic.x - 2*SMALLCHAR_WIDTH; - oldvalue = s->curvalue; - s->curvalue = (x/(float)(SLIDER_RANGE*SMALLCHAR_WIDTH)) * (s->maxvalue-s->minvalue) + s->minvalue; - - if (s->curvalue < s->minvalue) - s->curvalue = s->minvalue; - else if (s->curvalue > s->maxvalue) - s->curvalue = s->maxvalue; - if (s->curvalue != oldvalue) - sound = menu_move_sound; - else - sound = 0; - break; - - case K_KP_LEFTARROW: - case K_LEFTARROW: - if (s->curvalue > s->minvalue) - { - s->curvalue--; - sound = menu_move_sound; - } - else - sound = menu_buzz_sound; - break; - - case K_KP_RIGHTARROW: - case K_RIGHTARROW: - if (s->curvalue < s->maxvalue) - { - s->curvalue++; - sound = menu_move_sound; - } - else - sound = menu_buzz_sound; - break; - - default: - // key not handled - sound = 0; - break; - } - - if ( sound && s->generic.callback ) - s->generic.callback( s, QM_ACTIVATED ); - - return (sound); -} - -#if 1 -/* -================= -Slider_Draw -================= -*/ -static void Slider_Draw( menuslider_s *s ) { - int x; - int y; - int style; - float *color; - int button; - qboolean focus; - - x = s->generic.x; - y = s->generic.y; - focus = (s->generic.parent->cursor == s->generic.menuPosition); - - if( s->generic.flags & QMF_GRAYED ) { - color = text_color_disabled; - style = UI_SMALLFONT; - } - else if( focus ) { - color = text_color_highlight; - style = UI_SMALLFONT | UI_PULSE; - } - else { - color = text_color_normal; - style = UI_SMALLFONT; - } - - // draw label - UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, UI_RIGHT|style, color ); - - // draw slider - UI_SetColor( color ); - UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y, 96, 16, sliderBar ); - UI_SetColor( NULL ); - - // clamp thumb - if( s->maxvalue > s->minvalue ) { - s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue ); - if( s->range < 0 ) { - s->range = 0; - } - else if( s->range > 1) { - s->range = 1; - } - } - else { - s->range = 0; - } - - // draw thumb - if( style & UI_PULSE) { - button = sliderButton_1; - } - else { - button = sliderButton_0; - } - - UI_DrawHandlePic( (int)( x + 2*SMALLCHAR_WIDTH + (SLIDER_RANGE-1)*SMALLCHAR_WIDTH* s->range ) - 2, y - 2, 12, 20, button ); -} -#else -/* -================= -Slider_Draw -================= -*/ -static void Slider_Draw( menuslider_s *s ) -{ - float *color; - int style; - int i; - int x; - int y; - qboolean focus; - - x = s->generic.x; - y = s->generic.y; - focus = (s->generic.parent->cursor == s->generic.menuPosition); - - style = UI_SMALLFONT; - if ( s->generic.flags & QMF_GRAYED ) - { - color = text_color_disabled; - } - else if (focus) - { - color = text_color_highlight; - style |= UI_PULSE; - } - else - { - color = text_color_normal; - } - - if ( focus ) - { - // draw cursor - UI_FillRect( s->generic.left, s->generic.top, s->generic.right-s->generic.left+1, s->generic.bottom-s->generic.top+1, listbar_color ); - UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color); - } - - // draw label - UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, UI_RIGHT|style, color ); - - // draw slider - UI_DrawChar( x + SMALLCHAR_WIDTH, y, 128, UI_LEFT|style, color); - for ( i = 0; i < SLIDER_RANGE; i++ ) - UI_DrawChar( x + (i+2)*SMALLCHAR_WIDTH, y, 129, UI_LEFT|style, color); - UI_DrawChar( x + (i+2)*SMALLCHAR_WIDTH, y, 130, UI_LEFT|style, color); - - // clamp thumb - if (s->maxvalue > s->minvalue) - { - s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue ); - if ( s->range < 0) - s->range = 0; - else if ( s->range > 1) - s->range = 1; - } - else - s->range = 0; - - // draw thumb - if (style & UI_PULSE) { - style &= ~UI_PULSE; - style |= UI_BLINK; - } - UI_DrawChar( (int)( x + 2*SMALLCHAR_WIDTH + (SLIDER_RANGE-1)*SMALLCHAR_WIDTH* s->range ), y, 131, UI_LEFT|style, color); -} -#endif - -/* -================= -SpinControl_Init -================= -*/ -static void SpinControl_Init( menulist_s *s ) { - int len; - int l; - const char* str; - - if (s->generic.name) - len = strlen(s->generic.name) * SMALLCHAR_WIDTH; - else - len = 0; - - s->generic.left = s->generic.x - SMALLCHAR_WIDTH - len; - - len = s->numitems = 0; - while ( (str = s->itemnames[s->numitems]) != 0 ) - { - l = strlen(str); - if (l > len) - len = l; - - s->numitems++; - } - - s->generic.top = s->generic.y; - s->generic.right = s->generic.x + (len+1)*SMALLCHAR_WIDTH; - s->generic.bottom = s->generic.y + SMALLCHAR_HEIGHT; -} - -/* -================= -SpinControl_Key -================= -*/ -static sfxHandle_t SpinControl_Key( menulist_s *s, int key ) -{ - sfxHandle_t sound; - - sound = 0; - switch (key) - { - case K_MOUSE1: - s->curvalue++; - if (s->curvalue >= s->numitems) - s->curvalue = 0; - sound = menu_move_sound; - break; - - case K_KP_LEFTARROW: - case K_LEFTARROW: - if (s->curvalue > 0) - { - s->curvalue--; - sound = menu_move_sound; - } - else - sound = menu_buzz_sound; - break; - - case K_KP_RIGHTARROW: - case K_RIGHTARROW: - if (s->curvalue < s->numitems-1) - { - s->curvalue++; - sound = menu_move_sound; - } - else - sound = menu_buzz_sound; - break; - } - - if ( sound && s->generic.callback ) - s->generic.callback( s, QM_ACTIVATED ); - - return (sound); -} - -/* -================= -SpinControl_Draw -================= -*/ -static void SpinControl_Draw( menulist_s *s ) -{ - float *color; - int x,y; - int style; - qboolean focus; - - x = s->generic.x; - y = s->generic.y; - - style = UI_SMALLFONT; - focus = (s->generic.parent->cursor == s->generic.menuPosition); - - if ( s->generic.flags & QMF_GRAYED ) - color = text_color_disabled; - else if ( focus ) - { - color = text_color_highlight; - style |= UI_PULSE; - } - else if ( s->generic.flags & QMF_BLINK ) - { - color = text_color_highlight; - style |= UI_BLINK; - } - else - color = text_color_normal; - - if ( focus ) - { - // draw cursor - UI_FillRect( s->generic.left, s->generic.top, s->generic.right-s->generic.left+1, s->generic.bottom-s->generic.top+1, listbar_color ); - UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color); - } - - UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, style|UI_RIGHT, color ); - UI_DrawString( x + SMALLCHAR_WIDTH, y, s->itemnames[s->curvalue], style|UI_LEFT, color ); -} - -/* -================= -ScrollList_Init -================= -*/ -static void ScrollList_Init( menulist_s *l ) -{ - int w; - - l->oldvalue = 0; - l->curvalue = 0; - l->top = 0; - - if( !l->columns ) { - l->columns = 1; - l->seperation = 0; - } - else if( !l->seperation ) { - l->seperation = 3; - } - - w = ( (l->width + l->seperation) * l->columns - l->seperation) * SMALLCHAR_WIDTH; - - l->generic.left = l->generic.x; - l->generic.top = l->generic.y; - l->generic.right = l->generic.x + w; - l->generic.bottom = l->generic.y + l->height * SMALLCHAR_HEIGHT; - - if( l->generic.flags & QMF_CENTER_JUSTIFY ) { - l->generic.left -= w / 2; - l->generic.right -= w / 2; - } -} - -/* -================= -ScrollList_Key -================= -*/ -sfxHandle_t ScrollList_Key( menulist_s *l, int key ) -{ - int x; - int y; - int w; - int i; - int j; - int c; - int cursorx; - int cursory; - int column; - int index; - - switch (key) - { - case K_MOUSE1: - if (l->generic.flags & QMF_HASMOUSEFOCUS) - { - // check scroll region - x = l->generic.x; - y = l->generic.y; - w = ( (l->width + l->seperation) * l->columns - l->seperation) * SMALLCHAR_WIDTH; - if( l->generic.flags & QMF_CENTER_JUSTIFY ) { - x -= w / 2; - } - if (UI_CursorInRect( x, y, w, l->height*SMALLCHAR_HEIGHT )) - { - cursorx = (uis.cursorx - x)/SMALLCHAR_WIDTH; - column = cursorx / (l->width + l->seperation); - cursory = (uis.cursory - y)/SMALLCHAR_HEIGHT; - index = column * l->height + cursory; - if (l->top + index < l->numitems) - { - l->oldvalue = l->curvalue; - l->curvalue = l->top + index; - - if (l->oldvalue != l->curvalue && l->generic.callback) - { - l->generic.callback( l, QM_GOTFOCUS ); - return (menu_move_sound); - } - } - } - - // absorbed, silent sound effect - return (menu_null_sound); - } - break; - - case K_KP_HOME: - case K_HOME: - l->oldvalue = l->curvalue; - l->curvalue = 0; - l->top = 0; - - if (l->oldvalue != l->curvalue && l->generic.callback) - { - l->generic.callback( l, QM_GOTFOCUS ); - return (menu_move_sound); - } - return (menu_buzz_sound); - - case K_KP_END: - case K_END: - l->oldvalue = l->curvalue; - l->curvalue = l->numitems-1; - if( l->columns > 1 ) { - c = (l->curvalue / l->height + 1) * l->height; - l->top = c - (l->columns * l->height); - } - else { - l->top = l->curvalue - (l->height - 1); - } - if (l->top < 0) - l->top = 0; - - if (l->oldvalue != l->curvalue && l->generic.callback) - { - l->generic.callback( l, QM_GOTFOCUS ); - return (menu_move_sound); - } - return (menu_buzz_sound); - - case K_PGUP: - case K_KP_PGUP: - if( l->columns > 1 ) { - return menu_null_sound; - } - - if (l->curvalue > 0) - { - l->oldvalue = l->curvalue; - l->curvalue -= l->height-1; - if (l->curvalue < 0) - l->curvalue = 0; - l->top = l->curvalue; - if (l->top < 0) - l->top = 0; - - if (l->generic.callback) - l->generic.callback( l, QM_GOTFOCUS ); - - return (menu_move_sound); - } - return (menu_buzz_sound); - - case K_PGDN: - case K_KP_PGDN: - if( l->columns > 1 ) { - return menu_null_sound; - } - - if (l->curvalue < l->numitems-1) - { - l->oldvalue = l->curvalue; - l->curvalue += l->height-1; - if (l->curvalue > l->numitems-1) - l->curvalue = l->numitems-1; - l->top = l->curvalue - (l->height-1); - if (l->top < 0) - l->top = 0; - - if (l->generic.callback) - l->generic.callback( l, QM_GOTFOCUS ); - - return (menu_move_sound); - } - return (menu_buzz_sound); - - case K_KP_UPARROW: - case K_UPARROW: - if( l->curvalue == 0 ) { - return menu_buzz_sound; - } - - l->oldvalue = l->curvalue; - l->curvalue--; - - if( l->curvalue < l->top ) { - if( l->columns == 1 ) { - l->top--; - } - else { - l->top -= l->height; - } - } - - if( l->generic.callback ) { - l->generic.callback( l, QM_GOTFOCUS ); - } - - return (menu_move_sound); - - case K_KP_DOWNARROW: - case K_DOWNARROW: - if( l->curvalue == l->numitems - 1 ) { - return menu_buzz_sound; - } - - l->oldvalue = l->curvalue; - l->curvalue++; - - if( l->curvalue >= l->top + l->columns * l->height ) { - if( l->columns == 1 ) { - l->top++; - } - else { - l->top += l->height; - } - } - - if( l->generic.callback ) { - l->generic.callback( l, QM_GOTFOCUS ); - } - - return menu_move_sound; - - case K_KP_LEFTARROW: - case K_LEFTARROW: - if( l->columns == 1 ) { - return menu_null_sound; - } - - if( l->curvalue < l->height ) { - return menu_buzz_sound; - } - - l->oldvalue = l->curvalue; - l->curvalue -= l->height; - - if( l->curvalue < l->top ) { - l->top -= l->height; - } - - if( l->generic.callback ) { - l->generic.callback( l, QM_GOTFOCUS ); - } - - return menu_move_sound; - - case K_KP_RIGHTARROW: - case K_RIGHTARROW: - if( l->columns == 1 ) { - return menu_null_sound; - } - - c = l->curvalue + l->height; - - if( c >= l->numitems ) { - return menu_buzz_sound; - } - - l->oldvalue = l->curvalue; - l->curvalue = c; - - if( l->curvalue > l->top + l->columns * l->height - 1 ) { - l->top += l->height; - } - - if( l->generic.callback ) { - l->generic.callback( l, QM_GOTFOCUS ); - } - - return menu_move_sound; - } - - // cycle look for ascii key inside list items - if ( !Q_isprint( key ) ) - return (0); - - // force to lower for case insensitive compare - if ( Q_isupper( key ) ) - { - key -= 'A' - 'a'; - } - - // iterate list items - for (i=1; i<=l->numitems; i++) - { - j = (l->curvalue + i) % l->numitems; - c = l->itemnames[j][0]; - if ( Q_isupper( c ) ) - { - c -= 'A' - 'a'; - } - - if (c == key) - { - // set current item, mimic windows listbox scroll behavior - if (j < l->top) - { - // behind top most item, set this as new top - l->top = j; - } - else if (j > l->top+l->height-1) - { - // past end of list box, do page down - l->top = (j+1) - l->height; - } - - if (l->curvalue != j) - { - l->oldvalue = l->curvalue; - l->curvalue = j; - if (l->generic.callback) - l->generic.callback( l, QM_GOTFOCUS ); - return ( menu_move_sound ); - } - - return (menu_buzz_sound); - } - } - - return (menu_buzz_sound); -} - -/* -================= -ScrollList_Draw -================= -*/ -void ScrollList_Draw( menulist_s *l ) -{ - int x; - int u; - int y; - int i; - int base; - int column; - float* color; - qboolean hasfocus; - int style; - - hasfocus = (l->generic.parent->cursor == l->generic.menuPosition); - - x = l->generic.x; - for( column = 0; column < l->columns; column++ ) { - y = l->generic.y; - base = l->top + column * l->height; - for( i = base; i < base + l->height; i++) { - if (i >= l->numitems) - break; - - if (i == l->curvalue) - { - u = x - 2; - if( l->generic.flags & QMF_CENTER_JUSTIFY ) { - u -= (l->width * SMALLCHAR_WIDTH) / 2 + 1; - } - - UI_FillRect(u,y,l->width*SMALLCHAR_WIDTH,SMALLCHAR_HEIGHT+2,listbar_color); - color = text_color_highlight; - - if (hasfocus) - style = UI_PULSE|UI_LEFT|UI_SMALLFONT; - else - style = UI_LEFT|UI_SMALLFONT; - } - else - { - color = text_color_normal; - style = UI_LEFT|UI_SMALLFONT; - } - if( l->generic.flags & QMF_CENTER_JUSTIFY ) { - style |= UI_CENTER; - } - - UI_DrawString( - x, - y, - l->itemnames[i], - style, - color); - - y += SMALLCHAR_HEIGHT; - } - x += (l->width + l->seperation) * SMALLCHAR_WIDTH; - } -} - -/* -================= -Menu_AddItem -================= -*/ -void Menu_AddItem( menuframework_s *menu, void *item ) -{ - menucommon_s *itemptr; - - if (menu->nitems >= MAX_MENUITEMS) - trap_Error ("Menu_AddItem: excessive items"); - - menu->items[menu->nitems] = item; - ((menucommon_s*)menu->items[menu->nitems])->parent = menu; - ((menucommon_s*)menu->items[menu->nitems])->menuPosition = menu->nitems; - ((menucommon_s*)menu->items[menu->nitems])->flags &= ~QMF_HASMOUSEFOCUS; - - // perform any item specific initializations - itemptr = (menucommon_s*)item; - if (!(itemptr->flags & QMF_NODEFAULTINIT)) - { - switch (itemptr->type) - { - case MTYPE_ACTION: - Action_Init((menuaction_s*)item); - break; - - case MTYPE_FIELD: - MenuField_Init((menufield_s*)item); - break; - - case MTYPE_SPINCONTROL: - SpinControl_Init((menulist_s*)item); - break; - - case MTYPE_RADIOBUTTON: - RadioButton_Init((menuradiobutton_s*)item); - break; - - case MTYPE_SLIDER: - Slider_Init((menuslider_s*)item); - break; - - case MTYPE_BITMAP: - Bitmap_Init((menubitmap_s*)item); - break; - - case MTYPE_TEXT: - Text_Init((menutext_s*)item); - break; - - case MTYPE_SCROLLLIST: - ScrollList_Init((menulist_s*)item); - break; - - case MTYPE_PTEXT: - PText_Init((menutext_s*)item); - break; - - case MTYPE_BTEXT: - BText_Init((menutext_s*)item); - break; - - default: - trap_Error( va("Menu_Init: unknown type %d", itemptr->type) ); - } - } - - menu->nitems++; -} - -/* -================= -Menu_CursorMoved -================= -*/ -void Menu_CursorMoved( menuframework_s *m ) -{ - void (*callback)( void *self, int notification ); - - if (m->cursor_prev == m->cursor) - return; - - if (m->cursor_prev >= 0 && m->cursor_prev < m->nitems) - { - callback = ((menucommon_s*)(m->items[m->cursor_prev]))->callback; - if (callback) - callback(m->items[m->cursor_prev],QM_LOSTFOCUS); - } - - if (m->cursor >= 0 && m->cursor < m->nitems) - { - callback = ((menucommon_s*)(m->items[m->cursor]))->callback; - if (callback) - callback(m->items[m->cursor],QM_GOTFOCUS); - } -} - -/* -================= -Menu_SetCursor -================= -*/ -void Menu_SetCursor( menuframework_s *m, int cursor ) -{ - if (((menucommon_s*)(m->items[cursor]))->flags & (QMF_GRAYED|QMF_INACTIVE)) - { - // cursor can't go there - return; - } - - m->cursor_prev = m->cursor; - m->cursor = cursor; - - Menu_CursorMoved( m ); -} - -/* -================= -Menu_SetCursorToItem -================= -*/ -void Menu_SetCursorToItem( menuframework_s *m, void* ptr ) -{ - int i; - - for (i=0; initems; i++) - { - if (m->items[i] == ptr) - { - Menu_SetCursor( m, i ); - return; - } - } -} - -/* -** Menu_AdjustCursor -** -** This function takes the given menu, the direction, and attempts -** to adjust the menu's cursor so that it's at the next available -** slot. -*/ -void Menu_AdjustCursor( menuframework_s *m, int dir ) { - menucommon_s *item = NULL; - qboolean wrapped = qfalse; - -wrap: - while ( m->cursor >= 0 && m->cursor < m->nitems ) { - item = ( menucommon_s * ) m->items[m->cursor]; - if (( item->flags & (QMF_GRAYED|QMF_MOUSEONLY|QMF_INACTIVE) ) ) { - m->cursor += dir; - } - else { - break; - } - } - - if ( dir == 1 ) { - if ( m->cursor >= m->nitems ) { - if ( m->wrapAround ) { - if ( wrapped ) { - m->cursor = m->cursor_prev; - return; - } - m->cursor = 0; - wrapped = qtrue; - goto wrap; - } - m->cursor = m->cursor_prev; - } - } - else { - if ( m->cursor < 0 ) { - if ( m->wrapAround ) { - if ( wrapped ) { - m->cursor = m->cursor_prev; - return; - } - m->cursor = m->nitems - 1; - wrapped = qtrue; - goto wrap; - } - m->cursor = m->cursor_prev; - } - } -} - -/* -================= -Menu_Draw -================= -*/ -void Menu_Draw( menuframework_s *menu ) -{ - int i; - menucommon_s *itemptr; - - // draw menu - for (i=0; initems; i++) - { - itemptr = (menucommon_s*)menu->items[i]; - - if (itemptr->flags & QMF_HIDDEN) - continue; - - if (itemptr->ownerdraw) - { - // total subclassing, owner draws everything - itemptr->ownerdraw( itemptr ); - } - else - { - switch (itemptr->type) - { - case MTYPE_RADIOBUTTON: - RadioButton_Draw( (menuradiobutton_s*)itemptr ); - break; - - case MTYPE_FIELD: - MenuField_Draw( (menufield_s*)itemptr ); - break; - - case MTYPE_SLIDER: - Slider_Draw( (menuslider_s*)itemptr ); - break; - - case MTYPE_SPINCONTROL: - SpinControl_Draw( (menulist_s*)itemptr ); - break; - - case MTYPE_ACTION: - Action_Draw( (menuaction_s*)itemptr ); - break; - - case MTYPE_BITMAP: - Bitmap_Draw( (menubitmap_s*)itemptr ); - break; - - case MTYPE_TEXT: - Text_Draw( (menutext_s*)itemptr ); - break; - - case MTYPE_SCROLLLIST: - ScrollList_Draw( (menulist_s*)itemptr ); - break; - - case MTYPE_PTEXT: - PText_Draw( (menutext_s*)itemptr ); - break; - - case MTYPE_BTEXT: - BText_Draw( (menutext_s*)itemptr ); - break; - - default: - trap_Error( va("Menu_Draw: unknown type %d", itemptr->type) ); - } - } -#ifndef NDEBUG - if( uis.debug ) { - int x; - int y; - int w; - int h; - - if( !( itemptr->flags & QMF_INACTIVE ) ) { - x = itemptr->left; - y = itemptr->top; - w = itemptr->right - itemptr->left + 1; - h = itemptr->bottom - itemptr->top + 1; - - if (itemptr->flags & QMF_HASMOUSEFOCUS) { - UI_DrawRect(x, y, w, h, colorYellow ); - } - else { - UI_DrawRect(x, y, w, h, colorWhite ); - } - } - } -#endif - } - - itemptr = Menu_ItemAtCursor( menu ); - if ( itemptr && itemptr->statusbar) - itemptr->statusbar( ( void * ) itemptr ); -} - -/* -================= -Menu_ItemAtCursor -================= -*/ -void *Menu_ItemAtCursor( menuframework_s *m ) -{ - if ( m->cursor < 0 || m->cursor >= m->nitems ) - return 0; - - return m->items[m->cursor]; -} - -/* -================= -Menu_ActivateItem -================= -*/ -sfxHandle_t Menu_ActivateItem( menuframework_s *s, menucommon_s* item ) { - if ( item->callback ) { - item->callback( item, QM_ACTIVATED ); - if( !( item->flags & QMF_SILENT ) ) { - return menu_move_sound; - } - } - - return 0; -} - -/* -================= -Menu_DefaultKey -================= -*/ -sfxHandle_t Menu_DefaultKey( menuframework_s *m, int key ) -{ - sfxHandle_t sound = 0; - menucommon_s *item; - int cursor_prev; - - // menu system keys - switch ( key ) - { - case K_MOUSE2: - case K_ESCAPE: - UI_PopMenu(); - return menu_out_sound; - } - - if (!m || !m->nitems) - return 0; - - // route key stimulus to widget - item = Menu_ItemAtCursor( m ); - if (item && !(item->flags & (QMF_GRAYED|QMF_INACTIVE))) - { - switch (item->type) - { - case MTYPE_SPINCONTROL: - sound = SpinControl_Key( (menulist_s*)item, key ); - break; - - case MTYPE_RADIOBUTTON: - sound = RadioButton_Key( (menuradiobutton_s*)item, key ); - break; - - case MTYPE_SLIDER: - sound = Slider_Key( (menuslider_s*)item, key ); - break; - - case MTYPE_SCROLLLIST: - sound = ScrollList_Key( (menulist_s*)item, key ); - break; - - case MTYPE_FIELD: - sound = MenuField_Key( (menufield_s*)item, &key ); - break; - } - - if (sound) { - // key was handled - return sound; - } - } - - // default handling - switch ( key ) - { -#ifndef NDEBUG - case K_F11: - uis.debug ^= 1; - break; - - case K_F12: - trap_Cmd_ExecuteText(EXEC_APPEND, "screenshot\n"); - break; -#endif - case K_KP_UPARROW: - case K_UPARROW: - cursor_prev = m->cursor; - m->cursor_prev = m->cursor; - m->cursor--; - Menu_AdjustCursor( m, -1 ); - if ( cursor_prev != m->cursor ) { - Menu_CursorMoved( m ); - sound = menu_move_sound; - } - break; - - case K_TAB: - case K_KP_DOWNARROW: - case K_DOWNARROW: - cursor_prev = m->cursor; - m->cursor_prev = m->cursor; - m->cursor++; - Menu_AdjustCursor( m, 1 ); - if ( cursor_prev != m->cursor ) { - Menu_CursorMoved( m ); - sound = menu_move_sound; - } - break; - - case K_MOUSE1: - case K_MOUSE3: - if (item) - if ((item->flags & QMF_HASMOUSEFOCUS) && !(item->flags & (QMF_GRAYED|QMF_INACTIVE))) - return (Menu_ActivateItem( m, item )); - break; - - case K_JOY1: - case K_JOY2: - case K_JOY3: - case K_JOY4: - case K_AUX1: - case K_AUX2: - case K_AUX3: - case K_AUX4: - case K_AUX5: - case K_AUX6: - case K_AUX7: - case K_AUX8: - case K_AUX9: - case K_AUX10: - case K_AUX11: - case K_AUX12: - case K_AUX13: - case K_AUX14: - case K_AUX15: - case K_AUX16: - case K_KP_ENTER: - case K_ENTER: - if (item) - if (!(item->flags & (QMF_MOUSEONLY|QMF_GRAYED|QMF_INACTIVE))) - return (Menu_ActivateItem( m, item )); - break; - } - - return sound; -} - -/* -================= -Menu_Cache -================= -*/ -void Menu_Cache( void ) -{ - uis.charset = trap_R_RegisterShaderNoMip( "gfx/2d/bigchars" ); - uis.charsetProp = trap_R_RegisterShaderNoMip( "menu/art/font1_prop.tga" ); - uis.charsetPropGlow = trap_R_RegisterShaderNoMip( "menu/art/font1_prop_glo.tga" ); - uis.charsetPropB = trap_R_RegisterShaderNoMip( "menu/art/font2_prop.tga" ); - uis.cursor = trap_R_RegisterShaderNoMip( "menu/art/3_cursor2" ); - uis.rb_on = trap_R_RegisterShaderNoMip( "menu/art/switch_on" ); - uis.rb_off = trap_R_RegisterShaderNoMip( "menu/art/switch_off" ); - - uis.whiteShader = trap_R_RegisterShaderNoMip( "white" ); - if ( uis.glconfig.hardwareType == GLHW_RAGEPRO ) { - // the blend effect turns to shit with the normal - uis.menuBackShader = trap_R_RegisterShaderNoMip( "menubackRagePro" ); - } else { - uis.menuBackShader = trap_R_RegisterShaderNoMip( "menuback" ); - } - uis.menuBackNoLogoShader = trap_R_RegisterShaderNoMip( "menubacknologo" ); - - menu_in_sound = trap_S_RegisterSound( "sound/misc/menu1.wav", qfalse ); - menu_move_sound = trap_S_RegisterSound( "sound/misc/menu2.wav", qfalse ); - menu_out_sound = trap_S_RegisterSound( "sound/misc/menu3.wav", qfalse ); - menu_buzz_sound = trap_S_RegisterSound( "sound/misc/menu4.wav", qfalse ); - weaponChangeSound = trap_S_RegisterSound( "sound/weapons/change.wav", qfalse ); - - // need a nonzero sound, make an empty sound for this - menu_null_sound = -1; - - sliderBar = trap_R_RegisterShaderNoMip( "menu/art/slider2" ); - sliderButton_0 = trap_R_RegisterShaderNoMip( "menu/art/sliderbutt_0" ); - sliderButton_1 = trap_R_RegisterShaderNoMip( "menu/art/sliderbutt_1" ); -} - +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +// +/********************************************************************** + UI_QMENU.C + + Quake's menu framework system. +**********************************************************************/ +#include "ui_local.h" + +sfxHandle_t menu_in_sound; +sfxHandle_t menu_move_sound; +sfxHandle_t menu_out_sound; +sfxHandle_t menu_buzz_sound; +sfxHandle_t menu_null_sound; +sfxHandle_t weaponChangeSound; + +static qhandle_t sliderBar; +static qhandle_t sliderButton_0; +static qhandle_t sliderButton_1; + +vec4_t menu_text_color = {1.0f, 1.0f, 1.0f, 1.0f}; +vec4_t menu_dim_color = {0.0f, 0.0f, 0.0f, 0.75f}; +vec4_t color_black = {0.00f, 0.00f, 0.00f, 1.00f}; +vec4_t color_white = {1.00f, 1.00f, 1.00f, 1.00f}; +vec4_t color_yellow = {1.00f, 1.00f, 0.00f, 1.00f}; +vec4_t color_blue = {0.00f, 0.00f, 1.00f, 1.00f}; +vec4_t color_lightOrange = {1.00f, 0.68f, 0.00f, 1.00f }; +vec4_t color_orange = {1.00f, 0.43f, 0.00f, 1.00f}; +vec4_t color_red = {1.00f, 0.00f, 0.00f, 1.00f}; +vec4_t color_dim = {0.00f, 0.00f, 0.00f, 0.25f}; + +// current color scheme +vec4_t pulse_color = {1.00f, 1.00f, 1.00f, 1.00f}; +vec4_t text_color_disabled = {0.50f, 0.50f, 0.50f, 1.00f}; // light gray +vec4_t text_color_normal = {1.00f, 0.43f, 0.00f, 1.00f}; // light orange +vec4_t text_color_highlight = {1.00f, 1.00f, 0.00f, 1.00f}; // bright yellow +vec4_t listbar_color = {1.00f, 0.43f, 0.00f, 0.30f}; // transluscent orange +vec4_t text_color_status = {1.00f, 1.00f, 1.00f, 1.00f}; // bright white + +// action widget +static void Action_Init( menuaction_s *a ); +static void Action_Draw( menuaction_s *a ); + +// radio button widget +static void RadioButton_Init( menuradiobutton_s *rb ); +static void RadioButton_Draw( menuradiobutton_s *rb ); +static sfxHandle_t RadioButton_Key( menuradiobutton_s *rb, int key ); + +// slider widget +static void Slider_Init( menuslider_s *s ); +static sfxHandle_t Slider_Key( menuslider_s *s, int key ); +static void Slider_Draw( menuslider_s *s ); + +// spin control widget +static void SpinControl_Init( menulist_s *s ); +static void SpinControl_Draw( menulist_s *s ); +static sfxHandle_t SpinControl_Key( menulist_s *l, int key ); + +// text widget +static void Text_Init( menutext_s *b ); +static void Text_Draw( menutext_s *b ); + +// scrolllist widget +static void ScrollList_Init( menulist_s *l ); +sfxHandle_t ScrollList_Key( menulist_s *l, int key ); + +// proportional text widget +static void PText_Init( menutext_s *b ); +static void PText_Draw( menutext_s *b ); + +// proportional banner text widget +static void BText_Init( menutext_s *b ); +static void BText_Draw( menutext_s *b ); + +/* +================= +Text_Init +================= +*/ +static void Text_Init( menutext_s *t ) +{ + t->generic.flags |= QMF_INACTIVE; +} + +/* +================= +Text_Draw +================= +*/ +static void Text_Draw( menutext_s *t ) +{ + int x; + int y; + char buff[512]; + float* color; + + x = t->generic.x; + y = t->generic.y; + + buff[0] = '\0'; + + // possible label + if (t->generic.name) + strcpy(buff,t->generic.name); + + // possible value + if (t->string) + strcat(buff,t->string); + + if (t->generic.flags & QMF_GRAYED) + color = text_color_disabled; + else + color = t->color; + + UI_DrawString( x, y, buff, t->style, color ); +} + +/* +================= +BText_Init +================= +*/ +static void BText_Init( menutext_s *t ) +{ + t->generic.flags |= QMF_INACTIVE; +} + +/* +================= +BText_Draw +================= +*/ +static void BText_Draw( menutext_s *t ) +{ + int x; + int y; + float* color; + + x = t->generic.x; + y = t->generic.y; + + if (t->generic.flags & QMF_GRAYED) + color = text_color_disabled; + else + color = t->color; + + UI_DrawBannerString( x, y, t->string, t->style, color ); +} + +/* +================= +PText_Init +================= +*/ +static void PText_Init( menutext_s *t ) +{ + int x; + int y; + int w; + int h; + float sizeScale; + + sizeScale = UI_ProportionalSizeScale( t->style ); + + x = t->generic.x; + y = t->generic.y; + w = UI_ProportionalStringWidth( t->string ) * sizeScale; + h = PROP_HEIGHT * sizeScale; + + if( t->generic.flags & QMF_RIGHT_JUSTIFY ) { + x -= w; + } + else if( t->generic.flags & QMF_CENTER_JUSTIFY ) { + x -= w / 2; + } + + t->generic.left = x - PROP_GAP_WIDTH * sizeScale; + t->generic.right = x + w + PROP_GAP_WIDTH * sizeScale; + t->generic.top = y; + t->generic.bottom = y + h; +} + +/* +================= +PText_Draw +================= +*/ +static void PText_Draw( menutext_s *t ) +{ + int x; + int y; + float * color; + int style; + + x = t->generic.x; + y = t->generic.y; + + if (t->generic.flags & QMF_GRAYED) + color = text_color_disabled; + else + color = t->color; + + style = t->style; + if( t->generic.flags & QMF_PULSEIFFOCUS ) { + if( Menu_ItemAtCursor( t->generic.parent ) == t ) { + style |= UI_PULSE; + } + else { + style |= UI_INVERSE; + } + } + + UI_DrawProportionalString( x, y, t->string, style, color ); +} + +/* +================= +Bitmap_Init +================= +*/ +void Bitmap_Init( menubitmap_s *b ) +{ + int x; + int y; + int w; + int h; + + x = b->generic.x; + y = b->generic.y; + w = b->width; + h = b->height; + if( w < 0 ) { + w = -w; + } + if( h < 0 ) { + h = -h; + } + + if (b->generic.flags & QMF_RIGHT_JUSTIFY) + { + x = x - w; + } + else if (b->generic.flags & QMF_CENTER_JUSTIFY) + { + x = x - w/2; + } + + b->generic.left = x; + b->generic.right = x + w; + b->generic.top = y; + b->generic.bottom = y + h; + + b->shader = 0; + b->focusshader = 0; +} + +/* +================= +Bitmap_Draw +================= +*/ +void Bitmap_Draw( menubitmap_s *b ) +{ + float x; + float y; + float w; + float h; + vec4_t tempcolor; + float* color; + + x = b->generic.x; + y = b->generic.y; + w = b->width; + h = b->height; + + if (b->generic.flags & QMF_RIGHT_JUSTIFY) + { + x = x - w; + } + else if (b->generic.flags & QMF_CENTER_JUSTIFY) + { + x = x - w/2; + } + + // used to refresh shader + if (b->generic.name && !b->shader) + { + b->shader = trap_R_RegisterShaderNoMip( b->generic.name ); + if (!b->shader && b->errorpic) + b->shader = trap_R_RegisterShaderNoMip( b->errorpic ); + } + + if (b->focuspic && !b->focusshader) + b->focusshader = trap_R_RegisterShaderNoMip( b->focuspic ); + + if (b->generic.flags & QMF_GRAYED) + { + if (b->shader) + { + trap_R_SetColor( colorMdGrey ); + UI_DrawHandlePic( x, y, w, h, b->shader ); + trap_R_SetColor( NULL ); + } + } + else + { + if (b->shader) + UI_DrawHandlePic( x, y, w, h, b->shader ); + + // bk001204 - parentheses + if ( ( (b->generic.flags & QMF_PULSE) + || (b->generic.flags & QMF_PULSEIFFOCUS) ) + && (Menu_ItemAtCursor( b->generic.parent ) == b)) + { + if (b->focuscolor) + { + tempcolor[0] = b->focuscolor[0]; + tempcolor[1] = b->focuscolor[1]; + tempcolor[2] = b->focuscolor[2]; + color = tempcolor; + } + else + color = pulse_color; + color[3] = 0.5+0.5*sin(uis.realtime/PULSE_DIVISOR); + + trap_R_SetColor( color ); + UI_DrawHandlePic( x, y, w, h, b->focusshader ); + trap_R_SetColor( NULL ); + } + else if ((b->generic.flags & QMF_HIGHLIGHT) || ((b->generic.flags & QMF_HIGHLIGHT_IF_FOCUS) && (Menu_ItemAtCursor( b->generic.parent ) == b))) + { + if (b->focuscolor) + { + trap_R_SetColor( b->focuscolor ); + UI_DrawHandlePic( x, y, w, h, b->focusshader ); + trap_R_SetColor( NULL ); + } + else + UI_DrawHandlePic( x, y, w, h, b->focusshader ); + } + } +} + +/* +================= +Action_Init +================= +*/ +static void Action_Init( menuaction_s *a ) +{ + int len; + + // calculate bounds + if (a->generic.name) + len = strlen(a->generic.name); + else + len = 0; + + // left justify text + a->generic.left = a->generic.x; + a->generic.right = a->generic.x + len*BIGCHAR_WIDTH; + a->generic.top = a->generic.y; + a->generic.bottom = a->generic.y + BIGCHAR_HEIGHT; +} + +/* +================= +Action_Draw +================= +*/ +static void Action_Draw( menuaction_s *a ) +{ + int x, y; + int style; + float* color; + + style = 0; + color = menu_text_color; + if ( a->generic.flags & QMF_GRAYED ) + { + color = text_color_disabled; + } + else if (( a->generic.flags & QMF_PULSEIFFOCUS ) && ( a->generic.parent->cursor == a->generic.menuPosition )) + { + color = text_color_highlight; + style = UI_PULSE; + } + else if (( a->generic.flags & QMF_HIGHLIGHT_IF_FOCUS ) && ( a->generic.parent->cursor == a->generic.menuPosition )) + { + color = text_color_highlight; + } + else if ( a->generic.flags & QMF_BLINK ) + { + style = UI_BLINK; + color = text_color_highlight; + } + + x = a->generic.x; + y = a->generic.y; + + UI_DrawString( x, y, a->generic.name, UI_LEFT|style, color ); + + if ( a->generic.parent->cursor == a->generic.menuPosition ) + { + // draw cursor + UI_DrawChar( x - BIGCHAR_WIDTH, y, 13, UI_LEFT|UI_BLINK, color); + } +} + +/* +================= +RadioButton_Init +================= +*/ +static void RadioButton_Init( menuradiobutton_s *rb ) +{ + int len; + + // calculate bounds + if (rb->generic.name) + len = strlen(rb->generic.name); + else + len = 0; + + rb->generic.left = rb->generic.x - (len+1)*SMALLCHAR_WIDTH; + rb->generic.right = rb->generic.x + 6*SMALLCHAR_WIDTH; + rb->generic.top = rb->generic.y; + rb->generic.bottom = rb->generic.y + SMALLCHAR_HEIGHT; +} + +/* +================= +RadioButton_Key +================= +*/ +static sfxHandle_t RadioButton_Key( menuradiobutton_s *rb, int key ) +{ + switch (key) + { + case K_MOUSE1: + if (!(rb->generic.flags & QMF_HASMOUSEFOCUS)) + break; + + case K_JOY1: + case K_JOY2: + case K_JOY3: + case K_JOY4: + case K_ENTER: + case K_KP_ENTER: + case K_KP_LEFTARROW: + case K_LEFTARROW: + case K_KP_RIGHTARROW: + case K_RIGHTARROW: + rb->curvalue = !rb->curvalue; + if ( rb->generic.callback ) + rb->generic.callback( rb, QM_ACTIVATED ); + + return (menu_move_sound); + } + + // key not handled + return 0; +} + +/* +================= +RadioButton_Draw +================= +*/ +static void RadioButton_Draw( menuradiobutton_s *rb ) +{ + int x; + int y; + float *color; + int style; + qboolean focus; + + x = rb->generic.x; + y = rb->generic.y; + + focus = (rb->generic.parent->cursor == rb->generic.menuPosition); + + if ( rb->generic.flags & QMF_GRAYED ) + { + color = text_color_disabled; + style = UI_LEFT|UI_SMALLFONT; + } + else if ( focus ) + { + color = text_color_highlight; + style = UI_LEFT|UI_PULSE|UI_SMALLFONT; + } + else + { + color = text_color_normal; + style = UI_LEFT|UI_SMALLFONT; + } + + if ( focus ) + { + // draw cursor + UI_FillRect( rb->generic.left, rb->generic.top, rb->generic.right-rb->generic.left+1, rb->generic.bottom-rb->generic.top+1, listbar_color ); + UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color); + } + + if ( rb->generic.name ) + UI_DrawString( x - SMALLCHAR_WIDTH, y, rb->generic.name, UI_RIGHT|UI_SMALLFONT, color ); + + if ( !rb->curvalue ) + { + UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y + 2, 16, 16, uis.rb_off); + UI_DrawString( x + SMALLCHAR_WIDTH + 16, y, "off", style, color ); + } + else + { + UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y + 2, 16, 16, uis.rb_on ); + UI_DrawString( x + SMALLCHAR_WIDTH + 16, y, "on", style, color ); + } +} + +/* +================= +Slider_Init +================= +*/ +static void Slider_Init( menuslider_s *s ) +{ + int len; + + // calculate bounds + if (s->generic.name) + len = strlen(s->generic.name); + else + len = 0; + + s->generic.left = s->generic.x - (len+1)*SMALLCHAR_WIDTH; + s->generic.right = s->generic.x + (SLIDER_RANGE+2+1)*SMALLCHAR_WIDTH; + s->generic.top = s->generic.y; + s->generic.bottom = s->generic.y + SMALLCHAR_HEIGHT; +} + +/* +================= +Slider_Key +================= +*/ +static sfxHandle_t Slider_Key( menuslider_s *s, int key ) +{ + sfxHandle_t sound; + int x; + int oldvalue; + + switch (key) + { + case K_MOUSE1: + x = uis.cursorx - s->generic.x - 2*SMALLCHAR_WIDTH; + oldvalue = s->curvalue; + s->curvalue = (x/(float)(SLIDER_RANGE*SMALLCHAR_WIDTH)) * (s->maxvalue-s->minvalue) + s->minvalue; + + if (s->curvalue < s->minvalue) + s->curvalue = s->minvalue; + else if (s->curvalue > s->maxvalue) + s->curvalue = s->maxvalue; + if (s->curvalue != oldvalue) + sound = menu_move_sound; + else + sound = 0; + break; + + case K_KP_LEFTARROW: + case K_LEFTARROW: + if (s->curvalue > s->minvalue) + { + s->curvalue--; + sound = menu_move_sound; + } + else + sound = menu_buzz_sound; + break; + + case K_KP_RIGHTARROW: + case K_RIGHTARROW: + if (s->curvalue < s->maxvalue) + { + s->curvalue++; + sound = menu_move_sound; + } + else + sound = menu_buzz_sound; + break; + + default: + // key not handled + sound = 0; + break; + } + + if ( sound && s->generic.callback ) + s->generic.callback( s, QM_ACTIVATED ); + + return (sound); +} + +#if 1 +/* +================= +Slider_Draw +================= +*/ +static void Slider_Draw( menuslider_s *s ) { + int x; + int y; + int style; + float *color; + int button; + qboolean focus; + + x = s->generic.x; + y = s->generic.y; + focus = (s->generic.parent->cursor == s->generic.menuPosition); + + if( s->generic.flags & QMF_GRAYED ) { + color = text_color_disabled; + style = UI_SMALLFONT; + } + else if( focus ) { + color = text_color_highlight; + style = UI_SMALLFONT | UI_PULSE; + } + else { + color = text_color_normal; + style = UI_SMALLFONT; + } + + // draw label + UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, UI_RIGHT|style, color ); + + // draw slider + UI_SetColor( color ); + UI_DrawHandlePic( x + SMALLCHAR_WIDTH, y, 96, 16, sliderBar ); + UI_SetColor( NULL ); + + // clamp thumb + if( s->maxvalue > s->minvalue ) { + s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue ); + if( s->range < 0 ) { + s->range = 0; + } + else if( s->range > 1) { + s->range = 1; + } + } + else { + s->range = 0; + } + + // draw thumb + if( style & UI_PULSE) { + button = sliderButton_1; + } + else { + button = sliderButton_0; + } + + UI_DrawHandlePic( (int)( x + 2*SMALLCHAR_WIDTH + (SLIDER_RANGE-1)*SMALLCHAR_WIDTH* s->range ) - 2, y - 2, 12, 20, button ); +} +#else +/* +================= +Slider_Draw +================= +*/ +static void Slider_Draw( menuslider_s *s ) +{ + float *color; + int style; + int i; + int x; + int y; + qboolean focus; + + x = s->generic.x; + y = s->generic.y; + focus = (s->generic.parent->cursor == s->generic.menuPosition); + + style = UI_SMALLFONT; + if ( s->generic.flags & QMF_GRAYED ) + { + color = text_color_disabled; + } + else if (focus) + { + color = text_color_highlight; + style |= UI_PULSE; + } + else + { + color = text_color_normal; + } + + if ( focus ) + { + // draw cursor + UI_FillRect( s->generic.left, s->generic.top, s->generic.right-s->generic.left+1, s->generic.bottom-s->generic.top+1, listbar_color ); + UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color); + } + + // draw label + UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, UI_RIGHT|style, color ); + + // draw slider + UI_DrawChar( x + SMALLCHAR_WIDTH, y, 128, UI_LEFT|style, color); + for ( i = 0; i < SLIDER_RANGE; i++ ) + UI_DrawChar( x + (i+2)*SMALLCHAR_WIDTH, y, 129, UI_LEFT|style, color); + UI_DrawChar( x + (i+2)*SMALLCHAR_WIDTH, y, 130, UI_LEFT|style, color); + + // clamp thumb + if (s->maxvalue > s->minvalue) + { + s->range = ( s->curvalue - s->minvalue ) / ( float ) ( s->maxvalue - s->minvalue ); + if ( s->range < 0) + s->range = 0; + else if ( s->range > 1) + s->range = 1; + } + else + s->range = 0; + + // draw thumb + if (style & UI_PULSE) { + style &= ~UI_PULSE; + style |= UI_BLINK; + } + UI_DrawChar( (int)( x + 2*SMALLCHAR_WIDTH + (SLIDER_RANGE-1)*SMALLCHAR_WIDTH* s->range ), y, 131, UI_LEFT|style, color); +} +#endif + +/* +================= +SpinControl_Init +================= +*/ +static void SpinControl_Init( menulist_s *s ) { + int len; + int l; + const char* str; + + if (s->generic.name) + len = strlen(s->generic.name) * SMALLCHAR_WIDTH; + else + len = 0; + + s->generic.left = s->generic.x - SMALLCHAR_WIDTH - len; + + len = s->numitems = 0; + while ( (str = s->itemnames[s->numitems]) != 0 ) + { + l = strlen(str); + if (l > len) + len = l; + + s->numitems++; + } + + s->generic.top = s->generic.y; + s->generic.right = s->generic.x + (len+1)*SMALLCHAR_WIDTH; + s->generic.bottom = s->generic.y + SMALLCHAR_HEIGHT; +} + +/* +================= +SpinControl_Key +================= +*/ +static sfxHandle_t SpinControl_Key( menulist_s *s, int key ) +{ + sfxHandle_t sound; + + sound = 0; + switch (key) + { + case K_MOUSE1: + s->curvalue++; + if (s->curvalue >= s->numitems) + s->curvalue = 0; + sound = menu_move_sound; + break; + + case K_KP_LEFTARROW: + case K_LEFTARROW: + if (s->curvalue > 0) + { + s->curvalue--; + sound = menu_move_sound; + } + else + sound = menu_buzz_sound; + break; + + case K_KP_RIGHTARROW: + case K_RIGHTARROW: + if (s->curvalue < s->numitems-1) + { + s->curvalue++; + sound = menu_move_sound; + } + else + sound = menu_buzz_sound; + break; + } + + if ( sound && s->generic.callback ) + s->generic.callback( s, QM_ACTIVATED ); + + return (sound); +} + +/* +================= +SpinControl_Draw +================= +*/ +static void SpinControl_Draw( menulist_s *s ) +{ + float *color; + int x,y; + int style; + qboolean focus; + + x = s->generic.x; + y = s->generic.y; + + style = UI_SMALLFONT; + focus = (s->generic.parent->cursor == s->generic.menuPosition); + + if ( s->generic.flags & QMF_GRAYED ) + color = text_color_disabled; + else if ( focus ) + { + color = text_color_highlight; + style |= UI_PULSE; + } + else if ( s->generic.flags & QMF_BLINK ) + { + color = text_color_highlight; + style |= UI_BLINK; + } + else + color = text_color_normal; + + if ( focus ) + { + // draw cursor + UI_FillRect( s->generic.left, s->generic.top, s->generic.right-s->generic.left+1, s->generic.bottom-s->generic.top+1, listbar_color ); + UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, color); + } + + UI_DrawString( x - SMALLCHAR_WIDTH, y, s->generic.name, style|UI_RIGHT, color ); + UI_DrawString( x + SMALLCHAR_WIDTH, y, s->itemnames[s->curvalue], style|UI_LEFT, color ); +} + +/* +================= +ScrollList_Init +================= +*/ +static void ScrollList_Init( menulist_s *l ) +{ + int w; + + l->oldvalue = 0; + l->curvalue = 0; + l->top = 0; + + if( !l->columns ) { + l->columns = 1; + l->seperation = 0; + } + else if( !l->seperation ) { + l->seperation = 3; + } + + w = ( (l->width + l->seperation) * l->columns - l->seperation) * SMALLCHAR_WIDTH; + + l->generic.left = l->generic.x; + l->generic.top = l->generic.y; + l->generic.right = l->generic.x + w; + l->generic.bottom = l->generic.y + l->height * SMALLCHAR_HEIGHT; + + if( l->generic.flags & QMF_CENTER_JUSTIFY ) { + l->generic.left -= w / 2; + l->generic.right -= w / 2; + } +} + +/* +================= +ScrollList_Key +================= +*/ +sfxHandle_t ScrollList_Key( menulist_s *l, int key ) +{ + int x; + int y; + int w; + int i; + int j; + int c; + int cursorx; + int cursory; + int column; + int index; + + switch (key) + { + case K_MOUSE1: + if (l->generic.flags & QMF_HASMOUSEFOCUS) + { + // check scroll region + x = l->generic.x; + y = l->generic.y; + w = ( (l->width + l->seperation) * l->columns - l->seperation) * SMALLCHAR_WIDTH; + if( l->generic.flags & QMF_CENTER_JUSTIFY ) { + x -= w / 2; + } + if (UI_CursorInRect( x, y, w, l->height*SMALLCHAR_HEIGHT )) + { + cursorx = (uis.cursorx - x)/SMALLCHAR_WIDTH; + column = cursorx / (l->width + l->seperation); + cursory = (uis.cursory - y)/SMALLCHAR_HEIGHT; + index = column * l->height + cursory; + if (l->top + index < l->numitems) + { + l->oldvalue = l->curvalue; + l->curvalue = l->top + index; + + if (l->oldvalue != l->curvalue && l->generic.callback) + { + l->generic.callback( l, QM_GOTFOCUS ); + return (menu_move_sound); + } + } + } + + // absorbed, silent sound effect + return (menu_null_sound); + } + break; + + case K_KP_HOME: + case K_HOME: + l->oldvalue = l->curvalue; + l->curvalue = 0; + l->top = 0; + + if (l->oldvalue != l->curvalue && l->generic.callback) + { + l->generic.callback( l, QM_GOTFOCUS ); + return (menu_move_sound); + } + return (menu_buzz_sound); + + case K_KP_END: + case K_END: + l->oldvalue = l->curvalue; + l->curvalue = l->numitems-1; + if( l->columns > 1 ) { + c = (l->curvalue / l->height + 1) * l->height; + l->top = c - (l->columns * l->height); + } + else { + l->top = l->curvalue - (l->height - 1); + } + if (l->top < 0) + l->top = 0; + + if (l->oldvalue != l->curvalue && l->generic.callback) + { + l->generic.callback( l, QM_GOTFOCUS ); + return (menu_move_sound); + } + return (menu_buzz_sound); + + case K_PGUP: + case K_KP_PGUP: + if( l->columns > 1 ) { + return menu_null_sound; + } + + if (l->curvalue > 0) + { + l->oldvalue = l->curvalue; + l->curvalue -= l->height-1; + if (l->curvalue < 0) + l->curvalue = 0; + l->top = l->curvalue; + if (l->top < 0) + l->top = 0; + + if (l->generic.callback) + l->generic.callback( l, QM_GOTFOCUS ); + + return (menu_move_sound); + } + return (menu_buzz_sound); + + case K_PGDN: + case K_KP_PGDN: + if( l->columns > 1 ) { + return menu_null_sound; + } + + if (l->curvalue < l->numitems-1) + { + l->oldvalue = l->curvalue; + l->curvalue += l->height-1; + if (l->curvalue > l->numitems-1) + l->curvalue = l->numitems-1; + l->top = l->curvalue - (l->height-1); + if (l->top < 0) + l->top = 0; + + if (l->generic.callback) + l->generic.callback( l, QM_GOTFOCUS ); + + return (menu_move_sound); + } + return (menu_buzz_sound); + + case K_KP_UPARROW: + case K_UPARROW: + if( l->curvalue == 0 ) { + return menu_buzz_sound; + } + + l->oldvalue = l->curvalue; + l->curvalue--; + + if( l->curvalue < l->top ) { + if( l->columns == 1 ) { + l->top--; + } + else { + l->top -= l->height; + } + } + + if( l->generic.callback ) { + l->generic.callback( l, QM_GOTFOCUS ); + } + + return (menu_move_sound); + + case K_KP_DOWNARROW: + case K_DOWNARROW: + if( l->curvalue == l->numitems - 1 ) { + return menu_buzz_sound; + } + + l->oldvalue = l->curvalue; + l->curvalue++; + + if( l->curvalue >= l->top + l->columns * l->height ) { + if( l->columns == 1 ) { + l->top++; + } + else { + l->top += l->height; + } + } + + if( l->generic.callback ) { + l->generic.callback( l, QM_GOTFOCUS ); + } + + return menu_move_sound; + + case K_KP_LEFTARROW: + case K_LEFTARROW: + if( l->columns == 1 ) { + return menu_null_sound; + } + + if( l->curvalue < l->height ) { + return menu_buzz_sound; + } + + l->oldvalue = l->curvalue; + l->curvalue -= l->height; + + if( l->curvalue < l->top ) { + l->top -= l->height; + } + + if( l->generic.callback ) { + l->generic.callback( l, QM_GOTFOCUS ); + } + + return menu_move_sound; + + case K_KP_RIGHTARROW: + case K_RIGHTARROW: + if( l->columns == 1 ) { + return menu_null_sound; + } + + c = l->curvalue + l->height; + + if( c >= l->numitems ) { + return menu_buzz_sound; + } + + l->oldvalue = l->curvalue; + l->curvalue = c; + + if( l->curvalue > l->top + l->columns * l->height - 1 ) { + l->top += l->height; + } + + if( l->generic.callback ) { + l->generic.callback( l, QM_GOTFOCUS ); + } + + return menu_move_sound; + } + + // cycle look for ascii key inside list items + if ( !Q_isprint( key ) ) + return (0); + + // force to lower for case insensitive compare + if ( Q_isupper( key ) ) + { + key -= 'A' - 'a'; + } + + // iterate list items + for (i=1; i<=l->numitems; i++) + { + j = (l->curvalue + i) % l->numitems; + c = l->itemnames[j][0]; + if ( Q_isupper( c ) ) + { + c -= 'A' - 'a'; + } + + if (c == key) + { + // set current item, mimic windows listbox scroll behavior + if (j < l->top) + { + // behind top most item, set this as new top + l->top = j; + } + else if (j > l->top+l->height-1) + { + // past end of list box, do page down + l->top = (j+1) - l->height; + } + + if (l->curvalue != j) + { + l->oldvalue = l->curvalue; + l->curvalue = j; + if (l->generic.callback) + l->generic.callback( l, QM_GOTFOCUS ); + return ( menu_move_sound ); + } + + return (menu_buzz_sound); + } + } + + return (menu_buzz_sound); +} + +/* +================= +ScrollList_Draw +================= +*/ +void ScrollList_Draw( menulist_s *l ) +{ + int x; + int u; + int y; + int i; + int base; + int column; + float* color; + qboolean hasfocus; + int style; + + hasfocus = (l->generic.parent->cursor == l->generic.menuPosition); + + x = l->generic.x; + for( column = 0; column < l->columns; column++ ) { + y = l->generic.y; + base = l->top + column * l->height; + for( i = base; i < base + l->height; i++) { + if (i >= l->numitems) + break; + + if (i == l->curvalue) + { + u = x - 2; + if( l->generic.flags & QMF_CENTER_JUSTIFY ) { + u -= (l->width * SMALLCHAR_WIDTH) / 2 + 1; + } + + UI_FillRect(u,y,l->width*SMALLCHAR_WIDTH,SMALLCHAR_HEIGHT+2,listbar_color); + color = text_color_highlight; + + if (hasfocus) + style = UI_PULSE|UI_LEFT|UI_SMALLFONT; + else + style = UI_LEFT|UI_SMALLFONT; + } + else + { + color = text_color_normal; + style = UI_LEFT|UI_SMALLFONT; + } + if( l->generic.flags & QMF_CENTER_JUSTIFY ) { + style |= UI_CENTER; + } + + UI_DrawString( + x, + y, + l->itemnames[i], + style, + color); + + y += SMALLCHAR_HEIGHT; + } + x += (l->width + l->seperation) * SMALLCHAR_WIDTH; + } +} + +/* +================= +Menu_AddItem +================= +*/ +void Menu_AddItem( menuframework_s *menu, void *item ) +{ + menucommon_s *itemptr; + + if (menu->nitems >= MAX_MENUITEMS) + trap_Error ("Menu_AddItem: excessive items"); + + menu->items[menu->nitems] = item; + ((menucommon_s*)menu->items[menu->nitems])->parent = menu; + ((menucommon_s*)menu->items[menu->nitems])->menuPosition = menu->nitems; + ((menucommon_s*)menu->items[menu->nitems])->flags &= ~QMF_HASMOUSEFOCUS; + + // perform any item specific initializations + itemptr = (menucommon_s*)item; + if (!(itemptr->flags & QMF_NODEFAULTINIT)) + { + switch (itemptr->type) + { + case MTYPE_ACTION: + Action_Init((menuaction_s*)item); + break; + + case MTYPE_FIELD: + MenuField_Init((menufield_s*)item); + break; + + case MTYPE_SPINCONTROL: + SpinControl_Init((menulist_s*)item); + break; + + case MTYPE_RADIOBUTTON: + RadioButton_Init((menuradiobutton_s*)item); + break; + + case MTYPE_SLIDER: + Slider_Init((menuslider_s*)item); + break; + + case MTYPE_BITMAP: + Bitmap_Init((menubitmap_s*)item); + break; + + case MTYPE_TEXT: + Text_Init((menutext_s*)item); + break; + + case MTYPE_SCROLLLIST: + ScrollList_Init((menulist_s*)item); + break; + + case MTYPE_PTEXT: + PText_Init((menutext_s*)item); + break; + + case MTYPE_BTEXT: + BText_Init((menutext_s*)item); + break; + + default: + trap_Error( va("Menu_Init: unknown type %d", itemptr->type) ); + } + } + + menu->nitems++; +} + +/* +================= +Menu_CursorMoved +================= +*/ +void Menu_CursorMoved( menuframework_s *m ) +{ + void (*callback)( void *self, int notification ); + + if (m->cursor_prev == m->cursor) + return; + + if (m->cursor_prev >= 0 && m->cursor_prev < m->nitems) + { + callback = ((menucommon_s*)(m->items[m->cursor_prev]))->callback; + if (callback) + callback(m->items[m->cursor_prev],QM_LOSTFOCUS); + } + + if (m->cursor >= 0 && m->cursor < m->nitems) + { + callback = ((menucommon_s*)(m->items[m->cursor]))->callback; + if (callback) + callback(m->items[m->cursor],QM_GOTFOCUS); + } +} + +/* +================= +Menu_SetCursor +================= +*/ +void Menu_SetCursor( menuframework_s *m, int cursor ) +{ + if (((menucommon_s*)(m->items[cursor]))->flags & (QMF_GRAYED|QMF_INACTIVE)) + { + // cursor can't go there + return; + } + + m->cursor_prev = m->cursor; + m->cursor = cursor; + + Menu_CursorMoved( m ); +} + +/* +================= +Menu_SetCursorToItem +================= +*/ +void Menu_SetCursorToItem( menuframework_s *m, void* ptr ) +{ + int i; + + for (i=0; initems; i++) + { + if (m->items[i] == ptr) + { + Menu_SetCursor( m, i ); + return; + } + } +} + +/* +** Menu_AdjustCursor +** +** This function takes the given menu, the direction, and attempts +** to adjust the menu's cursor so that it's at the next available +** slot. +*/ +void Menu_AdjustCursor( menuframework_s *m, int dir ) { + menucommon_s *item = NULL; + qboolean wrapped = qfalse; + +wrap: + while ( m->cursor >= 0 && m->cursor < m->nitems ) { + item = ( menucommon_s * ) m->items[m->cursor]; + if (( item->flags & (QMF_GRAYED|QMF_MOUSEONLY|QMF_INACTIVE) ) ) { + m->cursor += dir; + } + else { + break; + } + } + + if ( dir == 1 ) { + if ( m->cursor >= m->nitems ) { + if ( m->wrapAround ) { + if ( wrapped ) { + m->cursor = m->cursor_prev; + return; + } + m->cursor = 0; + wrapped = qtrue; + goto wrap; + } + m->cursor = m->cursor_prev; + } + } + else { + if ( m->cursor < 0 ) { + if ( m->wrapAround ) { + if ( wrapped ) { + m->cursor = m->cursor_prev; + return; + } + m->cursor = m->nitems - 1; + wrapped = qtrue; + goto wrap; + } + m->cursor = m->cursor_prev; + } + } +} + +/* +================= +Menu_Draw +================= +*/ +void Menu_Draw( menuframework_s *menu ) +{ + int i; + menucommon_s *itemptr; + + // draw menu + for (i=0; initems; i++) + { + itemptr = (menucommon_s*)menu->items[i]; + + if (itemptr->flags & QMF_HIDDEN) + continue; + + if (itemptr->ownerdraw) + { + // total subclassing, owner draws everything + itemptr->ownerdraw( itemptr ); + } + else + { + switch (itemptr->type) + { + case MTYPE_RADIOBUTTON: + RadioButton_Draw( (menuradiobutton_s*)itemptr ); + break; + + case MTYPE_FIELD: + MenuField_Draw( (menufield_s*)itemptr ); + break; + + case MTYPE_SLIDER: + Slider_Draw( (menuslider_s*)itemptr ); + break; + + case MTYPE_SPINCONTROL: + SpinControl_Draw( (menulist_s*)itemptr ); + break; + + case MTYPE_ACTION: + Action_Draw( (menuaction_s*)itemptr ); + break; + + case MTYPE_BITMAP: + Bitmap_Draw( (menubitmap_s*)itemptr ); + break; + + case MTYPE_TEXT: + Text_Draw( (menutext_s*)itemptr ); + break; + + case MTYPE_SCROLLLIST: + ScrollList_Draw( (menulist_s*)itemptr ); + break; + + case MTYPE_PTEXT: + PText_Draw( (menutext_s*)itemptr ); + break; + + case MTYPE_BTEXT: + BText_Draw( (menutext_s*)itemptr ); + break; + + default: + trap_Error( va("Menu_Draw: unknown type %d", itemptr->type) ); + } + } +#ifndef NDEBUG + if( uis.debug ) { + int x; + int y; + int w; + int h; + + if( !( itemptr->flags & QMF_INACTIVE ) ) { + x = itemptr->left; + y = itemptr->top; + w = itemptr->right - itemptr->left + 1; + h = itemptr->bottom - itemptr->top + 1; + + if (itemptr->flags & QMF_HASMOUSEFOCUS) { + UI_DrawRect(x, y, w, h, colorYellow ); + } + else { + UI_DrawRect(x, y, w, h, colorWhite ); + } + } + } +#endif + } + + itemptr = Menu_ItemAtCursor( menu ); + if ( itemptr && itemptr->statusbar) + itemptr->statusbar( ( void * ) itemptr ); +} + +/* +================= +Menu_ItemAtCursor +================= +*/ +void *Menu_ItemAtCursor( menuframework_s *m ) +{ + if ( m->cursor < 0 || m->cursor >= m->nitems ) + return 0; + + return m->items[m->cursor]; +} + +/* +================= +Menu_ActivateItem +================= +*/ +sfxHandle_t Menu_ActivateItem( menuframework_s *s, menucommon_s* item ) { + if ( item->callback ) { + item->callback( item, QM_ACTIVATED ); + if( !( item->flags & QMF_SILENT ) ) { + return menu_move_sound; + } + } + + return 0; +} + +/* +================= +Menu_DefaultKey +================= +*/ +sfxHandle_t Menu_DefaultKey( menuframework_s *m, int key ) +{ + sfxHandle_t sound = 0; + menucommon_s *item; + int cursor_prev; + + // menu system keys + switch ( key ) + { + case K_MOUSE2: + case K_ESCAPE: + UI_PopMenu(); + return menu_out_sound; + } + + if (!m || !m->nitems) + return 0; + + // route key stimulus to widget + item = Menu_ItemAtCursor( m ); + if (item && !(item->flags & (QMF_GRAYED|QMF_INACTIVE))) + { + switch (item->type) + { + case MTYPE_SPINCONTROL: + sound = SpinControl_Key( (menulist_s*)item, key ); + break; + + case MTYPE_RADIOBUTTON: + sound = RadioButton_Key( (menuradiobutton_s*)item, key ); + break; + + case MTYPE_SLIDER: + sound = Slider_Key( (menuslider_s*)item, key ); + break; + + case MTYPE_SCROLLLIST: + sound = ScrollList_Key( (menulist_s*)item, key ); + break; + + case MTYPE_FIELD: + sound = MenuField_Key( (menufield_s*)item, &key ); + break; + } + + if (sound) { + // key was handled + return sound; + } + } + + // default handling + switch ( key ) + { +#ifndef NDEBUG + case K_F11: + uis.debug ^= 1; + break; + + case K_F12: + trap_Cmd_ExecuteText(EXEC_APPEND, "screenshot\n"); + break; +#endif + case K_KP_UPARROW: + case K_UPARROW: + cursor_prev = m->cursor; + m->cursor_prev = m->cursor; + m->cursor--; + Menu_AdjustCursor( m, -1 ); + if ( cursor_prev != m->cursor ) { + Menu_CursorMoved( m ); + sound = menu_move_sound; + } + break; + + case K_TAB: + case K_KP_DOWNARROW: + case K_DOWNARROW: + cursor_prev = m->cursor; + m->cursor_prev = m->cursor; + m->cursor++; + Menu_AdjustCursor( m, 1 ); + if ( cursor_prev != m->cursor ) { + Menu_CursorMoved( m ); + sound = menu_move_sound; + } + break; + + case K_MOUSE1: + case K_MOUSE3: + if (item) + if ((item->flags & QMF_HASMOUSEFOCUS) && !(item->flags & (QMF_GRAYED|QMF_INACTIVE))) + return (Menu_ActivateItem( m, item )); + break; + + case K_JOY1: + case K_JOY2: + case K_JOY3: + case K_JOY4: + case K_AUX1: + case K_AUX2: + case K_AUX3: + case K_AUX4: + case K_AUX5: + case K_AUX6: + case K_AUX7: + case K_AUX8: + case K_AUX9: + case K_AUX10: + case K_AUX11: + case K_AUX12: + case K_AUX13: + case K_AUX14: + case K_AUX15: + case K_AUX16: + case K_KP_ENTER: + case K_ENTER: + if (item) + if (!(item->flags & (QMF_MOUSEONLY|QMF_GRAYED|QMF_INACTIVE))) + return (Menu_ActivateItem( m, item )); + break; + } + + return sound; +} + +/* +================= +Menu_Cache +================= +*/ +void Menu_Cache( void ) +{ + uis.charset = trap_R_RegisterShaderNoMip( "gfx/2d/bigchars" ); + uis.charsetProp = trap_R_RegisterShaderNoMip( "menu/art/font1_prop.tga" ); + uis.charsetPropGlow = trap_R_RegisterShaderNoMip( "menu/art/font1_prop_glo.tga" ); + uis.charsetPropB = trap_R_RegisterShaderNoMip( "menu/art/font2_prop.tga" ); + uis.cursor = trap_R_RegisterShaderNoMip( "menu/art/3_cursor2" ); + uis.rb_on = trap_R_RegisterShaderNoMip( "menu/art/switch_on" ); + uis.rb_off = trap_R_RegisterShaderNoMip( "menu/art/switch_off" ); + + uis.whiteShader = trap_R_RegisterShaderNoMip( "white" ); + if ( uis.glconfig.hardwareType == GLHW_RAGEPRO ) { + // the blend effect turns to shit with the normal + uis.menuBackShader = trap_R_RegisterShaderNoMip( "menubackRagePro" ); + } else { + uis.menuBackShader = trap_R_RegisterShaderNoMip( "menuback" ); + } + uis.menuBackNoLogoShader = trap_R_RegisterShaderNoMip( "menubacknologo" ); + + menu_in_sound = trap_S_RegisterSound( "sound/misc/menu1.wav", qfalse ); + menu_move_sound = trap_S_RegisterSound( "sound/misc/menu2.wav", qfalse ); + menu_out_sound = trap_S_RegisterSound( "sound/misc/menu3.wav", qfalse ); + menu_buzz_sound = trap_S_RegisterSound( "sound/misc/menu4.wav", qfalse ); + weaponChangeSound = trap_S_RegisterSound( "sound/weapons/change.wav", qfalse ); + + // need a nonzero sound, make an empty sound for this + menu_null_sound = -1; + + sliderBar = trap_R_RegisterShaderNoMip( "menu/art/slider2" ); + sliderButton_0 = trap_R_RegisterShaderNoMip( "menu/art/sliderbutt_0" ); + sliderButton_1 = trap_R_RegisterShaderNoMip( "menu/art/sliderbutt_1" ); +} + -- cgit v1.2.3