00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "ui_shared.h"
00026
00027 #define SCROLL_TIME_START 500
00028 #define SCROLL_TIME_ADJUST 150
00029 #define SCROLL_TIME_ADJUSTOFFSET 40
00030 #define SCROLL_TIME_FLOOR 20
00031
00032 typedef struct scrollInfo_s {
00033 int nextScrollTime;
00034 int nextAdjustTime;
00035 int adjustValue;
00036 int scrollKey;
00037 float xStart;
00038 float yStart;
00039 itemDef_t *item;
00040 qboolean scrollDir;
00041 } scrollInfo_t;
00042
00043 static scrollInfo_t scrollInfo;
00044
00045 static void (*captureFunc) (void *p) = NULL;
00046 static void *captureData = NULL;
00047 static itemDef_t *itemCapture = NULL;
00048
00049 displayContextDef_t *DC = NULL;
00050
00051 static qboolean g_waitingForKey = qfalse;
00052 static qboolean g_editingField = qfalse;
00053
00054 static itemDef_t *g_bindItem = NULL;
00055 static itemDef_t *g_editItem = NULL;
00056
00057 menuDef_t Menus[MAX_MENUS];
00058 int menuCount = 0;
00059
00060 menuDef_t *menuStack[MAX_OPEN_MENUS];
00061 int openMenuCount = 0;
00062
00063 static qboolean debugMode = qfalse;
00064
00065 #define DOUBLE_CLICK_DELAY 300
00066 static int lastListBoxClickTime = 0;
00067
00068 void Item_RunScript(itemDef_t *item, const char *s);
00069 void Item_SetupKeywordHash(void);
00070 void Menu_SetupKeywordHash(void);
00071 int BindingIDFromName(const char *name);
00072 qboolean Item_Bind_HandleKey(itemDef_t *item, int key, qboolean down);
00073 itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu);
00074 itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu);
00075 static qboolean Menu_OverActiveItem(menuDef_t *menu, float x, float y);
00076
00077 #ifdef CGAME
00078 #define MEM_POOL_SIZE 128 * 1024
00079 #else
00080 #define MEM_POOL_SIZE 1024 * 1024
00081 #endif
00082
00083 static char memoryPool[MEM_POOL_SIZE];
00084 static int allocPoint, outOfMemory;
00085
00086
00087
00088
00089
00090
00091
00092 void *UI_Alloc( int size ) {
00093 char *p;
00094
00095 if ( allocPoint + size > MEM_POOL_SIZE ) {
00096 outOfMemory = qtrue;
00097 if (DC->Print) {
00098 DC->Print("UI_Alloc: Failure. Out of memory!\n");
00099 }
00100
00101 return NULL;
00102 }
00103
00104 p = &memoryPool[allocPoint];
00105
00106 allocPoint += ( size + 15 ) & ~15;
00107
00108 return p;
00109 }
00110
00111
00112
00113
00114
00115
00116 void UI_InitMemory( void ) {
00117 allocPoint = 0;
00118 outOfMemory = qfalse;
00119 }
00120
00121 qboolean UI_OutOfMemory() {
00122 return outOfMemory;
00123 }
00124
00125
00126
00127
00128
00129 #define HASH_TABLE_SIZE 2048
00130
00131
00132
00133
00134
00135 static long hashForString(const char *str) {
00136 int i;
00137 long hash;
00138 char letter;
00139
00140 hash = 0;
00141 i = 0;
00142 while (str[i] != '\0') {
00143 letter = tolower(str[i]);
00144 hash+=(long)(letter)*(i+119);
00145 i++;
00146 }
00147 hash &= (HASH_TABLE_SIZE-1);
00148 return hash;
00149 }
00150
00151 typedef struct stringDef_s {
00152 struct stringDef_s *next;
00153 const char *str;
00154 } stringDef_t;
00155
00156 static int strPoolIndex = 0;
00157 static char strPool[STRING_POOL_SIZE];
00158
00159 static int strHandleCount = 0;
00160 static stringDef_t *strHandle[HASH_TABLE_SIZE];
00161
00162
00163 const char *String_Alloc(const char *p) {
00164 int len;
00165 long hash;
00166 stringDef_t *str, *last;
00167 static const char *staticNULL = "";
00168
00169 if (p == NULL) {
00170 return NULL;
00171 }
00172
00173 if (*p == 0) {
00174 return staticNULL;
00175 }
00176
00177 hash = hashForString(p);
00178
00179 str = strHandle[hash];
00180 while (str) {
00181 if (strcmp(p, str->str) == 0) {
00182 return str->str;
00183 }
00184 str = str->next;
00185 }
00186
00187 len = strlen(p);
00188 if (len + strPoolIndex + 1 < STRING_POOL_SIZE) {
00189 int ph = strPoolIndex;
00190 strcpy(&strPool[strPoolIndex], p);
00191 strPoolIndex += len + 1;
00192
00193 str = strHandle[hash];
00194 last = str;
00195 while (str && str->next) {
00196 last = str;
00197 str = str->next;
00198 }
00199
00200 str = UI_Alloc(sizeof(stringDef_t));
00201 str->next = NULL;
00202 str->str = &strPool[ph];
00203 if (last) {
00204 last->next = str;
00205 } else {
00206 strHandle[hash] = str;
00207 }
00208 return &strPool[ph];
00209 }
00210 return NULL;
00211 }
00212
00213 void String_Report() {
00214 float f;
00215 Com_Printf("Memory/String Pool Info\n");
00216 Com_Printf("----------------\n");
00217 f = strPoolIndex;
00218 f /= STRING_POOL_SIZE;
00219 f *= 100;
00220 Com_Printf("String Pool is %.1f%% full, %i bytes out of %i used.\n", f, strPoolIndex, STRING_POOL_SIZE);
00221 f = allocPoint;
00222 f /= MEM_POOL_SIZE;
00223 f *= 100;
00224 Com_Printf("Memory Pool is %.1f%% full, %i bytes out of %i used.\n", f, allocPoint, MEM_POOL_SIZE);
00225 }
00226
00227
00228
00229
00230
00231
00232 void String_Init() {
00233 int i;
00234 for (i = 0; i < HASH_TABLE_SIZE; i++) {
00235 strHandle[i] = 0;
00236 }
00237 strHandleCount = 0;
00238 strPoolIndex = 0;
00239 menuCount = 0;
00240 openMenuCount = 0;
00241 UI_InitMemory();
00242 Item_SetupKeywordHash();
00243 Menu_SetupKeywordHash();
00244 if (DC && DC->getBindingBuf) {
00245 Controls_GetConfig();
00246 }
00247 }
00248
00249
00250
00251
00252
00253
00254 void PC_SourceWarning(int handle, char *format, ...) {
00255 int line;
00256 char filename[128];
00257 va_list argptr;
00258 static char string[4096];
00259
00260 va_start (argptr, format);
00261 vsprintf (string, format, argptr);
00262 va_end (argptr);
00263
00264 filename[0] = '\0';
00265 line = 0;
00266 trap_PC_SourceFileAndLine(handle, filename, &line);
00267
00268 Com_Printf(S_COLOR_YELLOW "WARNING: %s, line %d: %s\n", filename, line, string);
00269 }
00270
00271
00272
00273
00274
00275
00276 void PC_SourceError(int handle, char *format, ...) {
00277 int line;
00278 char filename[128];
00279 va_list argptr;
00280 static char string[4096];
00281
00282 va_start (argptr, format);
00283 vsprintf (string, format, argptr);
00284 va_end (argptr);
00285
00286 filename[0] = '\0';
00287 line = 0;
00288 trap_PC_SourceFileAndLine(handle, filename, &line);
00289
00290 Com_Printf(S_COLOR_RED "ERROR: %s, line %d: %s\n", filename, line, string);
00291 }
00292
00293
00294
00295
00296
00297
00298 void LerpColor(vec4_t a, vec4_t b, vec4_t c, float t)
00299 {
00300 int i;
00301
00302
00303 for (i=0; i<4; i++)
00304 {
00305 c[i] = a[i] + t*(b[i]-a[i]);
00306 if (c[i] < 0)
00307 c[i] = 0;
00308 else if (c[i] > 1.0)
00309 c[i] = 1.0;
00310 }
00311 }
00312
00313
00314
00315
00316
00317
00318 qboolean Float_Parse(char **p, float *f) {
00319 char *token;
00320 token = COM_ParseExt(p, qfalse);
00321 if (token && token[0] != 0) {
00322 *f = atof(token);
00323 return qtrue;
00324 } else {
00325 return qfalse;
00326 }
00327 }
00328
00329
00330
00331
00332
00333
00334 qboolean PC_Float_Parse(int handle, float *f) {
00335 pc_token_t token;
00336 int negative = qfalse;
00337
00338 if (!trap_PC_ReadToken(handle, &token))
00339 return qfalse;
00340 if (token.string[0] == '-') {
00341 if (!trap_PC_ReadToken(handle, &token))
00342 return qfalse;
00343 negative = qtrue;
00344 }
00345 if (token.type != TT_NUMBER) {
00346 PC_SourceError(handle, "expected float but found %s\n", token.string);
00347 return qfalse;
00348 }
00349 if (negative)
00350 *f = -token.floatvalue;
00351 else
00352 *f = token.floatvalue;
00353 return qtrue;
00354 }
00355
00356
00357
00358
00359
00360
00361 qboolean Color_Parse(char **p, vec4_t *c) {
00362 int i;
00363 float f;
00364
00365 for (i = 0; i < 4; i++) {
00366 if (!Float_Parse(p, &f)) {
00367 return qfalse;
00368 }
00369 (*c)[i] = f;
00370 }
00371 return qtrue;
00372 }
00373
00374
00375
00376
00377
00378
00379 qboolean PC_Color_Parse(int handle, vec4_t *c) {
00380 int i;
00381 float f;
00382
00383 for (i = 0; i < 4; i++) {
00384 if (!PC_Float_Parse(handle, &f)) {
00385 return qfalse;
00386 }
00387 (*c)[i] = f;
00388 }
00389 return qtrue;
00390 }
00391
00392
00393
00394
00395
00396
00397 qboolean Int_Parse(char **p, int *i) {
00398 char *token;
00399 token = COM_ParseExt(p, qfalse);
00400
00401 if (token && token[0] != 0) {
00402 *i = atoi(token);
00403 return qtrue;
00404 } else {
00405 return qfalse;
00406 }
00407 }
00408
00409
00410
00411
00412
00413
00414 qboolean PC_Int_Parse(int handle, int *i) {
00415 pc_token_t token;
00416 int negative = qfalse;
00417
00418 if (!trap_PC_ReadToken(handle, &token))
00419 return qfalse;
00420 if (token.string[0] == '-') {
00421 if (!trap_PC_ReadToken(handle, &token))
00422 return qfalse;
00423 negative = qtrue;
00424 }
00425 if (token.type != TT_NUMBER) {
00426 PC_SourceError(handle, "expected integer but found %s\n", token.string);
00427 return qfalse;
00428 }
00429 *i = token.intvalue;
00430 if (negative)
00431 *i = - *i;
00432 return qtrue;
00433 }
00434
00435
00436
00437
00438
00439
00440 qboolean Rect_Parse(char **p, rectDef_t *r) {
00441 if (Float_Parse(p, &r->x)) {
00442 if (Float_Parse(p, &r->y)) {
00443 if (Float_Parse(p, &r->w)) {
00444 if (Float_Parse(p, &r->h)) {
00445 return qtrue;
00446 }
00447 }
00448 }
00449 }
00450 return qfalse;
00451 }
00452
00453
00454
00455
00456
00457
00458 qboolean PC_Rect_Parse(int handle, rectDef_t *r) {
00459 if (PC_Float_Parse(handle, &r->x)) {
00460 if (PC_Float_Parse(handle, &r->y)) {
00461 if (PC_Float_Parse(handle, &r->w)) {
00462 if (PC_Float_Parse(handle, &r->h)) {
00463 return qtrue;
00464 }
00465 }
00466 }
00467 }
00468 return qfalse;
00469 }
00470
00471
00472
00473
00474
00475
00476 qboolean String_Parse(char **p, const char **out) {
00477 char *token;
00478
00479 token = COM_ParseExt(p, qfalse);
00480 if (token && token[0] != 0) {
00481 *(out) = String_Alloc(token);
00482 return qtrue;
00483 }
00484 return qfalse;
00485 }
00486
00487
00488
00489
00490
00491
00492 qboolean PC_String_Parse(int handle, const char **out) {
00493 pc_token_t token;
00494
00495 if (!trap_PC_ReadToken(handle, &token))
00496 return qfalse;
00497
00498 *(out) = String_Alloc(token.string);
00499 return qtrue;
00500 }
00501
00502
00503
00504
00505
00506
00507 qboolean PC_Script_Parse(int handle, const char **out) {
00508 char script[1024];
00509 pc_token_t token;
00510
00511 memset(script, 0, sizeof(script));
00512
00513
00514
00515 if (!trap_PC_ReadToken(handle, &token))
00516 return qfalse;
00517 if (Q_stricmp(token.string, "{") != 0) {
00518 return qfalse;
00519 }
00520
00521 while ( 1 ) {
00522 if (!trap_PC_ReadToken(handle, &token))
00523 return qfalse;
00524
00525 if (Q_stricmp(token.string, "}") == 0) {
00526 *out = String_Alloc(script);
00527 return qtrue;
00528 }
00529
00530 if (token.string[1] != '\0') {
00531 Q_strcat(script, 1024, va("\"%s\"", token.string));
00532 } else {
00533 Q_strcat(script, 1024, token.string);
00534 }
00535 Q_strcat(script, 1024, " ");
00536 }
00537 return qfalse;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 void Init_Display(displayContextDef_t *dc) {
00551 DC = dc;
00552 }
00553
00554
00555
00556
00557
00558 void GradientBar_Paint(rectDef_t *rect, vec4_t color) {
00559
00560 DC->setColor( color );
00561 DC->drawHandlePic(rect->x, rect->y, rect->w, rect->h, DC->Assets.gradientBar);
00562 DC->setColor( NULL );
00563 }
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 void Window_Init(Window *w) {
00575 memset(w, 0, sizeof(windowDef_t));
00576 w->borderSize = 1;
00577 w->foreColor[0] = w->foreColor[1] = w->foreColor[2] = w->foreColor[3] = 1.0;
00578 w->cinematic = -1;
00579 }
00580
00581 void Fade(int *flags, float *f, float clamp, int *nextTime, int offsetTime, qboolean bFlags, float fadeAmount) {
00582 if (*flags & (WINDOW_FADINGOUT | WINDOW_FADINGIN)) {
00583 if (DC->realTime > *nextTime) {
00584 *nextTime = DC->realTime + offsetTime;
00585 if (*flags & WINDOW_FADINGOUT) {
00586 *f -= fadeAmount;
00587 if (bFlags && *f <= 0.0) {
00588 *flags &= ~(WINDOW_FADINGOUT | WINDOW_VISIBLE);
00589 }
00590 } else {
00591 *f += fadeAmount;
00592 if (*f >= clamp) {
00593 *f = clamp;
00594 if (bFlags) {
00595 *flags &= ~WINDOW_FADINGIN;
00596 }
00597 }
00598 }
00599 }
00600 }
00601 }
00602
00603
00604
00605 void Window_Paint(Window *w, float fadeAmount, float fadeClamp, float fadeCycle) {
00606
00607 vec4_t color;
00608 rectDef_t fillRect = w->rect;
00609
00610
00611 if (debugMode) {
00612 color[0] = color[1] = color[2] = color[3] = 1;
00613 DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, 1, color);
00614 }
00615
00616 if (w == NULL || (w->style == 0 && w->border == 0)) {
00617 return;
00618 }
00619
00620 if (w->border != 0) {
00621 fillRect.x += w->borderSize;
00622 fillRect.y += w->borderSize;
00623 fillRect.w -= w->borderSize + 1;
00624 fillRect.h -= w->borderSize + 1;
00625 }
00626
00627 if (w->style == WINDOW_STYLE_FILLED) {
00628
00629 if (w->background) {
00630 Fade(&w->flags, &w->backColor[3], fadeClamp, &w->nextTime, fadeCycle, qtrue, fadeAmount);
00631 DC->setColor(w->backColor);
00632 DC->drawHandlePic(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->background);
00633 DC->setColor(NULL);
00634 } else {
00635 DC->fillRect(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->backColor);
00636 }
00637 } else if (w->style == WINDOW_STYLE_GRADIENT) {
00638 GradientBar_Paint(&fillRect, w->backColor);
00639
00640 } else if (w->style == WINDOW_STYLE_SHADER) {
00641 if (w->flags & WINDOW_FORECOLORSET) {
00642 DC->setColor(w->foreColor);
00643 }
00644 DC->drawHandlePic(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->background);
00645 DC->setColor(NULL);
00646 } else if (w->style == WINDOW_STYLE_TEAMCOLOR) {
00647 if (DC->getTeamColor) {
00648 DC->getTeamColor(&color);
00649 DC->fillRect(fillRect.x, fillRect.y, fillRect.w, fillRect.h, color);
00650 }
00651 } else if (w->style == WINDOW_STYLE_CINEMATIC) {
00652 if (w->cinematic == -1) {
00653 w->cinematic = DC->playCinematic(w->cinematicName, fillRect.x, fillRect.y, fillRect.w, fillRect.h);
00654 if (w->cinematic == -1) {
00655 w->cinematic = -2;
00656 }
00657 }
00658 if (w->cinematic >= 0) {
00659 DC->runCinematicFrame(w->cinematic);
00660 DC->drawCinematic(w->cinematic, fillRect.x, fillRect.y, fillRect.w, fillRect.h);
00661 }
00662 }
00663
00664 if (w->border == WINDOW_BORDER_FULL) {
00665
00666
00667 if (w->style == WINDOW_STYLE_TEAMCOLOR) {
00668 if (color[0] > 0) {
00669
00670 color[0] = 1;
00671 color[1] = color[2] = .5;
00672
00673 } else {
00674 color[2] = 1;
00675 color[0] = color[1] = .5;
00676 }
00677 color[3] = 1;
00678 DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize, color);
00679 } else {
00680 DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize, w->borderColor);
00681 }
00682 } else if (w->border == WINDOW_BORDER_HORZ) {
00683
00684 DC->setColor(w->borderColor);
00685 DC->drawTopBottom(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize);
00686 DC->setColor( NULL );
00687 } else if (w->border == WINDOW_BORDER_VERT) {
00688
00689 DC->setColor(w->borderColor);
00690 DC->drawSides(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize);
00691 DC->setColor( NULL );
00692 } else if (w->border == WINDOW_BORDER_KCGRADIENT) {
00693
00694 rectDef_t r = w->rect;
00695 r.h = w->borderSize;
00696 GradientBar_Paint(&r, w->borderColor);
00697 r.y = w->rect.y + w->rect.h - 1;
00698 GradientBar_Paint(&r, w->borderColor);
00699 }
00700
00701 }
00702
00703
00704 void Item_SetScreenCoords(itemDef_t *item, float x, float y) {
00705
00706 if (item == NULL) {
00707 return;
00708 }
00709
00710 if (item->window.border != 0) {
00711 x += item->window.borderSize;
00712 y += item->window.borderSize;
00713 }
00714
00715 item->window.rect.x = x + item->window.rectClient.x;
00716 item->window.rect.y = y + item->window.rectClient.y;
00717 item->window.rect.w = item->window.rectClient.w;
00718 item->window.rect.h = item->window.rectClient.h;
00719
00720
00721 item->textRect.w = 0;
00722 item->textRect.h = 0;
00723 }
00724
00725
00726 void Item_UpdatePosition(itemDef_t *item) {
00727 float x, y;
00728 menuDef_t *menu;
00729
00730 if (item == NULL || item->parent == NULL) {
00731 return;
00732 }
00733
00734 menu = item->parent;
00735
00736 x = menu->window.rect.x;
00737 y = menu->window.rect.y;
00738
00739 if (menu->window.border != 0) {
00740 x += menu->window.borderSize;
00741 y += menu->window.borderSize;
00742 }
00743
00744 Item_SetScreenCoords(item, x, y);
00745
00746 }
00747
00748
00749 void Menu_UpdatePosition(menuDef_t *menu) {
00750 int i;
00751 float x, y;
00752
00753 if (menu == NULL) {
00754 return;
00755 }
00756
00757 x = menu->window.rect.x;
00758 y = menu->window.rect.y;
00759 if (menu->window.border != 0) {
00760 x += menu->window.borderSize;
00761 y += menu->window.borderSize;
00762 }
00763
00764 for (i = 0; i < menu->itemCount; i++) {
00765 Item_SetScreenCoords(menu->items[i], x, y);
00766 }
00767 }
00768
00769 void Menu_PostParse(menuDef_t *menu) {
00770 if (menu == NULL) {
00771 return;
00772 }
00773 if (menu->fullScreen) {
00774 menu->window.rect.x = 0;
00775 menu->window.rect.y = 0;
00776 menu->window.rect.w = 640;
00777 menu->window.rect.h = 480;
00778 }
00779 Menu_UpdatePosition(menu);
00780 }
00781
00782 itemDef_t *Menu_ClearFocus(menuDef_t *menu) {
00783 int i;
00784 itemDef_t *ret = NULL;
00785
00786 if (menu == NULL) {
00787 return NULL;
00788 }
00789
00790 for (i = 0; i < menu->itemCount; i++) {
00791 if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
00792 ret = menu->items[i];
00793 }
00794 menu->items[i]->window.flags &= ~WINDOW_HASFOCUS;
00795 if (menu->items[i]->leaveFocus) {
00796 Item_RunScript(menu->items[i], menu->items[i]->leaveFocus);
00797 }
00798 }
00799
00800 return ret;
00801 }
00802
00803 qboolean IsVisible(int flags) {
00804 return (flags & WINDOW_VISIBLE && !(flags & WINDOW_FADINGOUT));
00805 }
00806
00807 qboolean Rect_ContainsPoint(rectDef_t *rect, float x, float y) {
00808 if (rect) {
00809 if (x > rect->x && x < rect->x + rect->w && y > rect->y && y < rect->y + rect->h) {
00810 return qtrue;
00811 }
00812 }
00813 return qfalse;
00814 }
00815
00816 int Menu_ItemsMatchingGroup(menuDef_t *menu, const char *name) {
00817 int i;
00818 int count = 0;
00819 for (i = 0; i < menu->itemCount; i++) {
00820 if (Q_stricmp(menu->items[i]->window.name, name) == 0 || (menu->items[i]->window.group && Q_stricmp(menu->items[i]->window.group, name) == 0)) {
00821 count++;
00822 }
00823 }
00824 return count;
00825 }
00826
00827 itemDef_t *Menu_GetMatchingItemByNumber(menuDef_t *menu, int index, const char *name) {
00828 int i;
00829 int count = 0;
00830 for (i = 0; i < menu->itemCount; i++) {
00831 if (Q_stricmp(menu->items[i]->window.name, name) == 0 || (menu->items[i]->window.group && Q_stricmp(menu->items[i]->window.group, name) == 0)) {
00832 if (count == index) {
00833 return menu->items[i];
00834 }
00835 count++;
00836 }
00837 }
00838 return NULL;
00839 }
00840
00841
00842
00843 void Script_SetColor(itemDef_t *item, char **args) {
00844 const char *name;
00845 int i;
00846 float f;
00847 vec4_t *out;
00848
00849 if (String_Parse(args, &name)) {
00850 out = NULL;
00851 if (Q_stricmp(name, "backcolor") == 0) {
00852 out = &item->window.backColor;
00853 item->window.flags |= WINDOW_BACKCOLORSET;
00854 } else if (Q_stricmp(name, "forecolor") == 0) {
00855 out = &item->window.foreColor;
00856 item->window.flags |= WINDOW_FORECOLORSET;
00857 } else if (Q_stricmp(name, "bordercolor") == 0) {
00858 out = &item->window.borderColor;
00859 }
00860
00861 if (out) {
00862 for (i = 0; i < 4; i++) {
00863 if (!Float_Parse(args, &f)) {
00864 return;
00865 }
00866 (*out)[i] = f;
00867 }
00868 }
00869 }
00870 }
00871
00872 void Script_SetAsset(itemDef_t *item, char **args) {
00873 const char *name;
00874
00875 if (String_Parse(args, &name)) {
00876
00877 if (item->type == ITEM_TYPE_MODEL) {
00878 }
00879 }
00880 }
00881
00882 void Script_SetBackground(itemDef_t *item, char **args) {
00883 const char *name;
00884
00885 if (String_Parse(args, &name)) {
00886 item->window.background = DC->registerShaderNoMip(name);
00887 }
00888 }
00889
00890
00891
00892
00893 itemDef_t *Menu_FindItemByName(menuDef_t *menu, const char *p) {
00894 int i;
00895 if (menu == NULL || p == NULL) {
00896 return NULL;
00897 }
00898
00899 for (i = 0; i < menu->itemCount; i++) {
00900 if (Q_stricmp(p, menu->items[i]->window.name) == 0) {
00901 return menu->items[i];
00902 }
00903 }
00904
00905 return NULL;
00906 }
00907
00908 void Script_SetTeamColor(itemDef_t *item, char **args) {
00909 if (DC->getTeamColor) {
00910 int i;
00911 vec4_t color;
00912 DC->getTeamColor(&color);
00913 for (i = 0; i < 4; i++) {
00914 item->window.backColor[i] = color[i];
00915 }
00916 }
00917 }
00918
00919 void Script_SetItemColor(itemDef_t *item, char **args) {
00920 const char *itemname;
00921 const char *name;
00922 vec4_t color;
00923 int i;
00924 vec4_t *out;
00925
00926 if (String_Parse(args, &itemname) && String_Parse(args, &name)) {
00927 itemDef_t *item2;
00928 int j;
00929 int count = Menu_ItemsMatchingGroup(item->parent, itemname);
00930
00931 if (!Color_Parse(args, &color)) {
00932 return;
00933 }
00934
00935 for (j = 0; j < count; j++) {
00936 item2 = Menu_GetMatchingItemByNumber(item->parent, j, itemname);
00937 if (item2 != NULL) {
00938 out = NULL;
00939 if (Q_stricmp(name, "backcolor") == 0) {
00940 out = &item2->window.backColor;
00941 } else if (Q_stricmp(name, "forecolor") == 0) {
00942 out = &item2->window.foreColor;
00943 item2->window.flags |= WINDOW_FORECOLORSET;
00944 } else if (Q_stricmp(name, "bordercolor") == 0) {
00945 out = &item2->window.borderColor;
00946 }
00947
00948 if (out) {
00949 for (i = 0; i < 4; i++) {
00950 (*out)[i] = color[i];
00951 }
00952 }
00953 }
00954 }
00955 }
00956 }
00957
00958
00959 void Menu_ShowItemByName(menuDef_t *menu, const char *p, qboolean bShow) {
00960 itemDef_t *item;
00961 int i;
00962 int count = Menu_ItemsMatchingGroup(menu, p);
00963 for (i = 0; i < count; i++) {
00964 item = Menu_GetMatchingItemByNumber(menu, i, p);
00965 if (item != NULL) {
00966 if (bShow) {
00967 item->window.flags |= WINDOW_VISIBLE;
00968 } else {
00969 item->window.flags &= ~WINDOW_VISIBLE;
00970
00971 if (item->window.cinematic >= 0) {
00972 DC->stopCinematic(item->window.cinematic);
00973 item->window.cinematic = -1;
00974 }
00975 }
00976 }
00977 }
00978 }
00979
00980 void Menu_FadeItemByName(menuDef_t *menu, const char *p, qboolean fadeOut) {
00981 itemDef_t *item;
00982 int i;
00983 int count = Menu_ItemsMatchingGroup(menu, p);
00984 for (i = 0; i < count; i++) {
00985 item = Menu_GetMatchingItemByNumber(menu, i, p);
00986 if (item != NULL) {
00987 if (fadeOut) {
00988 item->window.flags |= (WINDOW_FADINGOUT | WINDOW_VISIBLE);
00989 item->window.flags &= ~WINDOW_FADINGIN;
00990 } else {
00991 item->window.flags |= (WINDOW_VISIBLE | WINDOW_FADINGIN);
00992 item->window.flags &= ~WINDOW_FADINGOUT;
00993 }
00994 }
00995 }
00996 }
00997
00998 menuDef_t *Menus_FindByName(const char *p) {
00999 int i;
01000 for (i = 0; i < menuCount; i++) {
01001 if (Q_stricmp(Menus[i].window.name, p) == 0) {
01002 return &Menus[i];
01003 }
01004 }
01005 return NULL;
01006 }
01007
01008 void Menus_ShowByName(const char *p) {
01009 menuDef_t *menu = Menus_FindByName(p);
01010 if (menu) {
01011 Menus_Activate(menu);
01012 }
01013 }
01014
01015 void Menus_OpenByName(const char *p) {
01016 Menus_ActivateByName(p);
01017 }
01018
01019 static void Menu_RunCloseScript(menuDef_t *menu) {
01020 if (menu && menu->window.flags & WINDOW_VISIBLE && menu->onClose) {
01021 itemDef_t item;
01022 item.parent = menu;
01023 Item_RunScript(&item, menu->onClose);
01024 }
01025 }
01026
01027 void Menus_CloseByName(const char *p) {
01028 menuDef_t *menu = Menus_FindByName(p);
01029 if (menu != NULL) {
01030 Menu_RunCloseScript(menu);
01031 menu->window.flags &= ~(WINDOW_VISIBLE | WINDOW_HASFOCUS);
01032 }
01033 }
01034
01035 void Menus_CloseAll() {
01036 int i;
01037 for (i = 0; i < menuCount; i++) {
01038 Menu_RunCloseScript(&Menus[i]);
01039 Menus[i].window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
01040 }
01041 }
01042
01043
01044 void Script_Show(itemDef_t *item, char **args) {
01045 const char *name;
01046 if (String_Parse(args, &name)) {
01047 Menu_ShowItemByName(item->parent, name, qtrue);
01048 }
01049 }
01050
01051 void Script_Hide(itemDef_t *item, char **args) {
01052 const char *name;
01053 if (String_Parse(args, &name)) {
01054 Menu_ShowItemByName(item->parent, name, qfalse);
01055 }
01056 }
01057
01058 void Script_FadeIn(itemDef_t *item, char **args) {
01059 const char *name;
01060 if (String_Parse(args, &name)) {
01061 Menu_FadeItemByName(item->parent, name, qfalse);
01062 }
01063 }
01064
01065 void Script_FadeOut(itemDef_t *item, char **args) {
01066 const char *name;
01067 if (String_Parse(args, &name)) {
01068 Menu_FadeItemByName(item->parent, name, qtrue);
01069 }
01070 }
01071
01072
01073
01074 void Script_Open(itemDef_t *item, char **args) {
01075 const char *name;
01076 if (String_Parse(args, &name)) {
01077 Menus_OpenByName(name);
01078 }
01079 }
01080
01081 void Script_ConditionalOpen(itemDef_t *item, char **args) {
01082 const char *cvar;
01083 const char *name1;
01084 const char *name2;
01085 float val;
01086
01087 if ( String_Parse(args, &cvar) && String_Parse(args, &name1) && String_Parse(args, &name2) ) {
01088 val = DC->getCVarValue( cvar );
01089 if ( val == 0.f ) {
01090 Menus_OpenByName(name2);
01091 } else {
01092 Menus_OpenByName(name1);
01093 }
01094 }
01095 }
01096
01097 void Script_Close(itemDef_t *item, char **args) {
01098 const char *name;
01099 if (String_Parse(args, &name)) {
01100 Menus_CloseByName(name);
01101 }
01102 }
01103
01104 void Menu_TransitionItemByName(menuDef_t *menu, const char *p, rectDef_t rectFrom, rectDef_t rectTo, int time, float amt) {
01105 itemDef_t *item;
01106 int i;
01107 int count = Menu_ItemsMatchingGroup(menu, p);
01108 for (i = 0; i < count; i++) {
01109 item = Menu_GetMatchingItemByNumber(menu, i, p);
01110 if (item != NULL) {
01111 item->window.flags |= (WINDOW_INTRANSITION | WINDOW_VISIBLE);
01112 item->window.offsetTime = time;
01113 memcpy(&item->window.rectClient, &rectFrom, sizeof(rectDef_t));
01114 memcpy(&item->window.rectEffects, &rectTo, sizeof(rectDef_t));
01115 item->window.rectEffects2.x = abs(rectTo.x - rectFrom.x) / amt;
01116 item->window.rectEffects2.y = abs(rectTo.y - rectFrom.y) / amt;
01117 item->window.rectEffects2.w = abs(rectTo.w - rectFrom.w) / amt;
01118 item->window.rectEffects2.h = abs(rectTo.h - rectFrom.h) / amt;
01119 Item_UpdatePosition(item);
01120 }
01121 }
01122 }
01123
01124
01125 void Script_Transition(itemDef_t *item, char **args) {
01126 const char *name;
01127 rectDef_t rectFrom, rectTo;
01128 int time;
01129 float amt;
01130
01131 if (String_Parse(args, &name)) {
01132 if ( Rect_Parse(args, &rectFrom) && Rect_Parse(args, &rectTo) && Int_Parse(args, &time) && Float_Parse(args, &amt)) {
01133 Menu_TransitionItemByName(item->parent, name, rectFrom, rectTo, time, amt);
01134 }
01135 }
01136 }
01137
01138
01139 void Menu_OrbitItemByName(menuDef_t *menu, const char *p, float x, float y, float cx, float cy, int time) {
01140 itemDef_t *item;
01141 int i;
01142 int count = Menu_ItemsMatchingGroup(menu, p);
01143 for (i = 0; i < count; i++) {
01144 item = Menu_GetMatchingItemByNumber(menu, i, p);
01145 if (item != NULL) {
01146 item->window.flags |= (WINDOW_ORBITING | WINDOW_VISIBLE);
01147 item->window.offsetTime = time;
01148 item->window.rectEffects.x = cx;
01149 item->window.rectEffects.y = cy;
01150 item->window.rectClient.x = x;
01151 item->window.rectClient.y = y;
01152 Item_UpdatePosition(item);
01153 }
01154 }
01155 }
01156
01157
01158 void Script_Orbit(itemDef_t *item, char **args) {
01159 const char *name;
01160 float cx, cy, x, y;
01161 int time;
01162
01163 if (String_Parse(args, &name)) {
01164 if ( Float_Parse(args, &x) && Float_Parse(args, &y) && Float_Parse(args, &cx) && Float_Parse(args, &cy) && Int_Parse(args, &time) ) {
01165 Menu_OrbitItemByName(item->parent, name, x, y, cx, cy, time);
01166 }
01167 }
01168 }
01169
01170
01171
01172 void Script_SetFocus(itemDef_t *item, char **args) {
01173 const char *name;
01174 itemDef_t *focusItem;
01175
01176 if (String_Parse(args, &name)) {
01177 focusItem = Menu_FindItemByName(item->parent, name);
01178 if (focusItem && !(focusItem->window.flags & WINDOW_DECORATION) && !(focusItem->window.flags & WINDOW_HASFOCUS)) {
01179 Menu_ClearFocus(item->parent);
01180 focusItem->window.flags |= WINDOW_HASFOCUS;
01181 if (focusItem->onFocus) {
01182 Item_RunScript(focusItem, focusItem->onFocus);
01183 }
01184 if (DC->Assets.itemFocusSound) {
01185 DC->startLocalSound( DC->Assets.itemFocusSound, CHAN_LOCAL_SOUND );
01186 }
01187 }
01188 }
01189 }
01190
01191 void Script_SetPlayerModel(itemDef_t *item, char **args) {
01192 const char *name;
01193 if (String_Parse(args, &name)) {
01194 DC->setCVar("team_model", name);
01195 }
01196 }
01197
01198 void Script_SetPlayerHead(itemDef_t *item, char **args) {
01199 const char *name;
01200 if (String_Parse(args, &name)) {
01201 DC->setCVar("team_headmodel", name);
01202 }
01203 }
01204
01205 void Script_SetCvar(itemDef_t *item, char **args) {
01206 const char *cvar, *val;
01207 if (String_Parse(args, &cvar) && String_Parse(args, &val)) {
01208 DC->setCVar(cvar, val);
01209 }
01210
01211 }
01212
01213 void Script_Exec(itemDef_t *item, char **args) {
01214 const char *val;
01215 if (String_Parse(args, &val)) {
01216 DC->executeText(EXEC_APPEND, va("%s ; ", val));
01217 }
01218 }
01219
01220 void Script_Play(itemDef_t *item, char **args) {
01221 const char *val;
01222 if (String_Parse(args, &val)) {
01223 DC->startLocalSound(DC->registerSound(val, qfalse), CHAN_LOCAL_SOUND);
01224 }
01225 }
01226
01227 void Script_playLooped(itemDef_t *item, char **args) {
01228 const char *val;
01229 if (String_Parse(args, &val)) {
01230 DC->stopBackgroundTrack();
01231 DC->startBackgroundTrack(val, val);
01232 }
01233 }
01234
01235
01236 commandDef_t commandList[] =
01237 {
01238 {"fadein", &Script_FadeIn},
01239 {"fadeout", &Script_FadeOut},
01240 {"show", &Script_Show},
01241 {"hide", &Script_Hide},
01242 {"setcolor", &Script_SetColor},
01243 {"open", &Script_Open},
01244 {"conditionalopen", &Script_ConditionalOpen},
01245 {"close", &Script_Close},
01246 {"setasset", &Script_SetAsset},
01247 {"setbackground", &Script_SetBackground},
01248 {"setitemcolor", &Script_SetItemColor},
01249 {"setteamcolor", &Script_SetTeamColor},
01250 {"setfocus", &Script_SetFocus},
01251 {"setplayermodel", &Script_SetPlayerModel},
01252 {"setplayerhead", &Script_SetPlayerHead},
01253 {"transition", &Script_Transition},
01254 {"setcvar", &Script_SetCvar},
01255 {"exec", &Script_Exec},
01256 {"play", &Script_Play},
01257 {"playlooped", &Script_playLooped},
01258 {"orbit", &Script_Orbit}
01259 };
01260
01261 int scriptCommandCount = sizeof(commandList) / sizeof(commandDef_t);
01262
01263
01264 void Item_RunScript(itemDef_t *item, const char *s) {
01265 char script[1024], *p;
01266 int i;
01267 qboolean bRan;
01268 memset(script, 0, sizeof(script));
01269 if (item && s && s[0]) {
01270 Q_strcat(script, 1024, s);
01271 p = script;
01272 while (1) {
01273 const char *command;
01274
01275 if (!String_Parse(&p, &command)) {
01276 return;
01277 }
01278
01279 if (command[0] == ';' && command[1] == '\0') {
01280 continue;
01281 }
01282
01283 bRan = qfalse;
01284 for (i = 0; i < scriptCommandCount; i++) {
01285 if (Q_stricmp(command, commandList[i].name) == 0) {
01286 (commandList[i].handler(item, &p));
01287 bRan = qtrue;
01288 break;
01289 }
01290 }
01291
01292 if (!bRan) {
01293 DC->runScript(&p);
01294 }
01295 }
01296 }
01297 }
01298
01299
01300 qboolean Item_EnableShowViaCvar(itemDef_t *item, int flag) {
01301 char script[1024], *p;
01302 memset(script, 0, sizeof(script));
01303 if (item && item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest) {
01304 char buff[1024];
01305 DC->getCVarString(item->cvarTest, buff, sizeof(buff));
01306
01307 Q_strcat(script, 1024, item->enableCvar);
01308 p = script;
01309 while (1) {
01310 const char *val;
01311
01312 if (!String_Parse(&p, &val)) {
01313 return (item->cvarFlags & flag) ? qfalse : qtrue;
01314 }
01315
01316 if (val[0] == ';' && val[1] == '\0') {
01317 continue;
01318 }
01319
01320
01321 if (item->cvarFlags & flag) {
01322 if (Q_stricmp(buff, val) == 0) {
01323 return qtrue;
01324 }
01325 } else {
01326
01327 if (Q_stricmp(buff, val) == 0) {
01328 return qfalse;
01329 }
01330 }
01331
01332 }
01333 return (item->cvarFlags & flag) ? qfalse : qtrue;
01334 }
01335 return qtrue;
01336 }
01337
01338
01339
01340 qboolean Item_SetFocus(itemDef_t *item, float x, float y) {
01341 int i;
01342 itemDef_t *oldFocus;
01343 sfxHandle_t *sfx = &DC->Assets.itemFocusSound;
01344 qboolean playSound = qfalse;
01345 menuDef_t *parent;
01346
01347 if (item == NULL || item->window.flags & WINDOW_DECORATION || item->window.flags & WINDOW_HASFOCUS || !(item->window.flags & WINDOW_VISIBLE)) {
01348 return qfalse;
01349 }
01350
01351
01352 parent = (menuDef_t*)item->parent;
01353
01354
01355 if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
01356 return qfalse;
01357 }
01358
01359 if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW)) {
01360 return qfalse;
01361 }
01362
01363 oldFocus = Menu_ClearFocus(item->parent);
01364
01365 if (item->type == ITEM_TYPE_TEXT) {
01366 rectDef_t r;
01367 r = item->textRect;
01368 r.y -= r.h;
01369 if (Rect_ContainsPoint(&r, x, y)) {
01370 item->window.flags |= WINDOW_HASFOCUS;
01371 if (item->focusSound) {
01372 sfx = &item->focusSound;
01373 }
01374 playSound = qtrue;
01375 } else {
01376 if (oldFocus) {
01377 oldFocus->window.flags |= WINDOW_HASFOCUS;
01378 if (oldFocus->onFocus) {
01379 Item_RunScript(oldFocus, oldFocus->onFocus);
01380 }
01381 }
01382 }
01383 } else {
01384 item->window.flags |= WINDOW_HASFOCUS;
01385 if (item->onFocus) {
01386 Item_RunScript(item, item->onFocus);
01387 }
01388 if (item->focusSound) {
01389 sfx = &item->focusSound;
01390 }
01391 playSound = qtrue;
01392 }
01393
01394 if (playSound && sfx) {
01395 DC->startLocalSound( *sfx, CHAN_LOCAL_SOUND );
01396 }
01397
01398 for (i = 0; i < parent->itemCount; i++) {
01399 if (parent->items[i] == item) {
01400 parent->cursorItem = i;
01401 break;
01402 }
01403 }
01404
01405 return qtrue;
01406 }
01407
01408 int Item_ListBox_MaxScroll(itemDef_t *item) {
01409 listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
01410 int count = DC->feederCount(item->special);
01411 int max;
01412
01413 if (item->window.flags & WINDOW_HORIZONTAL) {
01414 max = count - (item->window.rect.w / listPtr->elementWidth) + 1;
01415 }
01416 else {
01417 max = count - (item->window.rect.h / listPtr->elementHeight) + 1;
01418 }
01419 if (max < 0) {
01420 return 0;
01421 }
01422 return max;
01423 }
01424
01425 int Item_ListBox_ThumbPosition(itemDef_t *item) {
01426 float max, pos, size;
01427 listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
01428
01429 max = Item_ListBox_MaxScroll(item);
01430 if (item->window.flags & WINDOW_HORIZONTAL) {
01431 size = item->window.rect.w - (SCROLLBAR_SIZE * 2) - 2;
01432 if (max > 0) {
01433 pos = (size-SCROLLBAR_SIZE) / (float) max;
01434 } else {
01435 pos = 0;
01436 }
01437 pos *= listPtr->startPos;
01438 return item->window.rect.x + 1 + SCROLLBAR_SIZE + pos;
01439 }
01440 else {
01441 size = item->window.rect.h - (SCROLLBAR_SIZE * 2) - 2;
01442 if (max > 0) {
01443 pos = (size-SCROLLBAR_SIZE) / (float) max;
01444 } else {
01445 pos = 0;
01446 }
01447 pos *= listPtr->startPos;
01448 return item->window.rect.y + 1 + SCROLLBAR_SIZE + pos;
01449 }
01450 }
01451
01452 int Item_ListBox_ThumbDrawPosition(itemDef_t *item) {
01453 int min, max;
01454
01455 if (itemCapture == item) {
01456 if (item->window.flags & WINDOW_HORIZONTAL) {
01457 min = item->window.rect.x + SCROLLBAR_SIZE + 1;
01458 max = item->window.rect.x + item->window.rect.w - 2*SCROLLBAR_SIZE - 1;
01459 if (DC->cursorx >= min + SCROLLBAR_SIZE/2 && DC->cursorx <= max + SCROLLBAR_SIZE/2) {
01460 return DC->cursorx - SCROLLBAR_SIZE/2;
01461 }
01462 else {
01463 return Item_ListBox_ThumbPosition(item);
01464 }
01465 }
01466 else {
01467 min = item->window.rect.y + SCROLLBAR_SIZE + 1;
01468 max = item->window.rect.y + item->window.rect.h - 2*SCROLLBAR_SIZE - 1;
01469 if (DC->cursory >= min + SCROLLBAR_SIZE/2 && DC->cursory <= max + SCROLLBAR_SIZE/2) {
01470 return DC->cursory - SCROLLBAR_SIZE/2;
01471 }
01472 else {
01473 return Item_ListBox_ThumbPosition(item);
01474 }
01475 }
01476 }
01477 else {
01478 return Item_ListBox_ThumbPosition(item);
01479 }
01480 }
01481
01482 float Item_Slider_ThumbPosition(itemDef_t *item) {
01483 float value, range, x;
01484 editFieldDef_t *editDef = item->typeData;
01485
01486 if (item->text) {
01487 x = item->textRect.x + item->textRect.w + 8;
01488 } else {
01489 x = item->window.rect.x;
01490 }
01491
01492 if (editDef == NULL && item->cvar) {
01493 return x;
01494 }
01495
01496 value = DC->getCVarValue(item->cvar);
01497
01498 if (value < editDef->minVal) {
01499 value = editDef->minVal;
01500 } else if (value > editDef->maxVal) {
01501 value = editDef->maxVal;
01502 }
01503
01504 range = editDef->maxVal - editDef->minVal;
01505 value -= editDef->minVal;
01506 value /= range;
01507
01508 value *= SLIDER_WIDTH;
01509 x += value;
01510
01511
01512 return x;
01513 }
01514
01515 int Item_Slider_OverSlider(itemDef_t *item, float x, float y) {
01516 rectDef_t r;
01517
01518 r.x = Item_Slider_ThumbPosition(item) - (SLIDER_THUMB_WIDTH / 2);
01519 r.y = item->window.rect.y - 2;
01520 r.w = SLIDER_THUMB_WIDTH;
01521 r.h = SLIDER_THUMB_HEIGHT;
01522
01523 if (Rect_ContainsPoint(&r, x, y)) {
01524 return WINDOW_LB_THUMB;
01525 }
01526 return 0;
01527 }
01528
01529 int Item_ListBox_OverLB(itemDef_t *item, float x, float y) {
01530 rectDef_t r;
01531 listBoxDef_t *listPtr;
01532 int thumbstart;
01533 int count;
01534
01535 count = DC->feederCount(item->special);
01536 listPtr = (listBoxDef_t*)item->typeData;
01537 if (item->window.flags & WINDOW_HORIZONTAL) {
01538
01539 r.x = item->window.rect.x;
01540 r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
01541 r.h = r.w = SCROLLBAR_SIZE;
01542 if (Rect_ContainsPoint(&r, x, y)) {
01543 return WINDOW_LB_LEFTARROW;
01544 }
01545
01546 r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
01547 if (Rect_ContainsPoint(&r, x, y)) {
01548 return WINDOW_LB_RIGHTARROW;
01549 }
01550
01551 thumbstart = Item_ListBox_ThumbPosition(item);
01552 r.x = thumbstart;
01553 if (Rect_ContainsPoint(&r, x, y)) {
01554 return WINDOW_LB_THUMB;
01555 }
01556 r.x = item->window.rect.x + SCROLLBAR_SIZE;
01557 r.w = thumbstart - r.x;
01558 if (Rect_ContainsPoint(&r, x, y)) {
01559 return WINDOW_LB_PGUP;
01560 }
01561 r.x = thumbstart + SCROLLBAR_SIZE;
01562 r.w = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
01563 if (Rect_ContainsPoint(&r, x, y)) {
01564 return WINDOW_LB_PGDN;
01565 }
01566 } else {
01567 r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
01568 r.y = item->window.rect.y;
01569 r.h = r.w = SCROLLBAR_SIZE;
01570 if (Rect_ContainsPoint(&r, x, y)) {
01571 return WINDOW_LB_LEFTARROW;
01572 }
01573 r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
01574 if (Rect_ContainsPoint(&r, x, y)) {
01575 return WINDOW_LB_RIGHTARROW;
01576 }
01577 thumbstart = Item_ListBox_ThumbPosition(item);
01578 r.y = thumbstart;
01579 if (Rect_ContainsPoint(&r, x, y)) {
01580 return WINDOW_LB_THUMB;
01581 }
01582 r.y = item->window.rect.y + SCROLLBAR_SIZE;
01583 r.h = thumbstart - r.y;
01584 if (Rect_ContainsPoint(&r, x, y)) {
01585 return WINDOW_LB_PGUP;
01586 }
01587 r.y = thumbstart + SCROLLBAR_SIZE;
01588 r.h = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
01589 if (Rect_ContainsPoint(&r, x, y)) {
01590 return WINDOW_LB_PGDN;
01591 }
01592 }
01593 return 0;
01594 }
01595
01596
01597 void Item_ListBox_MouseEnter(itemDef_t *item, float x, float y)
01598 {
01599 rectDef_t r;
01600 listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
01601
01602 item->window.flags &= ~(WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN);
01603 item->window.flags |= Item_ListBox_OverLB(item, x, y);
01604
01605 if (item->window.flags & WINDOW_HORIZONTAL) {
01606 if (!(item->window.flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN))) {
01607
01608 if (listPtr->elementStyle == LISTBOX_IMAGE) {
01609 r.x = item->window.rect.x;
01610 r.y = item->window.rect.y;
01611 r.h = item->window.rect.h - SCROLLBAR_SIZE;
01612 r.w = item->window.rect.w - listPtr->drawPadding;
01613 if (Rect_ContainsPoint(&r, x, y)) {
01614 listPtr->cursorPos = (int)((x - r.x) / listPtr->elementWidth) + listPtr->startPos;
01615 if (listPtr->cursorPos >= listPtr->endPos) {
01616 listPtr->cursorPos = listPtr->endPos;
01617 }
01618 }
01619 } else {
01620
01621 }
01622 }
01623 } else if (!(item->window.flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN))) {
01624 r.x = item->window.rect.x;
01625 r.y = item->window.rect.y;
01626 r.w = item->window.rect.w - SCROLLBAR_SIZE;
01627 r.h = item->window.rect.h - listPtr->drawPadding;
01628 if (Rect_ContainsPoint(&r, x, y)) {
01629 listPtr->cursorPos = (int)((y - 2 - r.y) / listPtr->elementHeight) + listPtr->startPos;
01630 if (listPtr->cursorPos > listPtr->endPos) {
01631 listPtr->cursorPos = listPtr->endPos;
01632 }
01633 }
01634 }
01635 }
01636
01637 void Item_MouseEnter(itemDef_t *item, float x, float y) {
01638 rectDef_t r;
01639 if (item) {
01640 r = item->textRect;
01641 r.y -= r.h;
01642
01643
01644
01645 if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
01646 return;
01647 }
01648
01649 if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW)) {
01650 return;
01651 }
01652
01653 if (Rect_ContainsPoint(&r, x, y)) {
01654 if (!(item->window.flags & WINDOW_MOUSEOVERTEXT)) {
01655 Item_RunScript(item, item->mouseEnterText);
01656 item->window.flags |= WINDOW_MOUSEOVERTEXT;
01657 }
01658 if (!(item->window.flags & WINDOW_MOUSEOVER)) {
01659 Item_RunScript(item, item->mouseEnter);
01660 item->window.flags |= WINDOW_MOUSEOVER;
01661 }
01662
01663 } else {
01664
01665 if (item->window.flags & WINDOW_MOUSEOVERTEXT) {
01666
01667 Item_RunScript(item, item->mouseExitText);
01668 item->window.flags &= ~WINDOW_MOUSEOVERTEXT;
01669 }
01670 if (!(item->window.flags & WINDOW_MOUSEOVER)) {
01671 Item_RunScript(item, item->mouseEnter);
01672 item->window.flags |= WINDOW_MOUSEOVER;
01673 }
01674
01675 if (item->type == ITEM_TYPE_LISTBOX) {
01676 Item_ListBox_MouseEnter(item, x, y);
01677 }
01678 }
01679 }
01680 }
01681
01682 void Item_MouseLeave(itemDef_t *item) {
01683 if (item) {
01684 if (item->window.flags & WINDOW_MOUSEOVERTEXT) {
01685 Item_RunScript(item, item->mouseExitText);
01686 item->window.flags &= ~WINDOW_MOUSEOVERTEXT;
01687 }
01688 Item_RunScript(item, item->mouseExit);
01689 item->window.flags &= ~(WINDOW_LB_RIGHTARROW | WINDOW_LB_LEFTARROW);
01690 }
01691 }
01692
01693 itemDef_t *Menu_HitTest(menuDef_t *menu, float x, float y) {
01694 int i;
01695 for (i = 0; i < menu->itemCount; i++) {
01696 if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
01697 return menu->items[i];
01698 }
01699 }
01700 return NULL;
01701 }
01702
01703 void Item_SetMouseOver(itemDef_t *item, qboolean focus) {
01704 if (item) {
01705 if (focus) {
01706 item->window.flags |= WINDOW_MOUSEOVER;
01707 } else {
01708 item->window.flags &= ~WINDOW_MOUSEOVER;
01709 }
01710 }
01711 }
01712
01713
01714 qboolean Item_OwnerDraw_HandleKey(itemDef_t *item, int key) {
01715 if (item && DC->ownerDrawHandleKey) {
01716 return DC->ownerDrawHandleKey(item->window.ownerDraw, item->window.ownerDrawFlags, &item->special, key);
01717 }
01718 return qfalse;
01719 }
01720
01721 qboolean Item_ListBox_HandleKey(itemDef_t *item, int key, qboolean down, qboolean force) {
01722 listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
01723 int count = DC->feederCount(item->special);
01724 int max, viewmax;
01725
01726 if (force || (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS)) {
01727 max = Item_ListBox_MaxScroll(item);
01728 if (item->window.flags & WINDOW_HORIZONTAL) {
01729 viewmax = (item->window.rect.w / listPtr->elementWidth);
01730 if ( key == K_LEFTARROW || key == K_KP_LEFTARROW )
01731 {
01732 if (!listPtr->notselectable) {
01733 listPtr->cursorPos--;
01734 if (listPtr->cursorPos < 0) {
01735 listPtr->cursorPos = 0;
01736 }
01737 if (listPtr->cursorPos < listPtr->startPos) {
01738 listPtr->startPos = listPtr->cursorPos;
01739 }
01740 if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
01741 listPtr->startPos = listPtr->cursorPos - viewmax + 1;
01742 }
01743 item->cursorPos = listPtr->cursorPos;
01744 DC->feederSelection(item->special, item->cursorPos);
01745 }
01746 else {
01747 listPtr->startPos--;
01748 if (listPtr->startPos < 0)
01749 listPtr->startPos = 0;
01750 }
01751 return qtrue;
01752 }
01753 if ( key == K_RIGHTARROW || key == K_KP_RIGHTARROW )
01754 {
01755 if (!listPtr->notselectable) {
01756 listPtr->cursorPos++;
01757 if (listPtr->cursorPos < listPtr->startPos) {
01758 listPtr->startPos = listPtr->cursorPos;
01759 }
01760 if (listPtr->cursorPos >= count) {
01761 listPtr->cursorPos = count-1;
01762 }
01763 if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
01764 listPtr->startPos = listPtr->cursorPos - viewmax + 1;
01765 }
01766 item->cursorPos = listPtr->cursorPos;
01767 DC->feederSelection(item->special, item->cursorPos);
01768 }
01769 else {
01770 listPtr->startPos++;
01771 if (listPtr->startPos >= count)
01772 listPtr->startPos = count-1;
01773 }
01774 return qtrue;
01775 }
01776 }
01777 else {
01778 viewmax = (item->window.rect.h / listPtr->elementHeight);
01779 if ( key == K_UPARROW || key == K_KP_UPARROW )
01780 {
01781 if (!listPtr->notselectable) {
01782 listPtr->cursorPos--;
01783 if (listPtr->cursorPos < 0) {
01784 listPtr->cursorPos = 0;
01785 }
01786 if (listPtr->cursorPos < listPtr->startPos) {
01787 listPtr->startPos = listPtr->cursorPos;
01788 }
01789 if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
01790 listPtr->startPos = listPtr->cursorPos - viewmax + 1;
01791 }
01792 item->cursorPos = listPtr->cursorPos;
01793 DC->feederSelection(item->special, item->cursorPos);
01794 }
01795 else {
01796 listPtr->startPos--;
01797 if (listPtr->startPos < 0)
01798 listPtr->startPos = 0;
01799 }
01800 return qtrue;
01801 }
01802 if ( key == K_DOWNARROW || key == K_KP_DOWNARROW )
01803 {
01804 if (!listPtr->notselectable) {
01805 listPtr->cursorPos++;
01806 if (listPtr->cursorPos < listPtr->startPos) {
01807 listPtr->startPos = listPtr->cursorPos;
01808 }
01809 if (listPtr->cursorPos >= count) {
01810 listPtr->cursorPos = count-1;
01811 }
01812 if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
01813 listPtr->startPos = listPtr->cursorPos - viewmax + 1;
01814 }
01815 item->cursorPos = listPtr->cursorPos;
01816 DC->feederSelection(item->special, item->cursorPos);
01817 }
01818 else {
01819 listPtr->startPos++;
01820 if (listPtr->startPos > max)
01821 listPtr->startPos = max;
01822 }
01823 return qtrue;
01824 }
01825 }
01826
01827 if (key == K_MOUSE1 || key == K_MOUSE2) {
01828 if (item->window.flags & WINDOW_LB_LEFTARROW) {
01829 listPtr->startPos--;
01830 if (listPtr->startPos < 0) {
01831 listPtr->startPos = 0;
01832 }
01833 } else if (item->window.flags & WINDOW_LB_RIGHTARROW) {
01834
01835 listPtr->startPos++;
01836 if (listPtr->startPos > max) {
01837 listPtr->startPos = max;
01838 }
01839 } else if (item->window.flags & WINDOW_LB_PGUP) {
01840
01841 listPtr->startPos -= viewmax;
01842 if (listPtr->startPos < 0) {
01843 listPtr->startPos = 0;
01844 }
01845 } else if (item->window.flags & WINDOW_LB_PGDN) {
01846
01847 listPtr->startPos += viewmax;
01848 if (listPtr->startPos > max) {
01849 listPtr->startPos = max;
01850 }
01851 } else if (item->window.flags & WINDOW_LB_THUMB) {
01852
01853 } else {
01854
01855 if (DC->realTime < lastListBoxClickTime && listPtr->doubleClick) {
01856 Item_RunScript(item, listPtr->doubleClick);
01857 }
01858 lastListBoxClickTime = DC->realTime + DOUBLE_CLICK_DELAY;
01859 if (item->cursorPos != listPtr->cursorPos) {
01860 item->cursorPos = listPtr->cursorPos;
01861 DC->feederSelection(item->special, item->cursorPos);
01862 }
01863 }
01864 return qtrue;
01865 }
01866 if ( key == K_HOME || key == K_KP_HOME) {
01867
01868 listPtr->startPos = 0;
01869 return qtrue;
01870 }
01871 if ( key == K_END || key == K_KP_END) {
01872
01873 listPtr->startPos = max;
01874 return qtrue;
01875 }
01876 if (key == K_PGUP || key == K_KP_PGUP ) {
01877
01878 if (!listPtr->notselectable) {
01879 listPtr->cursorPos -= viewmax;
01880 if (listPtr->cursorPos < 0) {
01881 listPtr->cursorPos = 0;
01882 }
01883 if (listPtr->cursorPos < listPtr->startPos) {
01884 listPtr->startPos = listPtr->cursorPos;
01885 }
01886 if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
01887 listPtr->startPos = listPtr->cursorPos - viewmax + 1;
01888 }
01889 item->cursorPos = listPtr->cursorPos;
01890 DC->feederSelection(item->special, item->cursorPos);
01891 }
01892 else {
01893 listPtr->startPos -= viewmax;
01894 if (listPtr->startPos < 0) {
01895 listPtr->startPos = 0;
01896 }
01897 }
01898 return qtrue;
01899 }
01900 if ( key == K_PGDN || key == K_KP_PGDN ) {
01901
01902 if (!listPtr->notselectable) {
01903 listPtr->cursorPos += viewmax;
01904 if (listPtr->cursorPos < listPtr->startPos) {
01905 listPtr->startPos = listPtr->cursorPos;
01906 }
01907 if (listPtr->cursorPos >= count) {
01908 listPtr->cursorPos = count-1;
01909 }
01910 if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
01911 listPtr->startPos = listPtr->cursorPos - viewmax + 1;
01912 }
01913 item->cursorPos = listPtr->cursorPos;
01914 DC->feederSelection(item->special, item->cursorPos);
01915 }
01916 else {
01917 listPtr->startPos += viewmax;
01918 if (listPtr->startPos > max) {
01919 listPtr->startPos = max;
01920 }
01921 }
01922 return qtrue;
01923 }
01924 }
01925 return qfalse;
01926 }
01927
01928 qboolean Item_YesNo_HandleKey(itemDef_t *item, int key) {
01929
01930 if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS && item->cvar) {
01931 if (key == K_MOUSE1 || key == K_ENTER || key == K_MOUSE2 || key == K_MOUSE3) {
01932 DC->setCVar(item->cvar, va("%i", !DC->getCVarValue(item->cvar)));
01933 return qtrue;
01934 }
01935 }
01936
01937 return qfalse;
01938
01939 }
01940
01941 int Item_Multi_CountSettings(itemDef_t *item) {
01942 multiDef_t *multiPtr = (multiDef_t*)item->typeData;
01943 if (multiPtr == NULL) {
01944 return 0;
01945 }
01946 return multiPtr->count;
01947 }
01948
01949 int Item_Multi_FindCvarByValue(itemDef_t *item) {
01950 char buff[1024];
01951 float value = 0;
01952 int i;
01953 multiDef_t *multiPtr = (multiDef_t*)item->typeData;
01954 if (multiPtr) {
01955 if (multiPtr->strDef) {
01956 DC->getCVarString(item->cvar, buff, sizeof(buff));
01957 } else {
01958 value = DC->getCVarValue(item->cvar);
01959 }
01960 for (i = 0; i < multiPtr->count; i++) {
01961 if (multiPtr->strDef) {
01962 if (Q_stricmp(buff, multiPtr->cvarStr[i]) == 0) {
01963 return i;
01964 }
01965 } else {
01966 if (multiPtr->cvarValue[i] == value) {
01967 return i;
01968 }
01969 }
01970 }
01971 }
01972 return 0;
01973 }
01974
01975 const char *Item_Multi_Setting(itemDef_t *item) {
01976 char buff[1024];
01977 float value = 0;
01978 int i;
01979 multiDef_t *multiPtr = (multiDef_t*)item->typeData;
01980 if (multiPtr) {
01981 if (multiPtr->strDef) {
01982 DC->getCVarString(item->cvar, buff, sizeof(buff));
01983 } else {
01984 value = DC->getCVarValue(item->cvar);
01985 }
01986 for (i = 0; i < multiPtr->count; i++) {
01987 if (multiPtr->strDef) {
01988 if (Q_stricmp(buff, multiPtr->cvarStr[i]) == 0) {
01989 return multiPtr->cvarList[i];
01990 }
01991 } else {
01992 if (multiPtr->cvarValue[i] == value) {
01993 return multiPtr->cvarList[i];
01994 }
01995 }
01996 }
01997 }
01998 return "";
01999 }
02000
02001 qboolean Item_Multi_HandleKey(itemDef_t *item, int key) {
02002 multiDef_t *multiPtr = (multiDef_t*)item->typeData;
02003 if (multiPtr) {
02004 if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS && item->cvar) {
02005 if (key == K_MOUSE1 || key == K_ENTER || key == K_MOUSE2 || key == K_MOUSE3) {
02006 int current = Item_Multi_FindCvarByValue(item) + 1;
02007 int max = Item_Multi_CountSettings(item);
02008 if ( current < 0 || current >= max ) {
02009 current = 0;
02010 }
02011 if (multiPtr->strDef) {
02012 DC->setCVar(item->cvar, multiPtr->cvarStr[current]);
02013 } else {
02014 float value = multiPtr->cvarValue[current];
02015 if (((float)((int) value)) == value) {
02016 DC->setCVar(item->cvar, va("%i", (int) value ));
02017 }
02018 else {
02019 DC->setCVar(item->cvar, va("%f", value ));
02020 }
02021 }
02022 return qtrue;
02023 }
02024 }
02025 }
02026 return qfalse;
02027 }
02028
02029 qboolean Item_TextField_HandleKey(itemDef_t *item, int key) {
02030 char buff[1024];
02031 int len;
02032 itemDef_t *newItem = NULL;
02033 editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
02034
02035 if (item->cvar) {
02036
02037 memset(buff, 0, sizeof(buff));
02038 DC->getCVarString(item->cvar, buff, sizeof(buff));
02039 len = strlen(buff);
02040 if (editPtr->maxChars && len > editPtr->maxChars) {
02041 len = editPtr->maxChars;
02042 }
02043 if ( key & K_CHAR_FLAG ) {
02044 key &= ~K_CHAR_FLAG;
02045
02046
02047 if (key == 'h' - 'a' + 1 ) {
02048 if ( item->cursorPos > 0 ) {
02049 memmove( &buff[item->cursorPos - 1], &buff[item->cursorPos], len + 1 - item->cursorPos);
02050 item->cursorPos--;
02051 if (item->cursorPos < editPtr->paintOffset) {
02052 editPtr->paintOffset--;
02053 }
02054 }
02055 DC->setCVar(item->cvar, buff);
02056 return qtrue;
02057 }
02058
02059
02060
02061
02062
02063 if ( key < 32 || !item->cvar) {
02064 return qtrue;
02065 }
02066
02067 if (item->type == ITEM_TYPE_NUMERICFIELD) {
02068 if (key < '0' || key > '9') {
02069 return qfalse;
02070 }
02071 }
02072
02073 if (!DC->getOverstrikeMode()) {
02074 if (( len == MAX_EDITFIELD - 1 ) || (editPtr->maxChars && len >= editPtr->maxChars)) {
02075 return qtrue;
02076 }
02077 memmove( &buff[item->cursorPos + 1], &buff[item->cursorPos], len + 1 - item->cursorPos );
02078 } else {
02079 if (editPtr->maxChars && item->cursorPos >= editPtr->maxChars) {
02080 return qtrue;
02081 }
02082 }
02083
02084 buff[item->cursorPos] = key;
02085
02086 DC->setCVar(item->cvar, buff);
02087
02088 if (item->cursorPos < len + 1) {
02089 item->cursorPos++;
02090 if (editPtr->maxPaintChars && item->cursorPos > editPtr->maxPaintChars) {
02091 editPtr->paintOffset++;
02092 }
02093 }
02094
02095 } else {
02096
02097 if ( key == K_DEL || key == K_KP_DEL ) {
02098 if ( item->cursorPos < len ) {
02099 memmove( buff + item->cursorPos, buff + item->cursorPos + 1, len - item->cursorPos);
02100 DC->setCVar(item->cvar, buff);
02101 }
02102 return qtrue;
02103 }
02104
02105 if ( key == K_RIGHTARROW || key == K_KP_RIGHTARROW )
02106 {
02107 if (editPtr->maxPaintChars && item->cursorPos >= editPtr->maxPaintChars && item->cursorPos < len) {
02108 item->cursorPos++;
02109 editPtr->paintOffset++;
02110 return qtrue;
02111 }
02112 if (item->cursorPos < len) {
02113 item->cursorPos++;
02114 }
02115 return qtrue;
02116 }
02117
02118 if ( key == K_LEFTARROW || key == K_KP_LEFTARROW )
02119 {
02120 if ( item->cursorPos > 0 ) {
02121 item->cursorPos--;
02122 }
02123 if (item->cursorPos < editPtr->paintOffset) {
02124 editPtr->paintOffset--;
02125 }
02126 return qtrue;
02127 }
02128
02129 if ( key == K_HOME || key == K_KP_HOME) {
02130 item->cursorPos = 0;
02131 editPtr->paintOffset = 0;
02132 return qtrue;
02133 }
02134
02135 if ( key == K_END || key == K_KP_END) {
02136 item->cursorPos = len;
02137 if(item->cursorPos > editPtr->maxPaintChars) {
02138 editPtr->paintOffset = len - editPtr->maxPaintChars;
02139 }
02140 return qtrue;
02141 }
02142
02143 if ( key == K_INS || key == K_KP_INS ) {
02144 DC->setOverstrikeMode(!DC->getOverstrikeMode());
02145 return qtrue;
02146 }
02147 }
02148
02149 if (key == K_TAB || key == K_DOWNARROW || key == K_KP_DOWNARROW) {
02150 newItem = Menu_SetNextCursorItem(item->parent);
02151 if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD)) {
02152 g_editItem = newItem;
02153 }
02154 }
02155
02156 if (key == K_UPARROW || key == K_KP_UPARROW) {
02157 newItem = Menu_SetPrevCursorItem(item->parent);
02158 if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD)) {
02159 g_editItem = newItem;
02160 }
02161 }
02162
02163 if ( key == K_ENTER || key == K_KP_ENTER || key == K_ESCAPE) {
02164 return qfalse;
02165 }
02166
02167 return qtrue;
02168 }
02169 return qfalse;
02170
02171 }
02172
02173 static void Scroll_ListBox_AutoFunc(void *p) {
02174 scrollInfo_t *si = (scrollInfo_t*)p;
02175 if (DC->realTime > si->nextScrollTime) {
02176
02177
02178
02179 Item_ListBox_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
02180 si->nextScrollTime = DC->realTime + si->adjustValue;
02181 }
02182
02183 if (DC->realTime > si->nextAdjustTime) {
02184 si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
02185 if (si->adjustValue > SCROLL_TIME_FLOOR) {
02186 si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
02187 }
02188 }
02189 }
02190
02191 static void Scroll_ListBox_ThumbFunc(void *p) {
02192 scrollInfo_t *si = (scrollInfo_t*)p;
02193 rectDef_t r;
02194 int pos, max;
02195
02196 listBoxDef_t *listPtr = (listBoxDef_t*)si->item->typeData;
02197 if (si->item->window.flags & WINDOW_HORIZONTAL) {
02198 if (DC->cursorx == si->xStart) {
02199 return;
02200 }
02201 r.x = si->item->window.rect.x + SCROLLBAR_SIZE + 1;
02202 r.y = si->item->window.rect.y + si->item->window.rect.h - SCROLLBAR_SIZE - 1;
02203 r.h = SCROLLBAR_SIZE;
02204 r.w = si->item->window.rect.w - (SCROLLBAR_SIZE*2) - 2;
02205 max = Item_ListBox_MaxScroll(si->item);
02206
02207 pos = (DC->cursorx - r.x - SCROLLBAR_SIZE/2) * max / (r.w - SCROLLBAR_SIZE);
02208 if (pos < 0) {
02209 pos = 0;
02210 }
02211 else if (pos > max) {
02212 pos = max;
02213 }
02214 listPtr->startPos = pos;
02215 si->xStart = DC->cursorx;
02216 }
02217 else if (DC->cursory != si->yStart) {
02218
02219 r.x = si->item->window.rect.x + si->item->window.rect.w - SCROLLBAR_SIZE - 1;
02220 r.y = si->item->window.rect.y + SCROLLBAR_SIZE + 1;
02221 r.h = si->item->window.rect.h - (SCROLLBAR_SIZE*2) - 2;
02222 r.w = SCROLLBAR_SIZE;
02223 max = Item_ListBox_MaxScroll(si->item);
02224
02225 pos = (DC->cursory - r.y - SCROLLBAR_SIZE/2) * max / (r.h - SCROLLBAR_SIZE);
02226 if (pos < 0) {
02227 pos = 0;
02228 }
02229 else if (pos > max) {
02230 pos = max;
02231 }
02232 listPtr->startPos = pos;
02233 si->yStart = DC->cursory;
02234 }
02235
02236 if (DC->realTime > si->nextScrollTime) {
02237
02238
02239
02240 Item_ListBox_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
02241 si->nextScrollTime = DC->realTime + si->adjustValue;
02242 }
02243
02244 if (DC->realTime > si->nextAdjustTime) {
02245 si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
02246 if (si->adjustValue > SCROLL_TIME_FLOOR) {
02247 si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
02248 }
02249 }
02250 }
02251
02252 static void Scroll_Slider_ThumbFunc(void *p) {
02253 float x, value, cursorx;
02254 scrollInfo_t *si = (scrollInfo_t*)p;
02255 editFieldDef_t *editDef = si->item->typeData;
02256
02257 if (si->item->text) {
02258 x = si->item->textRect.x + si->item->textRect.w + 8;
02259 } else {
02260 x = si->item->window.rect.x;
02261 }
02262
02263 cursorx = DC->cursorx;
02264
02265 if (cursorx < x) {
02266 cursorx = x;
02267 } else if (cursorx > x + SLIDER_WIDTH) {
02268 cursorx = x + SLIDER_WIDTH;
02269 }
02270 value = cursorx - x;
02271 value /= SLIDER_WIDTH;
02272 value *= (editDef->maxVal - editDef->minVal);
02273 value += editDef->minVal;
02274 DC->setCVar(si->item->cvar, va("%f", value));
02275 }
02276
02277 void Item_StartCapture(itemDef_t *item, int key) {
02278 int flags;
02279 switch (item->type) {
02280 case ITEM_TYPE_EDITFIELD:
02281 case ITEM_TYPE_NUMERICFIELD:
02282
02283 case ITEM_TYPE_LISTBOX:
02284 {
02285 flags = Item_ListBox_OverLB(item, DC->cursorx, DC->cursory);
02286 if (flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW)) {
02287 scrollInfo.nextScrollTime = DC->realTime + SCROLL_TIME_START;
02288 scrollInfo.nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
02289 scrollInfo.adjustValue = SCROLL_TIME_START;
02290 scrollInfo.scrollKey = key;
02291 scrollInfo.scrollDir = (flags & WINDOW_LB_LEFTARROW) ? qtrue : qfalse;
02292 scrollInfo.item = item;
02293 captureData = &scrollInfo;
02294 captureFunc = &Scroll_ListBox_AutoFunc;
02295 itemCapture = item;
02296 } else if (flags & WINDOW_LB_THUMB) {
02297 scrollInfo.scrollKey = key;
02298 scrollInfo.item = item;
02299 scrollInfo.xStart = DC->cursorx;
02300 scrollInfo.yStart = DC->cursory;
02301 captureData = &scrollInfo;
02302 captureFunc = &Scroll_ListBox_ThumbFunc;
02303 itemCapture = item;
02304 }
02305 break;
02306 }
02307 case ITEM_TYPE_SLIDER:
02308 {
02309 flags = Item_Slider_OverSlider(item, DC->cursorx, DC->cursory);
02310 if (flags & WINDOW_LB_THUMB) {
02311 scrollInfo.scrollKey = key;
02312 scrollInfo.item = item;
02313 scrollInfo.xStart = DC->cursorx;
02314 scrollInfo.yStart = DC->cursory;
02315 captureData = &scrollInfo;
02316 captureFunc = &Scroll_Slider_ThumbFunc;
02317 itemCapture = item;
02318 }
02319 break;
02320 }
02321 }
02322 }
02323
02324 void Item_StopCapture(itemDef_t *item) {
02325
02326 }
02327
02328 qboolean Item_Slider_HandleKey(itemDef_t *item, int key, qboolean down) {
02329 float x, value, width, work;
02330
02331
02332 if (item->window.flags & WINDOW_HASFOCUS && item->cvar && Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
02333 if (key == K_MOUSE1 || key == K_ENTER || key == K_MOUSE2 || key == K_MOUSE3) {
02334 editFieldDef_t *editDef = item->typeData;
02335 if (editDef) {
02336 rectDef_t testRect;
02337 width = SLIDER_WIDTH;
02338 if (item->text) {
02339 x = item->textRect.x + item->textRect.w + 8;
02340 } else {
02341 x = item->window.rect.x;
02342 }
02343
02344 testRect = item->window.rect;
02345 testRect.x = x;
02346 value = (float)SLIDER_THUMB_WIDTH / 2;
02347 testRect.x -= value;
02348
02349 testRect.w = (SLIDER_WIDTH + (float)SLIDER_THUMB_WIDTH / 2);
02350
02351 if (Rect_ContainsPoint(&testRect, DC->cursorx, DC->cursory)) {
02352 work = DC->cursorx - x;
02353 value = work / width;
02354 value *= (editDef->maxVal - editDef->minVal);
02355
02356
02357 value += editDef->minVal;
02358 DC->setCVar(item->cvar, va("%f", value));
02359 return qtrue;
02360 }
02361 }
02362 }
02363 }
02364 DC->Print("slider handle key exit\n");
02365 return qfalse;
02366 }
02367
02368
02369 qboolean Item_HandleKey(itemDef_t *item, int key, qboolean down) {
02370
02371 if (itemCapture) {
02372 Item_StopCapture(itemCapture);
02373 itemCapture = NULL;
02374 captureFunc = NULL;
02375 captureData = NULL;
02376 } else {
02377
02378 if ( down && ( key == K_MOUSE1 || key == K_MOUSE2 || key == K_MOUSE3 ) ) {
02379 Item_StartCapture(item, key);
02380 }
02381 }
02382
02383 if (!down) {
02384 return qfalse;
02385 }
02386
02387 switch (item->type) {
02388 case ITEM_TYPE_BUTTON:
02389 return qfalse;
02390 break;
02391 case ITEM_TYPE_RADIOBUTTON:
02392 return qfalse;
02393 break;
02394 case ITEM_TYPE_CHECKBOX:
02395 return qfalse;
02396 break;
02397 case ITEM_TYPE_EDITFIELD:
02398 case ITEM_TYPE_NUMERICFIELD:
02399
02400 return qfalse;
02401 break;
02402 case ITEM_TYPE_COMBO:
02403 return qfalse;
02404 break;
02405 case ITEM_TYPE_LISTBOX:
02406 return Item_ListBox_HandleKey(item, key, down, qfalse);
02407 break;
02408 case ITEM_TYPE_YESNO:
02409 return Item_YesNo_HandleKey(item, key);
02410 break;
02411 case ITEM_TYPE_MULTI:
02412 return Item_Multi_HandleKey(item, key);
02413 break;
02414 case ITEM_TYPE_OWNERDRAW:
02415 return Item_OwnerDraw_HandleKey(item, key);
02416 break;
02417 case ITEM_TYPE_BIND:
02418 return Item_Bind_HandleKey(item, key, down);
02419 break;
02420 case ITEM_TYPE_SLIDER:
02421 return Item_Slider_HandleKey(item, key, down);
02422 break;
02423
02424
02425
02426 default:
02427 return qfalse;
02428 break;
02429 }
02430
02431
02432 }
02433
02434 void Item_Action(itemDef_t *item) {
02435 if (item) {
02436 Item_RunScript(item, item->action);
02437 }
02438 }
02439
02440 itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu) {
02441 qboolean wrapped = qfalse;
02442 int oldCursor = menu->cursorItem;
02443
02444 if (menu->cursorItem < 0) {
02445 menu->cursorItem = menu->itemCount-1;
02446 wrapped = qtrue;
02447 }
02448
02449 while (menu->cursorItem > -1) {
02450
02451 menu->cursorItem--;
02452 if (menu->cursorItem < 0 && !wrapped) {
02453 wrapped = qtrue;
02454 menu->cursorItem = menu->itemCount -1;
02455 }
02456
02457 if (Item_SetFocus(menu->items[menu->cursorItem], DC->cursorx, DC->cursory)) {
02458 Menu_HandleMouseMove(menu, menu->items[menu->cursorItem]->window.rect.x + 1, menu->items[menu->cursorItem]->window.rect.y + 1);
02459 return menu->items[menu->cursorItem];
02460 }
02461 }
02462 menu->cursorItem = oldCursor;
02463 return NULL;
02464
02465 }
02466
02467 itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu) {
02468
02469 qboolean wrapped = qfalse;
02470 int oldCursor = menu->cursorItem;
02471
02472
02473 if (menu->cursorItem == -1) {
02474 menu->cursorItem = 0;
02475 wrapped = qtrue;
02476 }
02477
02478 while (menu->cursorItem < menu->itemCount) {
02479
02480 menu->cursorItem++;
02481 if (menu->cursorItem >= menu->itemCount && !wrapped) {
02482 wrapped = qtrue;
02483 menu->cursorItem = 0;
02484 }
02485 if (Item_SetFocus(menu->items[menu->cursorItem], DC->cursorx, DC->cursory)) {
02486 Menu_HandleMouseMove(menu, menu->items[menu->cursorItem]->window.rect.x + 1, menu->items[menu->cursorItem]->window.rect.y + 1);
02487 return menu->items[menu->cursorItem];
02488 }
02489
02490 }
02491
02492 menu->cursorItem = oldCursor;
02493 return NULL;
02494 }
02495
02496 static void Window_CloseCinematic(windowDef_t *window) {
02497 if (window->style == WINDOW_STYLE_CINEMATIC && window->cinematic >= 0) {
02498 DC->stopCinematic(window->cinematic);
02499 window->cinematic = -1;
02500 }
02501 }
02502
02503 static void Menu_CloseCinematics(menuDef_t *menu) {
02504 if (menu) {
02505 int i;
02506 Window_CloseCinematic(&menu->window);
02507 for (i = 0; i < menu->itemCount; i++) {
02508 Window_CloseCinematic(&menu->items[i]->window);
02509 if (menu->items[i]->type == ITEM_TYPE_OWNERDRAW) {
02510 DC->stopCinematic(0-menu->items[i]->window.ownerDraw);
02511 }
02512 }
02513 }
02514 }
02515
02516 static void Display_CloseCinematics() {
02517 int i;
02518 for (i = 0; i < menuCount; i++) {
02519 Menu_CloseCinematics(&Menus[i]);
02520 }
02521 }
02522
02523 void Menus_Activate(menuDef_t *menu) {
02524 menu->window.flags |= (WINDOW_HASFOCUS | WINDOW_VISIBLE);
02525 if (menu->onOpen) {
02526 itemDef_t item;
02527 item.parent = menu;
02528 Item_RunScript(&item, menu->onOpen);
02529 }
02530
02531 if (menu->soundName && *menu->soundName) {
02532
02533 DC->startBackgroundTrack(menu->soundName, menu->soundName);
02534 }
02535
02536 Display_CloseCinematics();
02537
02538 }
02539
02540 int Display_VisibleMenuCount() {
02541 int i, count;
02542 count = 0;
02543 for (i = 0; i < menuCount; i++) {
02544 if (Menus[i].window.flags & (WINDOW_FORCED | WINDOW_VISIBLE)) {
02545 count++;
02546 }
02547 }
02548 return count;
02549 }
02550
02551 void Menus_HandleOOBClick(menuDef_t *menu, int key, qboolean down) {
02552 if (menu) {
02553 int i;
02554
02555
02556
02557 if (down && menu->window.flags & WINDOW_OOB_CLICK) {
02558 Menu_RunCloseScript(menu);
02559 menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
02560 }
02561
02562 for (i = 0; i < menuCount; i++) {
02563 if (Menu_OverActiveItem(&Menus[i], DC->cursorx, DC->cursory)) {
02564 Menu_RunCloseScript(menu);
02565 menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
02566 Menus_Activate(&Menus[i]);
02567 Menu_HandleMouseMove(&Menus[i], DC->cursorx, DC->cursory);
02568 Menu_HandleKey(&Menus[i], key, down);
02569 }
02570 }
02571
02572 if (Display_VisibleMenuCount() == 0) {
02573 if (DC->Pause) {
02574 DC->Pause(qfalse);
02575 }
02576 }
02577 Display_CloseCinematics();
02578 }
02579 }
02580
02581 static rectDef_t *Item_CorrectedTextRect(itemDef_t *item) {
02582 static rectDef_t rect;
02583 memset(&rect, 0, sizeof(rectDef_t));
02584 if (item) {
02585 rect = item->textRect;
02586 if (rect.w) {
02587 rect.y -= rect.h;
02588 }
02589 }
02590 return ▭
02591 }
02592
02593 void Menu_HandleKey(menuDef_t *menu, int key, qboolean down) {
02594 int i;
02595 itemDef_t *item = NULL;
02596 qboolean inHandler = qfalse;
02597
02598 if (inHandler) {
02599 return;
02600 }
02601
02602 inHandler = qtrue;
02603 if (g_waitingForKey && down) {
02604 Item_Bind_HandleKey(g_bindItem, key, down);
02605 inHandler = qfalse;
02606 return;
02607 }
02608
02609 if (g_editingField && down) {
02610 if (!Item_TextField_HandleKey(g_editItem, key)) {
02611 g_editingField = qfalse;
02612 g_editItem = NULL;
02613 inHandler = qfalse;
02614 return;
02615 } else if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_MOUSE3) {
02616 g_editingField = qfalse;
02617 g_editItem = NULL;
02618 Display_MouseMove(NULL, DC->cursorx, DC->cursory);
02619 } else if (key == K_TAB || key == K_UPARROW || key == K_DOWNARROW) {
02620 return;
02621 }
02622 }
02623
02624 if (menu == NULL) {
02625 inHandler = qfalse;
02626 return;
02627 }
02628
02629
02630 if (down && !(menu->window.flags & WINDOW_POPUP) && !Rect_ContainsPoint(&menu->window.rect, DC->cursorx, DC->cursory)) {
02631 static qboolean inHandleKey = qfalse;
02632
02633 if (!inHandleKey && ( key == K_MOUSE1 || key == K_MOUSE2 || key == K_MOUSE3 ) ) {
02634 inHandleKey = qtrue;
02635 Menus_HandleOOBClick(menu, key, down);
02636 inHandleKey = qfalse;
02637 inHandler = qfalse;
02638 return;
02639 }
02640 }
02641
02642
02643 for (i = 0; i < menu->itemCount; i++) {
02644 if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
02645 item = menu->items[i];
02646 }
02647 }
02648
02649 if (item != NULL) {
02650 if (Item_HandleKey(item, key, down)) {
02651 Item_Action(item);
02652 inHandler = qfalse;
02653 return;
02654 }
02655 }
02656
02657 if (!down) {
02658 inHandler = qfalse;
02659 return;
02660 }
02661
02662
02663 switch ( key ) {
02664
02665 case K_F11:
02666 if (DC->getCVarValue("developer")) {
02667 debugMode ^= 1;
02668 }
02669 break;
02670
02671 case K_F12:
02672 if (DC->getCVarValue("developer")) {
02673 DC->executeText(EXEC_APPEND, "screenshot\n");
02674 }
02675 break;
02676 case K_KP_UPARROW:
02677 case K_UPARROW:
02678 Menu_SetPrevCursorItem(menu);
02679 break;
02680
02681 case K_ESCAPE:
02682 if (!g_waitingForKey && menu->onESC) {
02683 itemDef_t it;
02684 it.parent = menu;
02685 Item_RunScript(&it, menu->onESC);
02686 }
02687 break;
02688 case K_TAB:
02689 case K_KP_DOWNARROW:
02690 case K_DOWNARROW:
02691 Menu_SetNextCursorItem(menu);
02692 break;
02693
02694 case K_MOUSE1:
02695 case K_MOUSE2:
02696 if (item) {
02697 if (item->type == ITEM_TYPE_TEXT) {
02698 if (Rect_ContainsPoint(Item_CorrectedTextRect(item), DC->cursorx, DC->cursory)) {
02699 Item_Action(item);
02700 }
02701 } else if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD) {
02702 if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
02703 item->cursorPos = 0;
02704 g_editingField = qtrue;
02705 g_editItem = item;
02706 DC->setOverstrikeMode(qtrue);
02707 }
02708 } else {
02709 if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
02710 Item_Action(item);
02711 }
02712 }
02713 }
02714 break;
02715
02716 case K_JOY1:
02717 case K_JOY2:
02718 case K_JOY3:
02719 case K_JOY4:
02720 case K_AUX1:
02721 case K_AUX2:
02722 case K_AUX3:
02723 case K_AUX4:
02724 case K_AUX5:
02725 case K_AUX6:
02726 case K_AUX7:
02727 case K_AUX8:
02728 case K_AUX9:
02729 case K_AUX10:
02730 case K_AUX11:
02731 case K_AUX12:
02732 case K_AUX13:
02733 case K_AUX14:
02734 case K_AUX15:
02735 case K_AUX16:
02736 break;
02737 case K_KP_ENTER:
02738 case K_ENTER:
02739 if (item) {
02740 if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD) {
02741 item->cursorPos = 0;
02742 g_editingField = qtrue;
02743 g_editItem = item;
02744 DC->setOverstrikeMode(qtrue);
02745 } else {
02746 Item_Action(item);
02747 }
02748 }
02749 break;
02750 }
02751 inHandler = qfalse;
02752 }
02753
02754 void ToWindowCoords(float *x, float *y, windowDef_t *window) {
02755 if (window->border != 0) {
02756 *x += window->borderSize;
02757 *y += window->borderSize;
02758 }
02759 *x += window->rect.x;
02760 *y += window->rect.y;
02761 }
02762
02763 void Rect_ToWindowCoords(rectDef_t *rect, windowDef_t *window) {
02764 ToWindowCoords(&rect->x, &rect->y, window);
02765 }
02766
02767 void Item_SetTextExtents(itemDef_t *item, int *width, int *height, const char *text) {
02768 const char *textPtr = (text) ? text : item->text;
02769
02770 if (textPtr == NULL ) {
02771 return;
02772 }
02773
02774 *width = item->textRect.w;
02775 *height = item->textRect.h;
02776
02777
02778 if (*width == 0 || (item->type == ITEM_TYPE_OWNERDRAW && item->textalignment == ITEM_ALIGN_CENTER)) {
02779 int originalWidth = DC->textWidth(item->text, item->textscale, 0);
02780
02781 if (item->type == ITEM_TYPE_OWNERDRAW && (item->textalignment == ITEM_ALIGN_CENTER || item->textalignment == ITEM_ALIGN_RIGHT)) {
02782 originalWidth += DC->ownerDrawWidth(item->window.ownerDraw, item->textscale);
02783 } else if (item->type == ITEM_TYPE_EDITFIELD && item->textalignment == ITEM_ALIGN_CENTER && item->cvar) {
02784 char buff[256];
02785 DC->getCVarString(item->cvar, buff, 256);
02786 originalWidth += DC->textWidth(buff, item->textscale, 0);
02787 }
02788
02789 *width = DC->textWidth(textPtr, item->textscale, 0);
02790 *height = DC->textHeight(textPtr, item->textscale, 0);
02791 item->textRect.w = *width;
02792 item->textRect.h = *height;
02793 item->textRect.x = item->textalignx;
02794 item->textRect.y = item->textaligny;
02795 if (item->textalignment == ITEM_ALIGN_RIGHT) {
02796 item->textRect.x = item->textalignx - originalWidth;
02797 } else if (item->textalignment == ITEM_ALIGN_CENTER) {
02798 item->textRect.x = item->textalignx - originalWidth / 2;
02799 }
02800
02801 ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
02802 }
02803 }
02804
02805 void Item_TextColor(itemDef_t *item, vec4_t *newColor) {
02806 vec4_t lowLight;
02807 menuDef_t *parent = (menuDef_t*)item->parent;
02808
02809 Fade(&item->window.flags, &item->window.foreColor[3], parent->fadeClamp, &item->window.nextTime, parent->fadeCycle, qtrue, parent->fadeAmount);
02810
02811 if (item->window.flags & WINDOW_HASFOCUS) {
02812 lowLight[0] = 0.8 * parent->focusColor[0];
02813 lowLight[1] = 0.8 * parent->focusColor[1];
02814 lowLight[2] = 0.8 * parent->focusColor[2];
02815 lowLight[3] = 0.8 * parent->focusColor[3];
02816 LerpColor(parent->focusColor,lowLight,*newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
02817 } else if (item->textStyle == ITEM_TEXTSTYLE_BLINK && !((DC->realTime/BLINK_DIVISOR) & 1)) {
02818 lowLight[0] = 0.8 * item->window.foreColor[0];
02819 lowLight[1] = 0.8 * item->window.foreColor[1];
02820 lowLight[2] = 0.8 * item->window.foreColor[2];
02821 lowLight[3] = 0.8 * item->window.foreColor[3];
02822 LerpColor(item->window.foreColor,lowLight,*newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
02823 } else {
02824 memcpy(newColor, &item->window.foreColor, sizeof(vec4_t));
02825
02826 }
02827
02828 if (item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest) {
02829 if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
02830 memcpy(newColor, &parent->disableColor, sizeof(vec4_t));
02831 }
02832 }
02833 }
02834
02835 void Item_Text_AutoWrapped_Paint(itemDef_t *item) {
02836 char text[1024];
02837 const char *p, *textPtr, *newLinePtr;
02838 char buff[1024];
02839 int width, height, len, textWidth, newLine, newLineWidth;
02840 float y;
02841 vec4_t color;
02842
02843 textWidth = 0;
02844 newLinePtr = NULL;
02845
02846 if (item->text == NULL) {
02847 if (item->cvar == NULL) {
02848 return;
02849 }
02850 else {
02851 DC->getCVarString(item->cvar, text, sizeof(text));
02852 textPtr = text;
02853 }
02854 }
02855 else {
02856 textPtr = item->text;
02857 }
02858 if (*textPtr == '\0') {
02859 return;
02860 }
02861 Item_TextColor(item, &color);
02862 Item_SetTextExtents(item, &width, &height, textPtr);
02863
02864 y = item->textaligny;
02865 len = 0;
02866 buff[0] = '\0';
02867 newLine = 0;
02868 newLineWidth = 0;
02869 p = textPtr;
02870 while (p) {
02871 if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\0') {
02872 newLine = len;
02873 newLinePtr = p+1;
02874 newLineWidth = textWidth;
02875 }
02876 textWidth = DC->textWidth(buff, item->textscale, 0);
02877 if ( (newLine && textWidth > item->window.rect.w) || *p == '\n' || *p == '\0') {
02878 if (len) {
02879 if (item->textalignment == ITEM_ALIGN_LEFT) {
02880 item->textRect.x = item->textalignx;
02881 } else if (item->textalignment == ITEM_ALIGN_RIGHT) {
02882 item->textRect.x = item->textalignx - newLineWidth;
02883 } else if (item->textalignment == ITEM_ALIGN_CENTER) {
02884 item->textRect.x = item->textalignx - newLineWidth / 2;
02885 }
02886 item->textRect.y = y;
02887 ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
02888
02889 buff[newLine] = '\0';
02890 DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, buff, 0, 0, item->textStyle);
02891 }
02892 if (*p == '\0') {
02893 break;
02894 }
02895
02896 y += height + 5;
02897 p = newLinePtr;
02898 len = 0;
02899 newLine = 0;
02900 newLineWidth = 0;
02901 continue;
02902 }
02903 buff[len++] = *p++;
02904 buff[len] = '\0';
02905 }
02906 }
02907
02908 void Item_Text_Wrapped_Paint(itemDef_t *item) {
02909 char text[1024];
02910 const char *p, *start, *textPtr;
02911 char buff[1024];
02912 int width, height;
02913 float x, y;
02914 vec4_t color;
02915
02916
02917
02918
02919 if (item->text == NULL) {
02920 if (item->cvar == NULL) {
02921 return;
02922 }
02923 else {
02924 DC->getCVarString(item->cvar, text, sizeof(text));
02925 textPtr = text;
02926 }
02927 }
02928 else {
02929 textPtr = item->text;
02930 }
02931 if (*textPtr == '\0') {
02932 return;
02933 }
02934
02935 Item_TextColor(item, &color);
02936 Item_SetTextExtents(item, &width, &height, textPtr);
02937
02938 x = item->textRect.x;
02939 y = item->textRect.y;
02940 start = textPtr;
02941 p = strchr(textPtr, '\r');
02942 while (p && *p) {
02943 strncpy(buff, start, p-start+1);
02944 buff[p-start] = '\0';
02945 DC->drawText(x, y, item->textscale, color, buff, 0, 0, item->textStyle);
02946 y += height + 5;
02947 start += p - start + 1;
02948 p = strchr(p+1, '\r');
02949 }
02950 DC->drawText(x, y, item->textscale, color, start, 0, 0, item->textStyle);
02951 }
02952
02953 void Item_Text_Paint(itemDef_t *item) {
02954 char text[1024];
02955 const char *textPtr;
02956 int height, width;
02957 vec4_t color;
02958
02959 if (item->window.flags & WINDOW_WRAPPED) {
02960 Item_Text_Wrapped_Paint(item);
02961 return;
02962 }
02963 if (item->window.flags & WINDOW_AUTOWRAPPED) {
02964 Item_Text_AutoWrapped_Paint(item);
02965 return;
02966 }
02967
02968 if (item->text == NULL) {
02969 if (item->cvar == NULL) {
02970 return;
02971 }
02972 else {
02973 DC->getCVarString(item->cvar, text, sizeof(text));
02974 textPtr = text;
02975 }
02976 }
02977 else {
02978 textPtr = item->text;
02979 }
02980
02981
02982 Item_SetTextExtents(item, &width, &height, textPtr);
02983
02984 if (*textPtr == '\0') {
02985 return;
02986 }
02987
02988
02989 Item_TextColor(item, &color);
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020 DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, textPtr, 0, 0, item->textStyle);
03021 }
03022
03023
03024
03025
03026
03027
03028 void Item_TextField_Paint(itemDef_t *item) {
03029 char buff[1024];
03030 vec4_t newColor, lowLight;
03031 int offset;
03032 menuDef_t *parent = (menuDef_t*)item->parent;
03033 editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
03034
03035 Item_Text_Paint(item);
03036
03037 buff[0] = '\0';
03038
03039 if (item->cvar) {
03040 DC->getCVarString(item->cvar, buff, sizeof(buff));
03041 }
03042
03043 parent = (menuDef_t*)item->parent;
03044
03045 if (item->window.flags & WINDOW_HASFOCUS) {
03046 lowLight[0] = 0.8 * parent->focusColor[0];
03047 lowLight[1] = 0.8 * parent->focusColor[1];
03048 lowLight[2] = 0.8 * parent->focusColor[2];
03049 lowLight[3] = 0.8 * parent->focusColor[3];
03050 LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
03051 } else {
03052 memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
03053 }
03054
03055 offset = (item->text && *item->text) ? 8 : 0;
03056 if (item->window.flags & WINDOW_HASFOCUS && g_editingField) {
03057 char cursor = DC->getOverstrikeMode() ? '_' : '|';
03058 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);
03059 } else {
03060 DC->drawText(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, buff + editPtr->paintOffset, 0, editPtr->maxPaintChars, item->textStyle);
03061 }
03062
03063 }
03064
03065 void Item_YesNo_Paint(itemDef_t *item) {
03066 vec4_t newColor, lowLight;
03067 float value;
03068 menuDef_t *parent = (menuDef_t*)item->parent;
03069
03070 value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
03071
03072 if (item->window.flags & WINDOW_HASFOCUS) {
03073 lowLight[0] = 0.8 * parent->focusColor[0];
03074 lowLight[1] = 0.8 * parent->focusColor[1];
03075 lowLight[2] = 0.8 * parent->focusColor[2];
03076 lowLight[3] = 0.8 * parent->focusColor[3];
03077 LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
03078 } else {
03079 memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
03080 }
03081
03082 if (item->text) {
03083 Item_Text_Paint(item);
03084 DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, (value != 0) ? "Yes" : "No", 0, 0, item->textStyle);
03085 } else {
03086 DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? "Yes" : "No", 0, 0, item->textStyle);
03087 }
03088 }
03089
03090 void Item_Multi_Paint(itemDef_t *item) {
03091 vec4_t newColor, lowLight;
03092 const char *text = "";
03093 menuDef_t *parent = (menuDef_t*)item->parent;
03094
03095 if (item->window.flags & WINDOW_HASFOCUS) {
03096 lowLight[0] = 0.8 * parent->focusColor[0];
03097 lowLight[1] = 0.8 * parent->focusColor[1];
03098 lowLight[2] = 0.8 * parent->focusColor[2];
03099 lowLight[3] = 0.8 * parent->focusColor[3];
03100 LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
03101 } else {
03102 memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
03103 }
03104
03105 text = Item_Multi_Setting(item);
03106
03107 if (item->text) {
03108 Item_Text_Paint(item);
03109 DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle);
03110 } else {
03111 DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle);
03112 }
03113 }
03114
03115
03116 typedef struct {
03117 char *command;
03118 int id;
03119 int defaultbind1;
03120 int defaultbind2;
03121 int bind1;
03122 int bind2;
03123 } bind_t;
03124
03125 typedef struct
03126 {
03127 char* name;
03128 float defaultvalue;
03129 float value;
03130 } configcvar_t;
03131
03132
03133 static bind_t g_bindings[] =
03134 {
03135 {"+scores", K_TAB, -1, -1, -1},
03136 {"+button2", K_ENTER, -1, -1, -1},
03137 {"+speed", K_SHIFT, -1, -1, -1},
03138 {"+forward", K_UPARROW, -1, -1, -1},
03139 {"+back", K_DOWNARROW, -1, -1, -1},
03140 {"+moveleft", ',', -1, -1, -1},
03141 {"+moveright", '.', -1, -1, -1},
03142 {"+moveup", K_SPACE, -1, -1, -1},
03143 {"+movedown", 'c', -1, -1, -1},
03144 {"+left", K_LEFTARROW, -1, -1, -1},
03145 {"+right", K_RIGHTARROW, -1, -1, -1},
03146 {"+strafe", K_ALT, -1, -1, -1},
03147 {"+lookup", K_PGDN, -1, -1, -1},
03148 {"+lookdown", K_DEL, -1, -1, -1},
03149 {"+mlook", '/', -1, -1, -1},
03150 {"centerview", K_END, -1, -1, -1},
03151 {"+zoom", -1, -1, -1, -1},
03152 {"weapon 1", '1', -1, -1, -1},
03153 {"weapon 2", '2', -1, -1, -1},
03154 {"weapon 3", '3', -1, -1, -1},
03155 {"weapon 4", '4', -1, -1, -1},
03156 {"weapon 5", '5', -1, -1, -1},
03157 {"weapon 6", '6', -1, -1, -1},
03158 {"weapon 7", '7', -1, -1, -1},
03159 {"weapon 8", '8', -1, -1, -1},
03160 {"weapon 9", '9', -1, -1, -1},
03161 {"weapon 10", '0', -1, -1, -1},
03162 {"weapon 11", -1, -1, -1, -1},
03163 {"weapon 12", -1, -1, -1, -1},
03164 {"weapon 13", -1, -1, -1, -1},
03165 {"+attack", K_CTRL, -1, -1, -1},
03166 {"weapprev", '[', -1, -1, -1},
03167 {"weapnext", ']', -1, -1, -1},
03168 {"+button3", K_MOUSE3, -1, -1, -1},
03169 {"+button4", K_MOUSE4, -1, -1, -1},
03170 {"prevTeamMember", 'w', -1, -1, -1},
03171 {"nextTeamMember", 'r', -1, -1, -1},
03172 {"nextOrder", 't', -1, -1, -1},
03173 {"confirmOrder", 'y', -1, -1, -1},
03174 {"denyOrder", 'n', -1, -1, -1},
03175 {"taskOffense", 'o', -1, -1, -1},
03176 {"taskDefense", 'd', -1, -1, -1},
03177 {"taskPatrol", 'p', -1, -1, -1},
03178 {"taskCamp", 'c', -1, -1, -1},
03179 {"taskFollow", 'f', -1, -1, -1},
03180 {"taskRetrieve", 'v', -1, -1, -1},
03181 {"taskEscort", 'e', -1, -1, -1},
03182 {"taskOwnFlag", 'i', -1, -1, -1},
03183 {"taskSuicide", 'k', -1, -1, -1},
03184 {"tauntKillInsult", K_F1, -1, -1, -1},
03185 {"tauntPraise", K_F2, -1, -1, -1},
03186 {"tauntTaunt", K_F3, -1, -1, -1},
03187 {"tauntDeathInsult", K_F4, -1, -1, -1},
03188 {"tauntGauntlet", K_F5, -1, -1, -1},
03189 {"scoresUp", K_KP_PGUP, -1, -1, -1},
03190 {"scoresDown", K_KP_PGDN, -1, -1, -1},
03191
03192 {"messagemode", -1, -1, -1, -1},
03193 {"messagemode2", -1, -1, -1, -1},
03194 {"messagemode3", -1, -1, -1, -1},
03195 {"messagemode4", -1, -1, -1, -1}
03196 };
03197
03198
03199 static const int g_bindCount = sizeof(g_bindings) / sizeof(bind_t);
03200
03201 #ifndef MISSIONPACK // bk001206
03202 static configcvar_t g_configcvars[] =
03203 {
03204 {"cl_run", 0, 0},
03205 {"m_pitch", 0, 0},
03206 {"cg_autoswitch", 0, 0},
03207 {"sensitivity", 0, 0},
03208 {"in_joystick", 0, 0},
03209 {"joy_threshold", 0, 0},
03210 {"m_filter", 0, 0},
03211 {"cl_freelook", 0, 0},
03212 {NULL, 0, 0}
03213 };
03214 #endif
03215
03216
03217
03218
03219
03220
03221 static void Controls_GetKeyAssignment (char *command, int *twokeys)
03222 {
03223 int count;
03224 int j;
03225 char b[256];
03226
03227 twokeys[0] = twokeys[1] = -1;
03228 count = 0;
03229
03230 for ( j = 0; j < 256; j++ )
03231 {
03232 DC->getBindingBuf( j, b, 256 );
03233 if ( *b == 0 ) {
03234 continue;
03235 }
03236 if ( !Q_stricmp( b, command ) ) {
03237 twokeys[count] = j;
03238 count++;
03239 if (count == 2) {
03240 break;
03241 }
03242 }
03243 }
03244 }
03245
03246
03247
03248
03249
03250
03251 void Controls_GetConfig( void )
03252 {
03253 int i;
03254 int twokeys[2];
03255
03256
03257 for (i=0; i < g_bindCount; i++)
03258 {
03259
03260 Controls_GetKeyAssignment(g_bindings[i].command, twokeys);
03261
03262 g_bindings[i].bind1 = twokeys[0];
03263 g_bindings[i].bind2 = twokeys[1];
03264 }
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274 }
03275
03276
03277
03278
03279
03280
03281 void Controls_SetConfig(qboolean restart)
03282 {
03283 int i;
03284
03285
03286 for (i=0; i < g_bindCount; i++)
03287 {
03288
03289 if (g_bindings[i].bind1 != -1)
03290 {
03291 DC->setBinding( g_bindings[i].bind1, g_bindings[i].command );
03292
03293 if (g_bindings[i].bind2 != -1)
03294 DC->setBinding( g_bindings[i].bind2, g_bindings[i].command );
03295 }
03296 }
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310 DC->executeText(EXEC_APPEND, "in_restart\n");
03311
03312 }
03313
03314
03315
03316
03317
03318
03319 void Controls_SetDefaults( void )
03320 {
03321 int i;
03322
03323
03324 for (i=0; i < g_bindCount; i++)
03325 {
03326 g_bindings[i].bind1 = g_bindings[i].defaultbind1;
03327 g_bindings[i].bind2 = g_bindings[i].defaultbind2;
03328 }
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338 }
03339
03340 int BindingIDFromName(const char *name) {
03341 int i;
03342 for (i=0; i < g_bindCount; i++)
03343 {
03344 if (Q_stricmp(name, g_bindings[i].command) == 0) {
03345 return i;
03346 }
03347 }
03348 return -1;
03349 }
03350
03351 char g_nameBind1[32];
03352 char g_nameBind2[32];
03353
03354 void BindingFromName(const char *cvar) {
03355 int i, b1, b2;
03356
03357
03358 for (i=0; i < g_bindCount; i++)
03359 {
03360 if (Q_stricmp(cvar, g_bindings[i].command) == 0) {
03361 b1 = g_bindings[i].bind1;
03362 if (b1 == -1) {
03363 break;
03364 }
03365 DC->keynumToStringBuf( b1, g_nameBind1, 32 );
03366 Q_strupr(g_nameBind1);
03367
03368 b2 = g_bindings[i].bind2;
03369 if (b2 != -1)
03370 {
03371 DC->keynumToStringBuf( b2, g_nameBind2, 32 );
03372 Q_strupr(g_nameBind2);
03373 strcat( g_nameBind1, " or " );
03374 strcat( g_nameBind1, g_nameBind2 );
03375 }
03376 return;
03377 }
03378 }
03379 strcpy(g_nameBind1, "???");
03380 }
03381
03382 void Item_Slider_Paint(itemDef_t *item) {
03383 vec4_t newColor, lowLight;
03384 float x, y, value;
03385 menuDef_t *parent = (menuDef_t*)item->parent;
03386
03387 value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
03388
03389 if (item->window.flags & WINDOW_HASFOCUS) {
03390 lowLight[0] = 0.8 * parent->focusColor[0];
03391 lowLight[1] = 0.8 * parent->focusColor[1];
03392 lowLight[2] = 0.8 * parent->focusColor[2];
03393 lowLight[3] = 0.8 * parent->focusColor[3];
03394 LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
03395 } else {
03396 memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
03397 }
03398
03399 y = item->window.rect.y;
03400 if (item->text) {
03401 Item_Text_Paint(item);
03402 x = item->textRect.x + item->textRect.w + 8;
03403 } else {
03404 x = item->window.rect.x;
03405 }
03406 DC->setColor(newColor);
03407 DC->drawHandlePic( x, y, SLIDER_WIDTH, SLIDER_HEIGHT, DC->Assets.sliderBar );
03408
03409 x = Item_Slider_ThumbPosition(item);
03410 DC->drawHandlePic( x - (SLIDER_THUMB_WIDTH / 2), y - 2, SLIDER_THUMB_WIDTH, SLIDER_THUMB_HEIGHT, DC->Assets.sliderThumb );
03411
03412 }
03413
03414 void Item_Bind_Paint(itemDef_t *item) {
03415 vec4_t newColor, lowLight;
03416 float value;
03417 int maxChars = 0;
03418 menuDef_t *parent = (menuDef_t*)item->parent;
03419 editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
03420 if (editPtr) {
03421 maxChars = editPtr->maxPaintChars;
03422 }
03423
03424 value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
03425
03426 if (item->window.flags & WINDOW_HASFOCUS) {
03427 if (g_bindItem == item) {
03428 lowLight[0] = 0.8f * 1.0f;
03429 lowLight[1] = 0.8f * 0.0f;
03430 lowLight[2] = 0.8f * 0.0f;
03431 lowLight[3] = 0.8f * 1.0f;
03432 } else {
03433 lowLight[0] = 0.8f * parent->focusColor[0];
03434 lowLight[1] = 0.8f * parent->focusColor[1];
03435 lowLight[2] = 0.8f * parent->focusColor[2];
03436 lowLight[3] = 0.8f * parent->focusColor[3];
03437 }
03438 LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
03439 } else {
03440 memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
03441 }
03442
03443 if (item->text) {
03444 Item_Text_Paint(item);
03445 BindingFromName(item->cvar);
03446 DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, g_nameBind1, 0, maxChars, item->textStyle);
03447 } else {
03448 DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? "FIXME" : "FIXME", 0, maxChars, item->textStyle);
03449 }
03450 }
03451
03452 qboolean Display_KeyBindPending() {
03453 return g_waitingForKey;
03454 }
03455
03456 qboolean Item_Bind_HandleKey(itemDef_t *item, int key, qboolean down) {
03457 int id;
03458 int i;
03459
03460 if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && !g_waitingForKey)
03461 {
03462 if (down && (key == K_MOUSE1 || key == K_ENTER)) {
03463 g_waitingForKey = qtrue;
03464 g_bindItem = item;
03465 }
03466 return qtrue;
03467 }
03468 else
03469 {
03470 if (!g_waitingForKey || g_bindItem == NULL) {
03471 return qtrue;
03472 }
03473
03474 if (key & K_CHAR_FLAG) {
03475 return qtrue;
03476 }
03477
03478 switch (key)
03479 {
03480 case K_ESCAPE:
03481 g_waitingForKey = qfalse;
03482 return qtrue;
03483
03484 case K_BACKSPACE:
03485 id = BindingIDFromName(item->cvar);
03486 if (id != -1) {
03487 g_bindings[id].bind1 = -1;
03488 g_bindings[id].bind2 = -1;
03489 }
03490 Controls_SetConfig(qtrue);
03491 g_waitingForKey = qfalse;
03492 g_bindItem = NULL;
03493 return qtrue;
03494
03495 case '`':
03496 return qtrue;
03497 }
03498 }
03499
03500 if (key != -1)
03501 {
03502
03503 for (i=0; i < g_bindCount; i++)
03504 {
03505
03506 if (g_bindings[i].bind2 == key) {
03507 g_bindings[i].bind2 = -1;
03508 }
03509
03510 if (g_bindings[i].bind1 == key)
03511 {
03512 g_bindings[i].bind1 = g_bindings[i].bind2;
03513 g_bindings[i].bind2 = -1;
03514 }
03515 }
03516 }
03517
03518
03519 id = BindingIDFromName(item->cvar);
03520
03521 if (id != -1) {
03522 if (key == -1) {
03523 if( g_bindings[id].bind1 != -1 ) {
03524 DC->setBinding( g_bindings[id].bind1, "" );
03525 g_bindings[id].bind1 = -1;
03526 }
03527 if( g_bindings[id].bind2 != -1 ) {
03528 DC->setBinding( g_bindings[id].bind2, "" );
03529 g_bindings[id].bind2 = -1;
03530 }
03531 }
03532 else if (g_bindings[id].bind1 == -1) {
03533 g_bindings[id].bind1 = key;
03534 }
03535 else if (g_bindings[id].bind1 != key && g_bindings[id].bind2 == -1) {
03536 g_bindings[id].bind2 = key;
03537 }
03538 else {
03539 DC->setBinding( g_bindings[id].bind1, "" );
03540 DC->setBinding( g_bindings[id].bind2, "" );
03541 g_bindings[id].bind1 = key;
03542 g_bindings[id].bind2 = -1;
03543 }
03544 }
03545
03546 Controls_SetConfig(qtrue);
03547 g_waitingForKey = qfalse;
03548
03549 return qtrue;
03550 }
03551
03552
03553
03554 void AdjustFrom640(float *x, float *y, float *w, float *h) {
03555
03556 *x *= DC->xscale;
03557 *y *= DC->yscale;
03558 *w *= DC->xscale;
03559 *h *= DC->yscale;
03560 }
03561
03562 void Item_Model_Paint(itemDef_t *item) {
03563 float x, y, w, h;
03564 refdef_t refdef;
03565 refEntity_t ent;
03566 vec3_t mins, maxs, origin;
03567 vec3_t angles;
03568 modelDef_t *modelPtr = (modelDef_t*)item->typeData;
03569
03570 if (modelPtr == NULL) {
03571 return;
03572 }
03573
03574
03575 memset( &refdef, 0, sizeof( refdef ) );
03576 refdef.rdflags = RDF_NOWORLDMODEL;
03577 AxisClear( refdef.viewaxis );
03578 x = item->window.rect.x+1;
03579 y = item->window.rect.y+1;
03580 w = item->window.rect.w-2;
03581 h = item->window.rect.h-2;
03582
03583 AdjustFrom640( &x, &y, &w, &h );
03584
03585 refdef.x = x;
03586 refdef.y = y;
03587 refdef.width = w;
03588 refdef.height = h;
03589
03590 DC->modelBounds( item->asset, mins, maxs );
03591
03592 origin[2] = -0.5 * ( mins[2] + maxs[2] );
03593 origin[1] = 0.5 * ( mins[1] + maxs[1] );
03594
03595
03596 if (qtrue) {
03597 float len = 0.5 * ( maxs[2] - mins[2] );
03598 origin[0] = len / 0.268;
03599
03600 } else {
03601 origin[0] = item->textscale;
03602 }
03603 refdef.fov_x = (modelPtr->fov_x) ? modelPtr->fov_x : w;
03604 refdef.fov_y = (modelPtr->fov_y) ? modelPtr->fov_y : h;
03605
03606
03607
03608
03609
03610
03611 DC->clearScene();
03612
03613 refdef.time = DC->realTime;
03614
03615
03616
03617 memset( &ent, 0, sizeof(ent) );
03618
03619
03620
03621
03622
03623
03624 if (modelPtr->rotationSpeed) {
03625 if (DC->realTime > item->window.nextTime) {
03626 item->window.nextTime = DC->realTime + modelPtr->rotationSpeed;
03627 modelPtr->angle = (int)(modelPtr->angle + 1) % 360;
03628 }
03629 }
03630 VectorSet( angles, 0, modelPtr->angle, 0 );
03631 AnglesToAxis( angles, ent.axis );
03632
03633 ent.hModel = item->asset;
03634 VectorCopy( origin, ent.origin );
03635 VectorCopy( origin, ent.lightingOrigin );
03636 ent.renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW;
03637 VectorCopy( ent.origin, ent.oldorigin );
03638
03639 DC->addRefEntityToScene( &ent );
03640 DC->renderScene( &refdef );
03641
03642 }
03643
03644
03645 void Item_Image_Paint(itemDef_t *item) {
03646 if (item == NULL) {
03647 return;
03648 }
03649 DC->drawHandlePic(item->window.rect.x+1, item->window.rect.y+1, item->window.rect.w-2, item->window.rect.h-2, item->asset);
03650 }
03651
03652 void Item_ListBox_Paint(itemDef_t *item) {
03653 float x, y, size, count, i, thumb;
03654 qhandle_t image;
03655 qhandle_t optionalImage;
03656 listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
03657
03658
03659
03660
03661
03662 count = DC->feederCount(item->special);
03663
03664 if (item->window.flags & WINDOW_HORIZONTAL) {
03665
03666
03667 x = item->window.rect.x + 1;
03668 y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE - 1;
03669 DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowLeft);
03670 x += SCROLLBAR_SIZE - 1;
03671 size = item->window.rect.w - (SCROLLBAR_SIZE * 2);
03672 DC->drawHandlePic(x, y, size+1, SCROLLBAR_SIZE, DC->Assets.scrollBar);
03673 x += size - 1;
03674 DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowRight);
03675
03676 thumb = Item_ListBox_ThumbDrawPosition(item);
03677 if (thumb > x - SCROLLBAR_SIZE - 1) {
03678 thumb = x - SCROLLBAR_SIZE - 1;
03679 }
03680 DC->drawHandlePic(thumb, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
03681
03682 listPtr->endPos = listPtr->startPos;
03683 size = item->window.rect.w - 2;
03684
03685
03686 if (listPtr->elementStyle == LISTBOX_IMAGE) {
03687
03688 x = item->window.rect.x + 1;
03689 y = item->window.rect.y + 1;
03690 for (i = listPtr->startPos; i < count; i++) {
03691
03692
03693 image = DC->feederItemImage(item->special, i);
03694 if (image) {
03695 DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
03696 }
03697
03698 if (i == item->cursorPos) {
03699 DC->drawRect(x, y, listPtr->elementWidth-1, listPtr->elementHeight-1, item->window.borderSize, item->window.borderColor);
03700 }
03701
03702 size -= listPtr->elementWidth;
03703 if (size < listPtr->elementWidth) {
03704 listPtr->drawPadding = size;
03705 break;
03706 }
03707 x += listPtr->elementWidth;
03708 listPtr->endPos++;
03709
03710 }
03711 } else {
03712
03713 }
03714 } else {
03715
03716 x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE - 1;
03717 y = item->window.rect.y + 1;
03718 DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowUp);
03719 y += SCROLLBAR_SIZE - 1;
03720
03721 listPtr->endPos = listPtr->startPos;
03722 size = item->window.rect.h - (SCROLLBAR_SIZE * 2);
03723 DC->drawHandlePic(x, y, SCROLLBAR_SIZE, size+1, DC->Assets.scrollBar);
03724 y += size - 1;
03725 DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowDown);
03726
03727 thumb = Item_ListBox_ThumbDrawPosition(item);
03728 if (thumb > y - SCROLLBAR_SIZE - 1) {
03729 thumb = y - SCROLLBAR_SIZE - 1;
03730 }
03731 DC->drawHandlePic(x, thumb, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
03732
03733
03734 size = item->window.rect.h - 2;
03735 if (listPtr->elementStyle == LISTBOX_IMAGE) {
03736
03737 x = item->window.rect.x + 1;
03738 y = item->window.rect.y + 1;
03739 for (i = listPtr->startPos; i < count; i++) {
03740
03741
03742 image = DC->feederItemImage(item->special, i);
03743 if (image) {
03744 DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
03745 }
03746
03747 if (i == item->cursorPos) {
03748 DC->drawRect(x, y, listPtr->elementWidth - 1, listPtr->elementHeight - 1, item->window.borderSize, item->window.borderColor);
03749 }
03750
03751 listPtr->endPos++;
03752 size -= listPtr->elementWidth;
03753 if (size < listPtr->elementHeight) {
03754 listPtr->drawPadding = listPtr->elementHeight - size;
03755 break;
03756 }
03757 y += listPtr->elementHeight;
03758
03759 }
03760 } else {
03761 x = item->window.rect.x + 1;
03762 y = item->window.rect.y + 1;
03763 for (i = listPtr->startPos; i < count; i++) {
03764 const char *text;
03765
03766
03767
03768 if (listPtr->numColumns > 0) {
03769 int j;
03770 for (j = 0; j < listPtr->numColumns; j++) {
03771 text = DC->feederItemText(item->special, i, j, &optionalImage);
03772 if (optionalImage >= 0) {
03773 DC->drawHandlePic(x + 4 + listPtr->columnInfo[j].pos, y - 1 + listPtr->elementHeight / 2, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
03774 } else if (text) {
03775 DC->drawText(x + 4 + listPtr->columnInfo[j].pos, y + listPtr->elementHeight, item->textscale, item->window.foreColor, text, 0, listPtr->columnInfo[j].maxChars, item->textStyle);
03776 }
03777 }
03778 } else {
03779 text = DC->feederItemText(item->special, i, 0, &optionalImage);
03780 if (optionalImage >= 0) {
03781
03782 } else if (text) {
03783 DC->drawText(x + 4, y + listPtr->elementHeight, item->textscale, item->window.foreColor, text, 0, 0, item->textStyle);
03784 }
03785 }
03786
03787 if (i == item->cursorPos) {
03788 DC->fillRect(x + 2, y + 2, item->window.rect.w - SCROLLBAR_SIZE - 4, listPtr->elementHeight, item->window.outlineColor);
03789 }
03790
03791 size -= listPtr->elementHeight;
03792 if (size < listPtr->elementHeight) {
03793 listPtr->drawPadding = listPtr->elementHeight - size;
03794 break;
03795 }
03796 listPtr->endPos++;
03797 y += listPtr->elementHeight;
03798
03799 }
03800 }
03801 }
03802 }
03803
03804
03805 void Item_OwnerDraw_Paint(itemDef_t *item) {
03806 menuDef_t *parent;
03807
03808 if (item == NULL) {
03809 return;
03810 }
03811 parent = (menuDef_t*)item->parent;
03812
03813 if (DC->ownerDrawItem) {
03814 vec4_t color, lowLight;
03815 menuDef_t *parent = (menuDef_t*)item->parent;
03816 Fade(&item->window.flags, &item->window.foreColor[3], parent->fadeClamp, &item->window.nextTime, parent->fadeCycle, qtrue, parent->fadeAmount);
03817 memcpy(&color, &item->window.foreColor, sizeof(color));
03818 if (item->numColors > 0 && DC->getValue) {
03819
03820 int i;
03821 float f = DC->getValue(item->window.ownerDraw);
03822 for (i = 0; i < item->numColors; i++) {
03823 if (f >= item->colorRanges[i].low && f <= item->colorRanges[i].high) {
03824 memcpy(&color, &item->colorRanges[i].color, sizeof(color));
03825 break;
03826 }
03827 }
03828 }
03829
03830 if (item->window.flags & WINDOW_HASFOCUS) {
03831 lowLight[0] = 0.8 * parent->focusColor[0];
03832 lowLight[1] = 0.8 * parent->focusColor[1];
03833 lowLight[2] = 0.8 * parent->focusColor[2];
03834 lowLight[3] = 0.8 * parent->focusColor[3];
03835 LerpColor(parent->focusColor,lowLight,color,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
03836 } else if (item->textStyle == ITEM_TEXTSTYLE_BLINK && !((DC->realTime/BLINK_DIVISOR) & 1)) {
03837 lowLight[0] = 0.8 * item->window.foreColor[0];
03838 lowLight[1] = 0.8 * item->window.foreColor[1];
03839 lowLight[2] = 0.8 * item->window.foreColor[2];
03840 lowLight[3] = 0.8 * item->window.foreColor[3];
03841 LerpColor(item->window.foreColor,lowLight,color,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
03842 }
03843
03844 if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
03845 memcpy(color, parent->disableColor, sizeof(vec4_t));
03846 }
03847
03848 if (item->text) {
03849 Item_Text_Paint(item);
03850 if (item->text[0]) {
03851
03852 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 );
03853 } else {
03854 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 );
03855 }
03856 } else {
03857 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 );
03858 }
03859 }
03860 }
03861
03862
03863 void Item_Paint(itemDef_t *item) {
03864 vec4_t red;
03865 menuDef_t *parent = (menuDef_t*)item->parent;
03866 red[0] = red[3] = 1;
03867 red[1] = red[2] = 0;
03868
03869 if (item == NULL) {
03870 return;
03871 }
03872
03873 if (item->window.flags & WINDOW_ORBITING) {
03874 if (DC->realTime > item->window.nextTime) {
03875 float rx, ry, a, c, s, w, h;
03876
03877 item->window.nextTime = DC->realTime + item->window.offsetTime;
03878
03879 w = item->window.rectClient.w / 2;
03880 h = item->window.rectClient.h / 2;
03881 rx = item->window.rectClient.x + w - item->window.rectEffects.x;
03882 ry = item->window.rectClient.y + h - item->window.rectEffects.y;
03883 a = 3 * M_PI / 180;
03884 c = cos(a);
03885 s = sin(a);
03886 item->window.rectClient.x = (rx * c - ry * s) + item->window.rectEffects.x - w;
03887 item->window.rectClient.y = (rx * s + ry * c) + item->window.rectEffects.y - h;
03888 Item_UpdatePosition(item);
03889
03890 }
03891 }
03892
03893
03894 if (item->window.flags & WINDOW_INTRANSITION) {
03895 if (DC->realTime > item->window.nextTime) {
03896 int done = 0;
03897 item->window.nextTime = DC->realTime + item->window.offsetTime;
03898
03899 if (item->window.rectClient.x == item->window.rectEffects.x) {
03900 done++;
03901 } else {
03902 if (item->window.rectClient.x < item->window.rectEffects.x) {
03903 item->window.rectClient.x += item->window.rectEffects2.x;
03904 if (item->window.rectClient.x > item->window.rectEffects.x) {
03905 item->window.rectClient.x = item->window.rectEffects.x;
03906 done++;
03907 }
03908 } else {
03909 item->window.rectClient.x -= item->window.rectEffects2.x;
03910 if (item->window.rectClient.x < item->window.rectEffects.x) {
03911 item->window.rectClient.x = item->window.rectEffects.x;
03912 done++;
03913 }
03914 }
03915 }
03916 if (item->window.rectClient.y == item->window.rectEffects.y) {
03917 done++;
03918 } else {
03919 if (item->window.rectClient.y < item->window.rectEffects.y) {
03920 item->window.rectClient.y += item->window.rectEffects2.y;
03921 if (item->window.rectClient.y > item->window.rectEffects.y) {
03922 item->window.rectClient.y = item->window.rectEffects.y;
03923 done++;
03924 }
03925 } else {
03926 item->window.rectClient.y -= item->window.rectEffects2.y;
03927 if (item->window.rectClient.y < item->window.rectEffects.y) {
03928 item->window.rectClient.y = item->window.rectEffects.y;
03929 done++;
03930 }
03931 }
03932 }
03933 if (item->window.rectClient.w == item->window.rectEffects.w) {
03934 done++;
03935 } else {
03936 if (item->window.rectClient.w < item->window.rectEffects.w) {
03937 item->window.rectClient.w += item->window.rectEffects2.w;
03938 if (item->window.rectClient.w > item->window.rectEffects.w) {
03939 item->window.rectClient.w = item->window.rectEffects.w;
03940 done++;
03941 }
03942 } else {
03943 item->window.rectClient.w -= item->window.rectEffects2.w;
03944 if (item->window.rectClient.w < item->window.rectEffects.w) {
03945 item->window.rectClient.w = item->window.rectEffects.w;
03946 done++;
03947 }
03948 }
03949 }
03950 if (item->window.rectClient.h == item->window.rectEffects.h) {
03951 done++;
03952 } else {
03953 if (item->window.rectClient.h < item->window.rectEffects.h) {
03954 item->window.rectClient.h += item->window.rectEffects2.h;
03955 if (item->window.rectClient.h > item->window.rectEffects.h) {
03956 item->window.rectClient.h = item->window.rectEffects.h;
03957 done++;
03958 }
03959 } else {
03960 item->window.rectClient.h -= item->window.rectEffects2.h;
03961 if (item->window.rectClient.h < item->window.rectEffects.h) {
03962 item->window.rectClient.h = item->window.rectEffects.h;
03963 done++;
03964 }
03965 }
03966 }
03967
03968 Item_UpdatePosition(item);
03969
03970 if (done == 4) {
03971 item->window.flags &= ~WINDOW_INTRANSITION;
03972 }
03973
03974 }
03975 }
03976
03977 if (item->window.ownerDrawFlags && DC->ownerDrawVisible) {
03978 if (!DC->ownerDrawVisible(item->window.ownerDrawFlags)) {
03979 item->window.flags &= ~WINDOW_VISIBLE;
03980 } else {
03981 item->window.flags |= WINDOW_VISIBLE;
03982 }
03983 }
03984
03985 if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE)) {
03986 if (!Item_EnableShowViaCvar(item, CVAR_SHOW)) {
03987 return;
03988 }
03989 }
03990
03991 if (item->window.flags & WINDOW_TIMEDVISIBLE) {
03992
03993 }
03994
03995 if (!(item->window.flags & WINDOW_VISIBLE)) {
03996 return;
03997 }
03998
03999
04000 Window_Paint(&item->window, parent->fadeAmount , parent->fadeClamp, parent->fadeCycle);
04001
04002 if (debugMode) {
04003 vec4_t color;
04004 rectDef_t *r = Item_CorrectedTextRect(item);
04005 color[1] = color[3] = 1;
04006 color[0] = color[2] = 0;
04007 DC->drawRect(r->x, r->y, r->w, r->h, 1, color);
04008 }
04009
04010
04011
04012 switch (item->type) {
04013 case ITEM_TYPE_OWNERDRAW:
04014 Item_OwnerDraw_Paint(item);
04015 break;
04016 case ITEM_TYPE_TEXT:
04017 case ITEM_TYPE_BUTTON:
04018 Item_Text_Paint(item);
04019 break;
04020 case ITEM_TYPE_RADIOBUTTON:
04021 break;
04022 case ITEM_TYPE_CHECKBOX:
04023 break;
04024 case ITEM_TYPE_EDITFIELD:
04025 case ITEM_TYPE_NUMERICFIELD:
04026 Item_TextField_Paint(item);
04027 break;
04028 case ITEM_TYPE_COMBO:
04029 break;
04030 case ITEM_TYPE_LISTBOX:
04031 Item_ListBox_Paint(item);
04032 break;
04033
04034
04035
04036 case ITEM_TYPE_MODEL:
04037 Item_Model_Paint(item);
04038 break;
04039 case ITEM_TYPE_YESNO:
04040 Item_YesNo_Paint(item);
04041 break;
04042 case ITEM_TYPE_MULTI:
04043 Item_Multi_Paint(item);
04044 break;
04045 case ITEM_TYPE_BIND:
04046 Item_Bind_Paint(item);
04047 break;
04048 case ITEM_TYPE_SLIDER:
04049 Item_Slider_Paint(item);
04050 break;
04051 default:
04052 break;
04053 }
04054
04055 }
04056
04057 void Menu_Init(menuDef_t *menu) {
04058 memset(menu, 0, sizeof(menuDef_t));
04059 menu->cursorItem = -1;
04060 menu->fadeAmount = DC->Assets.fadeAmount;
04061 menu->fadeClamp = DC->Assets.fadeClamp;
04062 menu->fadeCycle = DC->Assets.fadeCycle;
04063 Window_Init(&menu->window);
04064 }
04065
04066 itemDef_t *Menu_GetFocusedItem(menuDef_t *menu) {
04067 int i;
04068 if (menu) {
04069 for (i = 0; i < menu->itemCount; i++) {
04070 if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
04071 return menu->items[i];
04072 }
04073 }
04074 }
04075 return NULL;
04076 }
04077
04078 menuDef_t *Menu_GetFocused() {
04079 int i;
04080 for (i = 0; i < menuCount; i++) {
04081 if (Menus[i].window.flags & WINDOW_HASFOCUS && Menus[i].window.flags & WINDOW_VISIBLE) {
04082 return &Menus[i];
04083 }
04084 }
04085 return NULL;
04086 }
04087
04088 void Menu_ScrollFeeder(menuDef_t *menu, int feeder, qboolean down) {
04089 if (menu) {
04090 int i;
04091 for (i = 0; i < menu->itemCount; i++) {
04092 if (menu->items[i]->special == feeder) {
04093 Item_ListBox_HandleKey(menu->items[i], (down) ? K_DOWNARROW : K_UPARROW, qtrue, qtrue);
04094 return;
04095 }
04096 }
04097 }
04098 }
04099
04100
04101
04102 void Menu_SetFeederSelection(menuDef_t *menu, int feeder, int index, const char *name) {
04103 if (menu == NULL) {
04104 if (name == NULL) {
04105 menu = Menu_GetFocused();
04106 } else {
04107 menu = Menus_FindByName(name);
04108 }
04109 }
04110
04111 if (menu) {
04112 int i;
04113 for (i = 0; i < menu->itemCount; i++) {
04114 if (menu->items[i]->special == feeder) {
04115 if (index == 0) {
04116 listBoxDef_t *listPtr = (listBoxDef_t*)menu->items[i]->typeData;
04117 listPtr->cursorPos = 0;
04118 listPtr->startPos = 0;
04119 }
04120 menu->items[i]->cursorPos = index;
04121 DC->feederSelection(menu->items[i]->special, menu->items[i]->cursorPos);
04122 return;
04123 }
04124 }
04125 }
04126 }
04127
04128 qboolean Menus_AnyFullScreenVisible() {
04129 int i;
04130 for (i = 0; i < menuCount; i++) {
04131 if (Menus[i].window.flags & WINDOW_VISIBLE && Menus[i].fullScreen) {
04132 return qtrue;
04133 }
04134 }
04135 return qfalse;
04136 }
04137
04138 menuDef_t *Menus_ActivateByName(const char *p) {
04139 int i;
04140 menuDef_t *m = NULL;
04141 menuDef_t *focus = Menu_GetFocused();
04142 for (i = 0; i < menuCount; i++) {
04143 if (Q_stricmp(Menus[i].window.name, p) == 0) {
04144 m = &Menus[i];
04145 Menus_Activate(m);
04146 if (openMenuCount < MAX_OPEN_MENUS && focus != NULL) {
04147 menuStack[openMenuCount++] = focus;
04148 }
04149 } else {
04150 Menus[i].window.flags &= ~WINDOW_HASFOCUS;
04151 }
04152 }
04153 Display_CloseCinematics();
04154 return m;
04155 }
04156
04157
04158 void Item_Init(itemDef_t *item) {
04159 memset(item, 0, sizeof(itemDef_t));
04160 item->textscale = 0.55f;
04161 Window_Init(&item->window);
04162 }
04163
04164 void Menu_HandleMouseMove(menuDef_t *menu, float x, float y) {
04165 int i, pass;
04166 qboolean focusSet = qfalse;
04167
04168 itemDef_t *overItem;
04169 if (menu == NULL) {
04170 return;
04171 }
04172
04173 if (!(menu->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
04174 return;
04175 }
04176
04177 if (itemCapture) {
04178
04179 return;
04180 }
04181
04182 if (g_waitingForKey || g_editingField) {
04183 return;
04184 }
04185
04186
04187
04188 for (pass = 0; pass < 2; pass++) {
04189 for (i = 0; i < menu->itemCount; i++) {
04190
04191
04192
04193 if (!(menu->items[i]->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
04194 continue;
04195 }
04196
04197
04198 if (menu->items[i]->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(menu->items[i], CVAR_ENABLE)) {
04199 continue;
04200 }
04201
04202 if (menu->items[i]->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(menu->items[i], CVAR_SHOW)) {
04203 continue;
04204 }
04205
04206
04207
04208 if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
04209 if (pass == 1) {
04210 overItem = menu->items[i];
04211 if (overItem->type == ITEM_TYPE_TEXT && overItem->text) {
04212 if (!Rect_ContainsPoint(Item_CorrectedTextRect(overItem), x, y)) {
04213 continue;
04214 }
04215 }
04216
04217 if (IsVisible(overItem->window.flags)) {
04218
04219 Item_MouseEnter(overItem, x, y);
04220
04221
04222
04223 if (!focusSet) {
04224 focusSet = Item_SetFocus(overItem, x, y);
04225 }
04226 }
04227 }
04228 } else if (menu->items[i]->window.flags & WINDOW_MOUSEOVER) {
04229 Item_MouseLeave(menu->items[i]);
04230 Item_SetMouseOver(menu->items[i], qfalse);
04231 }
04232 }
04233 }
04234
04235 }
04236
04237 void Menu_Paint(menuDef_t *menu, qboolean forcePaint) {
04238 int i;
04239
04240 if (menu == NULL) {
04241 return;
04242 }
04243
04244 if (!(menu->window.flags & WINDOW_VISIBLE) && !forcePaint) {
04245 return;
04246 }
04247
04248 if (menu->window.ownerDrawFlags && DC->ownerDrawVisible && !DC->ownerDrawVisible(menu->window.ownerDrawFlags)) {
04249 return;
04250 }
04251
04252 if (forcePaint) {
04253 menu->window.flags |= WINDOW_FORCED;
04254 }
04255
04256
04257 if (menu->fullScreen) {
04258
04259
04260 DC->drawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, menu->window.background );
04261 } else if (menu->window.background) {
04262
04263
04264 }
04265
04266
04267 Window_Paint(&menu->window, menu->fadeAmount, menu->fadeClamp, menu->fadeCycle );
04268
04269 for (i = 0; i < menu->itemCount; i++) {
04270 Item_Paint(menu->items[i]);
04271 }
04272
04273 if (debugMode) {
04274 vec4_t color;
04275 color[0] = color[2] = color[3] = 1;
04276 color[1] = 0;
04277 DC->drawRect(menu->window.rect.x, menu->window.rect.y, menu->window.rect.w, menu->window.rect.h, 1, color);
04278 }
04279 }
04280
04281
04282
04283
04284
04285
04286 void Item_ValidateTypeData(itemDef_t *item) {
04287 if (item->typeData) {
04288 return;
04289 }
04290
04291 if (item->type == ITEM_TYPE_LISTBOX) {
04292 item->typeData = UI_Alloc(sizeof(listBoxDef_t));
04293 memset(item->typeData, 0, sizeof(listBoxDef_t));
04294 } 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) {
04295 item->typeData = UI_Alloc(sizeof(editFieldDef_t));
04296 memset(item->typeData, 0, sizeof(editFieldDef_t));
04297 if (item->type == ITEM_TYPE_EDITFIELD) {
04298 if (!((editFieldDef_t *) item->typeData)->maxPaintChars) {
04299 ((editFieldDef_t *) item->typeData)->maxPaintChars = MAX_EDITFIELD;
04300 }
04301 }
04302 } else if (item->type == ITEM_TYPE_MULTI) {
04303 item->typeData = UI_Alloc(sizeof(multiDef_t));
04304 } else if (item->type == ITEM_TYPE_MODEL) {
04305 item->typeData = UI_Alloc(sizeof(modelDef_t));
04306 }
04307 }
04308
04309
04310
04311
04312
04313
04314
04315 #define KEYWORDHASH_SIZE 512
04316
04317 typedef struct keywordHash_s
04318 {
04319 char *keyword;
04320 qboolean (*func)(itemDef_t *item, int handle);
04321 struct keywordHash_s *next;
04322 } keywordHash_t;
04323
04324 int KeywordHash_Key(char *keyword) {
04325 int register hash, i;
04326
04327 hash = 0;
04328 for (i = 0; keyword[i] != '\0'; i++) {
04329 if (keyword[i] >= 'A' && keyword[i] <= 'Z')
04330 hash += (keyword[i] + ('a' - 'A')) * (119 + i);
04331 else
04332 hash += keyword[i] * (119 + i);
04333 }
04334 hash = (hash ^ (hash >> 10) ^ (hash >> 20)) & (KEYWORDHASH_SIZE-1);
04335 return hash;
04336 }
04337
04338 void KeywordHash_Add(keywordHash_t *table[], keywordHash_t *key) {
04339 int hash;
04340
04341 hash = KeywordHash_Key(key->keyword);
04342
04343
04344
04345
04346
04347 key->next = table[hash];
04348 table[hash] = key;
04349 }
04350
04351 keywordHash_t *KeywordHash_Find(keywordHash_t *table[], char *keyword)
04352 {
04353 keywordHash_t *key;
04354 int hash;
04355
04356 hash = KeywordHash_Key(keyword);
04357 for (key = table[hash]; key; key = key->next) {
04358 if (!Q_stricmp(key->keyword, keyword))
04359 return key;
04360 }
04361 return NULL;
04362 }
04363
04364
04365
04366
04367
04368
04369
04370
04371 qboolean ItemParse_name( itemDef_t *item, int handle ) {
04372 if (!PC_String_Parse(handle, &item->window.name)) {
04373 return qfalse;
04374 }
04375 return qtrue;
04376 }
04377
04378
04379 qboolean ItemParse_focusSound( itemDef_t *item, int handle ) {
04380 const char *temp;
04381 if (!PC_String_Parse(handle, &temp)) {
04382 return qfalse;
04383 }
04384 item->focusSound = DC->registerSound(temp, qfalse);
04385 return qtrue;
04386 }
04387
04388
04389
04390 qboolean ItemParse_text( itemDef_t *item, int handle ) {
04391 if (!PC_String_Parse(handle, &item->text)) {
04392 return qfalse;
04393 }
04394 return qtrue;
04395 }
04396
04397
04398 qboolean ItemParse_group( itemDef_t *item, int handle ) {
04399 if (!PC_String_Parse(handle, &item->window.group)) {
04400 return qfalse;
04401 }
04402 return qtrue;
04403 }
04404
04405
04406 qboolean ItemParse_asset_model( itemDef_t *item, int handle ) {
04407 const char *temp;
04408 modelDef_t *modelPtr;
04409 Item_ValidateTypeData(item);
04410 modelPtr = (modelDef_t*)item->typeData;
04411
04412 if (!PC_String_Parse(handle, &temp)) {
04413 return qfalse;
04414 }
04415 item->asset = DC->registerModel(temp);
04416 modelPtr->angle = rand() % 360;
04417 return qtrue;
04418 }
04419
04420
04421 qboolean ItemParse_asset_shader( itemDef_t *item, int handle ) {
04422 const char *temp;
04423
04424 if (!PC_String_Parse(handle, &temp)) {
04425 return qfalse;
04426 }
04427 item->asset = DC->registerShaderNoMip(temp);
04428 return qtrue;
04429 }
04430
04431
04432 qboolean ItemParse_model_origin( itemDef_t *item, int handle ) {
04433 modelDef_t *modelPtr;
04434 Item_ValidateTypeData(item);
04435 modelPtr = (modelDef_t*)item->typeData;
04436
04437 if (PC_Float_Parse(handle, &modelPtr->origin[0])) {
04438 if (PC_Float_Parse(handle, &modelPtr->origin[1])) {
04439 if (PC_Float_Parse(handle, &modelPtr->origin[2])) {
04440 return qtrue;
04441 }
04442 }
04443 }
04444 return qfalse;
04445 }
04446
04447
04448 qboolean ItemParse_model_fovx( itemDef_t *item, int handle ) {
04449 modelDef_t *modelPtr;
04450 Item_ValidateTypeData(item);
04451 modelPtr = (modelDef_t*)item->typeData;
04452
04453 if (!PC_Float_Parse(handle, &modelPtr->fov_x)) {
04454 return qfalse;
04455 }
04456 return qtrue;
04457 }
04458
04459
04460 qboolean ItemParse_model_fovy( itemDef_t *item, int handle ) {
04461 modelDef_t *modelPtr;
04462 Item_ValidateTypeData(item);
04463 modelPtr = (modelDef_t*)item->typeData;
04464
04465 if (!PC_Float_Parse(handle, &modelPtr->fov_y)) {
04466 return qfalse;
04467 }
04468 return qtrue;
04469 }
04470
04471
04472 qboolean ItemParse_model_rotation( itemDef_t *item, int handle ) {
04473 modelDef_t *modelPtr;
04474 Item_ValidateTypeData(item);
04475 modelPtr = (modelDef_t*)item->typeData;
04476
04477 if (!PC_Int_Parse(handle, &modelPtr->rotationSpeed)) {
04478 return qfalse;
04479 }
04480 return qtrue;
04481 }
04482
04483
04484 qboolean ItemParse_model_angle( itemDef_t *item, int handle ) {
04485 modelDef_t *modelPtr;
04486 Item_ValidateTypeData(item);
04487 modelPtr = (modelDef_t*)item->typeData;
04488
04489 if (!PC_Int_Parse(handle, &modelPtr->angle)) {
04490 return qfalse;
04491 }
04492 return qtrue;
04493 }
04494
04495
04496 qboolean ItemParse_rect( itemDef_t *item, int handle ) {
04497 if (!PC_Rect_Parse(handle, &item->window.rectClient)) {
04498 return qfalse;
04499 }
04500 return qtrue;
04501 }
04502
04503
04504 qboolean ItemParse_style( itemDef_t *item, int handle ) {
04505 if (!PC_Int_Parse(handle, &item->window.style)) {
04506 return qfalse;
04507 }
04508 return qtrue;
04509 }
04510
04511
04512 qboolean ItemParse_decoration( itemDef_t *item, int handle ) {
04513 item->window.flags |= WINDOW_DECORATION;
04514 return qtrue;
04515 }
04516
04517
04518 qboolean ItemParse_notselectable( itemDef_t *item, int handle ) {
04519 listBoxDef_t *listPtr;
04520 Item_ValidateTypeData(item);
04521 listPtr = (listBoxDef_t*)item->typeData;
04522 if (item->type == ITEM_TYPE_LISTBOX && listPtr) {
04523 listPtr->notselectable = qtrue;
04524 }
04525 return qtrue;
04526 }
04527
04528
04529 qboolean ItemParse_wrapped( itemDef_t *item, int handle ) {
04530 item->window.flags |= WINDOW_WRAPPED;
04531 return qtrue;
04532 }
04533
04534
04535 qboolean ItemParse_autowrapped( itemDef_t *item, int handle ) {
04536 item->window.flags |= WINDOW_AUTOWRAPPED;
04537 return qtrue;
04538 }
04539
04540
04541
04542 qboolean ItemParse_horizontalscroll( itemDef_t *item, int handle ) {
04543 item->window.flags |= WINDOW_HORIZONTAL;
04544 return qtrue;
04545 }
04546
04547
04548 qboolean ItemParse_type( itemDef_t *item, int handle ) {
04549 if (!PC_Int_Parse(handle, &item->type)) {
04550 return qfalse;
04551 }
04552 Item_ValidateTypeData(item);
04553 return qtrue;
04554 }
04555
04556
04557
04558 qboolean ItemParse_elementwidth( itemDef_t *item, int handle ) {
04559 listBoxDef_t *listPtr;
04560
04561 Item_ValidateTypeData(item);
04562 listPtr = (listBoxDef_t*)item->typeData;
04563 if (!PC_Float_Parse(handle, &listPtr->elementWidth)) {
04564 return qfalse;
04565 }
04566 return qtrue;
04567 }
04568
04569
04570
04571 qboolean ItemParse_elementheight( itemDef_t *item, int handle ) {
04572 listBoxDef_t *listPtr;
04573
04574 Item_ValidateTypeData(item);
04575 listPtr = (listBoxDef_t*)item->typeData;
04576 if (!PC_Float_Parse(handle, &listPtr->elementHeight)) {
04577 return qfalse;
04578 }
04579 return qtrue;
04580 }
04581
04582
04583 qboolean ItemParse_feeder( itemDef_t *item, int handle ) {
04584 if (!PC_Float_Parse(handle, &item->special)) {
04585 return qfalse;
04586 }
04587 return qtrue;
04588 }
04589
04590
04591
04592 qboolean ItemParse_elementtype( itemDef_t *item, int handle ) {
04593 listBoxDef_t *listPtr;
04594
04595 Item_ValidateTypeData(item);
04596 if (!item->typeData)
04597 return qfalse;
04598 listPtr = (listBoxDef_t*)item->typeData;
04599 if (!PC_Int_Parse(handle, &listPtr->elementStyle)) {
04600 return qfalse;
04601 }
04602 return qtrue;
04603 }
04604
04605
04606 qboolean ItemParse_columns( itemDef_t *item, int handle ) {
04607 int num, i;
04608 listBoxDef_t *listPtr;
04609
04610 Item_ValidateTypeData(item);
04611 if (!item->typeData)
04612 return qfalse;
04613 listPtr = (listBoxDef_t*)item->typeData;
04614 if (PC_Int_Parse(handle, &num)) {
04615 if (num > MAX_LB_COLUMNS) {
04616 num = MAX_LB_COLUMNS;
04617 }
04618 listPtr->numColumns = num;
04619 for (i = 0; i < num; i++) {
04620 int pos, width, maxChars;
04621
04622 if (PC_Int_Parse(handle, &pos) && PC_Int_Parse(handle, &width) && PC_Int_Parse(handle, &maxChars)) {
04623 listPtr->columnInfo[i].pos = pos;
04624 listPtr->columnInfo[i].width = width;
04625 listPtr->columnInfo[i].maxChars = maxChars;
04626 } else {
04627 return qfalse;
04628 }
04629 }
04630 } else {
04631 return qfalse;
04632 }
04633 return qtrue;
04634 }
04635
04636 qboolean ItemParse_border( itemDef_t *item, int handle ) {
04637 if (!PC_Int_Parse(handle, &item->window.border)) {
04638 return qfalse;
04639 }
04640 return qtrue;
04641 }
04642
04643 qboolean ItemParse_bordersize( itemDef_t *item, int handle ) {
04644 if (!PC_Float_Parse(handle, &item->window.borderSize)) {
04645 return qfalse;
04646 }
04647 return qtrue;
04648 }
04649
04650 qboolean ItemParse_visible( itemDef_t *item, int handle ) {
04651 int i;
04652
04653 if (!PC_Int_Parse(handle, &i)) {
04654 return qfalse;
04655 }
04656 if (i) {
04657 item->window.flags |= WINDOW_VISIBLE;
04658 }
04659 return qtrue;
04660 }
04661
04662 qboolean ItemParse_ownerdraw( itemDef_t *item, int handle ) {
04663 if (!PC_Int_Parse(handle, &item->window.ownerDraw)) {
04664 return qfalse;
04665 }
04666 item->type = ITEM_TYPE_OWNERDRAW;
04667 return qtrue;
04668 }
04669
04670 qboolean ItemParse_align( itemDef_t *item, int handle ) {
04671 if (!PC_Int_Parse(handle, &item->alignment)) {
04672 return qfalse;
04673 }
04674 return qtrue;
04675 }
04676
04677 qboolean ItemParse_textalign( itemDef_t *item, int handle ) {
04678 if (!PC_Int_Parse(handle, &item->textalignment)) {
04679 return qfalse;
04680 }
04681 return qtrue;
04682 }
04683
04684 qboolean ItemParse_textalignx( itemDef_t *item, int handle ) {
04685 if (!PC_Float_Parse(handle, &item->textalignx)) {
04686 return qfalse;
04687 }
04688 return qtrue;
04689 }
04690
04691 qboolean ItemParse_textaligny( itemDef_t *item, int handle ) {
04692 if (!PC_Float_Parse(handle, &item->textaligny)) {
04693 return qfalse;
04694 }
04695 return qtrue;
04696 }
04697
04698 qboolean ItemParse_textscale( itemDef_t *item, int handle ) {
04699 if (!PC_Float_Parse(handle, &item->textscale)) {
04700 return qfalse;
04701 }
04702 return qtrue;
04703 }
04704
04705 qboolean ItemParse_textstyle( itemDef_t *item, int handle ) {
04706 if (!PC_Int_Parse(handle, &item->textStyle)) {
04707 return qfalse;
04708 }
04709 return qtrue;
04710 }
04711
04712 qboolean ItemParse_backcolor( itemDef_t *item, int handle ) {
04713 int i;
04714 float f;
04715
04716 for (i = 0; i < 4; i++) {
04717 if (!PC_Float_Parse(handle, &f)) {
04718 return qfalse;
04719 }
04720 item->window.backColor[i] = f;
04721 }
04722 return qtrue;
04723 }
04724
04725 qboolean ItemParse_forecolor( itemDef_t *item, int handle ) {
04726 int i;
04727 float f;
04728
04729 for (i = 0; i < 4; i++) {
04730 if (!PC_Float_Parse(handle, &f)) {
04731 return qfalse;
04732 }
04733 item->window.foreColor[i] = f;
04734 item->window.flags |= WINDOW_FORECOLORSET;
04735 }
04736 return qtrue;
04737 }
04738
04739 qboolean ItemParse_bordercolor( itemDef_t *item, int handle ) {
04740 int i;
04741 float f;
04742
04743 for (i = 0; i < 4; i++) {
04744 if (!PC_Float_Parse(handle, &f)) {
04745 return qfalse;
04746 }
04747 item->window.borderColor[i] = f;
04748 }
04749 return qtrue;
04750 }
04751
04752 qboolean ItemParse_outlinecolor( itemDef_t *item, int handle ) {
04753 if (!PC_Color_Parse(handle, &item->window.outlineColor)){
04754 return qfalse;
04755 }
04756 return qtrue;
04757 }
04758
04759 qboolean ItemParse_background( itemDef_t *item, int handle ) {
04760 const char *temp;
04761
04762 if (!PC_String_Parse(handle, &temp)) {
04763 return qfalse;
04764 }
04765 item->window.background = DC->registerShaderNoMip(temp);
04766 return qtrue;
04767 }
04768
04769 qboolean ItemParse_cinematic( itemDef_t *item, int handle ) {
04770 if (!PC_String_Parse(handle, &item->window.cinematicName)) {
04771 return qfalse;
04772 }
04773 return qtrue;
04774 }
04775
04776 qboolean ItemParse_doubleClick( itemDef_t *item, int handle ) {
04777 listBoxDef_t *listPtr;
04778
04779 Item_ValidateTypeData(item);
04780 if (!item->typeData) {
04781 return qfalse;
04782 }
04783
04784 listPtr = (listBoxDef_t*)item->typeData;
04785
04786 if (!PC_Script_Parse(handle, &listPtr->doubleClick)) {
04787 return qfalse;
04788 }
04789 return qtrue;
04790 }
04791
04792 qboolean ItemParse_onFocus( itemDef_t *item, int handle ) {
04793 if (!PC_Script_Parse(handle, &item->onFocus)) {
04794 return qfalse;
04795 }
04796 return qtrue;
04797 }
04798
04799 qboolean ItemParse_leaveFocus( itemDef_t *item, int handle ) {
04800 if (!PC_Script_Parse(handle, &item->leaveFocus)) {
04801 return qfalse;
04802 }
04803 return qtrue;
04804 }
04805
04806 qboolean ItemParse_mouseEnter( itemDef_t *item, int handle ) {
04807 if (!PC_Script_Parse(handle, &item->mouseEnter)) {
04808 return qfalse;
04809 }
04810 return qtrue;
04811 }
04812
04813 qboolean ItemParse_mouseExit( itemDef_t *item, int handle ) {
04814 if (!PC_Script_Parse(handle, &item->mouseExit)) {
04815 return qfalse;
04816 }
04817 return qtrue;
04818 }
04819
04820 qboolean ItemParse_mouseEnterText( itemDef_t *item, int handle ) {
04821 if (!PC_Script_Parse(handle, &item->mouseEnterText)) {
04822 return qfalse;
04823 }
04824 return qtrue;
04825 }
04826
04827 qboolean ItemParse_mouseExitText( itemDef_t *item, int handle ) {
04828 if (!PC_Script_Parse(handle, &item->mouseExitText)) {
04829 return qfalse;
04830 }
04831 return qtrue;
04832 }
04833
04834 qboolean ItemParse_action( itemDef_t *item, int handle ) {
04835 if (!PC_Script_Parse(handle, &item->action)) {
04836 return qfalse;
04837 }
04838 return qtrue;
04839 }
04840
04841 qboolean ItemParse_special( itemDef_t *item, int handle ) {
04842 if (!PC_Float_Parse(handle, &item->special)) {
04843 return qfalse;
04844 }
04845 return qtrue;
04846 }
04847
04848 qboolean ItemParse_cvarTest( itemDef_t *item, int handle ) {
04849 if (!PC_String_Parse(handle, &item->cvarTest)) {
04850 return qfalse;
04851 }
04852 return qtrue;
04853 }
04854
04855 qboolean ItemParse_cvar( itemDef_t *item, int handle ) {
04856 editFieldDef_t *editPtr;
04857
04858 Item_ValidateTypeData(item);
04859 if (!PC_String_Parse(handle, &item->cvar)) {
04860 return qfalse;
04861 }
04862 if (item->typeData) {
04863 editPtr = (editFieldDef_t*)item->typeData;
04864 editPtr->minVal = -1;
04865 editPtr->maxVal = -1;
04866 editPtr->defVal = -1;
04867 }
04868 return qtrue;
04869 }
04870
04871 qboolean ItemParse_maxChars( itemDef_t *item, int handle ) {
04872 editFieldDef_t *editPtr;
04873 int maxChars;
04874
04875 Item_ValidateTypeData(item);
04876 if (!item->typeData)
04877 return qfalse;
04878
04879 if (!PC_Int_Parse(handle, &maxChars)) {
04880 return qfalse;
04881 }
04882 editPtr = (editFieldDef_t*)item->typeData;
04883 editPtr->maxChars = maxChars;
04884 return qtrue;
04885 }
04886
04887 qboolean ItemParse_maxPaintChars( itemDef_t *item, int handle ) {
04888 editFieldDef_t *editPtr;
04889 int maxChars;
04890
04891 Item_ValidateTypeData(item);
04892 if (!item->typeData)
04893 return qfalse;
04894
04895 if (!PC_Int_Parse(handle, &maxChars)) {
04896 return qfalse;
04897 }
04898 editPtr = (editFieldDef_t*)item->typeData;
04899 editPtr->maxPaintChars = maxChars;
04900 return qtrue;
04901 }
04902
04903
04904
04905 qboolean ItemParse_cvarFloat( itemDef_t *item, int handle ) {
04906 editFieldDef_t *editPtr;
04907
04908 Item_ValidateTypeData(item);
04909 if (!item->typeData)
04910 return qfalse;
04911 editPtr = (editFieldDef_t*)item->typeData;
04912 if (PC_String_Parse(handle, &item->cvar) &&
04913 PC_Float_Parse(handle, &editPtr->defVal) &&
04914 PC_Float_Parse(handle, &editPtr->minVal) &&
04915 PC_Float_Parse(handle, &editPtr->maxVal)) {
04916 return qtrue;
04917 }
04918 return qfalse;
04919 }
04920
04921 qboolean ItemParse_cvarStrList( itemDef_t *item, int handle ) {
04922 pc_token_t token;
04923 multiDef_t *multiPtr;
04924 int pass;
04925
04926 Item_ValidateTypeData(item);
04927 if (!item->typeData)
04928 return qfalse;
04929 multiPtr = (multiDef_t*)item->typeData;
04930 multiPtr->count = 0;
04931 multiPtr->strDef = qtrue;
04932
04933 if (!trap_PC_ReadToken(handle, &token))
04934 return qfalse;
04935 if (*token.string != '{') {
04936 return qfalse;
04937 }
04938
04939 pass = 0;
04940 while ( 1 ) {
04941 if (!trap_PC_ReadToken(handle, &token)) {
04942 PC_SourceError(handle, "end of file inside menu item\n");
04943 return qfalse;
04944 }
04945
04946 if (*token.string == '}') {
04947 return qtrue;
04948 }
04949
04950 if (*token.string == ',' || *token.string == ';') {
04951 continue;
04952 }
04953
04954 if (pass == 0) {
04955 multiPtr->cvarList[multiPtr->count] = String_Alloc(token.string);
04956 pass = 1;
04957 } else {
04958 multiPtr->cvarStr[multiPtr->count] = String_Alloc(token.string);
04959 pass = 0;
04960 multiPtr->count++;
04961 if (multiPtr->count >= MAX_MULTI_CVARS) {
04962 return qfalse;
04963 }
04964 }
04965
04966 }
04967 return qfalse;
04968 }
04969
04970 qboolean ItemParse_cvarFloatList( itemDef_t *item, int handle ) {
04971 pc_token_t token;
04972 multiDef_t *multiPtr;
04973
04974 Item_ValidateTypeData(item);
04975 if (!item->typeData)
04976 return qfalse;
04977 multiPtr = (multiDef_t*)item->typeData;
04978 multiPtr->count = 0;
04979 multiPtr->strDef = qfalse;
04980
04981 if (!trap_PC_ReadToken(handle, &token))
04982 return qfalse;
04983 if (*token.string != '{') {
04984 return qfalse;
04985 }
04986
04987 while ( 1 ) {
04988 if (!trap_PC_ReadToken(handle, &token)) {
04989 PC_SourceError(handle, "end of file inside menu item\n");
04990 return qfalse;
04991 }
04992
04993 if (*token.string == '}') {
04994 return qtrue;
04995 }
04996
04997 if (*token.string == ',' || *token.string == ';') {
04998 continue;
04999 }
05000
05001 multiPtr->cvarList[multiPtr->count] = String_Alloc(token.string);
05002 if (!PC_Float_Parse(handle, &multiPtr->cvarValue[multiPtr->count])) {
05003 return qfalse;
05004 }
05005
05006 multiPtr->count++;
05007 if (multiPtr->count >= MAX_MULTI_CVARS) {
05008 return qfalse;
05009 }
05010
05011 }
05012 return qfalse;
05013 }
05014
05015
05016
05017 qboolean ItemParse_addColorRange( itemDef_t *item, int handle ) {
05018 colorRangeDef_t color;
05019
05020 if (PC_Float_Parse(handle, &color.low) &&
05021 PC_Float_Parse(handle, &color.high) &&
05022 PC_Color_Parse(handle, &color.color) ) {
05023 if (item->numColors < MAX_COLOR_RANGES) {
05024 memcpy(&item->colorRanges[item->numColors], &color, sizeof(color));
05025 item->numColors++;
05026 }
05027 return qtrue;
05028 }
05029 return qfalse;
05030 }
05031
05032 qboolean ItemParse_ownerdrawFlag( itemDef_t *item, int handle ) {
05033 int i;
05034 if (!PC_Int_Parse(handle, &i)) {
05035 return qfalse;
05036 }
05037 item->window.ownerDrawFlags |= i;
05038 return qtrue;
05039 }
05040
05041 qboolean ItemParse_enableCvar( itemDef_t *item, int handle ) {
05042 if (PC_Script_Parse(handle, &item->enableCvar)) {
05043 item->cvarFlags = CVAR_ENABLE;
05044 return qtrue;
05045 }
05046 return qfalse;
05047 }
05048
05049 qboolean ItemParse_disableCvar( itemDef_t *item, int handle ) {
05050 if (PC_Script_Parse(handle, &item->enableCvar)) {
05051 item->cvarFlags = CVAR_DISABLE;
05052 return qtrue;
05053 }
05054 return qfalse;
05055 }
05056
05057 qboolean ItemParse_showCvar( itemDef_t *item, int handle ) {
05058 if (PC_Script_Parse(handle, &item->enableCvar)) {
05059 item->cvarFlags = CVAR_SHOW;
05060 return qtrue;
05061 }
05062 return qfalse;
05063 }
05064
05065 qboolean ItemParse_hideCvar( itemDef_t *item, int handle ) {
05066 if (PC_Script_Parse(handle, &item->enableCvar)) {
05067 item->cvarFlags = CVAR_HIDE;
05068 return qtrue;
05069 }
05070 return qfalse;
05071 }
05072
05073
05074 keywordHash_t itemParseKeywords[] = {
05075 {"name", ItemParse_name, NULL},
05076 {"text", ItemParse_text, NULL},
05077 {"group", ItemParse_group, NULL},
05078 {"asset_model", ItemParse_asset_model, NULL},
05079 {"asset_shader", ItemParse_asset_shader, NULL},
05080 {"model_origin", ItemParse_model_origin, NULL},
05081 {"model_fovx", ItemParse_model_fovx, NULL},
05082 {"model_fovy", ItemParse_model_fovy, NULL},
05083 {"model_rotation", ItemParse_model_rotation, NULL},
05084 {"model_angle", ItemParse_model_angle, NULL},
05085 {"rect", ItemParse_rect, NULL},
05086 {"style", ItemParse_style, NULL},
05087 {"decoration", ItemParse_decoration, NULL},
05088 {"notselectable", ItemParse_notselectable, NULL},
05089 {"wrapped", ItemParse_wrapped, NULL},
05090 {"autowrapped", ItemParse_autowrapped, NULL},
05091 {"horizontalscroll", ItemParse_horizontalscroll, NULL},
05092 {"type", ItemParse_type, NULL},
05093 {"elementwidth", ItemParse_elementwidth, NULL},
05094 {"elementheight", ItemParse_elementheight, NULL},
05095 {"feeder", ItemParse_feeder, NULL},
05096 {"elementtype", ItemParse_elementtype, NULL},
05097 {"columns", ItemParse_columns, NULL},
05098 {"border", ItemParse_border, NULL},
05099 {"bordersize", ItemParse_bordersize, NULL},
05100 {"visible", ItemParse_visible, NULL},
05101 {"ownerdraw", ItemParse_ownerdraw, NULL},
05102 {"align", ItemParse_align, NULL},
05103 {"textalign", ItemParse_textalign, NULL},
05104 {"textalignx", ItemParse_textalignx, NULL},
05105 {"textaligny", ItemParse_textaligny, NULL},
05106 {"textscale", ItemParse_textscale, NULL},
05107 {"textstyle", ItemParse_textstyle, NULL},
05108 {"backcolor", ItemParse_backcolor, NULL},
05109 {"forecolor", ItemParse_forecolor, NULL},
05110 {"bordercolor", ItemParse_bordercolor, NULL},
05111 {"outlinecolor", ItemParse_outlinecolor, NULL},
05112 {"background", ItemParse_background, NULL},
05113 {"onFocus", ItemParse_onFocus, NULL},
05114 {"leaveFocus", ItemParse_leaveFocus, NULL},
05115 {"mouseEnter", ItemParse_mouseEnter, NULL},
05116 {"mouseExit", ItemParse_mouseExit, NULL},
05117 {"mouseEnterText", ItemParse_mouseEnterText, NULL},
05118 {"mouseExitText", ItemParse_mouseExitText, NULL},
05119 {"action", ItemParse_action, NULL},
05120 {"special", ItemParse_special, NULL},
05121 {"cvar", ItemParse_cvar, NULL},
05122 {"maxChars", ItemParse_maxChars, NULL},
05123 {"maxPaintChars", ItemParse_maxPaintChars, NULL},
05124 {"focusSound", ItemParse_focusSound, NULL},
05125 {"cvarFloat", ItemParse_cvarFloat, NULL},
05126 {"cvarStrList", ItemParse_cvarStrList, NULL},
05127 {"cvarFloatList", ItemParse_cvarFloatList, NULL},
05128 {"addColorRange", ItemParse_addColorRange, NULL},
05129 {"ownerdrawFlag", ItemParse_ownerdrawFlag, NULL},
05130 {"enableCvar", ItemParse_enableCvar, NULL},
05131 {"cvarTest", ItemParse_cvarTest, NULL},
05132 {"disableCvar", ItemParse_disableCvar, NULL},
05133 {"showCvar", ItemParse_showCvar, NULL},
05134 {"hideCvar", ItemParse_hideCvar, NULL},
05135 {"cinematic", ItemParse_cinematic, NULL},
05136 {"doubleclick", ItemParse_doubleClick, NULL},
05137 {NULL, NULL, NULL}
05138 };
05139
05140 keywordHash_t *itemParseKeywordHash[KEYWORDHASH_SIZE];
05141
05142
05143
05144
05145
05146
05147 void Item_SetupKeywordHash(void) {
05148 int i;
05149
05150 memset(itemParseKeywordHash, 0, sizeof(itemParseKeywordHash));
05151 for (i = 0; itemParseKeywords[i].keyword; i++) {
05152 KeywordHash_Add(itemParseKeywordHash, &itemParseKeywords[i]);
05153 }
05154 }
05155
05156
05157
05158
05159
05160
05161 qboolean Item_Parse(int handle, itemDef_t *item) {
05162 pc_token_t token;
05163 keywordHash_t *key;
05164
05165
05166 if (!trap_PC_ReadToken(handle, &token))
05167 return qfalse;
05168 if (*token.string != '{') {
05169 return qfalse;
05170 }
05171 while ( 1 ) {
05172 if (!trap_PC_ReadToken(handle, &token)) {
05173 PC_SourceError(handle, "end of file inside menu item\n");
05174 return qfalse;
05175 }
05176
05177 if (*token.string == '}') {
05178 return qtrue;
05179 }
05180
05181 key = KeywordHash_Find(itemParseKeywordHash, token.string);
05182 if (!key) {
05183 PC_SourceError(handle, "unknown menu item keyword %s", token.string);
05184 continue;
05185 }
05186 if ( !key->func(item, handle) ) {
05187 PC_SourceError(handle, "couldn't parse menu item keyword %s", token.string);
05188 return qfalse;
05189 }
05190 }
05191 return qfalse;
05192 }
05193
05194
05195
05196
05197 void Item_InitControls(itemDef_t *item) {
05198 if (item == NULL) {
05199 return;
05200 }
05201 if (item->type == ITEM_TYPE_LISTBOX) {
05202 listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
05203 item->cursorPos = 0;
05204 if (listPtr) {
05205 listPtr->cursorPos = 0;
05206 listPtr->startPos = 0;
05207 listPtr->endPos = 0;
05208 listPtr->cursorPos = 0;
05209 }
05210 }
05211 }
05212
05213
05214
05215
05216
05217
05218
05219 qboolean MenuParse_font( itemDef_t *item, int handle ) {
05220 menuDef_t *menu = (menuDef_t*)item;
05221 if (!PC_String_Parse(handle, &menu->font)) {
05222 return qfalse;
05223 }
05224 if (!DC->Assets.fontRegistered) {
05225 DC->registerFont(menu->font, 48, &DC->Assets.textFont);
05226 DC->Assets.fontRegistered = qtrue;
05227 }
05228 return qtrue;
05229 }
05230
05231 qboolean MenuParse_name( itemDef_t *item, int handle ) {
05232 menuDef_t *menu = (menuDef_t*)item;
05233 if (!PC_String_Parse(handle, &menu->window.name)) {
05234 return qfalse;
05235 }
05236 if (Q_stricmp(menu->window.name, "main") == 0) {
05237
05238
05239 }
05240 return qtrue;
05241 }
05242
05243 qboolean MenuParse_fullscreen( itemDef_t *item, int handle ) {
05244 menuDef_t *menu = (menuDef_t*)item;
05245 if (!PC_Int_Parse(handle, (int*) &menu->fullScreen)) {
05246 return qfalse;
05247 }
05248 return qtrue;
05249 }
05250
05251 qboolean MenuParse_rect( itemDef_t *item, int handle ) {
05252 menuDef_t *menu = (menuDef_t*)item;
05253 if (!PC_Rect_Parse(handle, &menu->window.rect)) {
05254 return qfalse;
05255 }
05256 return qtrue;
05257 }
05258
05259 qboolean MenuParse_style( itemDef_t *item, int handle ) {
05260 menuDef_t *menu = (menuDef_t*)item;
05261 if (!PC_Int_Parse(handle, &menu->window.style)) {
05262 return qfalse;
05263 }
05264 return qtrue;
05265 }
05266
05267 qboolean MenuParse_visible( itemDef_t *item, int handle ) {
05268 int i;
05269 menuDef_t *menu = (menuDef_t*)item;
05270
05271 if (!PC_Int_Parse(handle, &i)) {
05272 return qfalse;
05273 }
05274 if (i) {
05275 menu->window.flags |= WINDOW_VISIBLE;
05276 }
05277 return qtrue;
05278 }
05279
05280 qboolean MenuParse_onOpen( itemDef_t *item, int handle ) {
05281 menuDef_t *menu = (menuDef_t*)item;
05282 if (!PC_Script_Parse(handle, &menu->onOpen)) {
05283 return qfalse;
05284 }
05285 return qtrue;
05286 }
05287
05288 qboolean MenuParse_onClose( itemDef_t *item, int handle ) {
05289 menuDef_t *menu = (menuDef_t*)item;
05290 if (!PC_Script_Parse(handle, &menu->onClose)) {
05291 return qfalse;
05292 }
05293 return qtrue;
05294 }
05295
05296 qboolean MenuParse_onESC( itemDef_t *item, int handle ) {
05297 menuDef_t *menu = (menuDef_t*)item;
05298 if (!PC_Script_Parse(handle, &menu->onESC)) {
05299 return qfalse;
05300 }
05301 return qtrue;
05302 }
05303
05304
05305
05306 qboolean MenuParse_border( itemDef_t *item, int handle ) {
05307 menuDef_t *menu = (menuDef_t*)item;
05308 if (!PC_Int_Parse(handle, &menu->window.border)) {
05309 return qfalse;
05310 }
05311 return qtrue;
05312 }
05313
05314 qboolean MenuParse_borderSize( itemDef_t *item, int handle ) {
05315 menuDef_t *menu = (menuDef_t*)item;
05316 if (!PC_Float_Parse(handle, &menu->window.borderSize)) {
05317 return qfalse;
05318 }
05319 return qtrue;
05320 }
05321
05322 qboolean MenuParse_backcolor( itemDef_t *item, int handle ) {
05323 int i;
05324 float f;
05325 menuDef_t *menu = (menuDef_t*)item;
05326
05327 for (i = 0; i < 4; i++) {
05328 if (!PC_Float_Parse(handle, &f)) {
05329 return qfalse;
05330 }
05331 menu->window.backColor[i] = f;
05332 }
05333 return qtrue;
05334 }
05335
05336 qboolean MenuParse_forecolor( itemDef_t *item, int handle ) {
05337 int i;
05338 float f;
05339 menuDef_t *menu = (menuDef_t*)item;
05340
05341 for (i = 0; i < 4; i++) {
05342 if (!PC_Float_Parse(handle, &f)) {
05343 return qfalse;
05344 }
05345 menu->window.foreColor[i] = f;
05346 menu->window.flags |= WINDOW_FORECOLORSET;
05347 }
05348 return qtrue;
05349 }
05350
05351 qboolean MenuParse_bordercolor( itemDef_t *item, int handle ) {
05352 int i;
05353 float f;
05354 menuDef_t *menu = (menuDef_t*)item;
05355
05356 for (i = 0; i < 4; i++) {
05357 if (!PC_Float_Parse(handle, &f)) {
05358 return qfalse;
05359 }
05360 menu->window.borderColor[i] = f;
05361 }
05362 return qtrue;
05363 }
05364
05365 qboolean MenuParse_focuscolor( itemDef_t *item, int handle ) {
05366 int i;
05367 float f;
05368 menuDef_t *menu = (menuDef_t*)item;
05369
05370 for (i = 0; i < 4; i++) {
05371 if (!PC_Float_Parse(handle, &f)) {
05372 return qfalse;
05373 }
05374 menu->focusColor[i] = f;
05375 }
05376 return qtrue;
05377 }
05378
05379 qboolean MenuParse_disablecolor( itemDef_t *item, int handle ) {
05380 int i;
05381 float f;
05382 menuDef_t *menu = (menuDef_t*)item;
05383 for (i = 0; i < 4; i++) {
05384 if (!PC_Float_Parse(handle, &f)) {
05385 return qfalse;
05386 }
05387 menu->disableColor[i] = f;
05388 }
05389 return qtrue;
05390 }
05391
05392
05393 qboolean MenuParse_outlinecolor( itemDef_t *item, int handle ) {
05394 menuDef_t *menu = (menuDef_t*)item;
05395 if (!PC_Color_Parse(handle, &menu->window.outlineColor)){
05396 return qfalse;
05397 }
05398 return qtrue;
05399 }
05400
05401 qboolean MenuParse_background( itemDef_t *item, int handle ) {
05402 const char *buff;
05403 menuDef_t *menu = (menuDef_t*)item;
05404
05405 if (!PC_String_Parse(handle, &buff)) {
05406 return qfalse;
05407 }
05408 menu->window.background = DC->registerShaderNoMip(buff);
05409 return qtrue;
05410 }
05411
05412 qboolean MenuParse_cinematic( itemDef_t *item, int handle ) {
05413 menuDef_t *menu = (menuDef_t*)item;
05414
05415 if (!PC_String_Parse(handle, &menu->window.cinematicName)) {
05416 return qfalse;
05417 }
05418 return qtrue;
05419 }
05420
05421 qboolean MenuParse_ownerdrawFlag( itemDef_t *item, int handle ) {
05422 int i;
05423 menuDef_t *menu = (menuDef_t*)item;
05424
05425 if (!PC_Int_Parse(handle, &i)) {
05426 return qfalse;
05427 }
05428 menu->window.ownerDrawFlags |= i;
05429 return qtrue;
05430 }
05431
05432 qboolean MenuParse_ownerdraw( itemDef_t *item, int handle ) {
05433 menuDef_t *menu = (menuDef_t*)item;
05434
05435 if (!PC_Int_Parse(handle, &menu->window.ownerDraw)) {
05436 return qfalse;
05437 }
05438 return qtrue;
05439 }
05440
05441
05442
05443 qboolean MenuParse_popup( itemDef_t *item, int handle ) {
05444 menuDef_t *menu = (menuDef_t*)item;
05445 menu->window.flags |= WINDOW_POPUP;
05446 return qtrue;
05447 }
05448
05449
05450 qboolean MenuParse_outOfBounds( itemDef_t *item, int handle ) {
05451 menuDef_t *menu = (menuDef_t*)item;
05452
05453 menu->window.flags |= WINDOW_OOB_CLICK;
05454 return qtrue;
05455 }
05456
05457 qboolean MenuParse_soundLoop( itemDef_t *item, int handle ) {
05458 menuDef_t *menu = (menuDef_t*)item;
05459
05460 if (!PC_String_Parse(handle, &menu->soundName)) {
05461 return qfalse;
05462 }
05463 return qtrue;
05464 }
05465
05466 qboolean MenuParse_fadeClamp( itemDef_t *item, int handle ) {
05467 menuDef_t *menu = (menuDef_t*)item;
05468
05469 if (!PC_Float_Parse(handle, &menu->fadeClamp)) {
05470 return qfalse;
05471 }
05472 return qtrue;
05473 }
05474
05475 qboolean MenuParse_fadeAmount( itemDef_t *item, int handle ) {
05476 menuDef_t *menu = (menuDef_t*)item;
05477
05478 if (!PC_Float_Parse(handle, &menu->fadeAmount)) {
05479 return qfalse;
05480 }
05481 return qtrue;
05482 }
05483
05484
05485 qboolean MenuParse_fadeCycle( itemDef_t *item, int handle ) {
05486 menuDef_t *menu = (menuDef_t*)item;
05487
05488 if (!PC_Int_Parse(handle, &menu->fadeCycle)) {
05489 return qfalse;
05490 }
05491 return qtrue;
05492 }
05493
05494
05495 qboolean MenuParse_itemDef( itemDef_t *item, int handle ) {
05496 menuDef_t *menu = (menuDef_t*)item;
05497 if (menu->itemCount < MAX_MENUITEMS) {
05498 menu->items[menu->itemCount] = UI_Alloc(sizeof(itemDef_t));
05499 Item_Init(menu->items[menu->itemCount]);
05500 if (!Item_Parse(handle, menu->items[menu->itemCount])) {
05501 return qfalse;
05502 }
05503 Item_InitControls(menu->items[menu->itemCount]);
05504 menu->items[menu->itemCount++]->parent = menu;
05505 }
05506 return qtrue;
05507 }
05508
05509 keywordHash_t menuParseKeywords[] = {
05510 {"font", MenuParse_font, NULL},
05511 {"name", MenuParse_name, NULL},
05512 {"fullscreen", MenuParse_fullscreen, NULL},
05513 {"rect", MenuParse_rect, NULL},
05514 {"style", MenuParse_style, NULL},
05515 {"visible", MenuParse_visible, NULL},
05516 {"onOpen", MenuParse_onOpen, NULL},
05517 {"onClose", MenuParse_onClose, NULL},
05518 {"onESC", MenuParse_onESC, NULL},
05519 {"border", MenuParse_border, NULL},
05520 {"borderSize", MenuParse_borderSize, NULL},
05521 {"backcolor", MenuParse_backcolor, NULL},
05522 {"forecolor", MenuParse_forecolor, NULL},
05523 {"bordercolor", MenuParse_bordercolor, NULL},
05524 {"focuscolor", MenuParse_focuscolor, NULL},
05525 {"disablecolor", MenuParse_disablecolor, NULL},
05526 {"outlinecolor", MenuParse_outlinecolor, NULL},
05527 {"background", MenuParse_background, NULL},
05528 {"ownerdraw", MenuParse_ownerdraw, NULL},
05529 {"ownerdrawFlag", MenuParse_ownerdrawFlag, NULL},
05530 {"outOfBoundsClick", MenuParse_outOfBounds, NULL},
05531 {"soundLoop", MenuParse_soundLoop, NULL},
05532 {"itemDef", MenuParse_itemDef, NULL},
05533 {"cinematic", MenuParse_cinematic, NULL},
05534 {"popup", MenuParse_popup, NULL},
05535 {"fadeClamp", MenuParse_fadeClamp, NULL},
05536 {"fadeCycle", MenuParse_fadeCycle, NULL},
05537 {"fadeAmount", MenuParse_fadeAmount, NULL},
05538 {NULL, NULL, NULL}
05539 };
05540
05541 keywordHash_t *menuParseKeywordHash[KEYWORDHASH_SIZE];
05542
05543
05544
05545
05546
05547
05548 void Menu_SetupKeywordHash(void) {
05549 int i;
05550
05551 memset(menuParseKeywordHash, 0, sizeof(menuParseKeywordHash));
05552 for (i = 0; menuParseKeywords[i].keyword; i++) {
05553 KeywordHash_Add(menuParseKeywordHash, &menuParseKeywords[i]);
05554 }
05555 }
05556
05557
05558
05559
05560
05561
05562 qboolean Menu_Parse(int handle, menuDef_t *menu) {
05563 pc_token_t token;
05564 keywordHash_t *key;
05565
05566 if (!trap_PC_ReadToken(handle, &token))
05567 return qfalse;
05568 if (*token.string != '{') {
05569 return qfalse;
05570 }
05571
05572 while ( 1 ) {
05573
05574 memset(&token, 0, sizeof(pc_token_t));
05575 if (!trap_PC_ReadToken(handle, &token)) {
05576 PC_SourceError(handle, "end of file inside menu\n");
05577 return qfalse;
05578 }
05579
05580 if (*token.string == '}') {
05581 return qtrue;
05582 }
05583
05584 key = KeywordHash_Find(menuParseKeywordHash, token.string);
05585 if (!key) {
05586 PC_SourceError(handle, "unknown menu keyword %s", token.string);
05587 continue;
05588 }
05589 if ( !key->func((itemDef_t*)menu, handle) ) {
05590 PC_SourceError(handle, "couldn't parse menu keyword %s", token.string);
05591 return qfalse;
05592 }
05593 }
05594 return qfalse;
05595 }
05596
05597
05598
05599
05600
05601
05602 void Menu_New(int handle) {
05603 menuDef_t *menu = &Menus[menuCount];
05604
05605 if (menuCount < MAX_MENUS) {
05606 Menu_Init(menu);
05607 if (Menu_Parse(handle, menu)) {
05608 Menu_PostParse(menu);
05609 menuCount++;
05610 }
05611 }
05612 }
05613
05614 int Menu_Count() {
05615 return menuCount;
05616 }
05617
05618 void Menu_PaintAll() {
05619 int i;
05620 if (captureFunc) {
05621 captureFunc(captureData);
05622 }
05623
05624 for (i = 0; i < Menu_Count(); i++) {
05625 Menu_Paint(&Menus[i], qfalse);
05626 }
05627
05628 if (debugMode) {
05629 vec4_t v = {1, 1, 1, 1};
05630 DC->drawText(5, 25, .5, v, va("fps: %f", DC->FPS), 0, 0, 0);
05631 }
05632 }
05633
05634 void Menu_Reset() {
05635 menuCount = 0;
05636 }
05637
05638 displayContextDef_t *Display_GetContext() {
05639 return DC;
05640 }
05641
05642 #ifndef MISSIONPACK // bk001206
05643 static float captureX;
05644 static float captureY;
05645 #endif
05646
05647 void *Display_CaptureItem(int x, int y) {
05648 int i;
05649
05650 for (i = 0; i < menuCount; i++) {
05651
05652
05653 if (Rect_ContainsPoint(&Menus[i].window.rect, x, y)) {
05654 return &Menus[i];
05655 }
05656 }
05657 return NULL;
05658 }
05659
05660
05661
05662 qboolean Display_MouseMove(void *p, int x, int y) {
05663 int i;
05664 menuDef_t *menu = p;
05665
05666 if (menu == NULL) {
05667 menu = Menu_GetFocused();
05668 if (menu) {
05669 if (menu->window.flags & WINDOW_POPUP) {
05670 Menu_HandleMouseMove(menu, x, y);
05671 return qtrue;
05672 }
05673 }
05674 for (i = 0; i < menuCount; i++) {
05675 Menu_HandleMouseMove(&Menus[i], x, y);
05676 }
05677 } else {
05678 menu->window.rect.x += x;
05679 menu->window.rect.y += y;
05680 Menu_UpdatePosition(menu);
05681 }
05682 return qtrue;
05683
05684 }
05685
05686 int Display_CursorType(int x, int y) {
05687 int i;
05688 for (i = 0; i < menuCount; i++) {
05689 rectDef_t r2;
05690 r2.x = Menus[i].window.rect.x - 3;
05691 r2.y = Menus[i].window.rect.y - 3;
05692 r2.w = r2.h = 7;
05693 if (Rect_ContainsPoint(&r2, x, y)) {
05694 return CURSOR_SIZER;
05695 }
05696 }
05697 return CURSOR_ARROW;
05698 }
05699
05700
05701 void Display_HandleKey(int key, qboolean down, int x, int y) {
05702 menuDef_t *menu = Display_CaptureItem(x, y);
05703 if (menu == NULL) {
05704 menu = Menu_GetFocused();
05705 }
05706 if (menu) {
05707 Menu_HandleKey(menu, key, down );
05708 }
05709 }
05710
05711 static void Window_CacheContents(windowDef_t *window) {
05712 if (window) {
05713 if (window->cinematicName) {
05714 int cin = DC->playCinematic(window->cinematicName, 0, 0, 0, 0);
05715 DC->stopCinematic(cin);
05716 }
05717 }
05718 }
05719
05720
05721 static void Item_CacheContents(itemDef_t *item) {
05722 if (item) {
05723 Window_CacheContents(&item->window);
05724 }
05725
05726 }
05727
05728 static void Menu_CacheContents(menuDef_t *menu) {
05729 if (menu) {
05730 int i;
05731 Window_CacheContents(&menu->window);
05732 for (i = 0; i < menu->itemCount; i++) {
05733 Item_CacheContents(menu->items[i]);
05734 }
05735
05736 if (menu->soundName && *menu->soundName) {
05737 DC->registerSound(menu->soundName, qfalse);
05738 }
05739 }
05740
05741 }
05742
05743 void Display_CacheAll() {
05744 int i;
05745 for (i = 0; i < menuCount; i++) {
05746 Menu_CacheContents(&Menus[i]);
05747 }
05748 }
05749
05750
05751 static qboolean Menu_OverActiveItem(menuDef_t *menu, float x, float y) {
05752 if (menu && menu->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED)) {
05753 if (Rect_ContainsPoint(&menu->window.rect, x, y)) {
05754 int i;
05755 for (i = 0; i < menu->itemCount; i++) {
05756
05757
05758
05759 if (!(menu->items[i]->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
05760 continue;
05761 }
05762
05763 if (menu->items[i]->window.flags & WINDOW_DECORATION) {
05764 continue;
05765 }
05766
05767 if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
05768 itemDef_t *overItem = menu->items[i];
05769 if (overItem->type == ITEM_TYPE_TEXT && overItem->text) {
05770 if (Rect_ContainsPoint(Item_CorrectedTextRect(overItem), x, y)) {
05771 return qtrue;
05772 } else {
05773 continue;
05774 }
05775 } else {
05776 return qtrue;
05777 }
05778 }
05779 }
05780
05781 }
05782 }
05783 return qfalse;
05784 }
05785