ui_node_radar.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2002-2010 UFO: Alien Invasion.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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     /* image */
00045     char *name;             
00046     char *path[PATHFINDING_HEIGHT];     
00047     int x, y;               
00048     int width, height;      
00050     /* position of this piece into the map */
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     /* load tiles */
00113     while (tiles) {
00114         int i;
00115         vec3_t sh;
00116         char name[MAX_VAR];
00117         hudRadarImage_t *image;
00118         /* get tile name */
00119         const char *token = Com_Parse(&tiles);
00120         if (!tiles) {
00121             /* finish */
00122             return;
00123         }
00124 
00125         /* get base path */
00126         if (token[0] == '-') {
00127             Q_strncpyz(radar.base, token + 1, sizeof(radar.base));
00128             continue;
00129         }
00130 
00131         /* get tile name */
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             /* it is a single background image*/
00142             return;
00143 
00144         /* get grid position and add a tile */
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     /* Set radar.gridMax */
00183     radar.gridMax[0] = radar.gridMin[0];
00184     radar.gridMax[1] = radar.gridMin[1];
00185 
00186     /* Initialize secondTileGridX to value higher that real value */
00187     secondTileGridX = radar.gridMin[0] + 1000;
00188     secondTileGridY = radar.gridMin[1] + 1000;
00189 
00190     /* Initialize screen size of last tile (will be used only if there is 1 tile in a line or in a row) */
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         /* we can assume this because every random map tile has it's origin in
00201          * (0, 0) and therefore there are no intersections possible on the min
00202          * x and the min y axis. We just have to add the image->w and image->h
00203          * values of those images that are placed on the gridMin values.
00204          * This also works for static maps, because they have a gridX and gridY
00205          * value of zero */
00206 
00207         if (image->gridX == radar.gridMin[0]) {
00208             /* radar.gridMax[1] is the maximum for FIRST column (maximum depends on column) */
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                 /* This is the tile of the map in the lower left: */
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             /* radar.gridMax[1] is the maximum for FIRST line (maximum depends on line) */
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     /* Maybe there was only one tile in a line or in a column? */
00231     if (!tileHeight[1])
00232         tileHeight[1] = tileHeight[0];
00233     if (!tileWidth[1])
00234         tileWidth[1] = tileWidth[0];
00235 
00236     /* Now we get the ratio conversion between screen coordinates and grid coordinates.
00237      * The problem is that some tiles may have L or T shape.
00238      * But we now that the tile in the lower left follows for sure the side of the map on it's whole length
00239      * at least either on its height or on its width.*/
00240     ratioConversion = max((secondTileGridX - radar.gridMin[0]) / (tileWidth[0] - ROUNDING_PIXEL),
00241         (secondTileGridY - radar.gridMin[1]) / (tileHeight[0] - ROUNDING_PIXEL));
00242 
00243     /* And now we fill radar.w and radar.h */
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     /* none found */
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     /* only check once per map whether all the needed images exist */
00290     for (j = 0; j < radar.numImages; j++) {
00291         hudRadarImage_t *tile = &radar.images[j];
00292         /* map_mins, map_maxs */
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                     /* there should be at least one level */
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     /* center tiles into the minMap/maxMap */
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     /* compute translation */
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     /* get the three points of the triangle */
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     /* get the dimensions for one grid field on the radar map */
00364     radar.gridWidth = radar.w / distAB;
00365     radar.gridHeight = radar.h / distBC;
00366 
00367     /* shift the x and y values according to their grid width/height and
00368      * their gridX and gridY position */
00369     {
00370         const float radarLength = max(1, abs(gridSize[0]));
00371         const float radarHeight = max(1, abs(gridSize[1]));
00372         /* image grid relations */
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     /* now align the screen coordinates like it's given by the node */
00384     radar.x -= (radar.w / 2);
00385     radar.y -= (radar.h / 2);
00386 }
00387 
00388 /*=========================================
00389  DRAW FUNCTIONS
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     /* use different alpha values for different levels */
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     /* use different colors for different teams */
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     /* show dead actors in full black */
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     /* draw FOV */
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         /* affine transformation */
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     /* a 0,0 centered square */
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     /* affine transformation */
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     /* a 0,0 centered square */
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     /* affine transformation */
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 /*#define RADARSIZE_DEBUG*/
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     /* the cl struct is wiped with every new map */
00592     if (!cl.radarInited) {
00593         UI_InitRadar(node);
00594         cl.radarInited = qtrue;
00595     }
00596 
00597     /* update context */
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     /* draw background */
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         /* check the max level value for this map tile */
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         /* convert to radar area coordinates */
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     /* from absolute to relative to node */
00689     UI_NodeAbsoluteToRelativePos(node, &x, &y);
00690 
00691     /* from node to map */
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     /* Coefficient come from metric (Bunker map, and game with resolution 1024x1024) == 0.350792947 */
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     /* compute width and height with the same round error on both sides */
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     /* map to screen */
00743     UI_GetRadarMapInFrameBuffer(&x, &y, &width, &height);
00744 
00745     /* from screen to virtual screen */
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 }

Generated by  doxygen 1.6.2