mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2024-11-14 16:40:57 +00:00
d0d781761d
Refactored key binding menu with new control type. Minor cleanup of menu implementations.
914 lines
24 KiB
C
914 lines
24 KiB
C
/*
|
|
===========================================================================
|
|
Copyright (C) 1997-2001 Id Software, Inc.
|
|
|
|
This file is part of Quake 2 source code.
|
|
|
|
Quake 2 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 2 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 Quake 2 source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
// ui_widgets.c -- supporting code for menu widgets
|
|
|
|
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "../client/client.h"
|
|
#include "ui_local.h"
|
|
|
|
static void MenuAction_DoEnter (menuaction_s *a);
|
|
static void MenuAction_Draw (menuaction_s *a);
|
|
static void Menulist_DoEnter (menulist_s *l);
|
|
static void MenuList_Draw (menulist_s *l);
|
|
static void MenuSeparator_Draw (menuseparator_s *s);
|
|
static void MenuSlider_DoSlide (menuslider_s *s, int dir);
|
|
static void MenuSlider_Draw (menuslider_s *s);
|
|
static void MenuSpinControl_DoEnter (menulist_s *s);
|
|
static void MenuSpinControl_Draw (menulist_s *s);
|
|
static void MenuSpinControl_DoSlide (menulist_s *s, int dir);
|
|
|
|
#define RCOLUMN_OFFSET MENU_FONT_SIZE*2 // was 16
|
|
#define LCOLUMN_OFFSET -MENU_FONT_SIZE*2 // was -16
|
|
|
|
vec4_t stCoord_arrow_left = {0.0, 0.0, 0.25, 0.25};
|
|
vec4_t stCoord_arrow_right = {0.25, 0.0, 0.5, 0.25};
|
|
vec4_t stCoord_arrow_up = {0.5, 0.0, 0.75, 0.25};
|
|
vec4_t stCoord_arrow_down = {0.75, 0.0, 1, 0.25};
|
|
vec4_t stCoord_scrollKnob_h = {0.0, 0.75, 0.25, 1.0};
|
|
vec4_t stCoord_scrollKnob_v = {0.25, 0.75, 0.5, 1.0};
|
|
vec4_t stCoord_field_left = {0.0, 0.0, 0.25, 1.0};
|
|
vec4_t stCoord_field_center = {0.25, 0.0, 0.5, 1.0};
|
|
vec4_t stCoord_field_right = {0.5, 0.0, 0.75, 1.0};
|
|
vec4_t stCoord_slider_left = {0.0, 0.0, 0.125, 1.0};
|
|
vec4_t stCoord_slider_center = {0.125, 0.0, 0.375, 1.0};
|
|
vec4_t stCoord_slider_right = {0.375, 0.0, 0.5, 1.0};
|
|
vec4_t stCoord_slider_knob = {0.5, 0.0, 0.625, 1.0};
|
|
|
|
extern viddef_t viddef;
|
|
|
|
#define VID_WIDTH viddef.width
|
|
#define VID_HEIGHT viddef.height
|
|
|
|
//======================================================
|
|
|
|
void MenuAction_DoEnter (menuaction_s *a)
|
|
{
|
|
if (!a) return;
|
|
|
|
if (a->generic.callback)
|
|
a->generic.callback(a);
|
|
}
|
|
|
|
void MenuAction_Draw (menuaction_s *a)
|
|
{
|
|
int alpha;
|
|
|
|
if (!a) return;
|
|
|
|
alpha = UI_MouseOverAlpha(&a->generic);
|
|
|
|
if (a->generic.flags & QMF_LEFT_JUSTIFY)
|
|
{
|
|
if (a->generic.flags & QMF_GRAYED)
|
|
UI_DrawStringDark (a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET,
|
|
a->generic.y + a->generic.parent->y, a->generic.textSize, a->generic.name, alpha);
|
|
else
|
|
UI_DrawString (a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET,
|
|
a->generic.y + a->generic.parent->y, a->generic.textSize, a->generic.name, alpha);
|
|
}
|
|
else
|
|
{
|
|
if (a->generic.flags & QMF_GRAYED)
|
|
UI_DrawStringR2LDark (a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET,
|
|
a->generic.y + a->generic.parent->y, a->generic.textSize, a->generic.name, alpha);
|
|
else
|
|
UI_DrawStringR2L (a->generic.x + a->generic.parent->x + LCOLUMN_OFFSET,
|
|
a->generic.y + a->generic.parent->y, a->generic.textSize, a->generic.name, alpha);
|
|
}
|
|
if (a->generic.ownerdraw)
|
|
a->generic.ownerdraw(a);
|
|
}
|
|
|
|
//=========================================================
|
|
|
|
qboolean MenuField_DoEnter (menufield_s *f)
|
|
{
|
|
if (!f) return false;
|
|
|
|
if (f->generic.callback)
|
|
{
|
|
f->generic.callback(f);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void MenuField_Draw (menufield_s *f)
|
|
{
|
|
int i, alpha, xtra;
|
|
char tempbuffer[128]="";
|
|
int offset;
|
|
|
|
if (!f) return;
|
|
|
|
alpha = UI_MouseOverAlpha(&f->generic);
|
|
|
|
if (f->generic.name)
|
|
UI_DrawStringR2LDark (f->generic.x + f->generic.parent->x + LCOLUMN_OFFSET,
|
|
f->generic.y + f->generic.parent->y, f->generic.textSize, f->generic.name, 255);
|
|
|
|
if (xtra = stringLengthExtra(f->buffer))
|
|
{
|
|
strncpy( tempbuffer, f->buffer + f->visible_offset, f->visible_length );
|
|
offset = (int)strlen(tempbuffer) - xtra;
|
|
|
|
if (offset > f->visible_length)
|
|
{
|
|
f->visible_offset = offset - f->visible_length;
|
|
strncpy( tempbuffer, f->buffer + f->visible_offset - xtra, f->visible_length + xtra );
|
|
offset = f->visible_offset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strncpy( tempbuffer, f->buffer + f->visible_offset, f->visible_length );
|
|
offset = (int)strlen(tempbuffer);
|
|
}
|
|
|
|
if (ui_new_textfield->integer)
|
|
{
|
|
UI_DrawPicST (f->generic.x + f->generic.parent->x + RCOLUMN_OFFSET,
|
|
f->generic.y + f->generic.parent->y - 4, f->generic.textSize, f->generic.textSize*2, stCoord_field_left,
|
|
ALIGN_CENTER, true, color_identity, UI_FIELD_PIC);
|
|
UI_DrawPicST (f->generic.x + f->generic.parent->x + (1+f->visible_length)*f->generic.textSize + RCOLUMN_OFFSET,
|
|
f->generic.y + f->generic.parent->y - 4, f->generic.textSize, f->generic.textSize*2, stCoord_field_right,
|
|
ALIGN_CENTER, true, color_identity, UI_FIELD_PIC);
|
|
}
|
|
else
|
|
{
|
|
UI_DrawChar (f->generic.x + f->generic.parent->x + RCOLUMN_OFFSET,
|
|
f->generic.y + f->generic.parent->y - 4, f->generic.textSize, ALIGN_CENTER, 18, 255, 255, 255, 255, false, false);
|
|
UI_DrawChar (f->generic.x + f->generic.parent->x + RCOLUMN_OFFSET,
|
|
f->generic.y + f->generic.parent->y + 4, f->generic.textSize, ALIGN_CENTER, 24, 255, 255, 255, 255, false, false);
|
|
UI_DrawChar (f->generic.x + f->generic.parent->x + (1+f->visible_length)*f->generic.textSize + RCOLUMN_OFFSET,
|
|
f->generic.y + f->generic.parent->y - 4, f->generic.textSize, ALIGN_CENTER, 20, 255, 255, 255, 255, false, false);
|
|
UI_DrawChar (f->generic.x + f->generic.parent->x + (1+f->visible_length)*f->generic.textSize + RCOLUMN_OFFSET,
|
|
f->generic.y + f->generic.parent->y + 4, f->generic.textSize, ALIGN_CENTER, 26, 255, 255, 255, 255, false, false);
|
|
}
|
|
|
|
for (i = 0; i < f->visible_length; i++)
|
|
{
|
|
if (ui_new_textfield->integer) {
|
|
UI_DrawPicST (f->generic.x + f->generic.parent->x + (1+i)*f->generic.textSize + RCOLUMN_OFFSET,
|
|
f->generic.y + f->generic.parent->y - 4, f->generic.textSize, f->generic.textSize*2, stCoord_field_center,
|
|
ALIGN_CENTER, true, color_identity, UI_FIELD_PIC);
|
|
}
|
|
else {
|
|
UI_DrawChar (f->generic.x + f->generic.parent->x + (1+i)*f->generic.textSize + RCOLUMN_OFFSET,
|
|
f->generic.y + f->generic.parent->y - 4, f->generic.textSize, ALIGN_CENTER, 19, 255, 255, 255, 255, false, false);
|
|
UI_DrawChar (f->generic.x + f->generic.parent->x + (1+i)*f->generic.textSize + RCOLUMN_OFFSET,
|
|
f->generic.y + f->generic.parent->y + 4, f->generic.textSize, ALIGN_CENTER, 25, 255, 255, 255, 255, false, (i==(f->visible_length-1)));
|
|
}
|
|
}
|
|
|
|
// add cursor thingie
|
|
if ( (UI_ItemAtMenuCursor(f->generic.parent) == f) && ((int)(Sys_Milliseconds()/250))&1 )
|
|
Com_sprintf (tempbuffer, sizeof(tempbuffer), "%s%c", tempbuffer, 11);
|
|
|
|
UI_DrawString (f->generic.x + f->generic.parent->x + f->generic.textSize*3,
|
|
f->generic.y + f->generic.parent->y, f->generic.textSize, tempbuffer, alpha);
|
|
}
|
|
|
|
qboolean UI_MenuField_Key (menufield_s *f, int key)
|
|
{
|
|
extern int keydown[];
|
|
|
|
if (!f) return false;
|
|
|
|
switch ( key )
|
|
{
|
|
case K_KP_SLASH:
|
|
key = '/';
|
|
break;
|
|
case K_KP_MINUS:
|
|
key = '-';
|
|
break;
|
|
case K_KP_PLUS:
|
|
key = '+';
|
|
break;
|
|
case K_KP_HOME:
|
|
key = '7';
|
|
break;
|
|
case K_KP_UPARROW:
|
|
key = '8';
|
|
break;
|
|
case K_KP_PGUP:
|
|
key = '9';
|
|
break;
|
|
case K_KP_LEFTARROW:
|
|
key = '4';
|
|
break;
|
|
case K_KP_5:
|
|
key = '5';
|
|
break;
|
|
case K_KP_RIGHTARROW:
|
|
key = '6';
|
|
break;
|
|
case K_KP_END:
|
|
key = '1';
|
|
break;
|
|
case K_KP_DOWNARROW:
|
|
key = '2';
|
|
break;
|
|
case K_KP_PGDN:
|
|
key = '3';
|
|
break;
|
|
case K_KP_INS:
|
|
key = '0';
|
|
break;
|
|
case K_KP_DEL:
|
|
key = '.';
|
|
break;
|
|
}
|
|
|
|
// mxd- This blocked Shift-Ins combo in the next block.
|
|
// Knightmare- allow only the INS key thru, otherwise mouse events end up as text input!
|
|
if (key > 127)
|
|
{
|
|
switch (key)
|
|
{
|
|
case K_INS:
|
|
case K_KP_INS:
|
|
break;
|
|
case K_DEL:
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// support pasting from the clipboard
|
|
//
|
|
if ( ( toupper(key) == 'V' && keydown[K_CTRL] ) ||
|
|
( ( (key == K_INS) || (key == K_KP_INS) ) && keydown[K_SHIFT] ) )
|
|
{
|
|
char *cbd;
|
|
|
|
if ( ( cbd = Sys_GetClipboardData() ) != 0 )
|
|
{
|
|
strtok( cbd, "\n\r\b" );
|
|
|
|
strncpy( f->buffer, cbd, f->length - 1 );
|
|
f->cursor = (int)strlen( f->buffer );
|
|
f->visible_offset = f->cursor - f->visible_length;
|
|
if ( f->visible_offset < 0 )
|
|
f->visible_offset = 0;
|
|
|
|
free( cbd );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
switch ( key )
|
|
{
|
|
case K_KP_LEFTARROW:
|
|
case K_LEFTARROW:
|
|
case K_BACKSPACE:
|
|
if ( f->cursor > 0 )
|
|
{
|
|
memmove( &f->buffer[f->cursor-1], &f->buffer[f->cursor], strlen( &f->buffer[f->cursor] ) + 1 );
|
|
f->cursor--;
|
|
|
|
if (f->visible_offset)
|
|
f->visible_offset--;
|
|
}
|
|
break;
|
|
|
|
case K_KP_DEL:
|
|
case K_DEL:
|
|
memmove( &f->buffer[f->cursor], &f->buffer[f->cursor+1], strlen( &f->buffer[f->cursor+1] ) + 1 );
|
|
break;
|
|
|
|
case K_KP_ENTER:
|
|
case K_ENTER:
|
|
case K_ESCAPE:
|
|
case K_TAB:
|
|
return false;
|
|
|
|
case K_SPACE:
|
|
default:
|
|
if ( !isdigit(key) && (f->generic.flags & QMF_NUMBERSONLY) )
|
|
return false;
|
|
|
|
if (f->cursor < f->length)
|
|
{
|
|
f->buffer[f->cursor++] = key;
|
|
f->buffer[f->cursor] = 0;
|
|
|
|
if (f->cursor > f->visible_length)
|
|
f->visible_offset++;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//=========================================================
|
|
|
|
void Menulist_DoEnter (menulist_s *l)
|
|
{
|
|
int start;
|
|
|
|
if (!l) return;
|
|
|
|
start = l->generic.y / 10 + 1;
|
|
|
|
l->curValue = l->generic.parent->cursor - start;
|
|
|
|
if (l->generic.callback)
|
|
l->generic.callback(l);
|
|
}
|
|
|
|
void MenuList_Draw (menulist_s *l)
|
|
{
|
|
const char **n;
|
|
int y = 0, alpha;
|
|
|
|
if (!l) return;
|
|
|
|
alpha = UI_MouseOverAlpha(&l->generic);
|
|
|
|
UI_DrawStringR2LDark (l->generic.x + l->generic.parent->x + LCOLUMN_OFFSET, // - 2*MENU_FONT_SIZE,
|
|
l->generic.y + l->generic.parent->y, l->generic.textSize, l->generic.name, alpha);
|
|
|
|
n = l->itemNames;
|
|
|
|
// UI_DrawFill (l->generic.parent->x + l->generic.x - 112, l->generic.parent->y + l->generic.y + (l->curValue+1)*MENU_LINE_SIZE,
|
|
// 128, MENU_LINE_SIZE, ALIGN_CENTER, false, 16);
|
|
UI_DrawFill (l->generic.parent->x + l->generic.x - 112, l->generic.parent->y + l->generic.y + (l->curValue+1)*MENU_LINE_SIZE,
|
|
128, MENU_LINE_SIZE, ALIGN_CENTER, false, color8red(16), color8green(16), color8blue(16), 255);
|
|
|
|
while (*n)
|
|
{
|
|
UI_DrawStringR2LDark (l->generic.x + l->generic.parent->x + LCOLUMN_OFFSET,
|
|
l->generic.y + l->generic.parent->y + y + MENU_LINE_SIZE, l->generic.textSize, *n, alpha);
|
|
n++;
|
|
y += MENU_LINE_SIZE;
|
|
}
|
|
}
|
|
|
|
//=========================================================
|
|
|
|
void MenuSeparator_Draw (menuseparator_s *s)
|
|
{
|
|
int alpha;
|
|
|
|
if (!s) return;
|
|
|
|
alpha = UI_MouseOverAlpha(&s->generic);
|
|
|
|
if (s->generic.name)
|
|
UI_DrawStringR2LDark (s->generic.x + s->generic.parent->x,
|
|
s->generic.y + s->generic.parent->y, s->generic.textSize, s->generic.name, alpha);
|
|
}
|
|
|
|
//=========================================================
|
|
|
|
void UI_MenuSlider_SetValue (menuslider_s *s, const char *varName, float cvarMin, float cvarMax, qboolean clamp)
|
|
{
|
|
if (!s || !varName || varName[0] == '\0')
|
|
return;
|
|
if (!s->increment)
|
|
s->increment = 1.0f;
|
|
|
|
if (clamp) {
|
|
UI_ClampCvar (varName, cvarMin, cvarMax);
|
|
}
|
|
s->curPos = (int)ceil((Cvar_VariableValue((char *)varName) - s->baseValue) / s->increment);
|
|
s->curPos = min(max(s->curPos, 0), s->maxPos);
|
|
}
|
|
|
|
void UI_MenuSlider_SaveValue (menuslider_s *s, const char *varName)
|
|
{
|
|
if (!s || !varName || varName[0] == '\0')
|
|
return;
|
|
|
|
Cvar_SetValue ((char *)varName, ((float)s->curPos * s->increment) + s->baseValue);
|
|
}
|
|
|
|
float UI_MenuSlider_GetValue (menuslider_s *s)
|
|
{
|
|
if (!s) return 0.0f;
|
|
|
|
if (!s->increment)
|
|
s->increment = 1.0f;
|
|
|
|
return ((float)s->curPos * s->increment) + s->baseValue;
|
|
}
|
|
|
|
void MenuSlider_DoSlide (menuslider_s *s, int dir)
|
|
{
|
|
if (!s) return;
|
|
|
|
s->curPos += dir;
|
|
|
|
s->curPos = min(max(s->curPos, 0), s->maxPos);
|
|
|
|
if (s->generic.callback)
|
|
s->generic.callback(s);
|
|
}
|
|
|
|
#define SLIDER_RANGE 10
|
|
|
|
void MenuSlider_Draw (menuslider_s *s)
|
|
{
|
|
int i, x, y, alpha;
|
|
float tmpValue;
|
|
char valueText[8];
|
|
|
|
if (!s) return;
|
|
|
|
alpha = UI_MouseOverAlpha(&s->generic);
|
|
|
|
UI_DrawStringR2LDark (s->generic.x + s->generic.parent->x + LCOLUMN_OFFSET,
|
|
s->generic.y + s->generic.parent->y, s->generic.textSize, s->generic.name, alpha);
|
|
|
|
if (!s->maxPos)
|
|
s->maxPos = 1;
|
|
if (!s->increment)
|
|
s->increment = 1.0f;
|
|
|
|
s->range = (float)s->curPos / (float)s->maxPos;
|
|
|
|
if (s->range < 0)
|
|
s->range = 0;
|
|
if (s->range > 1)
|
|
s->range = 1;
|
|
|
|
x = s->generic.x + s->generic.parent->x + RCOLUMN_OFFSET;
|
|
y = s->generic.y + s->generic.parent->y;
|
|
|
|
// draw left
|
|
UI_DrawPicST (x, y, SLIDER_ENDCAP_WIDTH, SLIDER_HEIGHT,
|
|
stCoord_slider_left, ALIGN_CENTER, true, color_identity, UI_SLIDER_PIC);
|
|
// UI_DrawChar (s->generic.x + s->generic.parent->x + RCOLUMN_OFFSET,
|
|
// s->generic.y + s->generic.parent->y, s->generic.textSize, ALIGN_CENTER, 128, 255,255,255,255, false, false);
|
|
|
|
// draw center
|
|
x += SLIDER_ENDCAP_WIDTH;
|
|
for (i = 0; i < SLIDER_RANGE; i++) {
|
|
UI_DrawPicST (x + i*SLIDER_SECTION_WIDTH, y, SLIDER_SECTION_WIDTH, SLIDER_HEIGHT,
|
|
stCoord_slider_center, ALIGN_CENTER, true, color_identity, UI_SLIDER_PIC);
|
|
// UI_DrawChar (s->generic.x + s->generic.parent->x + (i+1)*s->generic.textSize + RCOLUMN_OFFSET,
|
|
// s->generic.y + s->generic.parent->y, s->generic.textSize, ALIGN_CENTER, 129, 255,255,255,255, false, false);
|
|
}
|
|
|
|
// draw right
|
|
UI_DrawPicST (x + i*SLIDER_SECTION_WIDTH, y, SLIDER_ENDCAP_WIDTH, SLIDER_HEIGHT,
|
|
stCoord_slider_right, ALIGN_CENTER, true, color_identity, UI_SLIDER_PIC);
|
|
// UI_DrawChar (s->generic.x + s->generic.parent->x + (i+1)*s->generic.textSize + RCOLUMN_OFFSET,
|
|
// s->generic.y + s->generic.parent->y, s->generic.textSize, ALIGN_CENTER, 130, 255,255,255,255, false, false);
|
|
|
|
// draw knob
|
|
UI_DrawPicST (x + SLIDER_RANGE*SLIDER_SECTION_WIDTH*s->range - (SLIDER_KNOB_WIDTH/2), y, SLIDER_KNOB_WIDTH, SLIDER_HEIGHT,
|
|
stCoord_slider_knob, ALIGN_CENTER, true, color_identity, UI_SLIDER_PIC);
|
|
// UI_DrawChar (s->generic.x + s->generic.parent->x + s->generic.textSize*((SLIDER_RANGE-1)*s->range+1) + RCOLUMN_OFFSET,
|
|
// s->generic.y + s->generic.parent->y, s->generic.textSize, ALIGN_CENTER, 131, 255,255,255,255, false, true);
|
|
|
|
// draw value
|
|
tmpValue = s->curPos * s->increment + s->baseValue;
|
|
if (s->displayAsPercent) {
|
|
tmpValue *= 100.0f;
|
|
Com_sprintf (valueText, sizeof(valueText), "%.0f%%", tmpValue);
|
|
}
|
|
else {
|
|
if (fabs((int)tmpValue - tmpValue) < 0.01f)
|
|
Com_sprintf (valueText, sizeof(valueText), "%i", (int)tmpValue);
|
|
else
|
|
Com_sprintf (valueText, sizeof(valueText), "%4.2f", tmpValue);
|
|
}
|
|
UI_DrawString (s->generic.x + s->generic.parent->x + RCOLUMN_OFFSET + 2*SLIDER_ENDCAP_WIDTH + i*SLIDER_SECTION_WIDTH + MENU_FONT_SIZE/2,
|
|
s->generic.y + s->generic.parent->y + 1, MENU_FONT_SIZE-2, valueText, alpha);
|
|
// UI_DrawString (s->generic.x + s->generic.parent->x + s->generic.textSize*SLIDER_RANGE + RCOLUMN_OFFSET + 2.5*MENU_FONT_SIZE,
|
|
// s->generic.y + s->generic.parent->y + 1, MENU_FONT_SIZE-2, valueText, alpha);
|
|
}
|
|
|
|
//=========================================================
|
|
|
|
void UI_MenuSpinControl_SetValue (menulist_s *s, const char *varName, float cvarMin, float cvarMax, qboolean clamp)
|
|
{
|
|
if (!s || !varName || varName[0] == '\0')
|
|
return;
|
|
|
|
if (clamp) {
|
|
UI_ClampCvar (varName, cvarMin, cvarMax);
|
|
}
|
|
if (s->itemValues) {
|
|
s->curValue = UI_GetIndexForStringValue(s->itemValues, Cvar_VariableString((char *)varName));
|
|
}
|
|
else
|
|
{
|
|
if (s->invertValue) {
|
|
s->curValue = (Cvar_VariableValue((char *)varName) < 0);
|
|
}
|
|
else {
|
|
s->curValue = (int)min(max(Cvar_VariableValue((char *)varName), cvarMin), cvarMax);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UI_MenuSpinControl_SaveValue (menulist_s *s, const char *varName)
|
|
{
|
|
if (!s || !varName || varName[0] == '\0')
|
|
return;
|
|
if (!s->numItems) {
|
|
Com_Printf (S_COLOR_YELLOW"UI_MenuSpinControl_SaveValue: not initialized!\n");
|
|
return;
|
|
}
|
|
if ( (s->curValue < 0) || (s->curValue >= s->numItems) ) {
|
|
Com_Printf (S_COLOR_YELLOW"UI_MenuSpinControl_SaveValue: curvalue out of bounds!\n");
|
|
return;
|
|
}
|
|
|
|
if (s->itemValues) {
|
|
// Don't save to cvar if this itemvalue is the wildcard
|
|
if ( Q_stricmp(va("%s", s->itemValues[s->curValue]), UI_ITEMVALUE_WILDCARD) != 0 )
|
|
Cvar_Set ((char *)varName, va("%s", s->itemValues[s->curValue]));
|
|
}
|
|
else
|
|
{
|
|
if (s->invertValue) {
|
|
Cvar_SetValue ((char *)varName, Cvar_VariableValue((char *)varName) * -1 );
|
|
}
|
|
else {
|
|
Cvar_SetInteger ((char *)varName, s->curValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
const char *UI_MenuSpinControl_GetValue (menulist_s *s)
|
|
{
|
|
const char *value;
|
|
|
|
if (!s)
|
|
return NULL;
|
|
|
|
if (!s->numItems) {
|
|
Com_Printf (S_COLOR_YELLOW"UI_MenuSpinControl_GetValue: not initialized!\n");
|
|
return NULL;
|
|
}
|
|
if ( (s->curValue < 0) || (s->curValue >= s->numItems) ) {
|
|
Com_Printf (S_COLOR_YELLOW"UI_MenuSpinControl_GetValue: curvalue out of bounds!\n");
|
|
return NULL;
|
|
}
|
|
|
|
if (s->itemValues) {
|
|
value = s->itemValues[s->curValue];
|
|
}
|
|
else {
|
|
value = va("%d", s->curValue);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
void MenuSpinControl_DoEnter (menulist_s *s)
|
|
{
|
|
if (!s || !s->itemNames || !s->numItems)
|
|
return;
|
|
|
|
s->curValue++;
|
|
if (s->itemNames[s->curValue] == 0)
|
|
s->curValue = 0;
|
|
|
|
if (s->generic.callback)
|
|
s->generic.callback(s);
|
|
}
|
|
|
|
void MenuSpinControl_DoSlide (menulist_s *s, int dir)
|
|
{
|
|
if (!s || !s->itemNames || !s->numItems)
|
|
return;
|
|
|
|
s->curValue += dir;
|
|
|
|
if (s->generic.flags & QMF_SKINLIST) // don't allow looping around for skin lists
|
|
{
|
|
if (s->curValue < 0)
|
|
s->curValue = 0;
|
|
else if (s->itemNames[s->curValue] == 0)
|
|
s->curValue--;
|
|
}
|
|
else {
|
|
if (s->curValue < 0)
|
|
s->curValue = s->numItems-1; // was 0
|
|
else if (s->itemNames[s->curValue] == 0)
|
|
s->curValue = 0; // was --
|
|
}
|
|
|
|
if (s->generic.callback)
|
|
s->generic.callback(s);
|
|
}
|
|
|
|
void MenuSpinControl_Draw (menulist_s *s)
|
|
{
|
|
int alpha;
|
|
char buffer[100];
|
|
|
|
if (!s) return;
|
|
|
|
alpha = UI_MouseOverAlpha(&s->generic);
|
|
|
|
if (s->generic.name)
|
|
{
|
|
UI_DrawStringR2LDark (s->generic.x + s->generic.parent->x + LCOLUMN_OFFSET,
|
|
s->generic.y + s->generic.parent->y, s->generic.textSize, s->generic.name, alpha);
|
|
}
|
|
if (!strchr(s->itemNames[s->curValue], '\n'))
|
|
{
|
|
UI_DrawString (s->generic.x + s->generic.parent->x + RCOLUMN_OFFSET,
|
|
s->generic.y + s->generic.parent->y, s->generic.textSize, s->itemNames[s->curValue], alpha);
|
|
}
|
|
else
|
|
{
|
|
// strncpy(buffer, s->itemnames[s->curvalue]);
|
|
Q_strncpyz (buffer, sizeof(buffer), s->itemNames[s->curValue]);
|
|
*strchr(buffer, '\n') = 0;
|
|
UI_DrawString (s->generic.x + s->generic.parent->x + RCOLUMN_OFFSET,
|
|
s->generic.y + s->generic.parent->y, s->generic.textSize, buffer, alpha);
|
|
// strncpy(buffer, strchr( s->itemnames[s->curvalue], '\n' ) + 1 );
|
|
Q_strncpyz (buffer, sizeof(buffer), strchr( s->itemNames[s->curValue], '\n' ) + 1);
|
|
UI_DrawString (s->generic.x + s->generic.parent->x + RCOLUMN_OFFSET,
|
|
s->generic.y + s->generic.parent->y + MENU_LINE_SIZE, s->generic.textSize, buffer, alpha);
|
|
}
|
|
}
|
|
|
|
//=========================================================
|
|
|
|
void MenuKeyBind_DoEnter (menukeybind_s *k)
|
|
{
|
|
menuframework_s *menu = k->generic.parent;
|
|
|
|
if (!menu) return;
|
|
|
|
UI_FindKeysForCommand (k->commandName, k->keys);
|
|
|
|
// if (k->keys[1] != -1)
|
|
// UI_UnbindCommand (k->commandName);
|
|
|
|
UI_SetGrabBindItem (menu, (menucommon_s *)k);
|
|
|
|
if (k->generic.callback)
|
|
k->generic.callback (k);
|
|
}
|
|
|
|
void MenuKeyBind_Draw (menukeybind_s *k)
|
|
{
|
|
menuframework_s *menu = k->generic.parent;
|
|
int x, alpha = UI_MouseOverAlpha(&k->generic);
|
|
const char *keyName1, *keyName2;
|
|
|
|
UI_DrawMenuString (menu->x + k->generic.x + LCOLUMN_OFFSET,
|
|
menu->y + k->generic.y, MENU_FONT_SIZE, k->generic.name, alpha,
|
|
!(k->generic.flags & QMF_LEFT_JUSTIFY), (k->generic.flags & QMF_ALTCOLOR));
|
|
|
|
if (k->commandName)
|
|
{
|
|
UI_FindKeysForCommand (k->commandName, k->keys);
|
|
|
|
if (k->keys[0] == -1)
|
|
{
|
|
UI_DrawMenuString (menu->x + k->generic.x + RCOLUMN_OFFSET,
|
|
menu->y + k->generic.y, MENU_FONT_SIZE, "???", alpha, false, false);
|
|
}
|
|
else
|
|
{
|
|
keyName1 = Key_KeynumToString (k->keys[0]);
|
|
UI_DrawMenuString (menu->x + k->generic.x + RCOLUMN_OFFSET,
|
|
menu->y + k->generic.y, MENU_FONT_SIZE, keyName1, alpha, false, false);
|
|
if (k->keys[1] != -1)
|
|
{
|
|
x = (int)strlen(keyName1) * MENU_FONT_SIZE;
|
|
keyName2 = Key_KeynumToString (k->keys[1]);
|
|
UI_DrawMenuString (menu->x + k->generic.x + MENU_FONT_SIZE*3 + x,
|
|
menu->y + k->generic.y, MENU_FONT_SIZE, "or", alpha, false, false);
|
|
UI_DrawMenuString (menu->x + k->generic.x + MENU_FONT_SIZE*6 + x,
|
|
menu->y + k->generic.y, MENU_FONT_SIZE, keyName2, alpha, false, false);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
Com_Printf ("UI_MenuKeyBind_Draw: keybind has no commandName!\n");
|
|
|
|
// if (k->generic.ownerdraw)
|
|
// k->generic.ownerdraw(k);
|
|
}
|
|
|
|
const char *UI_MenuKeyBind_Key (menukeybind_s *k, int key)
|
|
{
|
|
menuframework_s *menu = k->generic.parent;
|
|
|
|
// pressing mouse1 to pick a new bind wont force bind/unbind itself - spaz
|
|
if (UI_HasValidGrabBindItem(menu) && k->grabBind
|
|
&& !(ui_mousecursor.buttonused[MOUSEBUTTON1] && key == K_MOUSE1))
|
|
{
|
|
// grab key here
|
|
if (key != K_ESCAPE && key != '`')
|
|
{
|
|
char cmd[1024];
|
|
|
|
if (k->keys[1] != -1) // if two keys are already bound to this, clear them
|
|
UI_UnbindCommand (k->commandName);
|
|
|
|
Com_sprintf (cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", Key_KeynumToString(key), k->commandName);
|
|
Cbuf_InsertText (cmd);
|
|
}
|
|
|
|
// don't let selecting with mouse buttons screw everything up
|
|
UI_RefreshCursorButtons();
|
|
if (key == K_MOUSE1)
|
|
ui_mousecursor.buttonclicks[MOUSEBUTTON1] = -1;
|
|
|
|
if (menu)
|
|
UI_ClearGrabBindItem (menu);
|
|
|
|
return ui_menu_out_sound;
|
|
}
|
|
|
|
switch (key)
|
|
{
|
|
case K_ESCAPE:
|
|
UI_PopMenu ();
|
|
return ui_menu_out_sound;
|
|
case K_ENTER:
|
|
case K_KP_ENTER:
|
|
MenuKeyBind_DoEnter (k);
|
|
return ui_menu_in_sound;
|
|
case K_BACKSPACE:
|
|
case K_DEL:
|
|
case K_KP_DEL:
|
|
UI_UnbindCommand (k->commandName); // delete bindings
|
|
return ui_menu_out_sound;
|
|
default:
|
|
return ui_menu_null_sound;
|
|
}
|
|
}
|
|
|
|
//=========================================================
|
|
|
|
/*
|
|
==========================
|
|
UI_DrawMenuItem
|
|
Calls draw functions for each item type
|
|
==========================
|
|
*/
|
|
void UI_DrawMenuItem (void *item)
|
|
{
|
|
if (!item) return;
|
|
|
|
// skip hidden items
|
|
if ( ((menucommon_s *)item)->flags & QMF_HIDDEN )
|
|
return;
|
|
|
|
switch ( ((menucommon_s *)item)->type )
|
|
{
|
|
case MTYPE_FIELD:
|
|
MenuField_Draw ((menufield_s *)item);
|
|
break;
|
|
case MTYPE_SLIDER:
|
|
MenuSlider_Draw ((menuslider_s *)item);
|
|
break;
|
|
case MTYPE_LIST:
|
|
MenuList_Draw ((menulist_s *)item);
|
|
break;
|
|
case MTYPE_SPINCONTROL:
|
|
MenuSpinControl_Draw ((menulist_s *)item);
|
|
break;
|
|
case MTYPE_ACTION:
|
|
MenuAction_Draw ((menuaction_s *)item);
|
|
break;
|
|
case MTYPE_SEPARATOR:
|
|
MenuSeparator_Draw ((menuseparator_s *)item);
|
|
break;
|
|
case MTYPE_KEYBIND:
|
|
MenuKeyBind_Draw ((menukeybind_s *)item);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
UI_SelectMenuItem
|
|
=================
|
|
*/
|
|
qboolean UI_SelectMenuItem (menuframework_s *s)
|
|
{
|
|
menucommon_s *item=NULL;
|
|
|
|
if (!s) return false;
|
|
|
|
item = (menucommon_s *)UI_ItemAtMenuCursor(s);
|
|
|
|
if (item)
|
|
{
|
|
switch (item->type)
|
|
{
|
|
case MTYPE_FIELD:
|
|
return MenuField_DoEnter ( (menufield_s *)item ) ;
|
|
case MTYPE_ACTION:
|
|
MenuAction_DoEnter ( (menuaction_s *)item );
|
|
return true;
|
|
case MTYPE_LIST:
|
|
// Menulist_DoEnter ( (menulist_s *)item );
|
|
return false;
|
|
case MTYPE_SPINCONTROL:
|
|
// MenuSpinControl_DoEnter ( (menulist_s *)item );
|
|
return false;
|
|
case MTYPE_KEYBIND:
|
|
MenuKeyBind_DoEnter ( (menukeybind_s *)item );
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
UI_MouseSelectItem
|
|
=================
|
|
*/
|
|
qboolean UI_MouseSelectItem (menucommon_s *item)
|
|
{
|
|
if (!item) return false;
|
|
|
|
if (item)
|
|
{
|
|
switch (item->type)
|
|
{
|
|
case MTYPE_FIELD:
|
|
return MenuField_DoEnter ( (menufield_s *)item ) ;
|
|
case MTYPE_ACTION:
|
|
MenuAction_DoEnter ( (menuaction_s *)item );
|
|
return true;
|
|
case MTYPE_KEYBIND:
|
|
MenuKeyBind_DoEnter ( (menukeybind_s *)item );
|
|
return true;
|
|
case MTYPE_LIST:
|
|
case MTYPE_SPINCONTROL:
|
|
return false;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
=================
|
|
UI_SlideMenuItem
|
|
=================
|
|
*/
|
|
void UI_SlideMenuItem (menuframework_s *s, int dir)
|
|
{
|
|
menucommon_s *item=NULL;
|
|
|
|
if (!s) return;
|
|
|
|
item = (menucommon_s *) UI_ItemAtMenuCursor(s);
|
|
|
|
if (item)
|
|
{
|
|
switch (item->type)
|
|
{
|
|
case MTYPE_SLIDER:
|
|
MenuSlider_DoSlide ((menuslider_s *) item, dir);
|
|
break;
|
|
case MTYPE_SPINCONTROL:
|
|
MenuSpinControl_DoSlide ((menulist_s *) item, dir);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|