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,