2
===========================================================================
3
Copyright (C) 1999-2005 Id Software, Inc.
5
This file is part of Quake III Arena source code.
7
Quake III Arena source code is free software; you can redistribute it
8
and/or modify it under the terms of the GNU General Public License as
9
published by the Free Software Foundation; either version 2 of the License,
10
or (at your option) any later version.
12
Quake III Arena source code is distributed in the hope that it will be
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with Quake III Arena source code; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
===========================================================================
23
// string allocation/managment
25
#include "ui_shared.h"
27
#define SCROLL_TIME_START 500
28
#define SCROLL_TIME_ADJUST 150
29
#define SCROLL_TIME_ADJUSTOFFSET 40
30
#define SCROLL_TIME_FLOOR 20
32
typedef struct scrollInfo_s {
43
static scrollInfo_t scrollInfo;
45
static void (*captureFunc) (void *p) = 0;
46
static void *captureData = NULL;
47
static itemDef_t *itemCapture = NULL; // item that has the mouse captured ( if any )
49
displayContextDef_t *DC = NULL;
51
static qboolean g_waitingForKey = qfalse;
52
static qboolean g_editingField = qfalse;
54
static itemDef_t *g_bindItem = NULL;
55
static itemDef_t *g_editItem = NULL;
57
menuDef_t Menus[MAX_MENUS]; // defined menus
58
int menuCount = 0; // how many
60
menuDef_t *menuStack[MAX_OPEN_MENUS];
61
int openMenuCount = 0;
63
static qboolean debugMode = qfalse;
65
#define DOUBLE_CLICK_DELAY 300
66
static int lastListBoxClickTime = 0;
68
void Item_RunScript(itemDef_t *item, const char *s);
69
void Item_SetupKeywordHash(void);
70
void Menu_SetupKeywordHash(void);
71
int BindingIDFromName(const char *name);
72
qboolean Item_Bind_HandleKey(itemDef_t *item, int key, qboolean down);
73
itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu);
74
itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu);
75
static qboolean Menu_OverActiveItem(menuDef_t *menu, float x, float y);
78
#define MEM_POOL_SIZE 128 * 1024
80
#define MEM_POOL_SIZE 1024 * 1024
83
static char memoryPool[MEM_POOL_SIZE];
84
static int allocPoint, outOfMemory;
92
void *UI_Alloc( int size ) {
95
if ( allocPoint + size > MEM_POOL_SIZE ) {
98
DC->Print("UI_Alloc: Failure. Out of memory!\n");
100
//DC->trap_Print(S_COLOR_YELLOW"WARNING: UI Out of Memory!\n");
104
p = &memoryPool[allocPoint];
106
allocPoint += ( size + 15 ) & ~15;
116
void UI_InitMemory( void ) {
118
outOfMemory = qfalse;
121
qboolean UI_OutOfMemory( void ) {
129
#define HASH_TABLE_SIZE 2048
132
return a hash value for the string
135
static unsigned hashForString(const char *str) {
142
while (str[i] != '\0') {
143
letter = tolower(str[i]);
144
hash+=(unsigned)(letter)*(i+119);
147
hash &= (HASH_TABLE_SIZE-1);
151
typedef struct stringDef_s {
152
struct stringDef_s *next;
156
static int strPoolIndex = 0;
157
static char strPool[STRING_POOL_SIZE];
159
static int strHandleCount = 0;
160
static stringDef_t *strHandle[HASH_TABLE_SIZE];
163
const char *String_Alloc(const char *p) {
166
stringDef_t *str, *last;
167
static const char *staticNULL = "";
177
hash = hashForString(p);
179
str = strHandle[hash];
181
if (strcmp(p, str->str) == 0) {
188
if (len + strPoolIndex + 1 < STRING_POOL_SIZE) {
189
int ph = strPoolIndex;
190
strcpy(&strPool[strPoolIndex], p);
191
strPoolIndex += len + 1;
193
str = strHandle[hash];
195
while (str && str->next) {
200
str = UI_Alloc(sizeof(stringDef_t));
202
str->str = &strPool[ph];
206
strHandle[hash] = str;
213
void String_Report(void) {
215
Com_Printf("Memory/String Pool Info\n");
216
Com_Printf("----------------\n");
218
f /= STRING_POOL_SIZE;
220
Com_Printf("String Pool is %.1f%% full, %i bytes out of %i used.\n", f, strPoolIndex, STRING_POOL_SIZE);
224
Com_Printf("Memory Pool is %.1f%% full, %i bytes out of %i used.\n", f, allocPoint, MEM_POOL_SIZE);
232
void String_Init(void) {
234
for (i = 0; i < HASH_TABLE_SIZE; i++) {
242
Item_SetupKeywordHash();
243
Menu_SetupKeywordHash();
244
if (DC && DC->getBindingBuf) {
245
Controls_GetConfig();
254
void PC_SourceWarning(int handle, char *format, ...) {
258
static char string[4096];
260
va_start (argptr, format);
261
vsprintf (string, format, argptr);
266
trap_PC_SourceFileAndLine(handle, filename, &line);
268
Com_Printf(S_COLOR_YELLOW "WARNING: %s, line %d: %s\n", filename, line, string);
276
void PC_SourceError(int handle, char *format, ...) {
280
static char string[4096];
282
va_start (argptr, format);
283
vsprintf (string, format, argptr);
288
trap_PC_SourceFileAndLine(handle, filename, &line);
290
Com_Printf(S_COLOR_RED "ERROR: %s, line %d: %s\n", filename, line, string);
298
void LerpColor(vec4_t a, vec4_t b, vec4_t c, float t)
302
// lerp and clamp each component
305
c[i] = a[i] + t*(b[i]-a[i]);
318
qboolean Float_Parse(char **p, float *f) {
320
token = COM_ParseExt(p, qfalse);
321
if (token && token[0] != 0) {
334
qboolean PC_Float_Parse(int handle, float *f) {
336
int negative = qfalse;
338
if (!trap_PC_ReadToken(handle, &token))
340
if (token.string[0] == '-') {
341
if (!trap_PC_ReadToken(handle, &token))
345
if (token.type != TT_NUMBER) {
346
PC_SourceError(handle, "expected float but found %s\n", token.string);
350
*f = -token.floatvalue;
352
*f = token.floatvalue;
361
qboolean Color_Parse(char **p, vec4_t *c) {
365
for (i = 0; i < 4; i++) {
366
if (!Float_Parse(p, &f)) {
379
qboolean PC_Color_Parse(int handle, vec4_t *c) {
383
for (i = 0; i < 4; i++) {
384
if (!PC_Float_Parse(handle, &f)) {
397
qboolean Int_Parse(char **p, int *i) {
399
token = COM_ParseExt(p, qfalse);
401
if (token && token[0] != 0) {
414
qboolean PC_Int_Parse(int handle, int *i) {
416
int negative = qfalse;
418
if (!trap_PC_ReadToken(handle, &token))
420
if (token.string[0] == '-') {
421
if (!trap_PC_ReadToken(handle, &token))
425
if (token.type != TT_NUMBER) {
426
PC_SourceError(handle, "expected integer but found %s\n", token.string);
440
qboolean Rect_Parse(char **p, rectDef_t *r) {
441
if (Float_Parse(p, &r->x)) {
442
if (Float_Parse(p, &r->y)) {
443
if (Float_Parse(p, &r->w)) {
444
if (Float_Parse(p, &r->h)) {
458
qboolean PC_Rect_Parse(int handle, rectDef_t *r) {
459
if (PC_Float_Parse(handle, &r->x)) {
460
if (PC_Float_Parse(handle, &r->y)) {
461
if (PC_Float_Parse(handle, &r->w)) {
462
if (PC_Float_Parse(handle, &r->h)) {
476
qboolean String_Parse(char **p, const char **out) {
479
token = COM_ParseExt(p, qfalse);
480
if (token && token[0] != 0) {
481
*(out) = String_Alloc(token);
492
qboolean PC_String_Parse(int handle, const char **out) {
495
if (!trap_PC_ReadToken(handle, &token))
498
*(out) = String_Alloc(token.string);
507
qboolean PC_Script_Parse(int handle, const char **out) {
511
memset(script, 0, sizeof(script));
512
// scripts start with { and have ; separated command lists.. commands are command, arg..
513
// basically we want everything between the { } as it will be interpreted at run time
515
if (!trap_PC_ReadToken(handle, &token))
517
if (Q_stricmp(token.string, "{") != 0) {
522
if (!trap_PC_ReadToken(handle, &token))
525
if (Q_stricmp(token.string, "}") == 0) {
526
*out = String_Alloc(script);
530
if (token.string[1] != '\0') {
531
Q_strcat(script, 1024, va("\"%s\"", token.string));
533
Q_strcat(script, 1024, token.string);
535
Q_strcat(script, 1024, " ");
537
return qfalse; // bk001105 - LCC missing return value
540
// display, window, menu, item code
547
Initializes the display with a structure to all the drawing routines
550
void Init_Display(displayContextDef_t *dc) {
556
// type and style painting
558
void GradientBar_Paint(rectDef_t *rect, vec4_t color) {
559
// gradient bar takes two paints
560
DC->setColor( color );
561
DC->drawHandlePic(rect->x, rect->y, rect->w, rect->h, DC->Assets.gradientBar);
562
DC->setColor( NULL );
570
Initializes a window structure ( windowDef_t ) with defaults
574
void Window_Init(Window *w) {
575
memset(w, 0, sizeof(windowDef_t));
577
w->foreColor[0] = w->foreColor[1] = w->foreColor[2] = w->foreColor[3] = 1.0;
581
void Fade(int *flags, float *f, float clamp, int *nextTime, int offsetTime, qboolean bFlags, float fadeAmount) {
582
if (*flags & (WINDOW_FADINGOUT | WINDOW_FADINGIN)) {
583
if (DC->realTime > *nextTime) {
584
*nextTime = DC->realTime + offsetTime;
585
if (*flags & WINDOW_FADINGOUT) {
587
if (bFlags && *f <= 0.0) {
588
*flags &= ~(WINDOW_FADINGOUT | WINDOW_VISIBLE);
595
*flags &= ~WINDOW_FADINGIN;
605
void Window_Paint(Window *w, float fadeAmount, float fadeClamp, float fadeCycle) {
606
//float bordersize = 0;
608
rectDef_t fillRect = w->rect;
612
color[0] = color[1] = color[2] = color[3] = 1;
613
DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, 1, color);
616
if (w == NULL || (w->style == 0 && w->border == 0)) {
620
if (w->border != 0) {
621
fillRect.x += w->borderSize;
622
fillRect.y += w->borderSize;
623
fillRect.w -= w->borderSize + 1;
624
fillRect.h -= w->borderSize + 1;
627
if (w->style == WINDOW_STYLE_FILLED) {
628
// box, but possible a shader that needs filled
630
Fade(&w->flags, &w->backColor[3], fadeClamp, &w->nextTime, fadeCycle, qtrue, fadeAmount);
631
DC->setColor(w->backColor);
632
DC->drawHandlePic(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->background);
635
DC->fillRect(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->backColor);
637
} else if (w->style == WINDOW_STYLE_GRADIENT) {
638
GradientBar_Paint(&fillRect, w->backColor);
640
} else if (w->style == WINDOW_STYLE_SHADER) {
641
if (w->flags & WINDOW_FORECOLORSET) {
642
DC->setColor(w->foreColor);
644
DC->drawHandlePic(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->background);
646
} else if (w->style == WINDOW_STYLE_TEAMCOLOR) {
647
if (DC->getTeamColor) {
648
DC->getTeamColor(&color);
649
DC->fillRect(fillRect.x, fillRect.y, fillRect.w, fillRect.h, color);
651
} else if (w->style == WINDOW_STYLE_CINEMATIC) {
652
if (w->cinematic == -1) {
653
w->cinematic = DC->playCinematic(w->cinematicName, fillRect.x, fillRect.y, fillRect.w, fillRect.h);
654
if (w->cinematic == -1) {
658
if (w->cinematic >= 0) {
659
DC->runCinematicFrame(w->cinematic);
660
DC->drawCinematic(w->cinematic, fillRect.x, fillRect.y, fillRect.w, fillRect.h);
664
if (w->border == WINDOW_BORDER_FULL) {
667
if (w->style == WINDOW_STYLE_TEAMCOLOR) {
671
color[1] = color[2] = .5;
675
color[0] = color[1] = .5;
678
DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize, color);
680
DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize, w->borderColor);
682
} else if (w->border == WINDOW_BORDER_HORZ) {
684
DC->setColor(w->borderColor);
685
DC->drawTopBottom(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize);
686
DC->setColor( NULL );
687
} else if (w->border == WINDOW_BORDER_VERT) {
689
DC->setColor(w->borderColor);
690
DC->drawSides(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize);
691
DC->setColor( NULL );
692
} else if (w->border == WINDOW_BORDER_KCGRADIENT) {
693
// this is just two gradient bars along each horz edge
694
rectDef_t r = w->rect;
696
GradientBar_Paint(&r, w->borderColor);
697
r.y = w->rect.y + w->rect.h - 1;
698
GradientBar_Paint(&r, w->borderColor);
704
void Item_SetScreenCoords(itemDef_t *item, float x, float y) {
710
if (item->window.border != 0) {
711
x += item->window.borderSize;
712
y += item->window.borderSize;
715
item->window.rect.x = x + item->window.rectClient.x;
716
item->window.rect.y = y + item->window.rectClient.y;
717
item->window.rect.w = item->window.rectClient.w;
718
item->window.rect.h = item->window.rectClient.h;
720
// force the text rects to recompute
721
item->textRect.w = 0;
722
item->textRect.h = 0;
725
// FIXME: consolidate this with nearby stuff
726
void Item_UpdatePosition(itemDef_t *item) {
730
if (item == NULL || item->parent == NULL) {
736
x = menu->window.rect.x;
737
y = menu->window.rect.y;
739
if (menu->window.border != 0) {
740
x += menu->window.borderSize;
741
y += menu->window.borderSize;
744
Item_SetScreenCoords(item, x, y);
749
void Menu_UpdatePosition(menuDef_t *menu) {
757
x = menu->window.rect.x;
758
y = menu->window.rect.y;
759
if (menu->window.border != 0) {
760
x += menu->window.borderSize;
761
y += menu->window.borderSize;
764
for (i = 0; i < menu->itemCount; i++) {
765
Item_SetScreenCoords(menu->items[i], x, y);
769
void Menu_PostParse(menuDef_t *menu) {
773
if (menu->fullScreen) {
774
menu->window.rect.x = 0;
775
menu->window.rect.y = 0;
776
menu->window.rect.w = 640;
777
menu->window.rect.h = 480;
779
Menu_UpdatePosition(menu);
782
itemDef_t *Menu_ClearFocus(menuDef_t *menu) {
784
itemDef_t *ret = NULL;
790
for (i = 0; i < menu->itemCount; i++) {
791
if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
792
ret = menu->items[i];
794
menu->items[i]->window.flags &= ~WINDOW_HASFOCUS;
795
if (menu->items[i]->leaveFocus) {
796
Item_RunScript(menu->items[i], menu->items[i]->leaveFocus);
803
qboolean IsVisible(int flags) {
804
return (flags & WINDOW_VISIBLE && !(flags & WINDOW_FADINGOUT));
807
qboolean Rect_ContainsPoint(rectDef_t *rect, float x, float y) {
809
if (x > rect->x && x < rect->x + rect->w && y > rect->y && y < rect->y + rect->h) {
816
int Menu_ItemsMatchingGroup(menuDef_t *menu, const char *name) {
819
for (i = 0; i < menu->itemCount; i++) {
820
if (Q_stricmp(menu->items[i]->window.name, name) == 0 || (menu->items[i]->window.group && Q_stricmp(menu->items[i]->window.group, name) == 0)) {
827
itemDef_t *Menu_GetMatchingItemByNumber(menuDef_t *menu, int index, const char *name) {
830
for (i = 0; i < menu->itemCount; i++) {
831
if (Q_stricmp(menu->items[i]->window.name, name) == 0 || (menu->items[i]->window.group && Q_stricmp(menu->items[i]->window.group, name) == 0)) {
832
if (count == index) {
833
return menu->items[i];
843
void Script_SetColor(itemDef_t *item, char **args) {
848
// expecting type of color to set and 4 args for the color
849
if (String_Parse(args, &name)) {
851
if (Q_stricmp(name, "backcolor") == 0) {
852
out = &item->window.backColor;
853
item->window.flags |= WINDOW_BACKCOLORSET;
854
} else if (Q_stricmp(name, "forecolor") == 0) {
855
out = &item->window.foreColor;
856
item->window.flags |= WINDOW_FORECOLORSET;
857
} else if (Q_stricmp(name, "bordercolor") == 0) {
858
out = &item->window.borderColor;
862
for (i = 0; i < 4; i++) {
863
if (!Float_Parse(args, &f)) {
872
void Script_SetAsset(itemDef_t *item, char **args) {
874
// expecting name to set asset to
875
if (String_Parse(args, &name)) {
877
if (item->type == ITEM_TYPE_MODEL) {
882
void Script_SetBackground(itemDef_t *item, char **args) {
884
// expecting name to set asset to
885
if (String_Parse(args, &name)) {
886
item->window.background = DC->registerShaderNoMip(name);
893
itemDef_t *Menu_FindItemByName(menuDef_t *menu, const char *p) {
895
if (menu == NULL || p == NULL) {
899
for (i = 0; i < menu->itemCount; i++) {
900
if (Q_stricmp(p, menu->items[i]->window.name) == 0) {
901
return menu->items[i];
908
void Script_SetTeamColor(itemDef_t *item, char **args) {
909
if (DC->getTeamColor) {
912
DC->getTeamColor(&color);
913
for (i = 0; i < 4; i++) {
914
item->window.backColor[i] = color[i];
919
void Script_SetItemColor(itemDef_t *item, char **args) {
920
const char *itemname;
925
// expecting type of color to set and 4 args for the color
926
if (String_Parse(args, &itemname) && String_Parse(args, &name)) {
929
int count = Menu_ItemsMatchingGroup(item->parent, itemname);
931
if (!Color_Parse(args, &color)) {
935
for (j = 0; j < count; j++) {
936
item2 = Menu_GetMatchingItemByNumber(item->parent, j, itemname);
939
if (Q_stricmp(name, "backcolor") == 0) {
940
out = &item2->window.backColor;
941
} else if (Q_stricmp(name, "forecolor") == 0) {
942
out = &item2->window.foreColor;
943
item2->window.flags |= WINDOW_FORECOLORSET;
944
} else if (Q_stricmp(name, "bordercolor") == 0) {
945
out = &item2->window.borderColor;
949
for (i = 0; i < 4; i++) {
950
(*out)[i] = color[i];
959
void Menu_ShowItemByName(menuDef_t *menu, const char *p, qboolean bShow) {
962
int count = Menu_ItemsMatchingGroup(menu, p);
963
for (i = 0; i < count; i++) {
964
item = Menu_GetMatchingItemByNumber(menu, i, p);
967
item->window.flags |= WINDOW_VISIBLE;
969
item->window.flags &= ~WINDOW_VISIBLE;
970
// stop cinematics playing in the window
971
if (item->window.cinematic >= 0) {
972
DC->stopCinematic(item->window.cinematic);
973
item->window.cinematic = -1;
980
void Menu_FadeItemByName(menuDef_t *menu, const char *p, qboolean fadeOut) {
983
int count = Menu_ItemsMatchingGroup(menu, p);
984
for (i = 0; i < count; i++) {
985
item = Menu_GetMatchingItemByNumber(menu, i, p);
988
item->window.flags |= (WINDOW_FADINGOUT | WINDOW_VISIBLE);
989
item->window.flags &= ~WINDOW_FADINGIN;
991
item->window.flags |= (WINDOW_VISIBLE | WINDOW_FADINGIN);
992
item->window.flags &= ~WINDOW_FADINGOUT;
998
menuDef_t *Menus_FindByName(const char *p) {
1000
for (i = 0; i < menuCount; i++) {
1001
if (Q_stricmp(Menus[i].window.name, p) == 0) {
1008
void Menus_ShowByName(const char *p) {
1009
menuDef_t *menu = Menus_FindByName(p);
1011
Menus_Activate(menu);
1015
void Menus_OpenByName(const char *p) {
1016
Menus_ActivateByName(p);
1019
static void Menu_RunCloseScript(menuDef_t *menu) {
1020
if (menu && menu->window.flags & WINDOW_VISIBLE && menu->onClose) {
1023
Item_RunScript(&item, menu->onClose);
1027
void Menus_CloseByName(const char *p) {
1028
menuDef_t *menu = Menus_FindByName(p);
1030
Menu_RunCloseScript(menu);
1031
menu->window.flags &= ~(WINDOW_VISIBLE | WINDOW_HASFOCUS);
1035
void Menus_CloseAll(void) {
1037
for (i = 0; i < menuCount; i++) {
1038
Menu_RunCloseScript(&Menus[i]);
1039
Menus[i].window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
1044
void Script_Show(itemDef_t *item, char **args) {
1046
if (String_Parse(args, &name)) {
1047
Menu_ShowItemByName(item->parent, name, qtrue);
1051
void Script_Hide(itemDef_t *item, char **args) {
1053
if (String_Parse(args, &name)) {
1054
Menu_ShowItemByName(item->parent, name, qfalse);
1058
void Script_FadeIn(itemDef_t *item, char **args) {
1060
if (String_Parse(args, &name)) {
1061
Menu_FadeItemByName(item->parent, name, qfalse);
1065
void Script_FadeOut(itemDef_t *item, char **args) {
1067
if (String_Parse(args, &name)) {
1068
Menu_FadeItemByName(item->parent, name, qtrue);
1074
void Script_Open(itemDef_t *item, char **args) {
1076
if (String_Parse(args, &name)) {
1077
Menus_OpenByName(name);
1081
void Script_ConditionalOpen(itemDef_t *item, char **args) {
1087
if ( String_Parse(args, &cvar) && String_Parse(args, &name1) && String_Parse(args, &name2) ) {
1088
val = DC->getCVarValue( cvar );
1090
Menus_OpenByName(name2);
1092
Menus_OpenByName(name1);
1097
void Script_Close(itemDef_t *item, char **args) {
1099
if (String_Parse(args, &name)) {
1100
Menus_CloseByName(name);
1104
void Menu_TransitionItemByName(menuDef_t *menu, const char *p, rectDef_t rectFrom, rectDef_t rectTo, int time, float amt) {
1107
int count = Menu_ItemsMatchingGroup(menu, p);
1108
for (i = 0; i < count; i++) {
1109
item = Menu_GetMatchingItemByNumber(menu, i, p);
1111
item->window.flags |= (WINDOW_INTRANSITION | WINDOW_VISIBLE);
1112
item->window.offsetTime = time;
1113
memcpy(&item->window.rectClient, &rectFrom, sizeof(rectDef_t));
1114
memcpy(&item->window.rectEffects, &rectTo, sizeof(rectDef_t));
1115
item->window.rectEffects2.x = abs(rectTo.x - rectFrom.x) / amt;
1116
item->window.rectEffects2.y = abs(rectTo.y - rectFrom.y) / amt;
1117
item->window.rectEffects2.w = abs(rectTo.w - rectFrom.w) / amt;
1118
item->window.rectEffects2.h = abs(rectTo.h - rectFrom.h) / amt;
1119
Item_UpdatePosition(item);
1125
void Script_Transition(itemDef_t *item, char **args) {
1127
rectDef_t rectFrom, rectTo;
1131
if (String_Parse(args, &name)) {
1132
if ( Rect_Parse(args, &rectFrom) && Rect_Parse(args, &rectTo) && Int_Parse(args, &time) && Float_Parse(args, &amt)) {
1133
Menu_TransitionItemByName(item->parent, name, rectFrom, rectTo, time, amt);
1139
void Menu_OrbitItemByName(menuDef_t *menu, const char *p, float x, float y, float cx, float cy, int time) {
1142
int count = Menu_ItemsMatchingGroup(menu, p);
1143
for (i = 0; i < count; i++) {
1144
item = Menu_GetMatchingItemByNumber(menu, i, p);
1146
item->window.flags |= (WINDOW_ORBITING | WINDOW_VISIBLE);
1147
item->window.offsetTime = time;
1148
item->window.rectEffects.x = cx;
1149
item->window.rectEffects.y = cy;
1150
item->window.rectClient.x = x;
1151
item->window.rectClient.y = y;
1152
Item_UpdatePosition(item);
1158
void Script_Orbit(itemDef_t *item, char **args) {
1163
if (String_Parse(args, &name)) {
1164
if ( Float_Parse(args, &x) && Float_Parse(args, &y) && Float_Parse(args, &cx) && Float_Parse(args, &cy) && Int_Parse(args, &time) ) {
1165
Menu_OrbitItemByName(item->parent, name, x, y, cx, cy, time);
1172
void Script_SetFocus(itemDef_t *item, char **args) {
1174
itemDef_t *focusItem;
1176
if (String_Parse(args, &name)) {
1177
focusItem = Menu_FindItemByName(item->parent, name);
1178
if (focusItem && !(focusItem->window.flags & WINDOW_DECORATION) && !(focusItem->window.flags & WINDOW_HASFOCUS)) {
1179
Menu_ClearFocus(item->parent);
1180
focusItem->window.flags |= WINDOW_HASFOCUS;
1181
if (focusItem->onFocus) {
1182
Item_RunScript(focusItem, focusItem->onFocus);
1184
if (DC->Assets.itemFocusSound) {
1185
DC->startLocalSound( DC->Assets.itemFocusSound, CHAN_LOCAL_SOUND );
1191
void Script_SetPlayerModel(itemDef_t *item, char **args) {
1193
if (String_Parse(args, &name)) {
1194
DC->setCVar("team_model", name);
1198
void Script_SetPlayerHead(itemDef_t *item, char **args) {
1200
if (String_Parse(args, &name)) {
1201
DC->setCVar("team_headmodel", name);
1205
void Script_SetCvar(itemDef_t *item, char **args) {
1206
const char *cvar, *val;
1207
if (String_Parse(args, &cvar) && String_Parse(args, &val)) {
1208
DC->setCVar(cvar, val);
1213
void Script_Exec(itemDef_t *item, char **args) {
1215
if (String_Parse(args, &val)) {
1216
DC->executeText(EXEC_APPEND, va("%s ; ", val));
1220
void Script_Play(itemDef_t *item, char **args) {
1222
if (String_Parse(args, &val)) {
1223
DC->startLocalSound(DC->registerSound(val, qfalse), CHAN_LOCAL_SOUND);
1227
void Script_playLooped(itemDef_t *item, char **args) {
1229
if (String_Parse(args, &val)) {
1230
DC->stopBackgroundTrack();
1231
DC->startBackgroundTrack(val, val);
1236
commandDef_t commandList[] =
1238
{"fadein", &Script_FadeIn}, // group/name
1239
{"fadeout", &Script_FadeOut}, // group/name
1240
{"show", &Script_Show}, // group/name
1241
{"hide", &Script_Hide}, // group/name
1242
{"setcolor", &Script_SetColor}, // works on this
1243
{"open", &Script_Open}, // menu
1244
{"conditionalopen", &Script_ConditionalOpen}, // menu
1245
{"close", &Script_Close}, // menu
1246
{"setasset", &Script_SetAsset}, // works on this
1247
{"setbackground", &Script_SetBackground}, // works on this
1248
{"setitemcolor", &Script_SetItemColor}, // group/name
1249
{"setteamcolor", &Script_SetTeamColor}, // sets this background color to team color
1250
{"setfocus", &Script_SetFocus}, // sets this background color to team color
1251
{"setplayermodel", &Script_SetPlayerModel}, // sets this background color to team color
1252
{"setplayerhead", &Script_SetPlayerHead}, // sets this background color to team color
1253
{"transition", &Script_Transition}, // group/name
1254
{"setcvar", &Script_SetCvar}, // group/name
1255
{"exec", &Script_Exec}, // group/name
1256
{"play", &Script_Play}, // group/name
1257
{"playlooped", &Script_playLooped}, // group/name
1258
{"orbit", &Script_Orbit} // group/name
1261
int scriptCommandCount = sizeof(commandList) / sizeof(commandDef_t);
1264
void Item_RunScript(itemDef_t *item, const char *s) {
1265
char script[1024], *p;
1268
memset(script, 0, sizeof(script));
1269
if (item && s && s[0]) {
1270
Q_strcat(script, 1024, s);
1273
const char *command;
1274
// expect command then arguments, ; ends command, NULL ends script
1275
if (!String_Parse(&p, &command)) {
1279
if (command[0] == ';' && command[1] == '\0') {
1284
for (i = 0; i < scriptCommandCount; i++) {
1285
if (Q_stricmp(command, commandList[i].name) == 0) {
1286
(commandList[i].handler(item, &p));
1291
// not in our auto list, pass to handler
1300
qboolean Item_EnableShowViaCvar(itemDef_t *item, int flag) {
1301
char script[1024], *p;
1302
memset(script, 0, sizeof(script));
1303
if (item && item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest) {
1305
DC->getCVarString(item->cvarTest, buff, sizeof(buff));
1307
Q_strcat(script, 1024, item->enableCvar);
1311
// expect value then ; or NULL, NULL ends list
1312
if (!String_Parse(&p, &val)) {
1313
return (item->cvarFlags & flag) ? qfalse : qtrue;
1316
if (val[0] == ';' && val[1] == '\0') {
1320
// enable it if any of the values are true
1321
if (item->cvarFlags & flag) {
1322
if (Q_stricmp(buff, val) == 0) {
1326
// disable it if any of the values are true
1327
if (Q_stricmp(buff, val) == 0) {
1333
return (item->cvarFlags & flag) ? qfalse : qtrue;
1339
// will optionaly set focus to this item
1340
qboolean Item_SetFocus(itemDef_t *item, float x, float y) {
1342
itemDef_t *oldFocus;
1343
sfxHandle_t *sfx = &DC->Assets.itemFocusSound;
1344
qboolean playSound = qfalse;
1345
menuDef_t *parent; // bk001206: = (menuDef_t*)item->parent;
1346
// sanity check, non-null, not a decoration and does not already have the focus
1347
if (item == NULL || item->window.flags & WINDOW_DECORATION || item->window.flags & WINDOW_HASFOCUS || !(item->window.flags & WINDOW_VISIBLE)) {
1351
// bk001206 - this can be NULL.
1352
parent = (menuDef_t*)item->parent;
1354
// items can be enabled and disabled based on cvars
1355
if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
1359
if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW)) {
1363
oldFocus = Menu_ClearFocus(item->parent);
1365
if (item->type == ITEM_TYPE_TEXT) {
1369
if (Rect_ContainsPoint(&r, x, y)) {
1370
item->window.flags |= WINDOW_HASFOCUS;
1371
if (item->focusSound) {
1372
sfx = &item->focusSound;
1377
oldFocus->window.flags |= WINDOW_HASFOCUS;
1378
if (oldFocus->onFocus) {
1379
Item_RunScript(oldFocus, oldFocus->onFocus);
1384
item->window.flags |= WINDOW_HASFOCUS;
1385
if (item->onFocus) {
1386
Item_RunScript(item, item->onFocus);
1388
if (item->focusSound) {
1389
sfx = &item->focusSound;
1394
if (playSound && sfx) {
1395
DC->startLocalSound( *sfx, CHAN_LOCAL_SOUND );
1398
for (i = 0; i < parent->itemCount; i++) {
1399
if (parent->items[i] == item) {
1400
parent->cursorItem = i;
1408
int Item_ListBox_MaxScroll(itemDef_t *item) {
1409
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
1410
int count = DC->feederCount(item->special);
1413
if (item->window.flags & WINDOW_HORIZONTAL) {
1414
max = count - (item->window.rect.w / listPtr->elementWidth) + 1;
1417
max = count - (item->window.rect.h / listPtr->elementHeight) + 1;
1425
int Item_ListBox_ThumbPosition(itemDef_t *item) {
1426
float max, pos, size;
1427
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
1429
max = Item_ListBox_MaxScroll(item);
1430
if (item->window.flags & WINDOW_HORIZONTAL) {
1431
size = item->window.rect.w - (SCROLLBAR_SIZE * 2) - 2;
1433
pos = (size-SCROLLBAR_SIZE) / (float) max;
1437
pos *= listPtr->startPos;
1438
return item->window.rect.x + 1 + SCROLLBAR_SIZE + pos;
1441
size = item->window.rect.h - (SCROLLBAR_SIZE * 2) - 2;
1443
pos = (size-SCROLLBAR_SIZE) / (float) max;
1447
pos *= listPtr->startPos;
1448
return item->window.rect.y + 1 + SCROLLBAR_SIZE + pos;
1452
int Item_ListBox_ThumbDrawPosition(itemDef_t *item) {
1455
if (itemCapture == item) {
1456
if (item->window.flags & WINDOW_HORIZONTAL) {
1457
min = item->window.rect.x + SCROLLBAR_SIZE + 1;
1458
max = item->window.rect.x + item->window.rect.w - 2*SCROLLBAR_SIZE - 1;
1459
if (DC->cursorx >= min + SCROLLBAR_SIZE/2 && DC->cursorx <= max + SCROLLBAR_SIZE/2) {
1460
return DC->cursorx - SCROLLBAR_SIZE/2;
1463
return Item_ListBox_ThumbPosition(item);
1467
min = item->window.rect.y + SCROLLBAR_SIZE + 1;
1468
max = item->window.rect.y + item->window.rect.h - 2*SCROLLBAR_SIZE - 1;
1469
if (DC->cursory >= min + SCROLLBAR_SIZE/2 && DC->cursory <= max + SCROLLBAR_SIZE/2) {
1470
return DC->cursory - SCROLLBAR_SIZE/2;
1473
return Item_ListBox_ThumbPosition(item);
1478
return Item_ListBox_ThumbPosition(item);
1482
float Item_Slider_ThumbPosition(itemDef_t *item) {
1483
float value, range, x;
1484
editFieldDef_t *editDef = item->typeData;
1487
x = item->textRect.x + item->textRect.w + 8;
1489
x = item->window.rect.x;
1492
if (editDef == NULL && item->cvar) {
1496
value = DC->getCVarValue(item->cvar);
1498
if (value < editDef->minVal) {
1499
value = editDef->minVal;
1500
} else if (value > editDef->maxVal) {
1501
value = editDef->maxVal;
1504
range = editDef->maxVal - editDef->minVal;
1505
value -= editDef->minVal;
1507
//value /= (editDef->maxVal - editDef->minVal);
1508
value *= SLIDER_WIDTH;
1511
//x = x + (((float)value / editDef->maxVal) * SLIDER_WIDTH);
1515
int Item_Slider_OverSlider(itemDef_t *item, float x, float y) {
1518
r.x = Item_Slider_ThumbPosition(item) - (SLIDER_THUMB_WIDTH / 2);
1519
r.y = item->window.rect.y - 2;
1520
r.w = SLIDER_THUMB_WIDTH;
1521
r.h = SLIDER_THUMB_HEIGHT;
1523
if (Rect_ContainsPoint(&r, x, y)) {
1524
return WINDOW_LB_THUMB;
1529
int Item_ListBox_OverLB(itemDef_t *item, float x, float y) {
1531
listBoxDef_t *listPtr;
1535
count = DC->feederCount(item->special);
1536
listPtr = (listBoxDef_t*)item->typeData;
1537
if (item->window.flags & WINDOW_HORIZONTAL) {
1538
// check if on left arrow
1539
r.x = item->window.rect.x;
1540
r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
1541
r.h = r.w = SCROLLBAR_SIZE;
1542
if (Rect_ContainsPoint(&r, x, y)) {
1543
return WINDOW_LB_LEFTARROW;
1545
// check if on right arrow
1546
r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
1547
if (Rect_ContainsPoint(&r, x, y)) {
1548
return WINDOW_LB_RIGHTARROW;
1550
// check if on thumb
1551
thumbstart = Item_ListBox_ThumbPosition(item);
1553
if (Rect_ContainsPoint(&r, x, y)) {
1554
return WINDOW_LB_THUMB;
1556
r.x = item->window.rect.x + SCROLLBAR_SIZE;
1557
r.w = thumbstart - r.x;
1558
if (Rect_ContainsPoint(&r, x, y)) {
1559
return WINDOW_LB_PGUP;
1561
r.x = thumbstart + SCROLLBAR_SIZE;
1562
r.w = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
1563
if (Rect_ContainsPoint(&r, x, y)) {
1564
return WINDOW_LB_PGDN;
1567
r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
1568
r.y = item->window.rect.y;
1569
r.h = r.w = SCROLLBAR_SIZE;
1570
if (Rect_ContainsPoint(&r, x, y)) {
1571
return WINDOW_LB_LEFTARROW;
1573
r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
1574
if (Rect_ContainsPoint(&r, x, y)) {
1575
return WINDOW_LB_RIGHTARROW;
1577
thumbstart = Item_ListBox_ThumbPosition(item);
1579
if (Rect_ContainsPoint(&r, x, y)) {
1580
return WINDOW_LB_THUMB;
1582
r.y = item->window.rect.y + SCROLLBAR_SIZE;
1583
r.h = thumbstart - r.y;
1584
if (Rect_ContainsPoint(&r, x, y)) {
1585
return WINDOW_LB_PGUP;
1587
r.y = thumbstart + SCROLLBAR_SIZE;
1588
r.h = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
1589
if (Rect_ContainsPoint(&r, x, y)) {
1590
return WINDOW_LB_PGDN;
1597
void Item_ListBox_MouseEnter(itemDef_t *item, float x, float y)
1600
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
1602
item->window.flags &= ~(WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN);
1603
item->window.flags |= Item_ListBox_OverLB(item, x, y);
1605
if (item->window.flags & WINDOW_HORIZONTAL) {
1606
if (!(item->window.flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN))) {
1607
// check for selection hit as we have exausted buttons and thumb
1608
if (listPtr->elementStyle == LISTBOX_IMAGE) {
1609
r.x = item->window.rect.x;
1610
r.y = item->window.rect.y;
1611
r.h = item->window.rect.h - SCROLLBAR_SIZE;
1612
r.w = item->window.rect.w - listPtr->drawPadding;
1613
if (Rect_ContainsPoint(&r, x, y)) {
1614
listPtr->cursorPos = (int)((x - r.x) / listPtr->elementWidth) + listPtr->startPos;
1615
if (listPtr->cursorPos >= listPtr->endPos) {
1616
listPtr->cursorPos = listPtr->endPos;
1623
} else if (!(item->window.flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN))) {
1624
r.x = item->window.rect.x;
1625
r.y = item->window.rect.y;
1626
r.w = item->window.rect.w - SCROLLBAR_SIZE;
1627
r.h = item->window.rect.h - listPtr->drawPadding;
1628
if (Rect_ContainsPoint(&r, x, y)) {
1629
listPtr->cursorPos = (int)((y - 2 - r.y) / listPtr->elementHeight) + listPtr->startPos;
1630
if (listPtr->cursorPos > listPtr->endPos) {
1631
listPtr->cursorPos = listPtr->endPos;
1637
void Item_MouseEnter(itemDef_t *item, float x, float y) {
1642
// in the text rect?
1644
// items can be enabled and disabled based on cvars
1645
if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
1649
if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW)) {
1653
if (Rect_ContainsPoint(&r, x, y)) {
1654
if (!(item->window.flags & WINDOW_MOUSEOVERTEXT)) {
1655
Item_RunScript(item, item->mouseEnterText);
1656
item->window.flags |= WINDOW_MOUSEOVERTEXT;
1658
if (!(item->window.flags & WINDOW_MOUSEOVER)) {
1659
Item_RunScript(item, item->mouseEnter);
1660
item->window.flags |= WINDOW_MOUSEOVER;
1664
// not in the text rect
1665
if (item->window.flags & WINDOW_MOUSEOVERTEXT) {
1667
Item_RunScript(item, item->mouseExitText);
1668
item->window.flags &= ~WINDOW_MOUSEOVERTEXT;
1670
if (!(item->window.flags & WINDOW_MOUSEOVER)) {
1671
Item_RunScript(item, item->mouseEnter);
1672
item->window.flags |= WINDOW_MOUSEOVER;
1675
if (item->type == ITEM_TYPE_LISTBOX) {
1676
Item_ListBox_MouseEnter(item, x, y);
1682
void Item_MouseLeave(itemDef_t *item) {
1684
if (item->window.flags & WINDOW_MOUSEOVERTEXT) {
1685
Item_RunScript(item, item->mouseExitText);
1686
item->window.flags &= ~WINDOW_MOUSEOVERTEXT;
1688
Item_RunScript(item, item->mouseExit);
1689
item->window.flags &= ~(WINDOW_LB_RIGHTARROW | WINDOW_LB_LEFTARROW);
1693
itemDef_t *Menu_HitTest(menuDef_t *menu, float x, float y) {
1695
for (i = 0; i < menu->itemCount; i++) {
1696
if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
1697
return menu->items[i];
1703
void Item_SetMouseOver(itemDef_t *item, qboolean focus) {
1706
item->window.flags |= WINDOW_MOUSEOVER;
1708
item->window.flags &= ~WINDOW_MOUSEOVER;
1714
qboolean Item_OwnerDraw_HandleKey(itemDef_t *item, int key) {
1715
if (item && DC->ownerDrawHandleKey) {
1716
return DC->ownerDrawHandleKey(item->window.ownerDraw, item->window.ownerDrawFlags, &item->special, key);
1721
qboolean Item_ListBox_HandleKey(itemDef_t *item, int key, qboolean down, qboolean force) {
1722
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
1723
int count = DC->feederCount(item->special);
1726
if (force || (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS)) {
1727
max = Item_ListBox_MaxScroll(item);
1728
if (item->window.flags & WINDOW_HORIZONTAL) {
1729
viewmax = (item->window.rect.w / listPtr->elementWidth);
1730
if ( key == K_LEFTARROW || key == K_KP_LEFTARROW )
1732
if (!listPtr->notselectable) {
1733
listPtr->cursorPos--;
1734
if (listPtr->cursorPos < 0) {
1735
listPtr->cursorPos = 0;
1737
if (listPtr->cursorPos < listPtr->startPos) {
1738
listPtr->startPos = listPtr->cursorPos;
1740
if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
1741
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
1743
item->cursorPos = listPtr->cursorPos;
1744
DC->feederSelection(item->special, item->cursorPos);
1747
listPtr->startPos--;
1748
if (listPtr->startPos < 0)
1749
listPtr->startPos = 0;
1753
if ( key == K_RIGHTARROW || key == K_KP_RIGHTARROW )
1755
if (!listPtr->notselectable) {
1756
listPtr->cursorPos++;
1757
if (listPtr->cursorPos < listPtr->startPos) {
1758
listPtr->startPos = listPtr->cursorPos;
1760
if (listPtr->cursorPos >= count) {
1761
listPtr->cursorPos = count-1;
1763
if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
1764
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
1766
item->cursorPos = listPtr->cursorPos;
1767
DC->feederSelection(item->special, item->cursorPos);
1770
listPtr->startPos++;
1771
if (listPtr->startPos >= count)
1772
listPtr->startPos = count-1;
1778
viewmax = (item->window.rect.h / listPtr->elementHeight);
1779
if ( key == K_UPARROW || key == K_KP_UPARROW )
1781
if (!listPtr->notselectable) {
1782
listPtr->cursorPos--;
1783
if (listPtr->cursorPos < 0) {
1784
listPtr->cursorPos = 0;
1786
if (listPtr->cursorPos < listPtr->startPos) {
1787
listPtr->startPos = listPtr->cursorPos;
1789
if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
1790
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
1792
item->cursorPos = listPtr->cursorPos;
1793
DC->feederSelection(item->special, item->cursorPos);
1796
listPtr->startPos--;
1797
if (listPtr->startPos < 0)
1798
listPtr->startPos = 0;
1802
if ( key == K_DOWNARROW || key == K_KP_DOWNARROW )
1804
if (!listPtr->notselectable) {
1805
listPtr->cursorPos++;
1806
if (listPtr->cursorPos < listPtr->startPos) {
1807
listPtr->startPos = listPtr->cursorPos;
1809
if (listPtr->cursorPos >= count) {
1810
listPtr->cursorPos = count-1;
1812
if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
1813
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
1815
item->cursorPos = listPtr->cursorPos;
1816
DC->feederSelection(item->special, item->cursorPos);
1819
listPtr->startPos++;
1820
if (listPtr->startPos > max)
1821
listPtr->startPos = max;
1827
if (key == K_MOUSE1 || key == K_MOUSE2) {
1828
if (item->window.flags & WINDOW_LB_LEFTARROW) {
1829
listPtr->startPos--;
1830
if (listPtr->startPos < 0) {
1831
listPtr->startPos = 0;
1833
} else if (item->window.flags & WINDOW_LB_RIGHTARROW) {
1835
listPtr->startPos++;
1836
if (listPtr->startPos > max) {
1837
listPtr->startPos = max;
1839
} else if (item->window.flags & WINDOW_LB_PGUP) {
1841
listPtr->startPos -= viewmax;
1842
if (listPtr->startPos < 0) {
1843
listPtr->startPos = 0;
1845
} else if (item->window.flags & WINDOW_LB_PGDN) {
1847
listPtr->startPos += viewmax;
1848
if (listPtr->startPos > max) {
1849
listPtr->startPos = max;
1851
} else if (item->window.flags & WINDOW_LB_THUMB) {
1852
// Display_SetCaptureItem(item);
1855
if (DC->realTime < lastListBoxClickTime && listPtr->doubleClick) {
1856
Item_RunScript(item, listPtr->doubleClick);
1858
lastListBoxClickTime = DC->realTime + DOUBLE_CLICK_DELAY;
1859
if (item->cursorPos != listPtr->cursorPos) {
1860
item->cursorPos = listPtr->cursorPos;
1861
DC->feederSelection(item->special, item->cursorPos);
1866
if ( key == K_HOME || key == K_KP_HOME) {
1868
listPtr->startPos = 0;
1871
if ( key == K_END || key == K_KP_END) {
1873
listPtr->startPos = max;
1876
if (key == K_PGUP || key == K_KP_PGUP ) {
1878
if (!listPtr->notselectable) {
1879
listPtr->cursorPos -= viewmax;
1880
if (listPtr->cursorPos < 0) {
1881
listPtr->cursorPos = 0;
1883
if (listPtr->cursorPos < listPtr->startPos) {
1884
listPtr->startPos = listPtr->cursorPos;
1886
if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
1887
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
1889
item->cursorPos = listPtr->cursorPos;
1890
DC->feederSelection(item->special, item->cursorPos);
1893
listPtr->startPos -= viewmax;
1894
if (listPtr->startPos < 0) {
1895
listPtr->startPos = 0;
1900
if ( key == K_PGDN || key == K_KP_PGDN ) {
1902
if (!listPtr->notselectable) {
1903
listPtr->cursorPos += viewmax;
1904
if (listPtr->cursorPos < listPtr->startPos) {
1905
listPtr->startPos = listPtr->cursorPos;
1907
if (listPtr->cursorPos >= count) {
1908
listPtr->cursorPos = count-1;
1910
if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
1911
listPtr->startPos = listPtr->cursorPos - viewmax + 1;
1913
item->cursorPos = listPtr->cursorPos;
1914
DC->feederSelection(item->special, item->cursorPos);
1917
listPtr->startPos += viewmax;
1918
if (listPtr->startPos > max) {
1919
listPtr->startPos = max;
1928
qboolean Item_YesNo_HandleKey(itemDef_t *item, int key) {
1930
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS && item->cvar) {
1931
if (key == K_MOUSE1 || key == K_ENTER || key == K_MOUSE2 || key == K_MOUSE3) {
1932
DC->setCVar(item->cvar, va("%i", !DC->getCVarValue(item->cvar)));
1941
int Item_Multi_CountSettings(itemDef_t *item) {
1942
multiDef_t *multiPtr = (multiDef_t*)item->typeData;
1943
if (multiPtr == NULL) {
1946
return multiPtr->count;
1949
int Item_Multi_FindCvarByValue(itemDef_t *item) {
1953
multiDef_t *multiPtr = (multiDef_t*)item->typeData;
1955
if (multiPtr->strDef) {
1956
DC->getCVarString(item->cvar, buff, sizeof(buff));
1958
value = DC->getCVarValue(item->cvar);
1960
for (i = 0; i < multiPtr->count; i++) {
1961
if (multiPtr->strDef) {
1962
if (Q_stricmp(buff, multiPtr->cvarStr[i]) == 0) {
1966
if (multiPtr->cvarValue[i] == value) {
1975
const char *Item_Multi_Setting(itemDef_t *item) {
1979
multiDef_t *multiPtr = (multiDef_t*)item->typeData;
1981
if (multiPtr->strDef) {
1982
DC->getCVarString(item->cvar, buff, sizeof(buff));
1984
value = DC->getCVarValue(item->cvar);
1986
for (i = 0; i < multiPtr->count; i++) {
1987
if (multiPtr->strDef) {
1988
if (Q_stricmp(buff, multiPtr->cvarStr[i]) == 0) {
1989
return multiPtr->cvarList[i];
1992
if (multiPtr->cvarValue[i] == value) {
1993
return multiPtr->cvarList[i];
2001
qboolean Item_Multi_HandleKey(itemDef_t *item, int key) {
2002
multiDef_t *multiPtr = (multiDef_t*)item->typeData;
2004
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS && item->cvar) {
2005
if (key == K_MOUSE1 || key == K_ENTER || key == K_MOUSE2 || key == K_MOUSE3) {
2006
int current = Item_Multi_FindCvarByValue(item) + 1;
2007
int max = Item_Multi_CountSettings(item);
2008
if ( current < 0 || current >= max ) {
2011
if (multiPtr->strDef) {
2012
DC->setCVar(item->cvar, multiPtr->cvarStr[current]);
2014
float value = multiPtr->cvarValue[current];
2015
if (((float)((int) value)) == value) {
2016
DC->setCVar(item->cvar, va("%i", (int) value ));
2019
DC->setCVar(item->cvar, va("%f", value ));
2029
qboolean Item_TextField_HandleKey(itemDef_t *item, int key) {
2032
itemDef_t *newItem = NULL;
2033
editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
2037
memset(buff, 0, sizeof(buff));
2038
DC->getCVarString(item->cvar, buff, sizeof(buff));
2040
if (editPtr->maxChars && len > editPtr->maxChars) {
2041
len = editPtr->maxChars;
2043
if ( key & K_CHAR_FLAG ) {
2044
key &= ~K_CHAR_FLAG;
2047
if (key == 'h' - 'a' + 1 ) { // ctrl-h is backspace
2048
if ( item->cursorPos > 0 ) {
2049
memmove( &buff[item->cursorPos - 1], &buff[item->cursorPos], len + 1 - item->cursorPos);
2051
if (item->cursorPos < editPtr->paintOffset) {
2052
editPtr->paintOffset--;
2055
DC->setCVar(item->cvar, buff);
2061
// ignore any non printable chars
2063
if ( key < 32 || !item->cvar) {
2067
if (item->type == ITEM_TYPE_NUMERICFIELD) {
2068
if (key < '0' || key > '9') {
2073
if (!DC->getOverstrikeMode()) {
2074
if (( len == MAX_EDITFIELD - 1 ) || (editPtr->maxChars && len >= editPtr->maxChars)) {
2077
memmove( &buff[item->cursorPos + 1], &buff[item->cursorPos], len + 1 - item->cursorPos );
2079
if (editPtr->maxChars && item->cursorPos >= editPtr->maxChars) {
2084
buff[item->cursorPos] = key;
2086
DC->setCVar(item->cvar, buff);
2088
if (item->cursorPos < len + 1) {
2090
if (editPtr->maxPaintChars && item->cursorPos > editPtr->maxPaintChars) {
2091
editPtr->paintOffset++;
2097
if ( key == K_DEL || key == K_KP_DEL ) {
2098
if ( item->cursorPos < len ) {
2099
memmove( buff + item->cursorPos, buff + item->cursorPos + 1, len - item->cursorPos);
2100
DC->setCVar(item->cvar, buff);
2105
if ( key == K_RIGHTARROW || key == K_KP_RIGHTARROW )
2107
if (editPtr->maxPaintChars && item->cursorPos >= editPtr->maxPaintChars && item->cursorPos < len) {
2109
editPtr->paintOffset++;
2112
if (item->cursorPos < len) {
2118
if ( key == K_LEFTARROW || key == K_KP_LEFTARROW )
2120
if ( item->cursorPos > 0 ) {
2123
if (item->cursorPos < editPtr->paintOffset) {
2124
editPtr->paintOffset--;
2129
if ( key == K_HOME || key == K_KP_HOME) {// || ( tolower(key) == 'a' && trap_Key_IsDown( K_CTRL ) ) ) {
2130
item->cursorPos = 0;
2131
editPtr->paintOffset = 0;
2135
if ( key == K_END || key == K_KP_END) {// ( tolower(key) == 'e' && trap_Key_IsDown( K_CTRL ) ) ) {
2136
item->cursorPos = len;
2137
if(item->cursorPos > editPtr->maxPaintChars) {
2138
editPtr->paintOffset = len - editPtr->maxPaintChars;
2143
if ( key == K_INS || key == K_KP_INS ) {
2144
DC->setOverstrikeMode(!DC->getOverstrikeMode());
2149
if (key == K_TAB || key == K_DOWNARROW || key == K_KP_DOWNARROW) {
2150
newItem = Menu_SetNextCursorItem(item->parent);
2151
if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD)) {
2152
g_editItem = newItem;
2156
if (key == K_UPARROW || key == K_KP_UPARROW) {
2157
newItem = Menu_SetPrevCursorItem(item->parent);
2158
if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD)) {
2159
g_editItem = newItem;
2163
if ( key == K_ENTER || key == K_KP_ENTER || key == K_ESCAPE) {
2173
static void Scroll_ListBox_AutoFunc(void *p) {
2174
scrollInfo_t *si = (scrollInfo_t*)p;
2175
if (DC->realTime > si->nextScrollTime) {
2176
// need to scroll which is done by simulating a click to the item
2177
// this is done a bit sideways as the autoscroll "knows" that the item is a listbox
2178
// so it calls it directly
2179
Item_ListBox_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
2180
si->nextScrollTime = DC->realTime + si->adjustValue;
2183
if (DC->realTime > si->nextAdjustTime) {
2184
si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
2185
if (si->adjustValue > SCROLL_TIME_FLOOR) {
2186
si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
2191
static void Scroll_ListBox_ThumbFunc(void *p) {
2192
scrollInfo_t *si = (scrollInfo_t*)p;
2196
listBoxDef_t *listPtr = (listBoxDef_t*)si->item->typeData;
2197
if (si->item->window.flags & WINDOW_HORIZONTAL) {
2198
if (DC->cursorx == si->xStart) {
2201
r.x = si->item->window.rect.x + SCROLLBAR_SIZE + 1;
2202
r.y = si->item->window.rect.y + si->item->window.rect.h - SCROLLBAR_SIZE - 1;
2203
r.h = SCROLLBAR_SIZE;
2204
r.w = si->item->window.rect.w - (SCROLLBAR_SIZE*2) - 2;
2205
max = Item_ListBox_MaxScroll(si->item);
2207
pos = (DC->cursorx - r.x - SCROLLBAR_SIZE/2) * max / (r.w - SCROLLBAR_SIZE);
2211
else if (pos > max) {
2214
listPtr->startPos = pos;
2215
si->xStart = DC->cursorx;
2217
else if (DC->cursory != si->yStart) {
2219
r.x = si->item->window.rect.x + si->item->window.rect.w - SCROLLBAR_SIZE - 1;
2220
r.y = si->item->window.rect.y + SCROLLBAR_SIZE + 1;
2221
r.h = si->item->window.rect.h - (SCROLLBAR_SIZE*2) - 2;
2222
r.w = SCROLLBAR_SIZE;
2223
max = Item_ListBox_MaxScroll(si->item);
2225
pos = (DC->cursory - r.y - SCROLLBAR_SIZE/2) * max / (r.h - SCROLLBAR_SIZE);
2229
else if (pos > max) {
2232
listPtr->startPos = pos;
2233
si->yStart = DC->cursory;
2236
if (DC->realTime > si->nextScrollTime) {
2237
// need to scroll which is done by simulating a click to the item
2238
// this is done a bit sideways as the autoscroll "knows" that the item is a listbox
2239
// so it calls it directly
2240
Item_ListBox_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
2241
si->nextScrollTime = DC->realTime + si->adjustValue;
2244
if (DC->realTime > si->nextAdjustTime) {
2245
si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
2246
if (si->adjustValue > SCROLL_TIME_FLOOR) {
2247
si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
2252
static void Scroll_Slider_ThumbFunc(void *p) {
2253
float x, value, cursorx;
2254
scrollInfo_t *si = (scrollInfo_t*)p;
2255
editFieldDef_t *editDef = si->item->typeData;
2257
if (si->item->text) {
2258
x = si->item->textRect.x + si->item->textRect.w + 8;
2260
x = si->item->window.rect.x;
2263
cursorx = DC->cursorx;
2267
} else if (cursorx > x + SLIDER_WIDTH) {
2268
cursorx = x + SLIDER_WIDTH;
2270
value = cursorx - x;
2271
value /= SLIDER_WIDTH;
2272
value *= (editDef->maxVal - editDef->minVal);
2273
value += editDef->minVal;
2274
DC->setCVar(si->item->cvar, va("%f", value));
2277
void Item_StartCapture(itemDef_t *item, int key) {
2279
switch (item->type) {
2280
case ITEM_TYPE_EDITFIELD:
2281
case ITEM_TYPE_NUMERICFIELD:
2283
case ITEM_TYPE_LISTBOX:
2285
flags = Item_ListBox_OverLB(item, DC->cursorx, DC->cursory);
2286
if (flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW)) {
2287
scrollInfo.nextScrollTime = DC->realTime + SCROLL_TIME_START;
2288
scrollInfo.nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
2289
scrollInfo.adjustValue = SCROLL_TIME_START;
2290
scrollInfo.scrollKey = key;
2291
scrollInfo.scrollDir = (flags & WINDOW_LB_LEFTARROW) ? qtrue : qfalse;
2292
scrollInfo.item = item;
2293
captureData = &scrollInfo;
2294
captureFunc = &Scroll_ListBox_AutoFunc;
2296
} else if (flags & WINDOW_LB_THUMB) {
2297
scrollInfo.scrollKey = key;
2298
scrollInfo.item = item;
2299
scrollInfo.xStart = DC->cursorx;
2300
scrollInfo.yStart = DC->cursory;
2301
captureData = &scrollInfo;
2302
captureFunc = &Scroll_ListBox_ThumbFunc;
2307
case ITEM_TYPE_SLIDER:
2309
flags = Item_Slider_OverSlider(item, DC->cursorx, DC->cursory);
2310
if (flags & WINDOW_LB_THUMB) {
2311
scrollInfo.scrollKey = key;
2312
scrollInfo.item = item;
2313
scrollInfo.xStart = DC->cursorx;
2314
scrollInfo.yStart = DC->cursory;
2315
captureData = &scrollInfo;
2316
captureFunc = &Scroll_Slider_ThumbFunc;
2324
void Item_StopCapture(itemDef_t *item) {
2328
qboolean Item_Slider_HandleKey(itemDef_t *item, int key, qboolean down) {
2329
float x, value, width, work;
2331
//DC->Print("slider handle key\n");
2332
if (item->window.flags & WINDOW_HASFOCUS && item->cvar && Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
2333
if (key == K_MOUSE1 || key == K_ENTER || key == K_MOUSE2 || key == K_MOUSE3) {
2334
editFieldDef_t *editDef = item->typeData;
2337
width = SLIDER_WIDTH;
2339
x = item->textRect.x + item->textRect.w + 8;
2341
x = item->window.rect.x;
2344
testRect = item->window.rect;
2346
value = (float)SLIDER_THUMB_WIDTH / 2;
2347
testRect.x -= value;
2348
//DC->Print("slider x: %f\n", testRect.x);
2349
testRect.w = (SLIDER_WIDTH + (float)SLIDER_THUMB_WIDTH / 2);
2350
//DC->Print("slider w: %f\n", testRect.w);
2351
if (Rect_ContainsPoint(&testRect, DC->cursorx, DC->cursory)) {
2352
work = DC->cursorx - x;
2353
value = work / width;
2354
value *= (editDef->maxVal - editDef->minVal);
2356
// value = (((float)(DC->cursorx - x)/ SLIDER_WIDTH) * (editDef->maxVal - editDef->minVal));
2357
value += editDef->minVal;
2358
DC->setCVar(item->cvar, va("%f", value));
2364
DC->Print("slider handle key exit\n");
2369
qboolean Item_HandleKey(itemDef_t *item, int key, qboolean down) {
2372
Item_StopCapture(itemCapture);
2377
// bk001206 - parentheses
2378
if ( down && ( key == K_MOUSE1 || key == K_MOUSE2 || key == K_MOUSE3 ) ) {
2379
Item_StartCapture(item, key);
2387
switch (item->type) {
2388
case ITEM_TYPE_BUTTON:
2391
case ITEM_TYPE_RADIOBUTTON:
2394
case ITEM_TYPE_CHECKBOX:
2397
case ITEM_TYPE_EDITFIELD:
2398
case ITEM_TYPE_NUMERICFIELD:
2399
//return Item_TextField_HandleKey(item, key);
2402
case ITEM_TYPE_COMBO:
2405
case ITEM_TYPE_LISTBOX:
2406
return Item_ListBox_HandleKey(item, key, down, qfalse);
2408
case ITEM_TYPE_YESNO:
2409
return Item_YesNo_HandleKey(item, key);
2411
case ITEM_TYPE_MULTI:
2412
return Item_Multi_HandleKey(item, key);
2414
case ITEM_TYPE_OWNERDRAW:
2415
return Item_OwnerDraw_HandleKey(item, key);
2417
case ITEM_TYPE_BIND:
2418
return Item_Bind_HandleKey(item, key, down);
2420
case ITEM_TYPE_SLIDER:
2421
return Item_Slider_HandleKey(item, key, down);
2423
//case ITEM_TYPE_IMAGE:
2424
// Item_Image_Paint(item);
2434
void Item_Action(itemDef_t *item) {
2436
Item_RunScript(item, item->action);
2440
itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu) {
2441
qboolean wrapped = qfalse;
2442
int oldCursor = menu->cursorItem;
2444
if (menu->cursorItem < 0) {
2445
menu->cursorItem = menu->itemCount-1;
2449
while (menu->cursorItem > -1) {
2452
if (menu->cursorItem < 0 && !wrapped) {
2454
menu->cursorItem = menu->itemCount -1;
2457
if (Item_SetFocus(menu->items[menu->cursorItem], DC->cursorx, DC->cursory)) {
2458
Menu_HandleMouseMove(menu, menu->items[menu->cursorItem]->window.rect.x + 1, menu->items[menu->cursorItem]->window.rect.y + 1);
2459
return menu->items[menu->cursorItem];
2462
menu->cursorItem = oldCursor;
2467
itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu) {
2469
qboolean wrapped = qfalse;
2470
int oldCursor = menu->cursorItem;
2473
if (menu->cursorItem == -1) {
2474
menu->cursorItem = 0;
2478
while (menu->cursorItem < menu->itemCount) {
2481
if (menu->cursorItem >= menu->itemCount && !wrapped) {
2483
menu->cursorItem = 0;
2485
if (Item_SetFocus(menu->items[menu->cursorItem], DC->cursorx, DC->cursory)) {
2486
Menu_HandleMouseMove(menu, menu->items[menu->cursorItem]->window.rect.x + 1, menu->items[menu->cursorItem]->window.rect.y + 1);
2487
return menu->items[menu->cursorItem];
2492
menu->cursorItem = oldCursor;
2496
static void Window_CloseCinematic(windowDef_t *window) {
2497
if (window->style == WINDOW_STYLE_CINEMATIC && window->cinematic >= 0) {
2498
DC->stopCinematic(window->cinematic);
2499
window->cinematic = -1;
2503
static void Menu_CloseCinematics(menuDef_t *menu) {
2506
Window_CloseCinematic(&menu->window);
2507
for (i = 0; i < menu->itemCount; i++) {
2508
Window_CloseCinematic(&menu->items[i]->window);
2509
if (menu->items[i]->type == ITEM_TYPE_OWNERDRAW) {
2510
DC->stopCinematic(0-menu->items[i]->window.ownerDraw);
2516
static void Display_CloseCinematics( void ) {
2518
for (i = 0; i < menuCount; i++) {
2519
Menu_CloseCinematics(&Menus[i]);
2523
void Menus_Activate(menuDef_t *menu) {
2524
menu->window.flags |= (WINDOW_HASFOCUS | WINDOW_VISIBLE);
2528
Item_RunScript(&item, menu->onOpen);
2531
if (menu->soundName && *menu->soundName) {
2532
// DC->stopBackgroundTrack(); // you don't want to do this since it will reset s_rawend
2533
DC->startBackgroundTrack(menu->soundName, menu->soundName);
2536
Display_CloseCinematics();
2540
int Display_VisibleMenuCount( void ) {
2543
for (i = 0; i < menuCount; i++) {
2544
if (Menus[i].window.flags & (WINDOW_FORCED | WINDOW_VISIBLE)) {
2551
void Menus_HandleOOBClick(menuDef_t *menu, int key, qboolean down) {
2554
// basically the behaviour we are looking for is if there are windows in the stack.. see if
2555
// the cursor is within any of them.. if not close them otherwise activate them and pass the
2556
// key on.. force a mouse move to activate focus and script stuff
2557
if (down && menu->window.flags & WINDOW_OOB_CLICK) {
2558
Menu_RunCloseScript(menu);
2559
menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
2562
for (i = 0; i < menuCount; i++) {
2563
if (Menu_OverActiveItem(&Menus[i], DC->cursorx, DC->cursory)) {
2564
Menu_RunCloseScript(menu);
2565
menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
2566
Menus_Activate(&Menus[i]);
2567
Menu_HandleMouseMove(&Menus[i], DC->cursorx, DC->cursory);
2568
Menu_HandleKey(&Menus[i], key, down);
2572
if (Display_VisibleMenuCount() == 0) {
2577
Display_CloseCinematics();
2581
static rectDef_t *Item_CorrectedTextRect(itemDef_t *item) {
2582
static rectDef_t rect;
2583
memset(&rect, 0, sizeof(rectDef_t));
2585
rect = item->textRect;
2593
void Menu_HandleKey(menuDef_t *menu, int key, qboolean down) {
2595
itemDef_t *item = NULL;
2596
qboolean inHandler = qfalse;
2603
if (g_waitingForKey && down) {
2604
Item_Bind_HandleKey(g_bindItem, key, down);
2609
if (g_editingField && down) {
2610
if (!Item_TextField_HandleKey(g_editItem, key)) {
2611
g_editingField = qfalse;
2615
} else if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_MOUSE3) {
2616
g_editingField = qfalse;
2618
Display_MouseMove(NULL, DC->cursorx, DC->cursory);
2619
} else if (key == K_TAB || key == K_UPARROW || key == K_DOWNARROW) {
2629
// see if the mouse is within the window bounds and if so is this a mouse click
2630
if (down && !(menu->window.flags & WINDOW_POPUP) && !Rect_ContainsPoint(&menu->window.rect, DC->cursorx, DC->cursory)) {
2631
static qboolean inHandleKey = qfalse;
2632
// bk001206 - parentheses
2633
if (!inHandleKey && ( key == K_MOUSE1 || key == K_MOUSE2 || key == K_MOUSE3 ) ) {
2634
inHandleKey = qtrue;
2635
Menus_HandleOOBClick(menu, key, down);
2636
inHandleKey = qfalse;
2642
// get the item with focus
2643
for (i = 0; i < menu->itemCount; i++) {
2644
if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
2645
item = menu->items[i];
2650
if (Item_HandleKey(item, key, down)) {
2666
if (DC->getCVarValue("developer")) {
2672
if (DC->getCVarValue("developer")) {
2673
DC->executeText(EXEC_APPEND, "screenshot\n");
2678
Menu_SetPrevCursorItem(menu);
2682
if (!g_waitingForKey && menu->onESC) {
2685
Item_RunScript(&it, menu->onESC);
2689
case K_KP_DOWNARROW:
2691
Menu_SetNextCursorItem(menu);
2697
if (item->type == ITEM_TYPE_TEXT) {
2698
if (Rect_ContainsPoint(Item_CorrectedTextRect(item), DC->cursorx, DC->cursory)) {
2701
} else if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD) {
2702
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
2703
item->cursorPos = 0;
2704
g_editingField = qtrue;
2706
DC->setOverstrikeMode(qtrue);
2709
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
2740
if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD) {
2741
item->cursorPos = 0;
2742
g_editingField = qtrue;
2744
DC->setOverstrikeMode(qtrue);
2754
void ToWindowCoords(float *x, float *y, windowDef_t *window) {
2755
if (window->border != 0) {
2756
*x += window->borderSize;
2757
*y += window->borderSize;
2759
*x += window->rect.x;
2760
*y += window->rect.y;
2763
void Rect_ToWindowCoords(rectDef_t *rect, windowDef_t *window) {
2764
ToWindowCoords(&rect->x, &rect->y, window);
2767
void Item_SetTextExtents(itemDef_t *item, int *width, int *height, const char *text) {
2768
const char *textPtr = (text) ? text : item->text;
2770
if (textPtr == NULL ) {
2774
*width = item->textRect.w;
2775
*height = item->textRect.h;
2777
// keeps us from computing the widths and heights more than once
2778
if (*width == 0 || (item->type == ITEM_TYPE_OWNERDRAW && item->textalignment == ITEM_ALIGN_CENTER)) {
2779
int originalWidth = DC->textWidth(item->text, item->textscale, 0);
2781
if (item->type == ITEM_TYPE_OWNERDRAW && (item->textalignment == ITEM_ALIGN_CENTER || item->textalignment == ITEM_ALIGN_RIGHT)) {
2782
originalWidth += DC->ownerDrawWidth(item->window.ownerDraw, item->textscale);
2783
} else if (item->type == ITEM_TYPE_EDITFIELD && item->textalignment == ITEM_ALIGN_CENTER && item->cvar) {
2785
DC->getCVarString(item->cvar, buff, 256);
2786
originalWidth += DC->textWidth(buff, item->textscale, 0);
2789
*width = DC->textWidth(textPtr, item->textscale, 0);
2790
*height = DC->textHeight(textPtr, item->textscale, 0);
2791
item->textRect.w = *width;
2792
item->textRect.h = *height;
2793
item->textRect.x = item->textalignx;
2794
item->textRect.y = item->textaligny;
2795
if (item->textalignment == ITEM_ALIGN_RIGHT) {
2796
item->textRect.x = item->textalignx - originalWidth;
2797
} else if (item->textalignment == ITEM_ALIGN_CENTER) {
2798
item->textRect.x = item->textalignx - originalWidth / 2;
2801
ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
2805
void Item_TextColor(itemDef_t *item, vec4_t *newColor) {
2807
menuDef_t *parent = (menuDef_t*)item->parent;
2809
Fade(&item->window.flags, &item->window.foreColor[3], parent->fadeClamp, &item->window.nextTime, parent->fadeCycle, qtrue, parent->fadeAmount);
2811
if (item->window.flags & WINDOW_HASFOCUS) {
2812
lowLight[0] = 0.8 * parent->focusColor[0];
2813
lowLight[1] = 0.8 * parent->focusColor[1];
2814
lowLight[2] = 0.8 * parent->focusColor[2];
2815
lowLight[3] = 0.8 * parent->focusColor[3];
2816
LerpColor(parent->focusColor,lowLight,*newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
2817
} else if (item->textStyle == ITEM_TEXTSTYLE_BLINK && !((DC->realTime/BLINK_DIVISOR) & 1)) {
2818
lowLight[0] = 0.8 * item->window.foreColor[0];
2819
lowLight[1] = 0.8 * item->window.foreColor[1];
2820
lowLight[2] = 0.8 * item->window.foreColor[2];
2821
lowLight[3] = 0.8 * item->window.foreColor[3];
2822
LerpColor(item->window.foreColor,lowLight,*newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
2824
memcpy(newColor, &item->window.foreColor, sizeof(vec4_t));
2825
// items can be enabled and disabled based on cvars
2828
if (item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest) {
2829
if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
2830
memcpy(newColor, &parent->disableColor, sizeof(vec4_t));
2835
void Item_Text_AutoWrapped_Paint(itemDef_t *item) {
2837
const char *p, *textPtr, *newLinePtr;
2839
int width, height, len, textWidth, newLine, newLineWidth;
2846
if (item->text == NULL) {
2847
if (item->cvar == NULL) {
2851
DC->getCVarString(item->cvar, text, sizeof(text));
2856
textPtr = item->text;
2858
if (*textPtr == '\0') {
2861
Item_TextColor(item, &color);
2862
Item_SetTextExtents(item, &width, &height, textPtr);
2864
y = item->textaligny;
2871
if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\0') {
2874
newLineWidth = textWidth;
2876
textWidth = DC->textWidth(buff, item->textscale, 0);
2877
if ( (newLine && textWidth > item->window.rect.w) || *p == '\n' || *p == '\0') {
2879
if (item->textalignment == ITEM_ALIGN_LEFT) {
2880
item->textRect.x = item->textalignx;
2881
} else if (item->textalignment == ITEM_ALIGN_RIGHT) {
2882
item->textRect.x = item->textalignx - newLineWidth;
2883
} else if (item->textalignment == ITEM_ALIGN_CENTER) {
2884
item->textRect.x = item->textalignx - newLineWidth / 2;
2886
item->textRect.y = y;
2887
ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
2889
buff[newLine] = '\0';
2890
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, buff, 0, 0, item->textStyle);
2908
void Item_Text_Wrapped_Paint(itemDef_t *item) {
2910
const char *p, *start, *textPtr;
2916
// now paint the text and/or any optional images
2919
if (item->text == NULL) {
2920
if (item->cvar == NULL) {
2924
DC->getCVarString(item->cvar, text, sizeof(text));
2929
textPtr = item->text;
2931
if (*textPtr == '\0') {
2935
Item_TextColor(item, &color);
2936
Item_SetTextExtents(item, &width, &height, textPtr);
2938
x = item->textRect.x;
2939
y = item->textRect.y;
2941
p = strchr(textPtr, '\r');
2943
strncpy(buff, start, p-start+1);
2944
buff[p-start] = '\0';
2945
DC->drawText(x, y, item->textscale, color, buff, 0, 0, item->textStyle);
2947
start += p - start + 1;
2948
p = strchr(p+1, '\r');
2950
DC->drawText(x, y, item->textscale, color, start, 0, 0, item->textStyle);
2953
void Item_Text_Paint(itemDef_t *item) {
2955
const char *textPtr;
2959
if (item->window.flags & WINDOW_WRAPPED) {
2960
Item_Text_Wrapped_Paint(item);
2963
if (item->window.flags & WINDOW_AUTOWRAPPED) {
2964
Item_Text_AutoWrapped_Paint(item);
2968
if (item->text == NULL) {
2969
if (item->cvar == NULL) {
2973
DC->getCVarString(item->cvar, text, sizeof(text));
2978
textPtr = item->text;
2981
// this needs to go here as it sets extents for cvar types as well
2982
Item_SetTextExtents(item, &width, &height, textPtr);
2984
if (*textPtr == '\0') {
2989
Item_TextColor(item, &color);
2991
//FIXME: this is a fucking mess
2994
if (item->textStyle == ITEM_TEXTSTYLE_OUTLINED || item->textStyle == ITEM_TEXTSTYLE_OUTLINESHADOWED) {
2998
if (item->textStyle == ITEM_TEXTSTYLE_SHADOWED || item->textStyle == ITEM_TEXTSTYLE_OUTLINESHADOWED) {
2999
Fade(&item->window.flags, &DC->Assets.shadowColor[3], DC->Assets.fadeClamp, &item->window.nextTime, DC->Assets.fadeCycle, qfalse);
3000
DC->drawText(item->textRect.x + DC->Assets.shadowX, item->textRect.y + DC->Assets.shadowY, item->textscale, DC->Assets.shadowColor, textPtr, adjust);
3005
// if (item->textStyle == ITEM_TEXTSTYLE_OUTLINED || item->textStyle == ITEM_TEXTSTYLE_OUTLINESHADOWED) {
3006
// Fade(&item->window.flags, &item->window.outlineColor[3], DC->Assets.fadeClamp, &item->window.nextTime, DC->Assets.fadeCycle, qfalse);
3008
// Text_Paint(item->textRect.x-1, item->textRect.y-1, item->textscale, item->window.foreColor, textPtr, adjust);
3009
// Text_Paint(item->textRect.x, item->textRect.y-1, item->textscale, item->window.foreColor, textPtr, adjust);
3010
// Text_Paint(item->textRect.x+1, item->textRect.y-1, item->textscale, item->window.foreColor, textPtr, adjust);
3011
// Text_Paint(item->textRect.x-1, item->textRect.y, item->textscale, item->window.foreColor, textPtr, adjust);
3012
// Text_Paint(item->textRect.x+1, item->textRect.y, item->textscale, item->window.foreColor, textPtr, adjust);
3013
// Text_Paint(item->textRect.x-1, item->textRect.y+1, item->textscale, item->window.foreColor, textPtr, adjust);
3014
// Text_Paint(item->textRect.x, item->textRect.y+1, item->textscale, item->window.foreColor, textPtr, adjust);
3015
// Text_Paint(item->textRect.x+1, item->textRect.y+1, item->textscale, item->window.foreColor, textPtr, adjust);
3017
// DC->drawText(item->textRect.x - 1, item->textRect.y + 1, item->textscale * 1.02, item->window.outlineColor, textPtr, adjust);
3020
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, textPtr, 0, 0, item->textStyle);
3025
//float trap_Cvar_VariableValue( const char *var_name );
3026
//void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
3028
void Item_TextField_Paint(itemDef_t *item) {
3030
vec4_t newColor, lowLight;
3032
menuDef_t *parent = (menuDef_t*)item->parent;
3033
editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
3035
Item_Text_Paint(item);
3040
DC->getCVarString(item->cvar, buff, sizeof(buff));
3043
parent = (menuDef_t*)item->parent;
3045
if (item->window.flags & WINDOW_HASFOCUS) {
3046
lowLight[0] = 0.8 * parent->focusColor[0];
3047
lowLight[1] = 0.8 * parent->focusColor[1];
3048
lowLight[2] = 0.8 * parent->focusColor[2];
3049
lowLight[3] = 0.8 * parent->focusColor[3];
3050
LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
3052
memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
3055
offset = (item->text && *item->text) ? 8 : 0;
3056
if (item->window.flags & WINDOW_HASFOCUS && g_editingField) {
3057
char cursor = DC->getOverstrikeMode() ? '_' : '|';
3058
DC->drawTextWithCursor(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, buff + editPtr->paintOffset, item->cursorPos - editPtr->paintOffset , cursor, editPtr->maxPaintChars, item->textStyle);
3060
DC->drawText(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, buff + editPtr->paintOffset, 0, editPtr->maxPaintChars, item->textStyle);
3065
void Item_YesNo_Paint(itemDef_t *item) {
3066
vec4_t newColor, lowLight;
3068
menuDef_t *parent = (menuDef_t*)item->parent;
3070
value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
3072
if (item->window.flags & WINDOW_HASFOCUS) {
3073
lowLight[0] = 0.8 * parent->focusColor[0];
3074
lowLight[1] = 0.8 * parent->focusColor[1];
3075
lowLight[2] = 0.8 * parent->focusColor[2];
3076
lowLight[3] = 0.8 * parent->focusColor[3];
3077
LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
3079
memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
3083
Item_Text_Paint(item);
3084
DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, (value != 0) ? "Yes" : "No", 0, 0, item->textStyle);
3086
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? "Yes" : "No", 0, 0, item->textStyle);
3090
void Item_Multi_Paint(itemDef_t *item) {
3091
vec4_t newColor, lowLight;
3092
const char *text = "";
3093
menuDef_t *parent = (menuDef_t*)item->parent;
3095
if (item->window.flags & WINDOW_HASFOCUS) {
3096
lowLight[0] = 0.8 * parent->focusColor[0];
3097
lowLight[1] = 0.8 * parent->focusColor[1];
3098
lowLight[2] = 0.8 * parent->focusColor[2];
3099
lowLight[3] = 0.8 * parent->focusColor[3];
3100
LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
3102
memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
3105
text = Item_Multi_Setting(item);
3108
Item_Text_Paint(item);
3109
DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle);
3111
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle);
3133
static bind_t g_bindings[] =
3135
{"+scores", K_TAB, -1, -1, -1},
3136
{"+button2", K_ENTER, -1, -1, -1},
3137
{"+speed", K_SHIFT, -1, -1, -1},
3138
{"+forward", K_UPARROW, -1, -1, -1},
3139
{"+back", K_DOWNARROW, -1, -1, -1},
3140
{"+moveleft", ',', -1, -1, -1},
3141
{"+moveright", '.', -1, -1, -1},
3142
{"+moveup", K_SPACE, -1, -1, -1},
3143
{"+movedown", 'c', -1, -1, -1},
3144
{"+left", K_LEFTARROW, -1, -1, -1},
3145
{"+right", K_RIGHTARROW, -1, -1, -1},
3146
{"+strafe", K_ALT, -1, -1, -1},
3147
{"+lookup", K_PGDN, -1, -1, -1},
3148
{"+lookdown", K_DEL, -1, -1, -1},
3149
{"+mlook", '/', -1, -1, -1},
3150
{"centerview", K_END, -1, -1, -1},
3151
{"+zoom", -1, -1, -1, -1},
3152
{"weapon 1", '1', -1, -1, -1},
3153
{"weapon 2", '2', -1, -1, -1},
3154
{"weapon 3", '3', -1, -1, -1},
3155
{"weapon 4", '4', -1, -1, -1},
3156
{"weapon 5", '5', -1, -1, -1},
3157
{"weapon 6", '6', -1, -1, -1},
3158
{"weapon 7", '7', -1, -1, -1},
3159
{"weapon 8", '8', -1, -1, -1},
3160
{"weapon 9", '9', -1, -1, -1},
3161
{"weapon 10", '0', -1, -1, -1},
3162
{"weapon 11", -1, -1, -1, -1},
3163
{"weapon 12", -1, -1, -1, -1},
3164
{"weapon 13", -1, -1, -1, -1},
3165
{"+attack", K_CTRL, -1, -1, -1},
3166
{"weapprev", '[', -1, -1, -1},
3167
{"weapnext", ']', -1, -1, -1},
3168
{"+button3", K_MOUSE3, -1, -1, -1},
3169
{"+button4", K_MOUSE4, -1, -1, -1},
3170
{"prevTeamMember", 'w', -1, -1, -1},
3171
{"nextTeamMember", 'r', -1, -1, -1},
3172
{"nextOrder", 't', -1, -1, -1},
3173
{"confirmOrder", 'y', -1, -1, -1},
3174
{"denyOrder", 'n', -1, -1, -1},
3175
{"taskOffense", 'o', -1, -1, -1},
3176
{"taskDefense", 'd', -1, -1, -1},
3177
{"taskPatrol", 'p', -1, -1, -1},
3178
{"taskCamp", 'c', -1, -1, -1},
3179
{"taskFollow", 'f', -1, -1, -1},
3180
{"taskRetrieve", 'v', -1, -1, -1},
3181
{"taskEscort", 'e', -1, -1, -1},
3182
{"taskOwnFlag", 'i', -1, -1, -1},
3183
{"taskSuicide", 'k', -1, -1, -1},
3184
{"tauntKillInsult", K_F1, -1, -1, -1},
3185
{"tauntPraise", K_F2, -1, -1, -1},
3186
{"tauntTaunt", K_F3, -1, -1, -1},
3187
{"tauntDeathInsult", K_F4, -1, -1, -1},
3188
{"tauntGauntlet", K_F5, -1, -1, -1},
3189
{"scoresUp", K_KP_PGUP, -1, -1, -1},
3190
{"scoresDown", K_KP_PGDN, -1, -1, -1},
3191
// bk001205 - this one below was: '-1'
3192
{"messagemode", -1, -1, -1, -1},
3193
{"messagemode2", -1, -1, -1, -1},
3194
{"messagemode3", -1, -1, -1, -1},
3195
{"messagemode4", -1, -1, -1, -1}
3199
static const int g_bindCount = sizeof(g_bindings) / sizeof(bind_t);
3201
#ifndef MISSIONPACK // bk001206
3202
static configcvar_t g_configcvars[] =
3206
{"cg_autoswitch", 0, 0},
3207
{"sensitivity", 0, 0},
3208
{"in_joystick", 0, 0},
3209
{"joy_threshold", 0, 0},
3211
{"cl_freelook", 0, 0},
3218
Controls_GetKeyAssignment
3221
static void Controls_GetKeyAssignment (char *command, int *twokeys)
3227
twokeys[0] = twokeys[1] = -1;
3230
for ( j = 0; j < 256; j++ )
3232
DC->getBindingBuf( j, b, 256 );
3236
if ( !Q_stricmp( b, command ) ) {
3251
void Controls_GetConfig( void )
3256
// iterate each command, get its numeric binding
3257
for (i=0; i < g_bindCount; i++)
3260
Controls_GetKeyAssignment(g_bindings[i].command, twokeys);
3262
g_bindings[i].bind1 = twokeys[0];
3263
g_bindings[i].bind2 = twokeys[1];
3266
//s_controls.invertmouse.curvalue = DC->getCVarValue( "m_pitch" ) < 0;
3267
//s_controls.smoothmouse.curvalue = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "m_filter" ) );
3268
//s_controls.alwaysrun.curvalue = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cl_run" ) );
3269
//s_controls.autoswitch.curvalue = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cg_autoswitch" ) );
3270
//s_controls.sensitivity.curvalue = UI_ClampCvar( 2, 30, Controls_GetCvarValue( "sensitivity" ) );
3271
//s_controls.joyenable.curvalue = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "in_joystick" ) );
3272
//s_controls.joythreshold.curvalue = UI_ClampCvar( 0.05, 0.75, Controls_GetCvarValue( "joy_threshold" ) );
3273
//s_controls.freelook.curvalue = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cl_freelook" ) );
3281
void Controls_SetConfig(qboolean restart)
3285
// iterate each command, get its numeric binding
3286
for (i=0; i < g_bindCount; i++)
3289
if (g_bindings[i].bind1 != -1)
3291
DC->setBinding( g_bindings[i].bind1, g_bindings[i].command );
3293
if (g_bindings[i].bind2 != -1)
3294
DC->setBinding( g_bindings[i].bind2, g_bindings[i].command );
3298
//if ( s_controls.invertmouse.curvalue )
3299
// DC->setCVar("m_pitch", va("%f),-fabs( DC->getCVarValue( "m_pitch" ) ) );
3301
// trap_Cvar_SetValue( "m_pitch", fabs( trap_Cvar_VariableValue( "m_pitch" ) ) );
3303
//trap_Cvar_SetValue( "m_filter", s_controls.smoothmouse.curvalue );
3304
//trap_Cvar_SetValue( "cl_run", s_controls.alwaysrun.curvalue );
3305
//trap_Cvar_SetValue( "cg_autoswitch", s_controls.autoswitch.curvalue );
3306
//trap_Cvar_SetValue( "sensitivity", s_controls.sensitivity.curvalue );
3307
//trap_Cvar_SetValue( "in_joystick", s_controls.joyenable.curvalue );
3308
//trap_Cvar_SetValue( "joy_threshold", s_controls.joythreshold.curvalue );
3309
//trap_Cvar_SetValue( "cl_freelook", s_controls.freelook.curvalue );
3310
DC->executeText(EXEC_APPEND, "in_restart\n");
3311
//trap_Cmd_ExecuteText( EXEC_APPEND, "in_restart\n" );
3316
Controls_SetDefaults
3319
void Controls_SetDefaults( void )
3323
// iterate each command, set its default binding
3324
for (i=0; i < g_bindCount; i++)
3326
g_bindings[i].bind1 = g_bindings[i].defaultbind1;
3327
g_bindings[i].bind2 = g_bindings[i].defaultbind2;
3330
//s_controls.invertmouse.curvalue = Controls_GetCvarDefault( "m_pitch" ) < 0;
3331
//s_controls.smoothmouse.curvalue = Controls_GetCvarDefault( "m_filter" );
3332
//s_controls.alwaysrun.curvalue = Controls_GetCvarDefault( "cl_run" );
3333
//s_controls.autoswitch.curvalue = Controls_GetCvarDefault( "cg_autoswitch" );
3334
//s_controls.sensitivity.curvalue = Controls_GetCvarDefault( "sensitivity" );
3335
//s_controls.joyenable.curvalue = Controls_GetCvarDefault( "in_joystick" );
3336
//s_controls.joythreshold.curvalue = Controls_GetCvarDefault( "joy_threshold" );
3337
//s_controls.freelook.curvalue = Controls_GetCvarDefault( "cl_freelook" );
3340
int BindingIDFromName(const char *name) {
3342
for (i=0; i < g_bindCount; i++)
3344
if (Q_stricmp(name, g_bindings[i].command) == 0) {
3351
char g_nameBind1[32];
3352
char g_nameBind2[32];
3354
void BindingFromName(const char *cvar) {
3357
// iterate each command, set its default binding
3358
for (i=0; i < g_bindCount; i++)
3360
if (Q_stricmp(cvar, g_bindings[i].command) == 0) {
3361
b1 = g_bindings[i].bind1;
3365
DC->keynumToStringBuf( b1, g_nameBind1, 32 );
3366
Q_strupr(g_nameBind1);
3368
b2 = g_bindings[i].bind2;
3371
DC->keynumToStringBuf( b2, g_nameBind2, 32 );
3372
Q_strupr(g_nameBind2);
3373
strcat( g_nameBind1, " or " );
3374
strcat( g_nameBind1, g_nameBind2 );
3379
strcpy(g_nameBind1, "???");
3382
void Item_Slider_Paint(itemDef_t *item) {
3383
vec4_t newColor, lowLight;
3385
menuDef_t *parent = (menuDef_t*)item->parent;
3387
value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
3389
if (item->window.flags & WINDOW_HASFOCUS) {
3390
lowLight[0] = 0.8 * parent->focusColor[0];
3391
lowLight[1] = 0.8 * parent->focusColor[1];
3392
lowLight[2] = 0.8 * parent->focusColor[2];
3393
lowLight[3] = 0.8 * parent->focusColor[3];
3394
LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
3396
memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
3399
y = item->window.rect.y;
3401
Item_Text_Paint(item);
3402
x = item->textRect.x + item->textRect.w + 8;
3404
x = item->window.rect.x;
3406
DC->setColor(newColor);
3407
DC->drawHandlePic( x, y, SLIDER_WIDTH, SLIDER_HEIGHT, DC->Assets.sliderBar );
3409
x = Item_Slider_ThumbPosition(item);
3410
DC->drawHandlePic( x - (SLIDER_THUMB_WIDTH / 2), y - 2, SLIDER_THUMB_WIDTH, SLIDER_THUMB_HEIGHT, DC->Assets.sliderThumb );
3414
void Item_Bind_Paint(itemDef_t *item) {
3415
vec4_t newColor, lowLight;
3418
menuDef_t *parent = (menuDef_t*)item->parent;
3419
editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
3421
maxChars = editPtr->maxPaintChars;
3424
value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
3426
if (item->window.flags & WINDOW_HASFOCUS) {
3427
if (g_bindItem == item) {
3428
lowLight[0] = 0.8f * 1.0f;
3429
lowLight[1] = 0.8f * 0.0f;
3430
lowLight[2] = 0.8f * 0.0f;
3431
lowLight[3] = 0.8f * 1.0f;
3433
lowLight[0] = 0.8f * parent->focusColor[0];
3434
lowLight[1] = 0.8f * parent->focusColor[1];
3435
lowLight[2] = 0.8f * parent->focusColor[2];
3436
lowLight[3] = 0.8f * parent->focusColor[3];
3438
LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
3440
memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
3444
Item_Text_Paint(item);
3445
BindingFromName(item->cvar);
3446
DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, g_nameBind1, 0, maxChars, item->textStyle);
3448
DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? "FIXME" : "FIXME", 0, maxChars, item->textStyle);
3452
qboolean Display_KeyBindPending(void) {
3453
return g_waitingForKey;
3456
qboolean Item_Bind_HandleKey(itemDef_t *item, int key, qboolean down) {
3460
if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && !g_waitingForKey)
3462
if (down && (key == K_MOUSE1 || key == K_ENTER)) {
3463
g_waitingForKey = qtrue;
3470
if (!g_waitingForKey || g_bindItem == NULL) {
3474
if (key & K_CHAR_FLAG) {
3481
g_waitingForKey = qfalse;
3485
id = BindingIDFromName(item->cvar);
3487
g_bindings[id].bind1 = -1;
3488
g_bindings[id].bind2 = -1;
3490
Controls_SetConfig(qtrue);
3491
g_waitingForKey = qfalse;
3503
for (i=0; i < g_bindCount; i++)
3506
if (g_bindings[i].bind2 == key) {
3507
g_bindings[i].bind2 = -1;
3510
if (g_bindings[i].bind1 == key)
3512
g_bindings[i].bind1 = g_bindings[i].bind2;
3513
g_bindings[i].bind2 = -1;
3519
id = BindingIDFromName(item->cvar);
3523
if( g_bindings[id].bind1 != -1 ) {
3524
DC->setBinding( g_bindings[id].bind1, "" );
3525
g_bindings[id].bind1 = -1;
3527
if( g_bindings[id].bind2 != -1 ) {
3528
DC->setBinding( g_bindings[id].bind2, "" );
3529
g_bindings[id].bind2 = -1;
3532
else if (g_bindings[id].bind1 == -1) {
3533
g_bindings[id].bind1 = key;
3535
else if (g_bindings[id].bind1 != key && g_bindings[id].bind2 == -1) {
3536
g_bindings[id].bind2 = key;
3539
DC->setBinding( g_bindings[id].bind1, "" );
3540
DC->setBinding( g_bindings[id].bind2, "" );
3541
g_bindings[id].bind1 = key;
3542
g_bindings[id].bind2 = -1;
3546
Controls_SetConfig(qtrue);
3547
g_waitingForKey = qfalse;
3554
void AdjustFrom640(float *x, float *y, float *w, float *h) {
3555
//*x = *x * DC->scale + DC->bias;
3562
void Item_Model_Paint(itemDef_t *item) {
3566
vec3_t mins, maxs, origin;
3568
modelDef_t *modelPtr = (modelDef_t*)item->typeData;
3570
if (modelPtr == NULL) {
3575
memset( &refdef, 0, sizeof( refdef ) );
3576
refdef.rdflags = RDF_NOWORLDMODEL;
3577
AxisClear( refdef.viewaxis );
3578
x = item->window.rect.x+1;
3579
y = item->window.rect.y+1;
3580
w = item->window.rect.w-2;
3581
h = item->window.rect.h-2;
3583
AdjustFrom640( &x, &y, &w, &h );
3590
DC->modelBounds( item->asset, mins, maxs );
3592
origin[2] = -0.5 * ( mins[2] + maxs[2] );
3593
origin[1] = 0.5 * ( mins[1] + maxs[1] );
3595
// calculate distance so the model nearly fills the box
3597
float len = 0.5 * ( maxs[2] - mins[2] );
3598
origin[0] = len / 0.268; // len / tan( fov/2 )
3599
//origin[0] = len / tan(w/2);
3601
origin[0] = item->textscale;
3603
refdef.fov_x = (modelPtr->fov_x) ? modelPtr->fov_x : w;
3604
refdef.fov_y = (modelPtr->fov_y) ? modelPtr->fov_y : h;
3606
//refdef.fov_x = (int)((float)refdef.width / 640.0f * 90.0f);
3607
//xx = refdef.width / tan( refdef.fov_x / 360 * M_PI );
3608
//refdef.fov_y = atan2( refdef.height, xx );
3609
//refdef.fov_y *= ( 360 / M_PI );
3613
refdef.time = DC->realTime;
3617
memset( &ent, 0, sizeof(ent) );
3619
//adjust = 5.0 * sin( (float)uis.realtime / 500 );
3620
//adjust = 360 % (int)((float)uis.realtime / 1000);
3621
//VectorSet( angles, 0, 0, 1 );
3623
// use item storage to track
3624
if (modelPtr->rotationSpeed) {
3625
if (DC->realTime > item->window.nextTime) {
3626
item->window.nextTime = DC->realTime + modelPtr->rotationSpeed;
3627
modelPtr->angle = (int)(modelPtr->angle + 1) % 360;
3630
VectorSet( angles, 0, modelPtr->angle, 0 );
3631
AnglesToAxis( angles, ent.axis );
3633
ent.hModel = item->asset;
3634
VectorCopy( origin, ent.origin );
3635
VectorCopy( origin, ent.lightingOrigin );
3636
ent.renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW;
3637
VectorCopy( ent.origin, ent.oldorigin );
3639
DC->addRefEntityToScene( &ent );
3640
DC->renderScene( &refdef );
3645
void Item_Image_Paint(itemDef_t *item) {
3649
DC->drawHandlePic(item->window.rect.x+1, item->window.rect.y+1, item->window.rect.w-2, item->window.rect.h-2, item->asset);
3652
void Item_ListBox_Paint(itemDef_t *item) {
3653
float x, y, size, count, i, thumb;
3655
qhandle_t optionalImage;
3656
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
3658
// the listbox is horizontal or vertical and has a fixed size scroll bar going either direction
3659
// elements are enumerated from the DC and either text or image handles are acquired from the DC as well
3660
// textscale is used to size the text, textalignx and textaligny are used to size image elements
3661
// there is no clipping available so only the last completely visible item is painted
3662
count = DC->feederCount(item->special);
3663
// default is vertical if horizontal flag is not here
3664
if (item->window.flags & WINDOW_HORIZONTAL) {
3665
// draw scrollbar in bottom of the window
3667
x = item->window.rect.x + 1;
3668
y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE - 1;
3669
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowLeft);
3670
x += SCROLLBAR_SIZE - 1;
3671
size = item->window.rect.w - (SCROLLBAR_SIZE * 2);
3672
DC->drawHandlePic(x, y, size+1, SCROLLBAR_SIZE, DC->Assets.scrollBar);
3674
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowRight);
3676
thumb = Item_ListBox_ThumbDrawPosition(item);//Item_ListBox_ThumbPosition(item);
3677
if (thumb > x - SCROLLBAR_SIZE - 1) {
3678
thumb = x - SCROLLBAR_SIZE - 1;
3680
DC->drawHandlePic(thumb, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
3682
listPtr->endPos = listPtr->startPos;
3683
size = item->window.rect.w - 2;
3685
// size contains max available space
3686
if (listPtr->elementStyle == LISTBOX_IMAGE) {
3688
x = item->window.rect.x + 1;
3689
y = item->window.rect.y + 1;
3690
for (i = listPtr->startPos; i < count; i++) {
3691
// always draw at least one
3692
// which may overdraw the box if it is too small for the element
3693
image = DC->feederItemImage(item->special, i);
3695
DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
3698
if (i == item->cursorPos) {
3699
DC->drawRect(x, y, listPtr->elementWidth-1, listPtr->elementHeight-1, item->window.borderSize, item->window.borderColor);
3702
size -= listPtr->elementWidth;
3703
if (size < listPtr->elementWidth) {
3704
listPtr->drawPadding = size; //listPtr->elementWidth - size;
3707
x += listPtr->elementWidth;
3715
// draw scrollbar to right side of the window
3716
x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE - 1;
3717
y = item->window.rect.y + 1;
3718
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowUp);
3719
y += SCROLLBAR_SIZE - 1;
3721
listPtr->endPos = listPtr->startPos;
3722
size = item->window.rect.h - (SCROLLBAR_SIZE * 2);
3723
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, size+1, DC->Assets.scrollBar);
3725
DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowDown);
3727
thumb = Item_ListBox_ThumbDrawPosition(item);//Item_ListBox_ThumbPosition(item);
3728
if (thumb > y - SCROLLBAR_SIZE - 1) {
3729
thumb = y - SCROLLBAR_SIZE - 1;
3731
DC->drawHandlePic(x, thumb, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
3733
// adjust size for item painting
3734
size = item->window.rect.h - 2;
3735
if (listPtr->elementStyle == LISTBOX_IMAGE) {
3737
x = item->window.rect.x + 1;
3738
y = item->window.rect.y + 1;
3739
for (i = listPtr->startPos; i < count; i++) {
3740
// always draw at least one
3741
// which may overdraw the box if it is too small for the element
3742
image = DC->feederItemImage(item->special, i);
3744
DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
3747
if (i == item->cursorPos) {
3748
DC->drawRect(x, y, listPtr->elementWidth - 1, listPtr->elementHeight - 1, item->window.borderSize, item->window.borderColor);
3752
size -= listPtr->elementWidth;
3753
if (size < listPtr->elementHeight) {
3754
listPtr->drawPadding = listPtr->elementHeight - size;
3757
y += listPtr->elementHeight;
3761
x = item->window.rect.x + 1;
3762
y = item->window.rect.y + 1;
3763
for (i = listPtr->startPos; i < count; i++) {
3765
// always draw at least one
3766
// which may overdraw the box if it is too small for the element
3768
if (listPtr->numColumns > 0) {
3770
for (j = 0; j < listPtr->numColumns; j++) {
3771
text = DC->feederItemText(item->special, i, j, &optionalImage);
3772
if (optionalImage >= 0) {
3773
DC->drawHandlePic(x + 4 + listPtr->columnInfo[j].pos, y - 1 + listPtr->elementHeight / 2, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
3775
DC->drawText(x + 4 + listPtr->columnInfo[j].pos, y + listPtr->elementHeight, item->textscale, item->window.foreColor, text, 0, listPtr->columnInfo[j].maxChars, item->textStyle);
3779
text = DC->feederItemText(item->special, i, 0, &optionalImage);
3780
if (optionalImage >= 0) {
3781
//DC->drawHandlePic(x + 4 + listPtr->elementHeight, y, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
3783
DC->drawText(x + 4, y + listPtr->elementHeight, item->textscale, item->window.foreColor, text, 0, 0, item->textStyle);
3787
if (i == item->cursorPos) {
3788
DC->fillRect(x + 2, y + 2, item->window.rect.w - SCROLLBAR_SIZE - 4, listPtr->elementHeight, item->window.outlineColor);
3791
size -= listPtr->elementHeight;
3792
if (size < listPtr->elementHeight) {
3793
listPtr->drawPadding = listPtr->elementHeight - size;
3797
y += listPtr->elementHeight;
3805
void Item_OwnerDraw_Paint(itemDef_t *item) {
3811
parent = (menuDef_t*)item->parent;
3813
if (DC->ownerDrawItem) {
3814
vec4_t color, lowLight;
3815
menuDef_t *parent = (menuDef_t*)item->parent;
3816
Fade(&item->window.flags, &item->window.foreColor[3], parent->fadeClamp, &item->window.nextTime, parent->fadeCycle, qtrue, parent->fadeAmount);
3817
memcpy(&color, &item->window.foreColor, sizeof(color));
3818
if (item->numColors > 0 && DC->getValue) {
3819
// if the value is within one of the ranges then set color to that, otherwise leave at default
3821
float f = DC->getValue(item->window.ownerDraw);
3822
for (i = 0; i < item->numColors; i++) {
3823
if (f >= item->colorRanges[i].low && f <= item->colorRanges[i].high) {
3824
memcpy(&color, &item->colorRanges[i].color, sizeof(color));
3830
if (item->window.flags & WINDOW_HASFOCUS) {
3831
lowLight[0] = 0.8 * parent->focusColor[0];
3832
lowLight[1] = 0.8 * parent->focusColor[1];
3833
lowLight[2] = 0.8 * parent->focusColor[2];
3834
lowLight[3] = 0.8 * parent->focusColor[3];
3835
LerpColor(parent->focusColor,lowLight,color,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
3836
} else if (item->textStyle == ITEM_TEXTSTYLE_BLINK && !((DC->realTime/BLINK_DIVISOR) & 1)) {
3837
lowLight[0] = 0.8 * item->window.foreColor[0];
3838
lowLight[1] = 0.8 * item->window.foreColor[1];
3839
lowLight[2] = 0.8 * item->window.foreColor[2];
3840
lowLight[3] = 0.8 * item->window.foreColor[3];
3841
LerpColor(item->window.foreColor,lowLight,color,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
3844
if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
3845
memcpy(color, parent->disableColor, sizeof(vec4_t)); // bk001207 - FIXME: Com_Memcpy
3849
Item_Text_Paint(item);
3850
if (item->text[0]) {
3851
// +8 is an offset kludge to properly align owner draw items that have text combined with them
3852
DC->ownerDrawItem(item->textRect.x + item->textRect.w + 8, item->window.rect.y, item->window.rect.w, item->window.rect.h, 0, item->textaligny, item->window.ownerDraw, item->window.ownerDrawFlags, item->alignment, item->special, item->textscale, color, item->window.background, item->textStyle );
3854
DC->ownerDrawItem(item->textRect.x + item->textRect.w, item->window.rect.y, item->window.rect.w, item->window.rect.h, 0, item->textaligny, item->window.ownerDraw, item->window.ownerDrawFlags, item->alignment, item->special, item->textscale, color, item->window.background, item->textStyle );
3857
DC->ownerDrawItem(item->window.rect.x, item->window.rect.y, item->window.rect.w, item->window.rect.h, item->textalignx, item->textaligny, item->window.ownerDraw, item->window.ownerDrawFlags, item->alignment, item->special, item->textscale, color, item->window.background, item->textStyle );
3863
void Item_Paint(itemDef_t *item) {
3865
menuDef_t *parent = (menuDef_t*)item->parent;
3866
red[0] = red[3] = 1;
3867
red[1] = red[2] = 0;
3873
if (item->window.flags & WINDOW_ORBITING) {
3874
if (DC->realTime > item->window.nextTime) {
3875
float rx, ry, a, c, s, w, h;
3877
item->window.nextTime = DC->realTime + item->window.offsetTime;
3879
w = item->window.rectClient.w / 2;
3880
h = item->window.rectClient.h / 2;
3881
rx = item->window.rectClient.x + w - item->window.rectEffects.x;
3882
ry = item->window.rectClient.y + h - item->window.rectEffects.y;
3886
item->window.rectClient.x = (rx * c - ry * s) + item->window.rectEffects.x - w;
3887
item->window.rectClient.y = (rx * s + ry * c) + item->window.rectEffects.y - h;
3888
Item_UpdatePosition(item);
3894
if (item->window.flags & WINDOW_INTRANSITION) {
3895
if (DC->realTime > item->window.nextTime) {
3897
item->window.nextTime = DC->realTime + item->window.offsetTime;
3898
// transition the x,y
3899
if (item->window.rectClient.x == item->window.rectEffects.x) {
3902
if (item->window.rectClient.x < item->window.rectEffects.x) {
3903
item->window.rectClient.x += item->window.rectEffects2.x;
3904
if (item->window.rectClient.x > item->window.rectEffects.x) {
3905
item->window.rectClient.x = item->window.rectEffects.x;
3909
item->window.rectClient.x -= item->window.rectEffects2.x;
3910
if (item->window.rectClient.x < item->window.rectEffects.x) {
3911
item->window.rectClient.x = item->window.rectEffects.x;
3916
if (item->window.rectClient.y == item->window.rectEffects.y) {
3919
if (item->window.rectClient.y < item->window.rectEffects.y) {
3920
item->window.rectClient.y += item->window.rectEffects2.y;
3921
if (item->window.rectClient.y > item->window.rectEffects.y) {
3922
item->window.rectClient.y = item->window.rectEffects.y;
3926
item->window.rectClient.y -= item->window.rectEffects2.y;
3927
if (item->window.rectClient.y < item->window.rectEffects.y) {
3928
item->window.rectClient.y = item->window.rectEffects.y;
3933
if (item->window.rectClient.w == item->window.rectEffects.w) {
3936
if (item->window.rectClient.w < item->window.rectEffects.w) {
3937
item->window.rectClient.w += item->window.rectEffects2.w;
3938
if (item->window.rectClient.w > item->window.rectEffects.w) {
3939
item->window.rectClient.w = item->window.rectEffects.w;
3943
item->window.rectClient.w -= item->window.rectEffects2.w;
3944
if (item->window.rectClient.w < item->window.rectEffects.w) {
3945
item->window.rectClient.w = item->window.rectEffects.w;
3950
if (item->window.rectClient.h == item->window.rectEffects.h) {
3953
if (item->window.rectClient.h < item->window.rectEffects.h) {
3954
item->window.rectClient.h += item->window.rectEffects2.h;
3955
if (item->window.rectClient.h > item->window.rectEffects.h) {
3956
item->window.rectClient.h = item->window.rectEffects.h;
3960
item->window.rectClient.h -= item->window.rectEffects2.h;
3961
if (item->window.rectClient.h < item->window.rectEffects.h) {
3962
item->window.rectClient.h = item->window.rectEffects.h;
3968
Item_UpdatePosition(item);
3971
item->window.flags &= ~WINDOW_INTRANSITION;
3977
if (item->window.ownerDrawFlags && DC->ownerDrawVisible) {
3978
if (!DC->ownerDrawVisible(item->window.ownerDrawFlags)) {
3979
item->window.flags &= ~WINDOW_VISIBLE;
3981
item->window.flags |= WINDOW_VISIBLE;
3985
if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE)) {
3986
if (!Item_EnableShowViaCvar(item, CVAR_SHOW)) {
3991
if (item->window.flags & WINDOW_TIMEDVISIBLE) {
3995
if (!(item->window.flags & WINDOW_VISIBLE)) {
3999
// paint the rect first..
4000
Window_Paint(&item->window, parent->fadeAmount , parent->fadeClamp, parent->fadeCycle);
4004
rectDef_t *r = Item_CorrectedTextRect(item);
4005
color[1] = color[3] = 1;
4006
color[0] = color[2] = 0;
4007
DC->drawRect(r->x, r->y, r->w, r->h, 1, color);
4010
//DC->drawRect(item->window.rect.x, item->window.rect.y, item->window.rect.w, item->window.rect.h, 1, red);
4012
switch (item->type) {
4013
case ITEM_TYPE_OWNERDRAW:
4014
Item_OwnerDraw_Paint(item);
4016
case ITEM_TYPE_TEXT:
4017
case ITEM_TYPE_BUTTON:
4018
Item_Text_Paint(item);
4020
case ITEM_TYPE_RADIOBUTTON:
4022
case ITEM_TYPE_CHECKBOX:
4024
case ITEM_TYPE_EDITFIELD:
4025
case ITEM_TYPE_NUMERICFIELD:
4026
Item_TextField_Paint(item);
4028
case ITEM_TYPE_COMBO:
4030
case ITEM_TYPE_LISTBOX:
4031
Item_ListBox_Paint(item);
4033
//case ITEM_TYPE_IMAGE:
4034
// Item_Image_Paint(item);
4036
case ITEM_TYPE_MODEL:
4037
Item_Model_Paint(item);
4039
case ITEM_TYPE_YESNO:
4040
Item_YesNo_Paint(item);
4042
case ITEM_TYPE_MULTI:
4043
Item_Multi_Paint(item);
4045
case ITEM_TYPE_BIND:
4046
Item_Bind_Paint(item);
4048
case ITEM_TYPE_SLIDER:
4049
Item_Slider_Paint(item);
4057
void Menu_Init(menuDef_t *menu) {
4058
memset(menu, 0, sizeof(menuDef_t));
4059
menu->cursorItem = -1;
4060
menu->fadeAmount = DC->Assets.fadeAmount;
4061
menu->fadeClamp = DC->Assets.fadeClamp;
4062
menu->fadeCycle = DC->Assets.fadeCycle;
4063
Window_Init(&menu->window);
4066
itemDef_t *Menu_GetFocusedItem(menuDef_t *menu) {
4069
for (i = 0; i < menu->itemCount; i++) {
4070
if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
4071
return menu->items[i];
4078
menuDef_t *Menu_GetFocused(void) {
4080
for (i = 0; i < menuCount; i++) {
4081
if (Menus[i].window.flags & WINDOW_HASFOCUS && Menus[i].window.flags & WINDOW_VISIBLE) {
4088
void Menu_ScrollFeeder(menuDef_t *menu, int feeder, qboolean down) {
4091
for (i = 0; i < menu->itemCount; i++) {
4092
if (menu->items[i]->special == feeder) {
4093
Item_ListBox_HandleKey(menu->items[i], (down) ? K_DOWNARROW : K_UPARROW, qtrue, qtrue);
4102
void Menu_SetFeederSelection(menuDef_t *menu, int feeder, int index, const char *name) {
4105
menu = Menu_GetFocused();
4107
menu = Menus_FindByName(name);
4113
for (i = 0; i < menu->itemCount; i++) {
4114
if (menu->items[i]->special == feeder) {
4116
listBoxDef_t *listPtr = (listBoxDef_t*)menu->items[i]->typeData;
4117
listPtr->cursorPos = 0;
4118
listPtr->startPos = 0;
4120
menu->items[i]->cursorPos = index;
4121
DC->feederSelection(menu->items[i]->special, menu->items[i]->cursorPos);
4128
qboolean Menus_AnyFullScreenVisible(void) {
4130
for (i = 0; i < menuCount; i++) {
4131
if (Menus[i].window.flags & WINDOW_VISIBLE && Menus[i].fullScreen) {
4138
menuDef_t *Menus_ActivateByName(const char *p) {
4140
menuDef_t *m = NULL;
4141
menuDef_t *focus = Menu_GetFocused();
4142
for (i = 0; i < menuCount; i++) {
4143
if (Q_stricmp(Menus[i].window.name, p) == 0) {
4146
if (openMenuCount < MAX_OPEN_MENUS && focus != NULL) {
4147
menuStack[openMenuCount++] = focus;
4150
Menus[i].window.flags &= ~WINDOW_HASFOCUS;
4153
Display_CloseCinematics();
4158
void Item_Init(itemDef_t *item) {
4159
memset(item, 0, sizeof(itemDef_t));
4160
item->textscale = 0.55f;
4161
Window_Init(&item->window);
4164
void Menu_HandleMouseMove(menuDef_t *menu, float x, float y) {
4166
qboolean focusSet = qfalse;
4168
itemDef_t *overItem;
4173
if (!(menu->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
4178
//Item_MouseMove(itemCapture, x, y);
4182
if (g_waitingForKey || g_editingField) {
4186
// FIXME: this is the whole issue of focus vs. mouse over..
4187
// need a better overall solution as i don't like going through everything twice
4188
for (pass = 0; pass < 2; pass++) {
4189
for (i = 0; i < menu->itemCount; i++) {
4190
// turn off focus each item
4191
// menu->items[i].window.flags &= ~WINDOW_HASFOCUS;
4193
if (!(menu->items[i]->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
4197
// items can be enabled and disabled based on cvars
4198
if (menu->items[i]->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(menu->items[i], CVAR_ENABLE)) {
4202
if (menu->items[i]->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(menu->items[i], CVAR_SHOW)) {
4208
if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
4210
overItem = menu->items[i];
4211
if (overItem->type == ITEM_TYPE_TEXT && overItem->text) {
4212
if (!Rect_ContainsPoint(Item_CorrectedTextRect(overItem), x, y)) {
4216
// if we are over an item
4217
if (IsVisible(overItem->window.flags)) {
4219
Item_MouseEnter(overItem, x, y);
4220
// Item_SetMouseOver(overItem, qtrue);
4222
// if item is not a decoration see if it can take focus
4224
focusSet = Item_SetFocus(overItem, x, y);
4228
} else if (menu->items[i]->window.flags & WINDOW_MOUSEOVER) {
4229
Item_MouseLeave(menu->items[i]);
4230
Item_SetMouseOver(menu->items[i], qfalse);
4237
void Menu_Paint(menuDef_t *menu, qboolean forcePaint) {
4244
if (!(menu->window.flags & WINDOW_VISIBLE) && !forcePaint) {
4248
if (menu->window.ownerDrawFlags && DC->ownerDrawVisible && !DC->ownerDrawVisible(menu->window.ownerDrawFlags)) {
4253
menu->window.flags |= WINDOW_FORCED;
4256
// draw the background if necessary
4257
if (menu->fullScreen) {
4258
// implies a background shader
4259
// FIXME: make sure we have a default shader if fullscreen is set with no background
4260
DC->drawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, menu->window.background );
4261
} else if (menu->window.background) {
4262
// this allows a background shader without being full screen
4263
//UI_DrawHandlePic(menu->window.rect.x, menu->window.rect.y, menu->window.rect.w, menu->window.rect.h, menu->backgroundShader);
4266
// paint the background and or border
4267
Window_Paint(&menu->window, menu->fadeAmount, menu->fadeClamp, menu->fadeCycle );
4269
for (i = 0; i < menu->itemCount; i++) {
4270
Item_Paint(menu->items[i]);
4275
color[0] = color[2] = color[3] = 1;
4277
DC->drawRect(menu->window.rect.x, menu->window.rect.y, menu->window.rect.w, menu->window.rect.h, 1, color);
4283
Item_ValidateTypeData
4286
void Item_ValidateTypeData(itemDef_t *item) {
4287
if (item->typeData) {
4291
if (item->type == ITEM_TYPE_LISTBOX) {
4292
item->typeData = UI_Alloc(sizeof(listBoxDef_t));
4293
memset(item->typeData, 0, sizeof(listBoxDef_t));
4294
} else if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD || item->type == ITEM_TYPE_YESNO || item->type == ITEM_TYPE_BIND || item->type == ITEM_TYPE_SLIDER || item->type == ITEM_TYPE_TEXT) {
4295
item->typeData = UI_Alloc(sizeof(editFieldDef_t));
4296
memset(item->typeData, 0, sizeof(editFieldDef_t));
4297
if (item->type == ITEM_TYPE_EDITFIELD) {
4298
if (!((editFieldDef_t *) item->typeData)->maxPaintChars) {
4299
((editFieldDef_t *) item->typeData)->maxPaintChars = MAX_EDITFIELD;
4302
} else if (item->type == ITEM_TYPE_MULTI) {
4303
item->typeData = UI_Alloc(sizeof(multiDef_t));
4304
} else if (item->type == ITEM_TYPE_MODEL) {
4305
item->typeData = UI_Alloc(sizeof(modelDef_t));
4315
#define KEYWORDHASH_SIZE 512
4317
typedef struct keywordHash_s
4320
qboolean (*func)(itemDef_t *item, int handle);
4321
struct keywordHash_s *next;
4324
int KeywordHash_Key(char *keyword) {
4325
int register hash, i;
4328
for (i = 0; keyword[i] != '\0'; i++) {
4329
if (keyword[i] >= 'A' && keyword[i] <= 'Z')
4330
hash += (keyword[i] + ('a' - 'A')) * (119 + i);
4332
hash += keyword[i] * (119 + i);
4334
hash = (hash ^ (hash >> 10) ^ (hash >> 20)) & (KEYWORDHASH_SIZE-1);
4338
void KeywordHash_Add(keywordHash_t *table[], keywordHash_t *key) {
4341
hash = KeywordHash_Key(key->keyword);
4344
int collision = qtrue;
4347
key->next = table[hash];
4351
keywordHash_t *KeywordHash_Find(keywordHash_t *table[], char *keyword)
4356
hash = KeywordHash_Key(keyword);
4357
for (key = table[hash]; key; key = key->next) {
4358
if (!Q_stricmp(key->keyword, keyword))
4366
Item Keyword Parse functions
4371
qboolean ItemParse_name( itemDef_t *item, int handle ) {
4372
if (!PC_String_Parse(handle, &item->window.name)) {
4379
qboolean ItemParse_focusSound( itemDef_t *item, int handle ) {
4381
if (!PC_String_Parse(handle, &temp)) {
4384
item->focusSound = DC->registerSound(temp, qfalse);
4390
qboolean ItemParse_text( itemDef_t *item, int handle ) {
4391
if (!PC_String_Parse(handle, &item->text)) {
4398
qboolean ItemParse_group( itemDef_t *item, int handle ) {
4399
if (!PC_String_Parse(handle, &item->window.group)) {
4405
// asset_model <string>
4406
qboolean ItemParse_asset_model( itemDef_t *item, int handle ) {
4408
modelDef_t *modelPtr;
4409
Item_ValidateTypeData(item);
4410
modelPtr = (modelDef_t*)item->typeData;
4412
if (!PC_String_Parse(handle, &temp)) {
4415
item->asset = DC->registerModel(temp);
4416
modelPtr->angle = rand() % 360;
4420
// asset_shader <string>
4421
qboolean ItemParse_asset_shader( itemDef_t *item, int handle ) {
4424
if (!PC_String_Parse(handle, &temp)) {
4427
item->asset = DC->registerShaderNoMip(temp);
4431
// model_origin <number> <number> <number>
4432
qboolean ItemParse_model_origin( itemDef_t *item, int handle ) {
4433
modelDef_t *modelPtr;
4434
Item_ValidateTypeData(item);
4435
modelPtr = (modelDef_t*)item->typeData;
4437
if (PC_Float_Parse(handle, &modelPtr->origin[0])) {
4438
if (PC_Float_Parse(handle, &modelPtr->origin[1])) {
4439
if (PC_Float_Parse(handle, &modelPtr->origin[2])) {
4447
// model_fovx <number>
4448
qboolean ItemParse_model_fovx( itemDef_t *item, int handle ) {
4449
modelDef_t *modelPtr;
4450
Item_ValidateTypeData(item);
4451
modelPtr = (modelDef_t*)item->typeData;
4453
if (!PC_Float_Parse(handle, &modelPtr->fov_x)) {
4459
// model_fovy <number>
4460
qboolean ItemParse_model_fovy( itemDef_t *item, int handle ) {
4461
modelDef_t *modelPtr;
4462
Item_ValidateTypeData(item);
4463
modelPtr = (modelDef_t*)item->typeData;
4465
if (!PC_Float_Parse(handle, &modelPtr->fov_y)) {
4471
// model_rotation <integer>
4472
qboolean ItemParse_model_rotation( itemDef_t *item, int handle ) {
4473
modelDef_t *modelPtr;
4474
Item_ValidateTypeData(item);
4475
modelPtr = (modelDef_t*)item->typeData;
4477
if (!PC_Int_Parse(handle, &modelPtr->rotationSpeed)) {
4483
// model_angle <integer>
4484
qboolean ItemParse_model_angle( itemDef_t *item, int handle ) {
4485
modelDef_t *modelPtr;
4486
Item_ValidateTypeData(item);
4487
modelPtr = (modelDef_t*)item->typeData;
4489
if (!PC_Int_Parse(handle, &modelPtr->angle)) {
4496
qboolean ItemParse_rect( itemDef_t *item, int handle ) {
4497
if (!PC_Rect_Parse(handle, &item->window.rectClient)) {
4504
qboolean ItemParse_style( itemDef_t *item, int handle ) {
4505
if (!PC_Int_Parse(handle, &item->window.style)) {
4512
qboolean ItemParse_decoration( itemDef_t *item, int handle ) {
4513
item->window.flags |= WINDOW_DECORATION;
4518
qboolean ItemParse_notselectable( itemDef_t *item, int handle ) {
4519
listBoxDef_t *listPtr;
4520
Item_ValidateTypeData(item);
4521
listPtr = (listBoxDef_t*)item->typeData;
4522
if (item->type == ITEM_TYPE_LISTBOX && listPtr) {
4523
listPtr->notselectable = qtrue;
4529
qboolean ItemParse_wrapped( itemDef_t *item, int handle ) {
4530
item->window.flags |= WINDOW_WRAPPED;
4535
qboolean ItemParse_autowrapped( itemDef_t *item, int handle ) {
4536
item->window.flags |= WINDOW_AUTOWRAPPED;
4542
qboolean ItemParse_horizontalscroll( itemDef_t *item, int handle ) {
4543
item->window.flags |= WINDOW_HORIZONTAL;
4548
qboolean ItemParse_type( itemDef_t *item, int handle ) {
4549
if (!PC_Int_Parse(handle, &item->type)) {
4552
Item_ValidateTypeData(item);
4556
// elementwidth, used for listbox image elements
4557
// uses textalignx for storage
4558
qboolean ItemParse_elementwidth( itemDef_t *item, int handle ) {
4559
listBoxDef_t *listPtr;
4561
Item_ValidateTypeData(item);
4562
listPtr = (listBoxDef_t*)item->typeData;
4563
if (!PC_Float_Parse(handle, &listPtr->elementWidth)) {
4569
// elementheight, used for listbox image elements
4570
// uses textaligny for storage
4571
qboolean ItemParse_elementheight( itemDef_t *item, int handle ) {
4572
listBoxDef_t *listPtr;
4574
Item_ValidateTypeData(item);
4575
listPtr = (listBoxDef_t*)item->typeData;
4576
if (!PC_Float_Parse(handle, &listPtr->elementHeight)) {
4583
qboolean ItemParse_feeder( itemDef_t *item, int handle ) {
4584
if (!PC_Float_Parse(handle, &item->special)) {
4590
// elementtype, used to specify what type of elements a listbox contains
4591
// uses textstyle for storage
4592
qboolean ItemParse_elementtype( itemDef_t *item, int handle ) {
4593
listBoxDef_t *listPtr;
4595
Item_ValidateTypeData(item);
4596
if (!item->typeData)
4598
listPtr = (listBoxDef_t*)item->typeData;
4599
if (!PC_Int_Parse(handle, &listPtr->elementStyle)) {
4605
// columns sets a number of columns and an x pos and width per..
4606
qboolean ItemParse_columns( itemDef_t *item, int handle ) {
4608
listBoxDef_t *listPtr;
4610
Item_ValidateTypeData(item);
4611
if (!item->typeData)
4613
listPtr = (listBoxDef_t*)item->typeData;
4614
if (PC_Int_Parse(handle, &num)) {
4615
if (num > MAX_LB_COLUMNS) {
4616
num = MAX_LB_COLUMNS;
4618
listPtr->numColumns = num;
4619
for (i = 0; i < num; i++) {
4620
int pos, width, maxChars;
4622
if (PC_Int_Parse(handle, &pos) && PC_Int_Parse(handle, &width) && PC_Int_Parse(handle, &maxChars)) {
4623
listPtr->columnInfo[i].pos = pos;
4624
listPtr->columnInfo[i].width = width;
4625
listPtr->columnInfo[i].maxChars = maxChars;
4636
qboolean ItemParse_border( itemDef_t *item, int handle ) {
4637
if (!PC_Int_Parse(handle, &item->window.border)) {
4643
qboolean ItemParse_bordersize( itemDef_t *item, int handle ) {
4644
if (!PC_Float_Parse(handle, &item->window.borderSize)) {
4650
qboolean ItemParse_visible( itemDef_t *item, int handle ) {
4653
if (!PC_Int_Parse(handle, &i)) {
4657
item->window.flags |= WINDOW_VISIBLE;
4662
qboolean ItemParse_ownerdraw( itemDef_t *item, int handle ) {
4663
if (!PC_Int_Parse(handle, &item->window.ownerDraw)) {
4666
item->type = ITEM_TYPE_OWNERDRAW;
4670
qboolean ItemParse_align( itemDef_t *item, int handle ) {
4671
if (!PC_Int_Parse(handle, &item->alignment)) {
4677
qboolean ItemParse_textalign( itemDef_t *item, int handle ) {
4678
if (!PC_Int_Parse(handle, &item->textalignment)) {
4684
qboolean ItemParse_textalignx( itemDef_t *item, int handle ) {
4685
if (!PC_Float_Parse(handle, &item->textalignx)) {
4691
qboolean ItemParse_textaligny( itemDef_t *item, int handle ) {
4692
if (!PC_Float_Parse(handle, &item->textaligny)) {
4698
qboolean ItemParse_textscale( itemDef_t *item, int handle ) {
4699
if (!PC_Float_Parse(handle, &item->textscale)) {
4705
qboolean ItemParse_textstyle( itemDef_t *item, int handle ) {
4706
if (!PC_Int_Parse(handle, &item->textStyle)) {
4712
qboolean ItemParse_backcolor( itemDef_t *item, int handle ) {
4716
for (i = 0; i < 4; i++) {
4717
if (!PC_Float_Parse(handle, &f)) {
4720
item->window.backColor[i] = f;
4725
qboolean ItemParse_forecolor( itemDef_t *item, int handle ) {
4729
for (i = 0; i < 4; i++) {
4730
if (!PC_Float_Parse(handle, &f)) {
4733
item->window.foreColor[i] = f;
4734
item->window.flags |= WINDOW_FORECOLORSET;
4739
qboolean ItemParse_bordercolor( itemDef_t *item, int handle ) {
4743
for (i = 0; i < 4; i++) {
4744
if (!PC_Float_Parse(handle, &f)) {
4747
item->window.borderColor[i] = f;
4752
qboolean ItemParse_outlinecolor( itemDef_t *item, int handle ) {
4753
if (!PC_Color_Parse(handle, &item->window.outlineColor)){
4759
qboolean ItemParse_background( itemDef_t *item, int handle ) {
4762
if (!PC_String_Parse(handle, &temp)) {
4765
item->window.background = DC->registerShaderNoMip(temp);
4769
qboolean ItemParse_cinematic( itemDef_t *item, int handle ) {
4770
if (!PC_String_Parse(handle, &item->window.cinematicName)) {
4776
qboolean ItemParse_doubleClick( itemDef_t *item, int handle ) {
4777
listBoxDef_t *listPtr;
4779
Item_ValidateTypeData(item);
4780
if (!item->typeData) {
4784
listPtr = (listBoxDef_t*)item->typeData;
4786
if (!PC_Script_Parse(handle, &listPtr->doubleClick)) {
4792
qboolean ItemParse_onFocus( itemDef_t *item, int handle ) {
4793
if (!PC_Script_Parse(handle, &item->onFocus)) {
4799
qboolean ItemParse_leaveFocus( itemDef_t *item, int handle ) {
4800
if (!PC_Script_Parse(handle, &item->leaveFocus)) {
4806
qboolean ItemParse_mouseEnter( itemDef_t *item, int handle ) {
4807
if (!PC_Script_Parse(handle, &item->mouseEnter)) {
4813
qboolean ItemParse_mouseExit( itemDef_t *item, int handle ) {
4814
if (!PC_Script_Parse(handle, &item->mouseExit)) {
4820
qboolean ItemParse_mouseEnterText( itemDef_t *item, int handle ) {
4821
if (!PC_Script_Parse(handle, &item->mouseEnterText)) {
4827
qboolean ItemParse_mouseExitText( itemDef_t *item, int handle ) {
4828
if (!PC_Script_Parse(handle, &item->mouseExitText)) {
4834
qboolean ItemParse_action( itemDef_t *item, int handle ) {
4835
if (!PC_Script_Parse(handle, &item->action)) {
4841
qboolean ItemParse_special( itemDef_t *item, int handle ) {
4842
if (!PC_Float_Parse(handle, &item->special)) {
4848
qboolean ItemParse_cvarTest( itemDef_t *item, int handle ) {
4849
if (!PC_String_Parse(handle, &item->cvarTest)) {
4855
qboolean ItemParse_cvar( itemDef_t *item, int handle ) {
4856
editFieldDef_t *editPtr;
4858
Item_ValidateTypeData(item);
4859
if (!PC_String_Parse(handle, &item->cvar)) {
4862
if (item->typeData) {
4863
editPtr = (editFieldDef_t*)item->typeData;
4864
editPtr->minVal = -1;
4865
editPtr->maxVal = -1;
4866
editPtr->defVal = -1;
4871
qboolean ItemParse_maxChars( itemDef_t *item, int handle ) {
4872
editFieldDef_t *editPtr;
4875
Item_ValidateTypeData(item);
4876
if (!item->typeData)
4879
if (!PC_Int_Parse(handle, &maxChars)) {
4882
editPtr = (editFieldDef_t*)item->typeData;
4883
editPtr->maxChars = maxChars;
4887
qboolean ItemParse_maxPaintChars( itemDef_t *item, int handle ) {
4888
editFieldDef_t *editPtr;
4891
Item_ValidateTypeData(item);
4892
if (!item->typeData)
4895
if (!PC_Int_Parse(handle, &maxChars)) {
4898
editPtr = (editFieldDef_t*)item->typeData;
4899
editPtr->maxPaintChars = maxChars;
4905
qboolean ItemParse_cvarFloat( itemDef_t *item, int handle ) {
4906
editFieldDef_t *editPtr;
4908
Item_ValidateTypeData(item);
4909
if (!item->typeData)
4911
editPtr = (editFieldDef_t*)item->typeData;
4912
if (PC_String_Parse(handle, &item->cvar) &&
4913
PC_Float_Parse(handle, &editPtr->defVal) &&
4914
PC_Float_Parse(handle, &editPtr->minVal) &&
4915
PC_Float_Parse(handle, &editPtr->maxVal)) {
4921
qboolean ItemParse_cvarStrList( itemDef_t *item, int handle ) {
4923
multiDef_t *multiPtr;
4926
Item_ValidateTypeData(item);
4927
if (!item->typeData)
4929
multiPtr = (multiDef_t*)item->typeData;
4930
multiPtr->count = 0;
4931
multiPtr->strDef = qtrue;
4933
if (!trap_PC_ReadToken(handle, &token))
4935
if (*token.string != '{') {
4941
if (!trap_PC_ReadToken(handle, &token)) {
4942
PC_SourceError(handle, "end of file inside menu item\n");
4946
if (*token.string == '}') {
4950
if (*token.string == ',' || *token.string == ';') {
4955
multiPtr->cvarList[multiPtr->count] = String_Alloc(token.string);
4958
multiPtr->cvarStr[multiPtr->count] = String_Alloc(token.string);
4961
if (multiPtr->count >= MAX_MULTI_CVARS) {
4967
return qfalse; // bk001205 - LCC missing return value
4970
qboolean ItemParse_cvarFloatList( itemDef_t *item, int handle ) {
4972
multiDef_t *multiPtr;
4974
Item_ValidateTypeData(item);
4975
if (!item->typeData)
4977
multiPtr = (multiDef_t*)item->typeData;
4978
multiPtr->count = 0;
4979
multiPtr->strDef = qfalse;
4981
if (!trap_PC_ReadToken(handle, &token))
4983
if (*token.string != '{') {
4988
if (!trap_PC_ReadToken(handle, &token)) {
4989
PC_SourceError(handle, "end of file inside menu item\n");
4993
if (*token.string == '}') {
4997
if (*token.string == ',' || *token.string == ';') {
5001
multiPtr->cvarList[multiPtr->count] = String_Alloc(token.string);
5002
if (!PC_Float_Parse(handle, &multiPtr->cvarValue[multiPtr->count])) {
5007
if (multiPtr->count >= MAX_MULTI_CVARS) {
5012
return qfalse; // bk001205 - LCC missing return value
5017
qboolean ItemParse_addColorRange( itemDef_t *item, int handle ) {
5018
colorRangeDef_t color;
5020
if (PC_Float_Parse(handle, &color.low) &&
5021
PC_Float_Parse(handle, &color.high) &&
5022
PC_Color_Parse(handle, &color.color) ) {
5023
if (item->numColors < MAX_COLOR_RANGES) {
5024
memcpy(&item->colorRanges[item->numColors], &color, sizeof(color));
5032
qboolean ItemParse_ownerdrawFlag( itemDef_t *item, int handle ) {
5034
if (!PC_Int_Parse(handle, &i)) {
5037
item->window.ownerDrawFlags |= i;
5041
qboolean ItemParse_enableCvar( itemDef_t *item, int handle ) {
5042
if (PC_Script_Parse(handle, &item->enableCvar)) {
5043
item->cvarFlags = CVAR_ENABLE;
5049
qboolean ItemParse_disableCvar( itemDef_t *item, int handle ) {
5050
if (PC_Script_Parse(handle, &item->enableCvar)) {
5051
item->cvarFlags = CVAR_DISABLE;
5057
qboolean ItemParse_showCvar( itemDef_t *item, int handle ) {
5058
if (PC_Script_Parse(handle, &item->enableCvar)) {
5059
item->cvarFlags = CVAR_SHOW;
5065
qboolean ItemParse_hideCvar( itemDef_t *item, int handle ) {
5066
if (PC_Script_Parse(handle, &item->enableCvar)) {
5067
item->cvarFlags = CVAR_HIDE;
5074
keywordHash_t itemParseKeywords[] = {
5075
{"name", ItemParse_name, NULL},
5076
{"text", ItemParse_text, NULL},
5077
{"group", ItemParse_group, NULL},
5078
{"asset_model", ItemParse_asset_model, NULL},
5079
{"asset_shader", ItemParse_asset_shader, NULL},
5080
{"model_origin", ItemParse_model_origin, NULL},
5081
{"model_fovx", ItemParse_model_fovx, NULL},
5082
{"model_fovy", ItemParse_model_fovy, NULL},
5083
{"model_rotation", ItemParse_model_rotation, NULL},
5084
{"model_angle", ItemParse_model_angle, NULL},
5085
{"rect", ItemParse_rect, NULL},
5086
{"style", ItemParse_style, NULL},
5087
{"decoration", ItemParse_decoration, NULL},
5088
{"notselectable", ItemParse_notselectable, NULL},
5089
{"wrapped", ItemParse_wrapped, NULL},
5090
{"autowrapped", ItemParse_autowrapped, NULL},
5091
{"horizontalscroll", ItemParse_horizontalscroll, NULL},
5092
{"type", ItemParse_type, NULL},
5093
{"elementwidth", ItemParse_elementwidth, NULL},
5094
{"elementheight", ItemParse_elementheight, NULL},
5095
{"feeder", ItemParse_feeder, NULL},
5096
{"elementtype", ItemParse_elementtype, NULL},
5097
{"columns", ItemParse_columns, NULL},
5098
{"border", ItemParse_border, NULL},
5099
{"bordersize", ItemParse_bordersize, NULL},
5100
{"visible", ItemParse_visible, NULL},
5101
{"ownerdraw", ItemParse_ownerdraw, NULL},
5102
{"align", ItemParse_align, NULL},
5103
{"textalign", ItemParse_textalign, NULL},
5104
{"textalignx", ItemParse_textalignx, NULL},
5105
{"textaligny", ItemParse_textaligny, NULL},
5106
{"textscale", ItemParse_textscale, NULL},
5107
{"textstyle", ItemParse_textstyle, NULL},
5108
{"backcolor", ItemParse_backcolor, NULL},
5109
{"forecolor", ItemParse_forecolor, NULL},
5110
{"bordercolor", ItemParse_bordercolor, NULL},
5111
{"outlinecolor", ItemParse_outlinecolor, NULL},
5112
{"background", ItemParse_background, NULL},
5113
{"onFocus", ItemParse_onFocus, NULL},
5114
{"leaveFocus", ItemParse_leaveFocus, NULL},
5115
{"mouseEnter", ItemParse_mouseEnter, NULL},
5116
{"mouseExit", ItemParse_mouseExit, NULL},
5117
{"mouseEnterText", ItemParse_mouseEnterText, NULL},
5118
{"mouseExitText", ItemParse_mouseExitText, NULL},
5119
{"action", ItemParse_action, NULL},
5120
{"special", ItemParse_special, NULL},
5121
{"cvar", ItemParse_cvar, NULL},
5122
{"maxChars", ItemParse_maxChars, NULL},
5123
{"maxPaintChars", ItemParse_maxPaintChars, NULL},
5124
{"focusSound", ItemParse_focusSound, NULL},
5125
{"cvarFloat", ItemParse_cvarFloat, NULL},
5126
{"cvarStrList", ItemParse_cvarStrList, NULL},
5127
{"cvarFloatList", ItemParse_cvarFloatList, NULL},
5128
{"addColorRange", ItemParse_addColorRange, NULL},
5129
{"ownerdrawFlag", ItemParse_ownerdrawFlag, NULL},
5130
{"enableCvar", ItemParse_enableCvar, NULL},
5131
{"cvarTest", ItemParse_cvarTest, NULL},
5132
{"disableCvar", ItemParse_disableCvar, NULL},
5133
{"showCvar", ItemParse_showCvar, NULL},
5134
{"hideCvar", ItemParse_hideCvar, NULL},
5135
{"cinematic", ItemParse_cinematic, NULL},
5136
{"doubleclick", ItemParse_doubleClick, NULL},
5140
keywordHash_t *itemParseKeywordHash[KEYWORDHASH_SIZE];
5144
Item_SetupKeywordHash
5147
void Item_SetupKeywordHash(void) {
5150
memset(itemParseKeywordHash, 0, sizeof(itemParseKeywordHash));
5151
for (i = 0; itemParseKeywords[i].keyword; i++) {
5152
KeywordHash_Add(itemParseKeywordHash, &itemParseKeywords[i]);
5161
qboolean Item_Parse(int handle, itemDef_t *item) {
5166
if (!trap_PC_ReadToken(handle, &token))
5168
if (*token.string != '{') {
5172
if (!trap_PC_ReadToken(handle, &token)) {
5173
PC_SourceError(handle, "end of file inside menu item\n");
5177
if (*token.string == '}') {
5181
key = KeywordHash_Find(itemParseKeywordHash, token.string);
5183
PC_SourceError(handle, "unknown menu item keyword %s", token.string);
5186
if ( !key->func(item, handle) ) {
5187
PC_SourceError(handle, "couldn't parse menu item keyword %s", token.string);
5191
return qfalse; // bk001205 - LCC missing return value
5195
// Item_InitControls
5196
// init's special control types
5197
void Item_InitControls(itemDef_t *item) {
5201
if (item->type == ITEM_TYPE_LISTBOX) {
5202
listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
5203
item->cursorPos = 0;
5205
listPtr->cursorPos = 0;
5206
listPtr->startPos = 0;
5207
listPtr->endPos = 0;
5208
listPtr->cursorPos = 0;
5215
Menu Keyword Parse functions
5219
qboolean MenuParse_font( itemDef_t *item, int handle ) {
5220
menuDef_t *menu = (menuDef_t*)item;
5221
if (!PC_String_Parse(handle, &menu->font)) {
5224
if (!DC->Assets.fontRegistered) {
5225
DC->registerFont(menu->font, 48, &DC->Assets.textFont);
5226
DC->Assets.fontRegistered = qtrue;
5231
qboolean MenuParse_name( itemDef_t *item, int handle ) {
5232
menuDef_t *menu = (menuDef_t*)item;
5233
if (!PC_String_Parse(handle, &menu->window.name)) {
5236
if (Q_stricmp(menu->window.name, "main") == 0) {
5237
// default main as having focus
5238
//menu->window.flags |= WINDOW_HASFOCUS;
5243
qboolean MenuParse_fullscreen( itemDef_t *item, int handle ) {
5244
menuDef_t *menu = (menuDef_t*)item;
5245
if (!PC_Int_Parse(handle, (int*) &menu->fullScreen)) { // bk001206 - cast qboolean
5251
qboolean MenuParse_rect( itemDef_t *item, int handle ) {
5252
menuDef_t *menu = (menuDef_t*)item;
5253
if (!PC_Rect_Parse(handle, &menu->window.rect)) {
5259
qboolean MenuParse_style( itemDef_t *item, int handle ) {
5260
menuDef_t *menu = (menuDef_t*)item;
5261
if (!PC_Int_Parse(handle, &menu->window.style)) {
5267
qboolean MenuParse_visible( itemDef_t *item, int handle ) {
5269
menuDef_t *menu = (menuDef_t*)item;
5271
if (!PC_Int_Parse(handle, &i)) {
5275
menu->window.flags |= WINDOW_VISIBLE;
5280
qboolean MenuParse_onOpen( itemDef_t *item, int handle ) {
5281
menuDef_t *menu = (menuDef_t*)item;
5282
if (!PC_Script_Parse(handle, &menu->onOpen)) {
5288
qboolean MenuParse_onClose( itemDef_t *item, int handle ) {
5289
menuDef_t *menu = (menuDef_t*)item;
5290
if (!PC_Script_Parse(handle, &menu->onClose)) {
5296
qboolean MenuParse_onESC( itemDef_t *item, int handle ) {
5297
menuDef_t *menu = (menuDef_t*)item;
5298
if (!PC_Script_Parse(handle, &menu->onESC)) {
5306
qboolean MenuParse_border( itemDef_t *item, int handle ) {
5307
menuDef_t *menu = (menuDef_t*)item;
5308
if (!PC_Int_Parse(handle, &menu->window.border)) {
5314
qboolean MenuParse_borderSize( itemDef_t *item, int handle ) {
5315
menuDef_t *menu = (menuDef_t*)item;
5316
if (!PC_Float_Parse(handle, &menu->window.borderSize)) {
5322
qboolean MenuParse_backcolor( itemDef_t *item, int handle ) {
5325
menuDef_t *menu = (menuDef_t*)item;
5327
for (i = 0; i < 4; i++) {
5328
if (!PC_Float_Parse(handle, &f)) {
5331
menu->window.backColor[i] = f;
5336
qboolean MenuParse_forecolor( itemDef_t *item, int handle ) {
5339
menuDef_t *menu = (menuDef_t*)item;
5341
for (i = 0; i < 4; i++) {
5342
if (!PC_Float_Parse(handle, &f)) {
5345
menu->window.foreColor[i] = f;
5346
menu->window.flags |= WINDOW_FORECOLORSET;
5351
qboolean MenuParse_bordercolor( itemDef_t *item, int handle ) {
5354
menuDef_t *menu = (menuDef_t*)item;
5356
for (i = 0; i < 4; i++) {
5357
if (!PC_Float_Parse(handle, &f)) {
5360
menu->window.borderColor[i] = f;
5365
qboolean MenuParse_focuscolor( itemDef_t *item, int handle ) {
5368
menuDef_t *menu = (menuDef_t*)item;
5370
for (i = 0; i < 4; i++) {
5371
if (!PC_Float_Parse(handle, &f)) {
5374
menu->focusColor[i] = f;
5379
qboolean MenuParse_disablecolor( itemDef_t *item, int handle ) {
5382
menuDef_t *menu = (menuDef_t*)item;
5383
for (i = 0; i < 4; i++) {
5384
if (!PC_Float_Parse(handle, &f)) {
5387
menu->disableColor[i] = f;
5393
qboolean MenuParse_outlinecolor( itemDef_t *item, int handle ) {
5394
menuDef_t *menu = (menuDef_t*)item;
5395
if (!PC_Color_Parse(handle, &menu->window.outlineColor)){
5401
qboolean MenuParse_background( itemDef_t *item, int handle ) {
5403
menuDef_t *menu = (menuDef_t*)item;
5405
if (!PC_String_Parse(handle, &buff)) {
5408
menu->window.background = DC->registerShaderNoMip(buff);
5412
qboolean MenuParse_cinematic( itemDef_t *item, int handle ) {
5413
menuDef_t *menu = (menuDef_t*)item;
5415
if (!PC_String_Parse(handle, &menu->window.cinematicName)) {
5421
qboolean MenuParse_ownerdrawFlag( itemDef_t *item, int handle ) {
5423
menuDef_t *menu = (menuDef_t*)item;
5425
if (!PC_Int_Parse(handle, &i)) {
5428
menu->window.ownerDrawFlags |= i;
5432
qboolean MenuParse_ownerdraw( itemDef_t *item, int handle ) {
5433
menuDef_t *menu = (menuDef_t*)item;
5435
if (!PC_Int_Parse(handle, &menu->window.ownerDraw)) {
5443
qboolean MenuParse_popup( itemDef_t *item, int handle ) {
5444
menuDef_t *menu = (menuDef_t*)item;
5445
menu->window.flags |= WINDOW_POPUP;
5450
qboolean MenuParse_outOfBounds( itemDef_t *item, int handle ) {
5451
menuDef_t *menu = (menuDef_t*)item;
5453
menu->window.flags |= WINDOW_OOB_CLICK;
5457
qboolean MenuParse_soundLoop( itemDef_t *item, int handle ) {
5458
menuDef_t *menu = (menuDef_t*)item;
5460
if (!PC_String_Parse(handle, &menu->soundName)) {
5466
qboolean MenuParse_fadeClamp( itemDef_t *item, int handle ) {
5467
menuDef_t *menu = (menuDef_t*)item;
5469
if (!PC_Float_Parse(handle, &menu->fadeClamp)) {
5475
qboolean MenuParse_fadeAmount( itemDef_t *item, int handle ) {
5476
menuDef_t *menu = (menuDef_t*)item;
5478
if (!PC_Float_Parse(handle, &menu->fadeAmount)) {
5485
qboolean MenuParse_fadeCycle( itemDef_t *item, int handle ) {
5486
menuDef_t *menu = (menuDef_t*)item;
5488
if (!PC_Int_Parse(handle, &menu->fadeCycle)) {
5495
qboolean MenuParse_itemDef( itemDef_t *item, int handle ) {
5496
menuDef_t *menu = (menuDef_t*)item;
5497
if (menu->itemCount < MAX_MENUITEMS) {
5498
menu->items[menu->itemCount] = UI_Alloc(sizeof(itemDef_t));
5499
Item_Init(menu->items[menu->itemCount]);
5500
if (!Item_Parse(handle, menu->items[menu->itemCount])) {
5503
Item_InitControls(menu->items[menu->itemCount]);
5504
menu->items[menu->itemCount++]->parent = menu;
5509
keywordHash_t menuParseKeywords[] = {
5510
{"font", MenuParse_font, NULL},
5511
{"name", MenuParse_name, NULL},
5512
{"fullscreen", MenuParse_fullscreen, NULL},
5513
{"rect", MenuParse_rect, NULL},
5514
{"style", MenuParse_style, NULL},
5515
{"visible", MenuParse_visible, NULL},
5516
{"onOpen", MenuParse_onOpen, NULL},
5517
{"onClose", MenuParse_onClose, NULL},
5518
{"onESC", MenuParse_onESC, NULL},
5519
{"border", MenuParse_border, NULL},
5520
{"borderSize", MenuParse_borderSize, NULL},
5521
{"backcolor", MenuParse_backcolor, NULL},
5522
{"forecolor", MenuParse_forecolor, NULL},
5523
{"bordercolor", MenuParse_bordercolor, NULL},
5524
{"focuscolor", MenuParse_focuscolor, NULL},
5525
{"disablecolor", MenuParse_disablecolor, NULL},
5526
{"outlinecolor", MenuParse_outlinecolor, NULL},
5527
{"background", MenuParse_background, NULL},
5528
{"ownerdraw", MenuParse_ownerdraw, NULL},
5529
{"ownerdrawFlag", MenuParse_ownerdrawFlag, NULL},
5530
{"outOfBoundsClick", MenuParse_outOfBounds, NULL},
5531
{"soundLoop", MenuParse_soundLoop, NULL},
5532
{"itemDef", MenuParse_itemDef, NULL},
5533
{"cinematic", MenuParse_cinematic, NULL},
5534
{"popup", MenuParse_popup, NULL},
5535
{"fadeClamp", MenuParse_fadeClamp, NULL},
5536
{"fadeCycle", MenuParse_fadeCycle, NULL},
5537
{"fadeAmount", MenuParse_fadeAmount, NULL},
5541
keywordHash_t *menuParseKeywordHash[KEYWORDHASH_SIZE];
5545
Menu_SetupKeywordHash
5548
void Menu_SetupKeywordHash(void) {
5551
memset(menuParseKeywordHash, 0, sizeof(menuParseKeywordHash));
5552
for (i = 0; menuParseKeywords[i].keyword; i++) {
5553
KeywordHash_Add(menuParseKeywordHash, &menuParseKeywords[i]);
5562
qboolean Menu_Parse(int handle, menuDef_t *menu) {
5566
if (!trap_PC_ReadToken(handle, &token))
5568
if (*token.string != '{') {
5574
memset(&token, 0, sizeof(pc_token_t));
5575
if (!trap_PC_ReadToken(handle, &token)) {
5576
PC_SourceError(handle, "end of file inside menu\n");
5580
if (*token.string == '}') {
5584
key = KeywordHash_Find(menuParseKeywordHash, token.string);
5586
PC_SourceError(handle, "unknown menu keyword %s", token.string);
5589
if ( !key->func((itemDef_t*)menu, handle) ) {
5590
PC_SourceError(handle, "couldn't parse menu keyword %s", token.string);
5594
return qfalse; // bk001205 - LCC missing return value
5602
void Menu_New(int handle) {
5603
menuDef_t *menu = &Menus[menuCount];
5605
if (menuCount < MAX_MENUS) {
5607
if (Menu_Parse(handle, menu)) {
5608
Menu_PostParse(menu);
5614
int Menu_Count(void) {
5618
void Menu_PaintAll(void) {
5621
captureFunc(captureData);
5624
for (i = 0; i < Menu_Count(); i++) {
5625
Menu_Paint(&Menus[i], qfalse);
5629
vec4_t v = {1, 1, 1, 1};
5630
DC->drawText(5, 25, .5, v, va("fps: %f", DC->FPS), 0, 0, 0);
5634
void Menu_Reset(void) {
5638
displayContextDef_t *Display_GetContext(void) {
5642
#ifndef MISSIONPACK // bk001206
5643
static float captureX;
5644
static float captureY;
5647
void *Display_CaptureItem(int x, int y) {
5650
for (i = 0; i < menuCount; i++) {
5651
// turn off focus each item
5652
// menu->items[i].window.flags &= ~WINDOW_HASFOCUS;
5653
if (Rect_ContainsPoint(&Menus[i].window.rect, x, y)) {
5662
qboolean Display_MouseMove(void *p, int x, int y) {
5664
menuDef_t *menu = p;
5667
menu = Menu_GetFocused();
5669
if (menu->window.flags & WINDOW_POPUP) {
5670
Menu_HandleMouseMove(menu, x, y);
5674
for (i = 0; i < menuCount; i++) {
5675
Menu_HandleMouseMove(&Menus[i], x, y);
5678
menu->window.rect.x += x;
5679
menu->window.rect.y += y;
5680
Menu_UpdatePosition(menu);
5686
int Display_CursorType(int x, int y) {
5688
for (i = 0; i < menuCount; i++) {
5690
r2.x = Menus[i].window.rect.x - 3;
5691
r2.y = Menus[i].window.rect.y - 3;
5693
if (Rect_ContainsPoint(&r2, x, y)) {
5694
return CURSOR_SIZER;
5697
return CURSOR_ARROW;
5701
void Display_HandleKey(int key, qboolean down, int x, int y) {
5702
menuDef_t *menu = Display_CaptureItem(x, y);
5704
menu = Menu_GetFocused();
5707
Menu_HandleKey(menu, key, down );
5711
static void Window_CacheContents(windowDef_t *window) {
5713
if (window->cinematicName) {
5714
int cin = DC->playCinematic(window->cinematicName, 0, 0, 0, 0);
5715
DC->stopCinematic(cin);
5721
static void Item_CacheContents(itemDef_t *item) {
5723
Window_CacheContents(&item->window);
5728
static void Menu_CacheContents(menuDef_t *menu) {
5731
Window_CacheContents(&menu->window);
5732
for (i = 0; i < menu->itemCount; i++) {
5733
Item_CacheContents(menu->items[i]);
5736
if (menu->soundName && *menu->soundName) {
5737
DC->registerSound(menu->soundName, qfalse);
5743
void Display_CacheAll(void) {
5745
for (i = 0; i < menuCount; i++) {
5746
Menu_CacheContents(&Menus[i]);
5751
static qboolean Menu_OverActiveItem(menuDef_t *menu, float x, float y) {
5752
if (menu && menu->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED)) {
5753
if (Rect_ContainsPoint(&menu->window.rect, x, y)) {
5755
for (i = 0; i < menu->itemCount; i++) {
5756
// turn off focus each item
5757
// menu->items[i].window.flags &= ~WINDOW_HASFOCUS;
5759
if (!(menu->items[i]->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
5763
if (menu->items[i]->window.flags & WINDOW_DECORATION) {
5767
if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
5768
itemDef_t *overItem = menu->items[i];
5769
if (overItem->type == ITEM_TYPE_TEXT && overItem->text) {
5770
if (Rect_ContainsPoint(Item_CorrectedTextRect(overItem), x, y)) {