ui_draw.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 "ui_main.h"
00026 #include "ui_nodes.h"
00027 #include "ui_internal.h"
00028 #include "ui_draw.h"
00029 #include "ui_actions.h"
00030 #include "ui_input.h"
00031 #include "ui_timer.h" /* define UI_HandleTimers */
00032 #include "ui_dragndrop.h"
00033 #include "ui_tooltip.h"
00034 #include "ui_render.h"
00035 #include "node/ui_node_abstractnode.h"
00036 
00037 #include "../client.h"
00038 #include "../renderer/r_draw.h"
00039 #include "../renderer/r_misc.h"
00040 
00041 static cvar_t *mn_show_tooltips;
00042 static const int TOOLTIP_DELAY = 500; /* delay that msecs before showing tooltip */
00043 static qboolean tooltipVisible = qfalse;
00044 static uiTimer_t *tooltipTimer;
00045 
00046 static int noticeTime;
00047 static char noticeText[256];
00048 static uiNode_t *noticeWindow;
00049 
00055 static uiNode_t *drawOverNode;
00056 
00062 void UI_CaptureDrawOver (uiNode_t *node)
00063 {
00064     drawOverNode = node;
00065 }
00066 
00067 #ifdef DEBUG
00068 
00069 static int debugTextPositionY = 0;
00070 static int debugPositionX = 0;
00071 #define DEBUG_PANEL_WIDTH 300
00072 
00073 static void UI_HighlightNode (const uiNode_t *node, const vec4_t color)
00074 {
00075     static const vec4_t grey = {0.7, 0.7, 0.7, 1.0};
00076     vec2_t pos;
00077     int width;
00078     int lineDefinition[4];
00079     const char* text;
00080 
00081     if (node->parent)
00082         UI_HighlightNode(node->parent, grey);
00083 
00084     UI_GetNodeAbsPos(node, pos);
00085 
00086     text = va("%s (%s)", node->name, node->behaviour->name);
00087     R_FontTextSize("f_small_bold", text, DEBUG_PANEL_WIDTH, LONGLINES_PRETTYCHOP, &width, NULL, NULL, NULL);
00088 
00089     R_Color(color);
00090     UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX + 20, debugTextPositionY, debugPositionX + 20, DEBUG_PANEL_WIDTH, 0, text, 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00091     debugTextPositionY += 15;
00092 
00093     if (debugPositionX != 0) {
00094         lineDefinition[0] = debugPositionX + 20;
00095         lineDefinition[2] = pos[0] + node->size[0];
00096     } else {
00097         lineDefinition[0] = debugPositionX + 20 + width;
00098         lineDefinition[2] = pos[0];
00099     }
00100     lineDefinition[1] = debugTextPositionY - 5;
00101     lineDefinition[3] = pos[1];
00102     R_DrawLine(lineDefinition, 1);
00103     R_Color(NULL);
00104 
00105     /* exclude rect */
00106     if (node->excludeRectNum) {
00107         int i;
00108         vec4_t trans = {1, 1, 1, 1};
00109         Vector4Copy(color, trans);
00110         trans[3] = trans[3] / 2;
00111         for (i = 0; i < node->excludeRectNum; i++) {
00112             const int x = pos[0] + node->excludeRect[i].pos[0];
00113             const int y = pos[1] + node->excludeRect[i].pos[1];
00114             UI_DrawFill(x, y, node->excludeRect[i].size[0], node->excludeRect[i].size[1], trans);
00115         }
00116     }
00117 
00118     /* bounded box */
00119     R_DrawRect(pos[0] - 1, pos[1] - 1, node->size[0] + 2, node->size[1] + 2, color, 2.0, 0x3333);
00120 }
00121 
00125 static void UI_DrawDebugNodeNames (void)
00126 {
00127     static const vec4_t red = {1.0, 0.0, 0.0, 1.0};
00128     static const vec4_t green = {0.0, 0.5, 0.0, 1.0};
00129     static const vec4_t white = {1, 1.0, 1.0, 1.0};
00130     static const vec4_t background = {0.0, 0.0, 0.0, 0.5};
00131     uiNode_t *hoveredNode;
00132     int stackPosition;
00133 
00134     debugTextPositionY = 100;
00135 
00136     /* x panel position with hysteresis */
00137     if (mousePosX < viddef.virtualWidth / 3)
00138         debugPositionX = viddef.virtualWidth - DEBUG_PANEL_WIDTH;
00139     if (mousePosX > 2 * viddef.virtualWidth / 3)
00140         debugPositionX = 0;
00141 
00142     /* mouse position */
00143     UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX, debugTextPositionY, debugPositionX, 200, 0, va("Mouse X: %i Y: %i", mousePosX, mousePosY), 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00144     debugTextPositionY += 15;
00145     /* global */
00146     UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX, debugTextPositionY, debugPositionX, 200, 0, "main active window:", 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00147     debugTextPositionY += 15;
00148     UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX+20, debugTextPositionY, debugPositionX + 20, 200, 0, Cvar_GetString("mn_sys_active"), 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00149     debugTextPositionY += 15;
00150     UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX, debugTextPositionY, debugPositionX, 200, 0, "main option window:", 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00151     debugTextPositionY += 15;
00152     UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX+20, debugTextPositionY, debugPositionX + 20, 200, 0, Cvar_GetString("mn_sys_main"), 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00153     debugTextPositionY += 15;
00154     UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX, debugTextPositionY, debugPositionX, 200, 0, "-----------------------", 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00155     debugTextPositionY += 15;
00156 
00157     /* background */
00158     UI_DrawFill(debugPositionX, debugTextPositionY, DEBUG_PANEL_WIDTH, VID_NORM_HEIGHT - debugTextPositionY - 100, background);
00159 
00160     /* window stack */
00161     R_Color(white);
00162     UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX, debugTextPositionY, debugPositionX, 200, 0, "window stack:", 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00163     debugTextPositionY += 15;
00164     for (stackPosition = 0; stackPosition < ui_global.windowStackPos; stackPosition++) {
00165         uiNode_t *window = ui_global.windowStack[stackPosition];
00166         UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX+20, debugTextPositionY, debugPositionX + 20, 200, 0, window->name, 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00167         debugTextPositionY += 15;
00168     }
00169 
00170     /* hovered node */
00171     hoveredNode = UI_GetHoveredNode();
00172     if (hoveredNode) {
00173         UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX, debugTextPositionY, debugPositionX, 200, 0, "-----------------------", 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00174         debugTextPositionY += 15;
00175 
00176         UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX, debugTextPositionY, debugPositionX, 200, 0, "hovered node:", 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00177         debugTextPositionY += 15;
00178         UI_HighlightNode(hoveredNode, red);
00179         R_Color(white);
00180     }
00181 
00182     /* target node */
00183     if (UI_DNDIsDragging()) {
00184         uiNode_t *targetNode = UI_DNDGetTargetNode();
00185         if (targetNode) {
00186             UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX, debugTextPositionY, debugPositionX, 200, 0, "-----------------------", 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00187             debugTextPositionY += 15;
00188 
00189             R_Color(green);
00190             UI_DrawString("f_small_bold", ALIGN_UL, debugPositionX, debugTextPositionY, debugPositionX, 200, 0, "drag and drop target node:", 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP);
00191             debugTextPositionY += 15;
00192             UI_HighlightNode(targetNode, green);
00193         }
00194     }
00195     R_Color(NULL);
00196 }
00197 #endif
00198 
00199 
00200 static void UI_CheckTooltipDelay (uiNode_t *node, uiTimer_t *timer)
00201 {
00202     tooltipVisible = qtrue;
00203     UI_TimerStop(timer);
00204 }
00205 
00206 static void UI_DrawNode (uiNode_t *node)
00207 {
00208     static int globalTransX = 0;
00209     static int globalTransY = 0;
00210     uiNode_t *child;
00211     vec2_t pos;
00212 
00213     /* update the layout */
00214     UI_Validate(node);
00215 
00216     /* skip invisible, virtual, and undrawable nodes */
00217     if (node->invis || node->behaviour->isVirtual)
00218         return;
00219     /* if construct */
00220     if (!UI_CheckVisibility(node))
00221         return;
00222 
00223     UI_GetNodeAbsPos(node, pos);
00224 
00228     /* check node size x and y value to check whether they are zero */
00229     if (node->size[0] && node->size[1]) {
00230         if (node->bgcolor[3] != 0)
00231             UI_DrawFill(pos[0], pos[1], node->size[0], node->size[1], node->bgcolor);
00232 
00233         if (node->border && node->bordercolor[3] != 0) {
00234             R_DrawRect(pos[0], pos[1], node->size[0], node->size[1],
00235                 node->bordercolor, node->border, 0xFFFF);
00236         }
00237     }
00238 
00239     /* draw the node */
00240     if (node->behaviour->draw) {
00241         node->behaviour->draw(node);
00242     }
00243 
00244     /* draw all child */
00245     if (!node->behaviour->drawItselfChild && node->firstChild) {
00246         qboolean hasClient = qfalse;
00247         vec2_t clientPosition;
00248         if (node->behaviour->getClientPosition) {
00249             node->behaviour->getClientPosition(node, clientPosition);
00250             hasClient = qtrue;
00251         }
00252 
00253         R_PushClipRect(pos[0] + globalTransX, pos[1] + globalTransY, node->size[0], node->size[1]);
00254 
00256         if (hasClient) {
00257             vec3_t trans;
00258             globalTransX += clientPosition[0];
00259             globalTransY += clientPosition[1];
00260             trans[0] = clientPosition[0];
00261             trans[1] = clientPosition[1];
00262             trans[2] = 0;
00263             R_Transform(trans, NULL, NULL);
00264         }
00265 
00266         for (child = node->firstChild; child; child = child->next)
00267             UI_DrawNode(child);
00268 
00270         if (hasClient) {
00271             vec3_t trans;
00272             globalTransX -= clientPosition[0];
00273             globalTransY -= clientPosition[1];
00274             trans[0] = -clientPosition[0];
00275             trans[1] = -clientPosition[1];
00276             trans[2] = 0;
00277             R_Transform(trans, NULL, NULL);
00278         }
00279 
00280         R_PopClipRect();
00281     }
00282 }
00283 
00288 static void UI_DrawNotice (void)
00289 {
00290     const vec4_t noticeBG = { 1.0f, 0.0f, 0.0f, 0.2f };
00291     const vec4_t noticeColor = { 1.0f, 1.0f, 1.0f, 1.0f };
00292     int height = 0, width = 0;
00293     const int maxWidth = 500;
00294     const char *font = "f_normal";
00295     int lines = 5;
00296     int dx; 
00297     int x, y;
00298     vec_t *noticePosition;
00299 
00300     noticePosition = UI_WindowNodeGetNoticePosition(noticeWindow);
00301     if (noticePosition) {
00302         x = noticePosition[0];
00303         y = noticePosition[1];
00304     } else {
00305         x = VID_NORM_WIDTH / 2;
00306         y = 110;
00307     }
00308 
00309     /* relative to the window */
00310     x += noticeWindow->pos[0];
00311     y += noticeWindow->pos[1];
00312 
00313     R_FontTextSize(font, noticeText, maxWidth, LONGLINES_WRAP, &width, &height, NULL, NULL);
00314 
00315     if (!width)
00316         return;
00317 
00318     if (x + width + 3 > viddef.virtualWidth)
00319         dx = -(width + 10);
00320     else
00321         dx = 0;
00322 
00323     UI_DrawFill((x - 2 + dx) - ((width + 2) / 2), (y - 2) - ((height + 2) / 2), width + 4, height + 4, noticeBG);
00324     R_Color(noticeColor);
00325     UI_DrawString(font, ALIGN_CC, x + 1 + dx, y + 1, x + 1, maxWidth, 0, noticeText, lines, 0, NULL, qfalse, LONGLINES_WRAP);
00326     R_Color(NULL);
00327 }
00328 
00333 void UI_Draw (void)
00334 {
00335     uiNode_t *hoveredNode;
00336     int pos;
00337     qboolean mouseMoved = qfalse;
00338 
00339     UI_HandleTimers();
00340 
00341     assert(ui_global.windowStackPos >= 0);
00342 
00343     mouseMoved = UI_CheckMouseMove();
00344     hoveredNode = UI_GetHoveredNode();
00345 
00346     /* handle delay time for tooltips */
00347     if (mouseMoved && tooltipVisible) {
00348         UI_TimerStop(tooltipTimer);
00349         tooltipVisible = qfalse;
00350     } else if (!tooltipVisible && !mouseMoved && !tooltipTimer->isRunning && mn_show_tooltips->integer && hoveredNode) {
00351         UI_TimerStart(tooltipTimer);
00352     }
00353 
00354     /* under a fullscreen, windows should not be visible */
00355     pos = UI_GetLastFullScreenWindow();
00356     if (pos < 0)
00357         return;
00358 
00359     /* draw all visible windows */
00360     for (; pos < ui_global.windowStackPos; pos++) {
00361         uiNode_t *window;
00362         window = ui_global.windowStack[pos];
00363 
00364         drawOverNode = NULL;
00365 
00366         UI_DrawNode(window);
00367 
00368         /* draw a node over the window */
00369         if (drawOverNode && drawOverNode->behaviour->drawOverWindow) {
00370             drawOverNode->behaviour->drawOverWindow(drawOverNode);
00371         }
00372     }
00373 
00374     /* draw a special notice */
00375     if (noticeWindow != NULL && CL_Milliseconds() < noticeTime)
00376         UI_DrawNotice();
00377 
00378     /* unactive notice */
00379     if (noticeWindow != NULL && CL_Milliseconds() >= noticeTime)
00380         noticeWindow = NULL;
00381 
00382     /* draw tooltip */
00383     if (hoveredNode && tooltipVisible && !UI_DNDIsDragging()) {
00384         if (hoveredNode->behaviour->drawTooltip) {
00385             hoveredNode->behaviour->drawTooltip(hoveredNode, mousePosX, mousePosY);
00386         } else {
00387             UI_Tooltip(hoveredNode, mousePosX, mousePosY);
00388         }
00389     }
00390 
00391 #ifdef DEBUG
00392     /* debug information */
00393     if (UI_DebugMode() >= 1) {
00394         UI_DrawDebugNodeNames();
00395     }
00396 #endif
00397 }
00398 
00399 void UI_DrawCursor (void)
00400 {
00401     UI_DrawDragAndDrop(mousePosX, mousePosY);
00402 }
00403 
00411 void UI_DisplayNotice (const char *text, int time, const char* windowName)
00412 {
00413     noticeTime = CL_Milliseconds() + time;
00414     Q_strncpyz(noticeText, text, sizeof(noticeText));
00415 
00416     if (windowName == NULL) {
00417         noticeWindow = UI_GetActiveWindow();
00418         if (noticeWindow == NULL)
00419             Com_Printf("UI_DisplayNotice: No active window\n");
00420     } else {
00421         noticeWindow = UI_GetWindow(windowName);
00422         if (noticeWindow == NULL)
00423             Com_Printf("UI_DisplayNotice: '%s' not found\n", windowName);
00424     }
00425 }
00426 
00427 void UI_InitDraw (void)
00428 {
00429     mn_show_tooltips = Cvar_Get("mn_show_tooltips", "1", CVAR_ARCHIVE, "Show tooltips in the UI");
00430     tooltipTimer = UI_AllocTimer(NULL, TOOLTIP_DELAY, UI_CheckTooltipDelay);
00431 }

Generated by  doxygen 1.6.2