00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <math.h>
00026
00027 #include "ui_node_radar.h"
00028 #include "ui_node_abstractnode.h"
00029 #include "../ui_render.h"
00030 #include "../ui_timer.h"
00031 #include "../ui_windows.h"
00032 #include "../ui_main.h"
00033 #include "../ui_input.h"
00034
00035 #include "../../client.h"
00036 #include "../../battlescape/cl_localentity.h"
00037 #include "../../battlescape/cl_hud.h"
00038 #include "../../renderer/r_draw.h"
00039 #include "../../renderer/r_misc.h"
00040 #include "../../../shared/parse.h"
00041
00043 typedef struct hudRadarImage_s {
00044
00045 char *name;
00046 char *path[PATHFINDING_HEIGHT];
00047 int x, y;
00048 int width, height;
00050
00051 float mapX;
00052 float mapY;
00053 float mapWidth;
00054 float mapHeight;
00055
00056 qboolean isTile;
00057 int gridX, gridY;
00058 int gridHeight;
00059 int gridWidth;
00060 int maxlevel;
00061 } hudRadarImage_t;
00062
00063 typedef struct hudRadar_s {
00065 float gridHeight, gridWidth;
00066 vec2_t gridMin, gridMax;
00067 char base[MAX_QPATH];
00068 int numImages;
00069 hudRadarImage_t images[MAX_MAPTILES];
00077 vec3_t a, b, c;
00079 int x, y;
00081 int w, h;
00082 } hudRadar_t;
00083
00084 static hudRadar_t radar;
00085
00086 static void UI_FreeRadarImages (void)
00087 {
00088 int i, j;
00089
00090 for (i = 0; i < radar.numImages; i++) {
00091 Mem_Free(radar.images[i].name);
00092 for (j = 0; j < radar.images[i].maxlevel; j++)
00093 Mem_Free(radar.images[i].path[j]);
00094 }
00095 memset(&radar, 0, sizeof(radar));
00096 }
00097
00107 static void UI_BuildRadarImageList (const char *tiles, const char *pos)
00108 {
00109 const float mapMidX = (cl.mapData->mapMax[0] + cl.mapData->mapMin[0]) * 0.5;
00110 const float mapMidY = (cl.mapData->mapMax[1] + cl.mapData->mapMin[1]) * 0.5;
00111
00112
00113 while (tiles) {
00114 int i;
00115 vec3_t sh;
00116 char name[MAX_VAR];
00117 hudRadarImage_t *image;
00118
00119 const char *token = Com_Parse(&tiles);
00120 if (!tiles) {
00121
00122 return;
00123 }
00124
00125
00126 if (token[0] == '-') {
00127 Q_strncpyz(radar.base, token + 1, sizeof(radar.base));
00128 continue;
00129 }
00130
00131
00132 if (token[0] == '+')
00133 token++;
00134 Com_sprintf(name, sizeof(name), "%s%s", radar.base, token);
00135
00136 image = &radar.images[radar.numImages++];
00137 image->name = Mem_StrDup(name);
00138
00139 image->isTile = pos && pos[0];
00140 if (!image->isTile)
00141
00142 return;
00143
00144
00145 for (i = 0; i < 3; i++) {
00146 token = Com_Parse(&pos);
00147 if (!pos)
00148 Com_Error(ERR_DROP, "UI_BuildRadarImageList: invalid positions\n");
00149 sh[i] = atoi(token);
00150 }
00151 image->gridX = sh[0];
00152 image->gridY = sh[1];
00153 image->mapX = mapMidX + sh[0] * UNIT_SIZE;
00154 image->mapY = mapMidY + sh[1] * UNIT_SIZE;
00155 Com_Printf("radar %s %dx%d\n", name, image->gridX, image->gridY);
00156
00157 if (radar.gridMin[0] > sh[0])
00158 radar.gridMin[0] = sh[0];
00159 if (radar.gridMin[1] > sh[1])
00160 radar.gridMin[1] = sh[1];
00161 }
00162 }
00163
00170 static void UI_GetRadarWidth (const uiNode_t *node, vec2_t gridSize)
00171 {
00172 int j;
00173 int tileWidth[2];
00174 int tileHeight[2];
00175 int secondTileGridX;
00176 int secondTileGridY;
00177 float ratioConversion;
00178 const int ROUNDING_PIXEL = 1;
00182
00183 radar.gridMax[0] = radar.gridMin[0];
00184 radar.gridMax[1] = radar.gridMin[1];
00185
00186
00187 secondTileGridX = radar.gridMin[0] + 1000;
00188 secondTileGridY = radar.gridMin[1] + 1000;
00189
00190
00191 Vector2Set(tileWidth, 0, 0);
00192 Vector2Set(tileHeight, 0, 0);
00193
00194 for (j = 0; j < radar.numImages; j++) {
00195 const hudRadarImage_t *image = &radar.images[j];
00196
00197 assert(image->gridX >= radar.gridMin[0]);
00198 assert(image->gridY >= radar.gridMin[1]);
00199
00200
00201
00202
00203
00204
00205
00206
00207 if (image->gridX == radar.gridMin[0]) {
00208
00209 if (image->gridY > radar.gridMax[1]) {
00210 tileHeight[1] = image->height;
00211 radar.gridMax[1] = image->gridY;
00212 }
00213 if (image->gridY == radar.gridMin[1]) {
00214
00215 tileHeight[0] = image->height;
00216 tileWidth[0] = image->width;
00217 } else if (image->gridY < secondTileGridY)
00218 secondTileGridY = image->gridY;
00219 }
00220 if (image->gridY == radar.gridMin[1]) {
00221
00222 if (image->gridX > radar.gridMax[0]) {
00223 tileWidth[1] = image->width;
00224 radar.gridMax[0] = image->gridX;
00225 } else if (image->gridX < secondTileGridX)
00226 secondTileGridX = image->gridX;
00227 }
00228 }
00229
00230
00231 if (!tileHeight[1])
00232 tileHeight[1] = tileHeight[0];
00233 if (!tileWidth[1])
00234 tileWidth[1] = tileWidth[0];
00235
00236
00237
00238
00239
00240 ratioConversion = max((secondTileGridX - radar.gridMin[0]) / (tileWidth[0] - ROUNDING_PIXEL),
00241 (secondTileGridY - radar.gridMin[1]) / (tileHeight[0] - ROUNDING_PIXEL));
00242
00243
00244 radar.w = floor((radar.gridMax[0] - radar.gridMin[0]) / ratioConversion) + tileWidth[1];
00245 radar.h = floor((radar.gridMax[1] - radar.gridMin[1]) / ratioConversion) + tileHeight[1];
00246
00247 Vector2Set(gridSize, round(radar.w * ratioConversion), round(radar.h * ratioConversion));
00248 }
00249
00250 static const char *imageExtensions[] = {
00251 "tga", "jpg", "png", NULL
00252 };
00253
00254 static qboolean UI_CheckRadarImage (const char *imageName, const int level)
00255 {
00256 const char **ext = imageExtensions;
00257
00258 while (*ext) {
00259 if (FS_CheckFile("pics/radars/%s_%i.%s", imageName, level, *ext) > 0)
00260 return qtrue;
00261 ext++;
00262 }
00263
00264 return qfalse;
00265 }
00266
00272 static void UI_InitRadar (const uiNode_t *node)
00273 {
00274 int i, j;
00275 const vec3_t offset = {MAP_SIZE_OFFSET, MAP_SIZE_OFFSET, MAP_SIZE_OFFSET};
00276 float distAB, distBC;
00277 vec2_t gridSize;
00278 vec2_t nodepos;
00279 vec2_t min;
00280 vec2_t max;
00281
00282 UI_FreeRadarImages();
00283 UI_BuildRadarImageList(CL_GetConfigString(CS_TILES), CL_GetConfigString(CS_POSITIONS));
00284
00285 UI_GetNodeAbsPos(node, nodepos);
00286 radar.x = nodepos[0] + node->size[0] / 2;
00287 radar.y = nodepos[1] + node->size[1] / 2;
00288
00289
00290 for (j = 0; j < radar.numImages; j++) {
00291 hudRadarImage_t *tile = &radar.images[j];
00292
00293 for (i = 0; i < PATHFINDING_HEIGHT; i++) {
00294 char imagePath[MAX_QPATH];
00295 const image_t *image;
00296 if (!UI_CheckRadarImage(tile->name, i + 1)) {
00297 if (i == 0) {
00298
00299 Com_Printf("No radar images for map: '%s'\n", tile->name);
00300 radar.numImages = 0;
00301 return;
00302 }
00303 continue;
00304 }
00305
00306 Com_sprintf(imagePath, sizeof(imagePath), "radars/%s_%i", tile->name, i + 1);
00307 tile->path[i] = Mem_StrDup(imagePath);
00308 tile->maxlevel++;
00309
00310 image = R_FindImage(va("pics/%s", tile->path[i]), it_pic);
00311 tile->width = image->width;
00312 tile->height = image->height;
00313 if (tile->isTile) {
00314 tile->gridWidth = round(image->width / 94.0f);
00315 tile->gridHeight = round(image->height / 94.0f);
00316 tile->mapWidth = tile->gridWidth * 8 * UNIT_SIZE;
00317 tile->mapHeight = tile->gridHeight * 8 * UNIT_SIZE;
00318 } else {
00319 tile->mapX = cl.mapData->mapMin[0];
00320 tile->mapY = cl.mapData->mapMin[1];
00321 tile->mapWidth = cl.mapData->mapMax[0] - cl.mapData->mapMin[0];
00322 tile->mapHeight = cl.mapData->mapMax[1] - cl.mapData->mapMin[1];
00323 }
00324 }
00325 if (tile->isTile) {
00326 tile->mapY = cl.mapData->mapMax[1] - tile->mapY - tile->mapHeight;
00327 }
00328 }
00329
00330
00331 Vector2Copy(cl.mapData->mapMax, min);
00332 Vector2Copy(cl.mapData->mapMin, max);
00333 for (j = 0; j < radar.numImages; j++) {
00334 hudRadarImage_t *tile = &radar.images[j];
00335 if (tile->mapX < min[0])
00336 min[0] = tile->mapX;
00337 if (tile->mapY < min[1])
00338 min[1] = tile->mapY;
00339 if (tile->mapX + tile->mapWidth > max[0])
00340 max[0] = tile->mapX + tile->mapWidth;
00341 if (tile->mapY + tile->mapHeight > max[1])
00342 max[1] = tile->mapY + tile->mapHeight;
00343 }
00344
00345 min[0] = cl.mapData->mapMin[0] + (cl.mapData->mapMax[0] - cl.mapData->mapMin[0] - (max[0] - min[0])) * 0.5 - min[0];
00346 min[1] = cl.mapData->mapMin[1] + (cl.mapData->mapMax[1] - cl.mapData->mapMin[1] - (max[1] - min[1])) * 0.5 - min[1];
00347 for (j = 0; j < radar.numImages; j++) {
00348 hudRadarImage_t *tile = &radar.images[j];
00349 tile->mapX += min[0];
00350 tile->mapY += min[1];
00351 }
00352
00353
00354 VectorSubtract(cl.mapData->mapMin, offset, radar.a);
00355 VectorAdd(cl.mapData->mapMax, offset, radar.c);
00356 VectorSet(radar.b, radar.c[0], radar.a[1], 0);
00357
00358 distAB = (Vector2Dist(radar.a, radar.b) / UNIT_SIZE);
00359 distBC = (Vector2Dist(radar.b, radar.c) / UNIT_SIZE);
00360
00361 UI_GetRadarWidth(node, gridSize);
00362
00363
00364 radar.gridWidth = radar.w / distAB;
00365 radar.gridHeight = radar.h / distBC;
00366
00367
00368
00369 {
00370 const float radarLength = max(1, abs(gridSize[0]));
00371 const float radarHeight = max(1, abs(gridSize[1]));
00372
00373 const float gridFactorX = radar.w / radarLength;
00374 const float gridFactorY = radar.h / radarHeight;
00375 for (j = 0; j < radar.numImages; j++) {
00376 hudRadarImage_t *image = &radar.images[j];
00377
00378 image->x = (image->gridX - radar.gridMin[0]) * gridFactorX;
00379 image->y = radar.h - (image->gridY - radar.gridMin[1]) * gridFactorY - image->height;
00380 }
00381 }
00382
00383
00384 radar.x -= (radar.w / 2);
00385 radar.y -= (radar.h / 2);
00386 }
00387
00388
00389
00390
00391
00392 static void UI_RadarNodeGetActorColor (const le_t *le, vec4_t color)
00393 {
00394 const int actorLevel = le->pos[2];
00395 Vector4Set(color, 0, 1, 0, 1);
00396
00397
00398 if (actorLevel < cl_worldlevel->integer)
00399 color[3] = 0.5;
00400 else if (actorLevel > cl_worldlevel->integer)
00401 color[3] = 0.3;
00402
00403
00404 if (LE_IsCivilian(le)) {
00405 color[0] = 1;
00406 } else if (le->team != cls.team) {
00407 color[1] = 0;
00408 color[0] = 1;
00409 }
00410
00411
00412 if (LE_IsDead(le)) {
00413 Vector4Set(color, 0, 0, 0, 0.3);
00414 }
00415 }
00416
00417 static void UI_RadarNodeDrawArrays (const vec4_t color, vec2_t coords[4], vec2_t vertices[4], const image_t *image)
00418 {
00419 R_Color(color);
00420 R_DrawImageArray((const vec2_t *)coords, (const vec2_t *)vertices, image);
00421 R_Color(NULL);
00422 }
00423
00424 static void UI_RadarNodeDrawActor (const le_t *le, const vec3_t pos)
00425 {
00426 vec2_t coords[4];
00427 vec2_t vertices[4];
00428 int i;
00429 const float size = 10;
00430 const int tileSize = 28;
00431 int tilePos = 4;
00432 const image_t *image;
00433 vec4_t color;
00434 const float pov = directionAngles[le->dir] * torad + M_PI;
00435
00436 image = UI_LoadImage("ui/radar");
00437 if (image == NULL)
00438 return;
00439
00440
00441 if (le->selected) {
00442 vertices[0][0] = - size * 4;
00443 vertices[0][1] = + 0;
00444 vertices[1][0] = + size * 4;
00445 vertices[1][1] = + 0;
00446 vertices[2][0] = + size * 4;
00447 vertices[2][1] = - size * 4;
00448 vertices[3][0] = - size * 4;
00449 vertices[3][1] = - size * 4;
00450 coords[0][0] = (7) / 128.0f;
00451 coords[0][1] = (37 + 63) / 128.0f;
00452 coords[1][0] = (7 + 114) / 128.0f;
00453 coords[1][1] = (37 + 63) / 128.0f;
00454 coords[2][0] = (7 + 114) / 128.0f;
00455 coords[2][1] = (37) / 128.0f;
00456 coords[3][0] = (7) / 128.0f;
00457 coords[3][1] = (37) / 128.0f;
00458
00459
00460 for (i = 0; i < 4; i++) {
00461 const float dx = vertices[i][0];
00462 const float dy = vertices[i][1];
00463 vertices[i][0] = pos[0] + dx * sin(pov) + dy * cos(pov);
00464 vertices[i][1] = pos[1] + dx * cos(pov) - dy * sin(pov);
00465 }
00466
00467 UI_RadarNodeGetActorColor(le, color);
00468 Vector4Set(color, 1, 1, 1, color[3] * 0.75);
00469 UI_RadarNodeDrawArrays(color, coords, vertices, image);
00470 }
00471
00472 if (LE_IsDead(le))
00473 tilePos = 4;
00474 else if (le->selected)
00475 tilePos = 66;
00476 else
00477 tilePos = 36;
00478
00479
00480 vertices[0][0] = - size;
00481 vertices[0][1] = + size;
00482 vertices[1][0] = + size;
00483 vertices[1][1] = + size;
00484 vertices[2][0] = + size;
00485 vertices[2][1] = - size;
00486 vertices[3][0] = - size;
00487 vertices[3][1] = - size;
00488 coords[0][0] = (tilePos) / 128.0f;
00489 coords[0][1] = (5 + tileSize) / 128.0f;
00490 coords[1][0] = (tilePos + tileSize) / 128.0f;
00491 coords[1][1] = (5 + tileSize) / 128.0f;
00492 coords[2][0] = (tilePos + tileSize) / 128.0f;
00493 coords[2][1] = (5) / 128.0f;
00494 coords[3][0] = (tilePos) / 128.0f;
00495 coords[3][1] = (5) / 128.0f;
00496
00497
00498 for (i = 0; i < 4; i++) {
00499 const float dx = vertices[i][0];
00500 const float dy = vertices[i][1];
00501 vertices[i][0] = pos[0] + dx * sin(pov) + dy * cos(pov);
00502 vertices[i][1] = pos[1] + dx * cos(pov) - dy * sin(pov);
00503 }
00504
00505 UI_RadarNodeGetActorColor(le, color);
00506 UI_RadarNodeDrawArrays(color, coords, vertices, image);
00507 }
00508
00512 static void UI_RadarNodeDrawItem (const le_t *le, const vec3_t pos)
00513 {
00514 float coords[4 * 2];
00515 short vertices[4 * 2];
00516 vec4_t color;
00517 int i;
00518 const float size = 10;
00519 const int tileSize = 28;
00520 int tilePos = 96;
00521 const image_t *image;
00522
00523 image = UI_LoadImage("ui/radar");
00524 if (image == NULL)
00525 return;
00526
00527
00528 vertices[0] = - size;
00529 vertices[1] = + size;
00530 vertices[2] = + size;
00531 vertices[3] = + size;
00532 vertices[4] = + size;
00533 vertices[5] = - size;
00534 vertices[6] = - size;
00535 vertices[7] = - size;
00536 coords[0] = (tilePos) / 128.0f;
00537 coords[1] = (5 + tileSize) / 128.0f;
00538 coords[2] = (tilePos + tileSize) / 128.0f;
00539 coords[3] = (5 + tileSize) / 128.0f;
00540 coords[4] = (tilePos + tileSize) / 128.0f;
00541 coords[5] = (5) / 128.0f;
00542 coords[6] = (tilePos) / 128.0f;
00543 coords[7] = (5) / 128.0f;
00544
00545
00546 for (i = 0; i < 8; i += 2) {
00547 vertices[i + 0] += pos[0];
00548 vertices[i + 1] += pos[1];
00549 }
00550
00551 UI_RadarNodeGetActorColor(le, color);
00552 Vector4Set(color, 0, 1, 0, color[3]);
00553 }
00554
00555
00556
00563 static void UI_RadarNodeDraw (uiNode_t *node)
00564 {
00565 le_t *le;
00566 int i;
00567 vec3_t pos;
00568 #ifdef RADARSIZE_DEBUG
00569 int textposy = 40;
00570 static const vec4_t red = {1, 0, 0, 0.5};
00571 #endif
00572
00573 static const vec4_t backgroundColor = {0.0, 0.0, 0.0, 1};
00574 const float mapWidth = cl.mapData->mapMax[0] - cl.mapData->mapMin[0];
00575 const float mapHeight = cl.mapData->mapMax[1] - cl.mapData->mapMin[1];
00576
00578 const float mapCoefX = (float) node->size[0] / (float) mapWidth;
00579 const float mapCoefY = (float) node->size[1] / (float) mapHeight;
00580
00581 if (cls.state != ca_active)
00582 return;
00583
00584 UI_GetNodeAbsPos(node, pos);
00585 R_CleanupDepthBuffer(pos[0], pos[1], node->size[0], node->size[1]);
00586 UI_DrawFill(pos[0], pos[1], mapWidth * mapCoefX, mapHeight * mapCoefY, backgroundColor);
00587 #ifndef RADARSIZE_DEBUG
00588 R_PushClipRect(pos[0], pos[1], node->size[0], node->size[1]);
00589 #endif
00590
00591
00592 if (!cl.radarInited) {
00593 UI_InitRadar(node);
00594 cl.radarInited = qtrue;
00595 }
00596
00597
00598 radar.x = pos[0];
00599 radar.y = pos[1];
00600 radar.w = node->size[0];
00601 radar.h = node->size[1];
00602 if (radar.gridWidth < 6)
00603 radar.gridWidth = 6;
00604 if (radar.gridHeight < 6)
00605 radar.gridHeight = 6;
00606
00607 #ifdef RADARSIZE_DEBUG
00608 UI_DrawStringInBox("f_small", 0, 50, textposy, 500, 25, va("%fx%f %fx%f map", mapMin[0], mapMin[1], mapMax[0], mapMax[1]), LONGLINES_PRETTYCHOP);
00609 textposy += 25;
00610 UI_DrawStringInBox("f_small", 0, 50, textposy, 500, 25, va("%fx%f map", mapWidth, mapHeight), LONGLINES_PRETTYCHOP);
00611 textposy += 25;
00612 #endif
00613
00614
00615 for (i = 0; i < radar.numImages; i++) {
00616 vec2_t imagePos;
00617 hudRadarImage_t *tile = &radar.images[i];
00618 int maxlevel = cl_worldlevel->integer;
00619
00620
00621 if (maxlevel >= tile->maxlevel)
00622 maxlevel = tile->maxlevel - 1;
00623 assert(tile->path[maxlevel]);
00624 imagePos[0] = radar.x + mapCoefX * (tile->mapX - cl.mapData->mapMin[0]);
00625 imagePos[1] = radar.y + mapCoefY * (tile->mapY - cl.mapData->mapMin[1]);
00626
00627 UI_DrawNormImageByName(imagePos[0], imagePos[1],
00628 mapCoefX * tile->mapWidth, mapCoefY * tile->mapHeight,
00629 0, 0, 0, 0, tile->path[maxlevel]);
00630 #ifdef RADARSIZE_DEBUG
00631 UI_DrawStringInBox("f_small", 0, 50, textposy, 500, 25, va("%dx%d %dx%d %s", tile->x, tile->y, tile->width, tile->height, tile->path[maxlevel]), LONGLINES_PRETTYCHOP);
00632 textposy += 25;
00633 UI_DrawStringInBox("f_small", 0, imagePos[0], imagePos[1],
00634 500, 25, va("%dx%d", tile->gridX, tile->gridY), LONGLINES_PRETTYCHOP);
00635 #endif
00636 }
00637
00638 #ifdef RADARSIZE_DEBUG
00639 UI_DrawFill(pos[0], pos[1], 100.0f * mapCoefX, 100.0f * mapCoefY, red);
00640 UI_DrawFill(pos[0], pos[1], UNIT_SIZE * mapCoefX, UNIT_SIZE * mapCoefY, red);
00641 #endif
00642
00643 le = NULL;
00644 while ((le = LE_GetNextInUse(le))) {
00645 vec3_t itempos;
00646 if (le->invis)
00647 continue;
00648
00649
00650 itempos[0] = pos[0] + (le->origin[0] - cl.mapData->mapMin[0]) * mapCoefX;
00651 itempos[1] = pos[1] + (mapHeight - (le->origin[1] - cl.mapData->mapMin[1])) * mapCoefY;
00652
00653 switch (le->type) {
00654 case ET_ACTOR:
00655 case ET_ACTOR2x2:
00656 UI_RadarNodeDrawActor(le, itempos);
00657 break;
00658 case ET_ITEM:
00659 UI_RadarNodeDrawItem(le, itempos);
00660 break;
00661 default:
00662 break;
00663 }
00664 #ifdef RADARSIZE_DEBUG
00665 UI_DrawStringInBox("f_small", 0, 50, textposy, 500, 25, va("%fx%f %dx%d actor", le->origin[0], le->origin[1], le->pos[0], le->pos[1]), LONGLINES_PRETTYCHOP);
00666 textposy += 25;
00667 UI_DrawFill(itempos[0], itempos[1], UNIT_SIZE * mapCoefX, 1, red);
00668 UI_DrawFill(itempos[0], itempos[1], 1, UNIT_SIZE * mapCoefY, red);
00669 #endif
00670 }
00671
00672 #ifndef RADARSIZE_DEBUG
00673 R_PopClipRect();
00674 #endif
00675 }
00676
00680 static void UI_RadarNodeCapturedMouseMove (uiNode_t *node, int x, int y)
00681 {
00682 const float mapWidth = cl.mapData->mapMax[0] - cl.mapData->mapMin[0];
00683 const float mapHeight = cl.mapData->mapMax[1] - cl.mapData->mapMin[1];
00684 const float mapCoefX = (float) node->size[0] / (float) mapWidth;
00685 const float mapCoefY = (float) node->size[1] / (float) mapHeight;
00686 vec3_t pos;
00687
00688
00689 UI_NodeAbsoluteToRelativePos(node, &x, &y);
00690
00691
00692 pos[0] = cl.mapData->mapMin[0] + x / mapCoefX;
00693 pos[1] = cl.mapData->mapMax[1] - y / mapCoefY;
00694
00695 VectorCopy(pos, cl.cam.origin);
00696 }
00697
00698 static void UI_RadarNodeMouseDown (uiNode_t *node, int x, int y, int button)
00699 {
00700 if (node->disabled)
00701 return;
00702
00703 if (button == K_MOUSE1) {
00704 UI_SetMouseCapture(node);
00705 UI_RadarNodeCapturedMouseMove(node, x, y);
00706 }
00707 }
00708
00709 static void UI_RadarNodeMouseUp (uiNode_t *node, int x, int y, int button)
00710 {
00711 if (button == K_MOUSE1)
00712 UI_MouseRelease();
00713 }
00714
00723 static void UI_GetRadarMapInFrameBuffer(int *x, int *y, int *width, int *height)
00724 {
00725
00726 static const float magicCoef = 0.351f;
00727 const float mapWidth = cl.mapData->mapMax[0] - cl.mapData->mapMin[0];
00728 const float mapHeight = cl.mapData->mapMax[1] - cl.mapData->mapMin[1];
00729
00730
00731 const int x2 = (viddef.width / 2) + (mapWidth * magicCoef * 0.5);
00732 const int y2 = (viddef.height / 2) + (mapHeight * magicCoef * 0.5) + 1;
00733 *x = (viddef.width / 2) - (mapWidth * magicCoef * 0.5);
00734 *y = (viddef.height / 2) - (mapHeight * magicCoef * 0.5);
00735 *width = (x2 - *x);
00736 *height = (y2 - *y);
00737 }
00738
00739 static void UI_GenPreviewRadarMap_f (void)
00740 {
00741 int x, y, width, height;
00742
00743 UI_GetRadarMapInFrameBuffer(&x, &y, &width, &height);
00744
00745
00746 x /= viddef.rx;
00747 width /= viddef.rx;
00748 y /= viddef.ry;
00749 height /= viddef.ry;
00750 y = viddef.virtualHeight - y - height;
00751
00752 UI_ExecuteConfunc("mn_radarhud_setmapborder %d %d %d %d", x, y, width, height);
00753 }
00754
00761 static void UI_GenRadarMap_f (void)
00762 {
00763 const int border = 0;
00764 const char *mapName = Cvar_GetString("sv_mapname");
00765
00766 const int level = Cvar_GetInteger("cl_worldlevel");
00767 const char *filename = NULL;
00768 int x, y, width, height;
00769
00770 UI_GetRadarMapInFrameBuffer(&x, &y, &width, &height);
00771 if (mapName)
00772 filename = va("%s_%i", mapName, level + 1);
00773 R_ScreenShot(x - border, y - border, width + border * 2, height + border * 2, filename, NULL);
00774 }
00775
00776 static void UI_GenAllRadarMap (uiNode_t *node, uiTimer_t *timer)
00777 {
00778 int level = (timer->calledTime - 1) / 2;
00779 int mode = (timer->calledTime - 1) % 2;
00780
00781 if (level >= cl.mapMaxLevel) {
00782 Cbuf_AddText("mn_genallradarmaprelease");
00783 return;
00784 }
00785
00786 if (mode == 0)
00787 Cvar_SetValue("cl_worldlevel", level);
00788 else
00789 Cmd_ExecuteString("mn_genradarmap");
00790 }
00791
00792 uiTimer_t* timer;
00793
00797 static void UI_GenAllRadarMapRelease_f (void) {
00798 UI_TimerRelease(timer);
00799 UI_ExecuteConfunc("mn_radarhud_reinit");
00800 }
00801
00806 static void UI_GenAllRadarMap_f (void)
00807 {
00808 const int delay = 1000;
00809 timer = UI_AllocTimer(NULL, delay, UI_GenAllRadarMap);
00810 UI_TimerStart(timer);
00811 }
00812
00813 void UI_RegisterRadarNode (uiBehaviour_t *behaviour)
00814 {
00815 behaviour->name = "radar";
00816 behaviour->draw = UI_RadarNodeDraw;
00817 behaviour->mouseDown = UI_RadarNodeMouseDown;
00818 behaviour->mouseUp = UI_RadarNodeMouseUp;
00819 behaviour->capturedMouseMove = UI_RadarNodeCapturedMouseMove;
00820
00821 Cmd_AddCommand("mn_genpreviewradarmap", UI_GenPreviewRadarMap_f, NULL);
00822 Cmd_AddCommand("mn_genradarmap", UI_GenRadarMap_f, NULL);
00823 Cmd_AddCommand("mn_genallradarmap", UI_GenAllRadarMap_f, NULL);
00824 Cmd_AddCommand("mn_genallradarmaprelease", UI_GenAllRadarMapRelease_f, NULL);
00825 }