📄 ui_qmenu.c
字号:
/*
===========================================================================
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -