Index: src/client/menu/m_node_text.c =================================================================== --- src/client/menu/m_node_text.c (revision 19496) +++ src/client/menu/m_node_text.c (working copy) @@ -139,6 +139,7 @@ vec4_t colorSelectedHover; char *cur, *tab, *end; int x1, y1; /* variable x and y position */ + vec2_t nodepos; if (text) { Q_strncpyz(textCopy, text, sizeof(textCopy)); @@ -148,6 +149,7 @@ Sys_Error("MN_DrawTextNode: Called without text or linkedList pointer"); cur = textCopy; + MN_GetNodeAbsPos(node, nodepos); /* Hover darkening effect for normal text lines. */ VectorScale(node->color, 0.8, colorHover); colorHover[3] = node->color[3]; @@ -165,8 +167,7 @@ y1 = y; /*Com_Printf("\n\n\nnode->textLines: %i \n", node->textLines);*/ - if (node) - node->textLines = 0; /* these are lines only in one-line texts! */ + node->textLines = 0; /* these are lines only in one-line texts! */ /* but it's easy to fix, just change FontDrawString * so that it returns a pair, #lines and height * and add that to variable line; the only other file @@ -274,18 +275,18 @@ /* draw scrollbars */ if (node->scrollbar && node->height && node->textLines > node->height) { - const int scrollbarX = node->pos[0] + (node->scrollbarLeft ? 0 : node->size[0] - MN_SCROLLBAR_WIDTH); + const int scrollbarX = nodepos[0] + (node->scrollbarLeft ? 0 : node->size[0] - MN_SCROLLBAR_WIDTH); const float scrollbarY = node->size[1] * node->height / node->textLines * MN_SCROLLBAR_HEIGHT; R_DrawFill(scrollbarX, - node->pos[1], + nodepos[1], MN_SCROLLBAR_WIDTH, node->size[1], ALIGN_UL, scrollbarBackground); R_DrawFill(scrollbarX, - node->pos[1] + (node->size[1] - scrollbarY) * node->textScroll / (node->textLines - node->height), + nodepos[1] + (node->size[1] - scrollbarY) * node->textScroll / (node->textLines - node->height), MN_SCROLLBAR_WIDTH, scrollbarY, ALIGN_UL, Index: src/client/menu/m_node_checkbox.c =================================================================== --- src/client/menu/m_node_checkbox.c (revision 19496) +++ src/client/menu/m_node_checkbox.c (working copy) @@ -6,7 +6,9 @@ { const char *image; const char *ref; + vec2_t nodepos; + MN_GetNodeAbsPos(node, nodepos); /* image set? */ if (checkBoxImage && *checkBoxImage) image = checkBoxImage; @@ -19,11 +21,11 @@ switch (*ref) { case '0': - R_DrawNormPic(node->pos[0], node->pos[1], node->size[0], node->size[1], + R_DrawNormPic(nodepos[0], nodepos[1], node->size[0], node->size[1], node->texh[0], node->texh[1], node->texl[0], node->texl[1], node->align, node->blend, va("%s_unchecked", image)); break; case '1': - R_DrawNormPic(node->pos[0], node->pos[1], node->size[0], node->size[1], + R_DrawNormPic(nodepos[0], nodepos[1], node->size[0], node->size[1], node->texh[0], node->texh[1], node->texl[0], node->texl[1], node->align, node->blend, va("%s_checked", image)); break; default: Index: src/client/menu/m_node_selectbox.c =================================================================== --- src/client/menu/m_node_selectbox.c (revision 19496) +++ src/client/menu/m_node_selectbox.c (working copy) @@ -73,24 +73,26 @@ int selBoxX, selBoxY; const char *ref; const char *font; + vec2_t nodepos; + MN_GetNodeAbsPos(node, nodepos); if (!image) image = "menu/selectbox"; ref = MN_GetReferenceString(node->menu, node->data[MN_DATA_MODEL_SKIN_OR_CVAR]); font = MN_GetFont(node->menu, node); - selBoxX = node->pos[0] + SELECTBOX_SIDE_WIDTH; - selBoxY = node->pos[1] + SELECTBOX_SPACER; + selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH; + selBoxY = nodepos[1] + SELECTBOX_SPACER; /* left border */ - R_DrawNormPic(node->pos[0], node->pos[1], SELECTBOX_SIDE_WIDTH, node->size[1], + R_DrawNormPic(nodepos[0], nodepos[1], SELECTBOX_SIDE_WIDTH, node->size[1], SELECTBOX_SIDE_WIDTH, 20.0f, 0.0f, 0.0f, node->align, node->blend, image); /* stretched middle bar */ - R_DrawNormPic(node->pos[0] + SELECTBOX_SIDE_WIDTH, node->pos[1], node->size[0], node->size[1], + R_DrawNormPic(nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1], node->size[0], node->size[1], 12.0f, 20.0f, 7.0f, 0.0f, node->align, node->blend, image); /* right border (arrow) */ - R_DrawNormPic(node->pos[0] + SELECTBOX_SIDE_WIDTH + node->size[0], node->pos[1], SELECTBOX_DEFAULT_HEIGHT, node->size[1], + R_DrawNormPic(nodepos[0] + SELECTBOX_SIDE_WIDTH + node->size[0], nodepos[1], SELECTBOX_DEFAULT_HEIGHT, node->size[1], 32.0f, 20.0f, 12.0f, 0.0f, node->align, node->blend, image); /* draw the label for the current selected option */ for (selectBoxOption = node->options; selectBoxOption; selectBoxOption = selectBoxOption->next) { @@ -108,15 +110,15 @@ /* drop down menu */ /* left side */ - R_DrawNormPic(node->pos[0], node->pos[1] + node->size[1], SELECTBOX_SIDE_WIDTH, node->size[1] * node->height, + R_DrawNormPic(nodepos[0], nodepos[1] + node->size[1], SELECTBOX_SIDE_WIDTH, node->size[1] * node->height, 7.0f, 28.0f, 0.0f, 21.0f, node->align, node->blend, image); /* stretched middle bar */ - R_DrawNormPic(node->pos[0] + SELECTBOX_SIDE_WIDTH, node->pos[1] + node->size[1], node->size[0], node->size[1] * node->height, + R_DrawNormPic(nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1] + node->size[1], node->size[0], node->size[1] * node->height, 16.0f, 28.0f, 7.0f, 21.0f, node->align, node->blend, image); /* right side */ - R_DrawNormPic(node->pos[0] + SELECTBOX_SIDE_WIDTH + node->size[0], node->pos[1] + node->size[1], SELECTBOX_SIDE_WIDTH, node->size[1] * node->height, + R_DrawNormPic(nodepos[0] + SELECTBOX_SIDE_WIDTH + node->size[0], nodepos[1] + node->size[1], SELECTBOX_SIDE_WIDTH, node->size[1] * node->height, 23.0f, 28.0f, 16.0f, 21.0f, node->align, node->blend, image); /* now draw all available options for this selectbox */ @@ -126,7 +128,7 @@ R_DrawFill(selBoxX, selBoxY, node->size[0], SELECTBOX_DEFAULT_HEIGHT, ALIGN_UL, node->color); /* print the option label */ R_FontDrawString(font, node->align, selBoxX, selBoxY, - selBoxX, node->pos[1] + node->size[1], node->size[0] - 4, 0, + selBoxX, nodepos[1] + node->size[1], node->size[0] - 4, 0, node->texh[0], _(selectBoxOption->label), 0, 0, NULL, qfalse); /* next entries' position */ selBoxY += node->size[1]; @@ -134,15 +136,15 @@ selectBoxOption->hovered = qfalse; } /* left side */ - R_DrawNormPic(node->pos[0], selBoxY - SELECTBOX_SPACER, SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT, + R_DrawNormPic(nodepos[0], selBoxY - SELECTBOX_SPACER, SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT, 7.0f, 32.0f, 0.0f, 28.0f, node->align, node->blend, image); /* stretched middle bar */ - R_DrawNormPic(node->pos[0] + SELECTBOX_SIDE_WIDTH, selBoxY - SELECTBOX_SPACER, node->size[0], SELECTBOX_BOTTOM_HEIGHT, + R_DrawNormPic(nodepos[0] + SELECTBOX_SIDE_WIDTH, selBoxY - SELECTBOX_SPACER, node->size[0], SELECTBOX_BOTTOM_HEIGHT, 16.0f, 32.0f, 7.0f, 28.0f, node->align, node->blend, image); /* right bottom side */ - R_DrawNormPic(node->pos[0] + SELECTBOX_SIDE_WIDTH + node->size[0], selBoxY - SELECTBOX_SPACER, + R_DrawNormPic(nodepos[0] + SELECTBOX_SIDE_WIDTH + node->size[0], selBoxY - SELECTBOX_SPACER, SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT, 23.0f, 32.0f, 16.0f, 28.0f, node->align, node->blend, image); } Index: src/client/menu/m_draw.c =================================================================== --- src/client/menu/m_draw.c (revision 19496) +++ src/client/menu/m_draw.c (working copy) @@ -36,18 +36,21 @@ static void MN_DrawBorder (const menuNode_t *node) { + vec2_t nodepos; + + MN_GetNodeAbsPos(node, nodepos); /** @todo use GL_LINE_LOOP + array here */ /* left */ - R_DrawFill(node->pos[0] - node->padding - node->border, node->pos[1] - node->padding - node->border, + R_DrawFill(nodepos[0] - node->padding - node->border, nodepos[1] - node->padding - node->border, node->border, node->size[1] + (node->padding*2) + (node->border*2), node->align, node->bordercolor); /* right */ - R_DrawFill(node->pos[0] + node->size[0] + node->padding, node->pos[1] - node->padding - node->border, + R_DrawFill(nodepos[0] + node->size[0] + node->padding, nodepos[1] - node->padding - node->border, node->border, node->size[1] + (node->padding*2) + (node->border*2), node->align, node->bordercolor); /* top */ - R_DrawFill(node->pos[0] - node->padding, node->pos[1] - node->padding - node->border, + R_DrawFill(nodepos[0] - node->padding, nodepos[1] - node->padding - node->border, node->size[0] + (node->padding*2), node->border, node->align, node->bordercolor); /* down */ - R_DrawFill(node->pos[0] - node->padding, node->pos[1] + node->size[1] + node->padding, + R_DrawFill(nodepos[0] - node->padding, nodepos[1] + node->size[1] + node->padding, node->size[0] + (node->padding*2), node->border, node->align, node->bordercolor); } @@ -68,6 +71,7 @@ int i; message_t *message; const invList_t *itemHover = NULL; + vec2_t nodepos; /* render every menu on top of a menu with a render node */ pp = 0; @@ -97,6 +101,7 @@ } } for (node = menu->firstNode; node; node = node->next) { + MN_GetNodeAbsPos(node, nodepos); if (!node->invis && ((node->data[MN_DATA_STRING_OR_IMAGE_OR_MODEL] /* 0 are images, models and strings e.g. */ || node->type == MN_CONTAINER || node->type == MN_TEXT || node->type == MN_BASELAYOUT || node->type == MN_BASEMAP || node->type == MN_MAP) || node->type == MN_CHECKBOX || node->type == MN_SELECTBOX || node->type == MN_LINESTRIP @@ -138,13 +143,13 @@ } /* check node size x and y value to check whether they are zero */ - if (node->bgcolor && node->size[0] && node->size[1] && node->pos) { + if (node->bgcolor && node->size[0] && node->size[1] && nodepos[0] && nodepos[1]) { if (node->type != MN_BASELAYOUT) - R_DrawFill(node->pos[0] - node->padding, node->pos[1] - node->padding, + R_DrawFill(nodepos[0] - node->padding, nodepos[1] - node->padding, node->size[0] + (node->padding * 2), node->size[1] + (node->padding * 2), 0, node->bgcolor); } - if (node->border && node->bordercolor && node->size[0] && node->size[1] && node->pos) + if (node->border && node->bordercolor && node->size[0] && node->size[1] && nodepos) MN_DrawBorder(node); /* mouse darken effect */ @@ -200,18 +205,18 @@ ref += node->horizontalScroll; /* blinking */ if (!node->mousefx || cl.time % 1000 < 500) - R_FontDrawString(font, node->align, node->pos[0], node->pos[1], node->pos[0], node->pos[1], node->size[0], 0, node->texh[0], ref, 0, 0, NULL, qfalse); + R_FontDrawString(font, node->align, nodepos[0], nodepos[1], nodepos[0], nodepos[1], node->size[0], 0, node->texh[0], ref, 0, 0, NULL, qfalse); else - R_FontDrawString(font, node->align, node->pos[0], node->pos[1], node->pos[0], node->pos[1], node->size[0], node->size[1], node->texh[0], va("%s*\n", ref), 0, 0, NULL, qfalse); + R_FontDrawString(font, node->align, nodepos[0], nodepos[1], nodepos[0], nodepos[1], node->size[0], node->size[1], node->texh[0], va("%s*\n", ref), 0, 0, NULL, qfalse); break; case MN_TEXT: if (mn.menuText[node->num]) { font = MN_GetFont(menu, node); - MN_DrawTextNode(mn.menuText[node->num], NULL, font, node, node->pos[0], node->pos[1], node->size[0], node->size[1]); + MN_DrawTextNode(mn.menuText[node->num], NULL, font, node, nodepos[0], nodepos[1], node->size[0], node->size[1]); } else if (mn.menuTextLinkedList[node->num]) { font = MN_GetFont(menu, node); - MN_DrawTextNode(NULL, mn.menuTextLinkedList[node->num], font, node, node->pos[0], node->pos[1], node->size[0], node->size[1]); + MN_DrawTextNode(NULL, mn.menuTextLinkedList[node->num], font, node, nodepos[0], nodepos[1], node->size[0], node->size[1]); } else if (node->num == TEXT_MESSAGESYSTEM) { linkedList_t *messagelist = NULL; char text[TIMESTAMP_TEXT + MAX_MESSAGE_TEXT]; @@ -233,7 +238,7 @@ message = message->next; } if (messagelist) { - MN_DrawTextNode(NULL, messagelist, font, node, node->pos[0], node->pos[1], node->size[0], node->size[1]); + MN_DrawTextNode(NULL, messagelist, font, node, nodepos[0], nodepos[1], node->size[0], node->size[1]); LIST_Delete(&messagelist); } } @@ -246,7 +251,7 @@ /* in the case of MN_BAR the first three data array values are float values - see menuDataValues_t */ fac = node->size[0] / (MN_GetReferenceFloat(menu, node->data[0]) - MN_GetReferenceFloat(menu, node->data[1])); bar_width = (MN_GetReferenceFloat(menu, node->data[2]) - MN_GetReferenceFloat(menu, node->data[1])) * fac; - R_DrawFill(node->pos[0], node->pos[1], bar_width, node->size[1], node->align, mouseOver ? color : node->color); + R_DrawFill(nodepos[0], nodepos[1], bar_width, node->size[1], node->align, mouseOver ? color : node->color); } break; @@ -259,7 +264,7 @@ shx = node->texl[0] + round(ps * node->pointWidth) + (ps > 0 ? floor((ps - 1) / 10) * node->gapWidth : 0); } else shx = node->texh[0]; - R_DrawNormPic(node->pos[0], node->pos[1], node->size[0], node->size[1], + R_DrawNormPic(nodepos[0], nodepos[1], node->size[0], node->size[1], shx, node->texh[1], node->texl[0], node->texl[1], node->align, node->blend, ref); } break; @@ -308,8 +313,8 @@ dragInfo.toNode = node; dragInfo.to = node->container; - dragInfo.toX = (mousePosX - node->pos[0] - itemX) / C_UNIT; - dragInfo.toY = (mousePosY - node->pos[1] - itemY) / C_UNIT; + dragInfo.toX = (mousePosX - nodepos[0] - itemX) / C_UNIT; + dragInfo.toY = (mousePosY - nodepos[1] - itemY) / C_UNIT; /** Check if the items already exists in the container. i.e. there is already at least one item. * @sa Com_AddToInventory */ @@ -384,7 +389,7 @@ CIN_PlayCinematic(node->data[MN_DATA_STRING_OR_IMAGE_OR_MODEL]); if (cls.playingCinematic) { /* only set replay to true if video was found and is running */ - CIN_SetParameters(node->pos[0], node->pos[1], node->size[0], node->size[1], CIN_STATUS_MENU, qtrue); + CIN_SetParameters(nodepos[0], nodepos[1], node->size[0], node->size[1], CIN_STATUS_MENU, qtrue); CIN_RunCinematic(); } } @@ -396,7 +401,7 @@ menu->hoverNode = node; if (mn_debugmenu->integer) - MN_DrawTooltip("f_small", node->name, node->pos[0], node->pos[1], node->size[1], 0); + MN_DrawTooltip("f_small", node->name, nodepos[0], nodepos[1], node->size[1], 0); R_ColorBlend(NULL); } /* if */ Index: src/client/menu/m_inventory.c =================================================================== --- src/client/menu/m_inventory.c (revision 19496) +++ src/client/menu/m_inventory.c (working copy) @@ -180,7 +180,7 @@ qboolean newRow = qfalse; vec2_t posMin; vec2_t posMax; - Vector2Copy(node->pos, posMin); + MN_GetNodeAbsPos(node, posMin); posMin[0] += curWidth; posMin[1] += curHeight; Vector2Copy(posMin, posMax); @@ -198,7 +198,7 @@ curWidth = maxHeight = 0; /* Re-calculate the min & max values for this item in the new row. */ - Vector2Copy(node->pos, posMin); + MN_GetNodeAbsPos(node, posMin); posMin[1] += curHeight; Vector2Copy(posMin, posMax); newRow = qtrue; @@ -297,16 +297,18 @@ if (mouseSpace == MS_MENU) { invList_t *ic; int fromX, fromY; - assert(node->container); /* Get coordinates inside a scrollable container (if it is one). */ if (node->container->scroll) { ic = MN_GetItemFromScrollableContainer(node, mouseX, mouseY, &fromX, &fromY); Com_DPrintf(DEBUG_CLIENT, "MN_Drag: item %i/%i selected from scrollable container.\n", fromX, fromY); } else { + vec2_t nodepos; + + MN_GetNodeAbsPos(node, nodepos); /* Normalize screen coordinates to container coordinates. */ - fromX = (int) (mouseX - node->pos[0]) / C_UNIT; - fromY = (int) (mouseY - node->pos[1]) / C_UNIT; + fromX = (int) (mouseX - nodepos[0]) / C_UNIT; + fromY = (int) (mouseY - nodepos[1]) / C_UNIT; ic = Com_SearchInInventory(menuInventory, node->container, fromX, fromY); } @@ -620,7 +622,10 @@ void MN_DrawDisabled (const menuNode_t* node) { const vec4_t color = { 0.3f, 0.3f, 0.3f, 0.7f }; - R_DrawFill(node->pos[0], node->pos[1], node->size[0], node->size[1], ALIGN_UL, color); + vec2_t nodepos; + + MN_GetNodeAbsPos(node, nodepos); + R_DrawFill(nodepos[0], nodepos[1], node->size[0], node->size[1], ALIGN_UL, color); } /** @@ -630,15 +635,18 @@ { const vec4_t color = { 0.0f, 1.0f, 0.0f, 0.7f }; invDef_t* inv = &csi.ids[container]; + vec2_t nodepos; + MN_GetNodeAbsPos(node, nodepos); R_DrawFill(posx, posy, sizex, sizey, ALIGN_UL, color); /* if showTUs is true (only the first time in none single containers) * and we are connected to a game */ - if (showTUs && cls.state == ca_active) - R_FontDrawString("f_verysmall", 0, node->pos[0] + 3, node->pos[1] + 3, - node->pos[0] + 3, node->pos[1] + 3, node->size[0] - 6, 0, 0, + if (showTUs && cls.state == ca_active){ + R_FontDrawString("f_verysmall", 0, nodepos[0] + 3, nodepos[1] + 3, + nodepos[0] + 3, nodepos[1] + 3, node->size[0] - 6, 0, 0, va(_("In: %i Out: %i"), inv->in, inv->out), 0, 0, NULL, qfalse); + } } /** @@ -648,8 +656,8 @@ void MN_InvDrawFree (inventory_t *inv, const menuNode_t *node) { objDef_t *od = dragInfo.item.t; /**< Get the 'type' of the dragged item. */ - qboolean showTUs = qtrue; + vec2_t nodepos; /* The shape of the free positions. */ uint32_t free[SHAPE_BIG_MAX_HEIGHT]; @@ -660,11 +668,12 @@ assert(mouseSpace == MS_DRAGITEM); assert(inv); + MN_GetNodeAbsPos(node, nodepos); /* if single container (hands, extension, headgear) */ if (node->container->single) { /* if container is free or the dragged-item is in it */ if (node->container == dragInfo.from || Com_CheckToInventory(inv, od, node->container, 0, 0, dragInfo.ic)) - MN_DrawFree(node->container->id, node, node->pos[0], node->pos[1], node->size[0], node->size[1], qtrue); + MN_DrawFree(node->container->id, node, nodepos[0], nodepos[1], node->size[0], node->size[1], qtrue); } else { memset(free, 0, sizeof(free)); for (y = 0; y < SHAPE_BIG_MAX_HEIGHT; y++) { @@ -681,7 +690,7 @@ /* Only draw on existing positions. */ if (Com_CheckShape(node->container->shape, x, y)) { if (Com_CheckShape(free, x, y)) { - MN_DrawFree(node->container->id, node, node->pos[0] + x * C_UNIT, node->pos[1] + y * C_UNIT, C_UNIT, C_UNIT, showTUs); + MN_DrawFree(node->container->id, node, nodepos[0] + x * C_UNIT, nodepos[1] + y * C_UNIT, C_UNIT, C_UNIT, showTUs); showTUs = qfalse; } } @@ -751,6 +760,7 @@ vec4_t color = {1, 1, 1, 1}; vec4_t colorLoadable = {0.5, 1, 0.5, 1}; qboolean drawLoadable = qfalse; + vec2_t nodepos; if (!node->container) MN_FindContainer(node); @@ -758,6 +768,7 @@ return NULL; assert(menuInventory); + MN_GetNodeAbsPos(node, nodepos); /* Highlight weapons that the dragged ammo (if it is one) can be loaded into. */ if (mouseSpace == MS_DRAGITEM && dragInfo.item.t) @@ -766,7 +777,7 @@ if (node->container->single) { /* Single container */ vec2_t pos; - Vector2Copy(node->pos, pos); + Vector2Copy(nodepos, pos); pos[0] += node->size[0] / 2.0; pos[1] += node->size[1] / 2.0; @@ -847,7 +858,7 @@ item_t tempItem = {1, NULL, NULL, 0, 0}; qboolean newRow = qfalse; vec2_t pos; - Vector2Copy(node->pos, pos); + Vector2Copy(nodepos, pos); pos[0] += curWidth; pos[1] += curHeight; @@ -864,7 +875,7 @@ curRow++; /* Re-calculate the position of this item in the new row. */ - Vector2Copy(node->pos, pos); + Vector2Copy(nodepos, pos); pos[1] += curHeight; newRow = qtrue; } @@ -927,7 +938,7 @@ if (icAmmo) { /* Calculate the center of the item model/image. */ pos[0] += tempItem.t->sx * C_UNIT / 2; - pos[1] = node->pos[1] + curHeight + icAmmo->item.t->sy * C_UNIT / 2.0; + pos[1] = nodepos[1] + curHeight + icAmmo->item.t->sy * C_UNIT / 2.0; curWidth += tempItem.t->sx * C_UNIT; @@ -975,9 +986,9 @@ for (ic = menuInventory->c[node->container->id]; ic; ic = ic->next) { assert(ic->item.t); if (drawLoadable && INVSH_LoadableInWeapon(dragInfo.item.t, ic->item.t)) - MN_DrawItem(node->pos, &ic->item, ic->x, ic->y, scale, colorLoadable); + MN_DrawItem(nodepos, &ic->item, ic->x, ic->y, scale, colorLoadable); else - MN_DrawItem(node->pos, &ic->item, ic->x, ic->y, scale, color); + MN_DrawItem(nodepos, &ic->item, ic->x, ic->y, scale, color); } } } @@ -997,8 +1008,8 @@ } else { return Com_SearchInInventory(menuInventory, node->container, - (mousePosX - node->pos[0]) / C_UNIT, - (mousePosY - node->pos[1]) / C_UNIT); + (mousePosX - nodepos[0]) / C_UNIT, + (mousePosY - nodepos[1]) / C_UNIT); } } @@ -1022,7 +1033,7 @@ /* We position the model of the item ourself (in the middle of the item * node). See the "-1, -1" parameter of MN_DrawItem. */ - Vector2Copy(node->pos, pos); + MN_GetNodeAbsPos(node, pos); pos[0] += node->size[0] / 2.0; pos[1] += node->size[1] / 2.0; MN_DrawItem(pos, &item, -1, -1, node->scale, color); Index: src/client/menu/m_input.c =================================================================== --- src/client/menu/m_input.c (revision 19496) +++ src/client/menu/m_input.c (working copy) @@ -125,8 +125,10 @@ { selectBoxOptions_t* selectBoxOption; int clickedAtOption; + vec2_t pos; - clickedAtOption = (y - node->pos[1]); + MN_GetNodeAbsPos(node, pos); + clickedAtOption = (y - pos[1]); if (node->size[1]) clickedAtOption = (clickedAtOption - node->size[1]) / node->size[1]; @@ -174,15 +176,17 @@ static void MN_BarClick (menu_t * menu, menuNode_t * node, int x) { char var[MAX_VAR]; + vec2_t pos; if (!node->mousefx) return; + MN_GetNodeAbsPos(node, pos); Q_strncpyz(var, node->data[2], sizeof(var)); /* no cvar? */ if (!Q_strncmp(var, "*cvar", 5)) { /* normalize it */ - const float frac = (float) (x - node->pos[0]) / node->size[0]; + const float frac = (float) (x - pos[0]) / node->size[0]; const float min = MN_GetReferenceFloat(menu, node->data[1]); const float value = min + frac * (MN_GetReferenceFloat(menu, node->data[0]) - min); /* in the case of MN_BAR the first three data array values are float values - see menuDataValues_t */ @@ -250,6 +254,8 @@ int row, col; assert(base); + assert(node); + assert(node->menu); if (gd.baseAction == BA_NEWBUILDING) { assert(base->buildingCurrent); @@ -302,12 +308,14 @@ int row, col; assert(base); + assert(node); + assert(node->menu); for (row = 0; row < BASE_SIZE; row++) for (col = 0; col < BASE_SIZE; col++) - if (base->map[row][col].building && x >= base->map[row][col].posX - && x < base->map[row][col].posX + node->size[0] / BASE_SIZE && y >= base->map[row][col].posY - && y < base->map[row][col].posY + node->size[1] / BASE_SIZE) { + if (base->map[row][col].building && x >= base->map[row][col].posX + node->menu->origin[0] + && x < base->map[row][col].posX + node->menu->origin[0] + node->size[0] / BASE_SIZE && y >= base->map[row][col].posY + node->menu->origin[1] + && y < base->map[row][col].posY + node->menu->origin[1] + node->size[1] / BASE_SIZE) { building_t *entry = base->map[row][col].building; if (!entry) Sys_Error("MN_BaseMapRightClick: no entry at %i:%i\n", x, y); Index: src/client/menu/m_messages.c =================================================================== --- src/client/menu/m_messages.c (revision 19496) +++ src/client/menu/m_messages.c (working copy) @@ -43,7 +43,8 @@ #ifdef DEBUG /** - * @brief Script command to delete all messages */ + * @brief Script command to delete all messages + */ static void CL_DeleteMessages_f (void) { message_t *m = mn.messageStack; Index: src/client/menu/m_nodes.c =================================================================== --- src/client/menu/m_nodes.c (revision 19496) +++ src/client/menu/m_nodes.c (working copy) @@ -29,6 +29,33 @@ extern menuNode_t *focusNode; +/** + * @brief Returns the absolute position of a menunode + * @param[in] menunode + * @param[out] pos + */ +void MN_GetNodeAbsPos (const menuNode_t* node, vec2_t pos) +{ + if (!node) + Sys_Error("MN_GetNodeAbsPos: No node given"); + if (!node->menu) + Sys_Error("MN_GetNodeAbsPos: Node '%s' has no menu", node->name); + + switch (node->type) { + case MN_NULL: + case MN_CONFUNC: + case MN_CVARFUNC: + case MN_FUNC: + break; + case MN_MODEL: + Vector2Set(pos, node->menu->origin[0] + node->origin[0], node->menu->origin[1] + node->origin[1]); + break; + default: + Vector2Set(pos, node->menu->origin[0] + node->pos[0], node->menu->origin[1] + node->pos[1]); + break; + } +} + #if 0 /** @todo to be integrated into MN_CheckNodeZone */ /** @@ -44,10 +71,12 @@ int width, height; /**< Width and height for the pic. */ int pic_x, pic_y; /**< Position inside image */ byte *color = NULL; /**< Pointer to specific pixel in image. */ + vec2_t nodepos; if (!node || node->type != MN_PIC || !node->data[MN_DATA_STRING_OR_IMAGE_OR_MODEL]) return qfalse; + MN_GetNodeAbsPos(node, nodepos); R_LoadImage(va("pics/menu/%s", path), &picture, &width, &height); if (!picture || !width || !height) { @@ -57,8 +86,8 @@ } /** @todo Get current location _inside_ image from global position. CHECKME */ - pic_x = x - node->pos[0]; - pic_y = y - node->pos[1]; + pic_x = x - nodepos[0]; + pic_y = y - nodepos[1]; if (pic_x < 0 || pic_y < 0) return qfalse; @@ -81,6 +110,7 @@ qboolean MN_CheckNodeZone (menuNode_t* const node, int x, int y) { int sx, sy, tx, ty, i; + vec2_t nodepos; /* don't hover nodes if we are executing an action on geoscape like rotating or moving */ if (mouseSpace >= MS_ROTATE && mouseSpace <= MS_SHIFT3DMAP) @@ -89,6 +119,7 @@ if (focusNode && mouseSpace != MS_NULL) return qfalse; + MN_GetNodeAbsPos(node, nodepos); switch (node->type) { case MN_CONTAINER: if (!node->container) @@ -97,7 +128,7 @@ return qfalse; /* check bounding box */ - if (x < node->pos[0] || x > node->pos[0] + node->size[0] || y < node->pos[1] || y > node->pos[1] + node->size[1]) + if (x < nodepos[0] || x > nodepos[0] + node->size[0] || y < nodepos[1] || y > nodepos[1] + node->size[1]) return qfalse; /* found a container */ @@ -146,7 +177,7 @@ int hoverOptionID; sy += (node->size[1] * node->height); /* hover a given entry in the list */ - hoverOptionID = (y - node->pos[1]); + hoverOptionID = (y - nodepos[1]); if (node->size[1]) hoverOptionID = (hoverOptionID - node->size[1]) / node->size[1]; @@ -159,17 +190,17 @@ } } - tx = x - node->pos[0]; - ty = y - node->pos[1]; + tx = x - nodepos[0]; + ty = y - nodepos[1]; if (node->align > 0 && node->align < ALIGN_LAST) { switch (node->align % 3) { /* center */ case 1: - tx = x - node->pos[0] + sx / 2; + tx = x - nodepos[0] + sx / 2; break; /* right */ case 2: - tx = x - node->pos[0] + sx; + tx = x - nodepos[0] + sx; break; } } @@ -178,8 +209,8 @@ return qfalse; for (i = 0; i < node->excludeNum; i++) { - if (x >= node->exclude[i].pos[0] && x <= node->exclude[i].pos[0] + node->exclude[i].size[0] - && y >= node->exclude[i].pos[1] && y <= node->exclude[i].pos[1] + node->exclude[i].size[1]) + if (x >= node->menu->origin[0] + node->exclude[i].pos[0] && x <= node->menu->origin[0] + node->exclude[i].pos[0] + node->exclude[i].size[0] + && y >= node->menu->origin[1] + node->exclude[i].pos[1] && y <= node->menu->origin[1] + node->exclude[i].pos[1] + node->exclude[i].size[1]) return qfalse; } Index: src/client/menu/m_menu.h =================================================================== --- src/client/menu/m_menu.h (revision 19496) +++ src/client/menu/m_menu.h (working copy) @@ -31,6 +31,7 @@ typedef struct menu_s { char name[MAX_VAR]; int eventTime; + vec2_t origin; /**< the position of the menu */ vec2_t noticePos; /**< the position where the cl.msgText messages are rendered */ struct menuNode_s *firstNode, *initNode, *closeNode, *renderNode; struct menuNode_s *popupNode, *hoverNode, *eventNode, *leaveNode; Index: src/client/menu/m_parse.c =================================================================== --- src/client/menu/m_parse.c (revision 19496) +++ src/client/menu/m_parse.c (working copy) @@ -614,6 +614,7 @@ int i; lastNode = NULL; + Vector2Set(menu->origin, 0, 0); /* if inheriting another menu, link in the super menu's nodes */ for (node = menu->firstNode; node; node = node->next) { @@ -657,6 +658,13 @@ return qfalse; Com_ParseValue(menu->noticePos, token, V_POS, 0, sizeof(vec2_t)); found = qtrue; + } else if (!Q_strcmp(token, "origin")) { + /* get new token */ + token = COM_EParse(text, errhead, menu->name); + if (!*text) + return qfalse; + Com_ParseValue(menu->origin, token, V_POS, 0, sizeof(vec2_t)); + found = qtrue; } else Com_Printf("Invalid special menu value '%s'\n", token); } while (found); Index: src/client/menu/m_nodes.h =================================================================== --- src/client/menu/m_nodes.h (revision 19496) +++ src/client/menu/m_nodes.h (working copy) @@ -173,6 +173,7 @@ menuNode_t* MN_GetNodeFromCurrentMenu(const char *name); void MN_SetNewNodePos(menuNode_t* node, int x, int y); menuNode_t *MN_GetNode(const menu_t* const menu, const char *name); +void MN_GetNodeAbsPos (const menuNode_t* node, vec2_t pos); void MN_InitNodes(void); Index: src/client/menu/m_main.c =================================================================== --- src/client/menu/m_main.c (revision 19496) +++ src/client/menu/m_main.c (working copy) @@ -294,8 +294,30 @@ return NULL; } +/** + * @brief Sets new x and y coordinates for a given menu + */ +void MN_SetNewMenuPos (menu_t* menu, int x, int y) +{ + if (menu) { + Vector2Set(menu->origin, x, y); + } +} /** + * @brief Console command for moving a menu + */ +void MN_SetNewMenuPos_f (void) +{ + menu_t* menu = MN_GetActiveMenu(); + + if (Cmd_Argc() < 3) + Com_Printf("Usage: %s \n", Cmd_Argv(0)); + + MN_SetNewMenuPos (menu, atoi(Cmd_Argv(1)), atoi(Cmd_Argv(2))); +} + +/** * @brief This will reinit the current visible menu * @note also available as script command mn_reinit */ @@ -634,6 +656,8 @@ Cmd_AddCommand("scrollcont_next", MN_ScrollContainerNext_f, "Scrolls the current container (forward)."); Cmd_AddCommand("scrollcont_prev", MN_ScrollContainerPrev_f, "Scrolls the current container (backward)."); + Cmd_AddCommand("mn_move", MN_SetNewMenuPos_f, "Moves the menu to a new position."); + /* 256kb */ /** @todo Get rid of adata, curadata and adataize */ mn.adataize = MENU_HUNK_SIZE; Index: src/client/menu/m_node_image.c =================================================================== --- src/client/menu/m_node_image.c (revision 19496) +++ src/client/menu/m_node_image.c (working copy) @@ -4,7 +4,9 @@ void MN_DrawImageNode (menuNode_t *node, const char *imageName, int time) { vec2_t size; + vec2_t nodepos; + MN_GetNodeAbsPos(node, nodepos); /* HACK for ekg pics */ if (!Q_strncmp(node->name, "ekg_", 4)) { int pt; @@ -35,6 +37,6 @@ } else { Vector2Copy(node->size, size); } - R_DrawNormPic(node->pos[0], node->pos[1], size[0], size[1], + R_DrawNormPic(nodepos[0], nodepos[1], size[0], size[1], node->texh[0], node->texh[1], node->texl[0], node->texl[1], node->align, node->blend, imageName); } Index: src/client/menu/m_main.h =================================================================== --- src/client/menu/m_main.h (revision 19496) +++ src/client/menu/m_main.h (working copy) @@ -92,7 +92,9 @@ void MN_Shutdown(void); qboolean MN_CheckCondition(menuNode_t *node); int MN_GetVisibleMenuCount(void); +void MN_SetNewMenuPos (menu_t* menu, int x, int y); +void MN_SetNewMenuPos_f (void); void MN_ScrollContainerUpdate_f(void); void MN_ScrollContainerNext_f(void); void MN_ScrollContainerPrev_f(void); Index: src/client/menu/m_node_radar.c =================================================================== --- src/client/menu/m_node_radar.c (revision 19496) +++ src/client/menu/m_node_radar.c (working copy) @@ -250,12 +250,14 @@ const vec3_t offset = {MAP_SIZE_OFFSET, MAP_SIZE_OFFSET, MAP_SIZE_OFFSET}; float distAB, distBC; vec2_t gridSize; /**< Size of the whole grid (in tiles units) */ + vec2_t nodepos; MN_FreeRadarImages(); MN_BuildRadarImageList(cl.configstrings[CS_TILES], cl.configstrings[CS_POSITIONS]); - radar.x = node->pos[0]; - radar.y = node->pos[1]; + MN_GetNodeAbsPos(node, nodepos); + radar.x = nodepos[0]; + radar.y = nodepos[1]; /* only check once per map whether all the needed images exist */ for (i = 0; i < PATHFINDING_HEIGHT; i++) { Index: src/client/menu/m_node_model.c =================================================================== --- src/client/menu/m_node_model.c (revision 19496) +++ src/client/menu/m_node_model.c (working copy) @@ -190,10 +190,17 @@ animState_t *as; const char *anim; /* model anim state */ menuModel_t *menuModel, *menuModelParent = NULL; - /* if true we have to reset the anim state and make sure the correct model is shown */ qboolean updateModel = qfalse; + vec2_t nodepos; + static vec3_t nodeorigin; + static vec3_t pmiorigin; + MN_GetNodeAbsPos(node, nodepos); + nodeorigin[0] = nodepos[0]; + nodeorigin[1] = nodepos[1]; + nodeorigin[3] = node->origin[2]; + menuModel = node->menuModel = MN_GetMenuModel(source); /* direct model name - no menumodel definition */ @@ -214,7 +221,7 @@ updateModel = qtrue; } - mi.origin = node->origin; + mi.origin = nodeorigin; mi.angles = node->angles; mi.scale = node->scale; mi.center = node->center; @@ -274,9 +281,9 @@ /* Use menu origin if defined. */ if (menuModel->menuTransform[i].useOrigin) { - VectorAdd(node->origin, menuModel->menuTransform[i].origin, mi.origin); + VectorAdd(nodeorigin, menuModel->menuTransform[i].origin, mi.origin); } else { - VectorCopy(node->origin, mi.origin); + VectorCopy(nodeorigin, mi.origin); } break; } @@ -285,12 +292,12 @@ if (i == menuModel->menuTransformCnt) { VectorCopy(node->scale, mi.scale); VectorCopy(node->angles, mi.angles); - VectorCopy(node->origin, mi.origin); + VectorCopy(nodeorigin, mi.origin); } } else { VectorCopy(node->scale, mi.scale); VectorCopy(node->angles, mi.angles); - VectorCopy(node->origin, mi.origin); + VectorCopy(nodeorigin, mi.origin); } Vector4Copy(node->color, mi.color); VectorCopy(node->center, mi.center); @@ -334,7 +341,13 @@ } pmi.name = menuModelParent->model; - pmi.origin = menuModelParent->origin; + pmi.origin = pmiorigin; + pmi.origin[0] = menuModelParent->origin[0] + mi.origin[0]; + pmi.origin[1] = menuModelParent->origin[1] + mi.origin[1]; + pmi.origin[2] = menuModelParent->origin[2]; + /* don't count menuoffset twice for tagged models */ + mi.origin[0] -= node->menu->origin[0]; + mi.origin[1] -= node->menu->origin[1]; pmi.angles = menuModelParent->angles; pmi.scale = menuModelParent->scale; pmi.center = menuModelParent->center; @@ -419,7 +432,13 @@ break; pmi.name = modelName; - pmi.origin = search->origin; + VectorCopy(search->origin, pmiorigin); + pmi.origin = pmiorigin; + pmi.origin[0] += mi.origin[0]; + pmi.origin[1] += mi.origin[1]; + /* don't count menuoffset twice for tagged models */ + mi.origin[0] -= node->menu->origin[0]; + mi.origin[1] -= node->menu->origin[1]; pmi.angles = search->angles; pmi.scale = search->scale; pmi.center = search->center; Index: src/client/cl_screen.c =================================================================== --- src/client/cl_screen.c (revision 19496) +++ src/client/cl_screen.c (working copy) @@ -327,10 +327,13 @@ dragInfo.item.rotated = qtrue; if (checkedTo && Q_strncmp(dragInfo.item.t->type, "armour", MAX_VAR)) { /* If the item fits somehow and it's not armour */ + vec2_t nodepos; + + MN_GetNodeAbsPos(dragInfo.toNode, nodepos); if (dragInfo.to->single) { /* Get center of single container for placement of preview item */ VectorSet(org, - dragInfo.toNode->pos[0] + dragInfo.toNode->size[0] / 2.0, - dragInfo.toNode->pos[1] + dragInfo.toNode->size[1] / 2.0, + nodepos[0] + dragInfo.toNode->size[0] / 2.0, + nodepos[1] + dragInfo.toNode->size[1] / 2.0, -40); } else { /* This is a "grid" container - we need to calculate the item-position @@ -338,13 +341,13 @@ * calculated rotation info. */ if (dragInfo.item.rotated) VectorSet(org, - dragInfo.toNode->pos[0] + (dragInfo.toX + dragInfo.item.t->sy / 2.0) * C_UNIT, - dragInfo.toNode->pos[1] + (dragInfo.toY + dragInfo.item.t->sx / 2.0) * C_UNIT, + nodepos[0] + (dragInfo.toX + dragInfo.item.t->sy / 2.0) * C_UNIT, + nodepos[1] + (dragInfo.toY + dragInfo.item.t->sx / 2.0) * C_UNIT, -40); else VectorSet(org, - dragInfo.toNode->pos[0] + (dragInfo.toX + dragInfo.item.t->sx / 2.0) * C_UNIT, - dragInfo.toNode->pos[1] + (dragInfo.toY + dragInfo.item.t->sy / 2.0) * C_UNIT, + nodepos[0] + (dragInfo.toX + dragInfo.item.t->sx / 2.0) * C_UNIT, + nodepos[1] + (dragInfo.toY + dragInfo.item.t->sy / 2.0) * C_UNIT, -40); } Vector4Set(color, 0.5, 0.5, 1, 1); /**< Make the preview item look blueish */