/** * @brief Draw to dragging object and catch mouse move event */ void UI_DrawDragAndDrop (int mousePosX, int mousePosY) { const vec3_t scale = { 3.5, 3.5, 3.5 }; vec3_t orgine; vec4_t color = { 1, 1, 1, 1 }; /* check mouse move */ if (mousePosX != oldMousePosX || mousePosY != oldMousePosY) { oldMousePosX = mousePosX; oldMousePosY = mousePosY; UI_DNDMouseMove(mousePosX, mousePosY); } /* draw the dragging item */ VectorSet(orgine, mousePosX, mousePosY, -50); /* Tune down the opacity of the cursor-item if the preview item is drawn. */ if (positionAcceptDND) color[3] = 0.2; switch (objectType) { case DND_ITEM: UI_DrawItem(nullptr, orgine, &draggingItem, -1, -1, scale, color); break; default: assert(false); } }
/** * @brief Draw an item node */ void uiItemNode::draw (uiNode_t* node) { const objDef_t* od; const char* ref = UI_GetReferenceString(node, EXTRADATA(node).model); vec2_t pos; if (Q_strnull(ref)) return; UI_GetNodeAbsPos(node, pos); R_CleanupDepthBuffer(pos[0], pos[1], node->box.size[0], node->box.size[1]); od = INVSH_GetItemByIDSilent(ref); if (od) { Item item(od, nullptr, 1); /* 1 so it's not reddish; fake item anyway */ const char* model = GAME_GetModelForItem(item.def(), nullptr); if (EXTRADATA(node).containerLike || Q_strnull(model)) { const vec4_t color = {1, 1, 1, 1}; vec3_t itemNodePos; /* We position the model of the item ourself (in the middle of the item * node). See the "-1, -1" parameter of UI_DrawItem. */ UI_GetNodeAbsPos(node, itemNodePos); itemNodePos[0] += node->box.size[0] / 2.0; itemNodePos[1] += node->box.size[1] / 2.0; itemNodePos[2] = 0; /** @todo we should not use DrawItem but draw the image with render function (remove dependency with container) */ UI_DrawItem(node, itemNodePos, &item, -1, -1, EXTRADATA(node).scale, color); } else { UI_DrawModelNode(node, model); } } else { GAME_DisplayItemInfo(node, ref); } }
/** * @brief Draw a grip container */ static void UI_ContainerNodeDrawGrid (uiNode_t *node, const objDef_t *highlightType) { const invList_t *ic; vec3_t pos; UI_GetNodeAbsPos(node, pos); pos[2] = 0; for (ic = ui_inventory->c[EXTRADATA(node).container->id]; ic; ic = ic->next) { assert(ic->item.item); if (highlightType && INVSH_LoadableInWeapon(highlightType, ic->item.item)) UI_DrawItem(node, pos, &ic->item, ic->x, ic->y, scale, colorLoadable); else UI_DrawItem(node, pos, &ic->item, ic->x, ic->y, scale, colorDefault); } }
/** * @brief Draw a preview of the DND item dropped into the node */ static void UI_ContainerNodeDrawDropPreview (uiNode_t *target) { item_t previewItem; int checkedTo; vec3_t origine; /* no preview into scrollable list */ if (UI_IsScrollContainerNode(target)) return; /* copy the DND item to not change the original one */ previewItem = *UI_DNDGetItem(); previewItem.rotated = false; checkedTo = INVSH_CheckToInventory(ui_inventory, previewItem.item, EXTRADATA(target).container, dragInfoToX, dragInfoToY, dragInfoIC); switch (checkedTo) { case INV_DOES_NOT_FIT: return; case INV_FITS: break; case INV_FITS_BOTH: /** @todo enable Shift-rotate for battlescape too when issues are solved */ if (!Key_IsDown(K_SHIFT) || CL_BattlescapeRunning()) break; case INV_FITS_ONLY_ROTATED: previewItem.rotated = true; } /* Hack, no preview for armour, we don't want it out of the armour container (and armour container is not visible) */ if (INV_IsArmour(previewItem.item)) return; UI_GetNodeAbsPos(target, origine); origine[2] = -40; /* Get center of single container for placement of preview item */ if (EXTRADATA(target).container->single) { origine[0] += target->box.size[0] / 2.0; origine[1] += target->box.size[1] / 2.0; /* This is a "grid" container - we need to calculate the item-position * (on the screen) from stored placement in the container and the * calculated rotation info. */ } else { if (previewItem.rotated) { origine[0] += (dragInfoToX + previewItem.item->sy / 2.0) * C_UNIT; origine[1] += (dragInfoToY + previewItem.item->sx / 2.0) * C_UNIT; } else { origine[0] += (dragInfoToX + previewItem.item->sx / 2.0) * C_UNIT; origine[1] += (dragInfoToY + previewItem.item->sy / 2.0) * C_UNIT; } } UI_DrawItem(NULL, origine, &previewItem, -1, -1, scale, colorPreview); }
/** * @brief Draw the base inventory * @return The full height requested by the current view (not the node height) */ static int UI_BaseInventoryNodeDrawItems (uiNode_t* node, const objDef_t* highlightType) { bool outOfNode = false; vec2_t nodepos; int items = 0; int rowHeight = 0; const int cellWidth = node->box.size[0] / EXTRADATA(node).columns; containerItemIterator_t iterator; int currentHeight = 0; UI_GetNodeAbsPos(node, nodepos); UI_ContainerItemIteratorInit(&iterator, node); for (; iterator.itemID < csi.numODs; UI_ContainerItemIteratorNext(&iterator)) { const int id = iterator.itemID; const objDef_t* obj = INVSH_GetItemByIDX(id); Item tempItem(obj, nullptr, 1); vec3_t pos; vec3_t ammopos; const float* color; bool isHighlight = false; int amount; const int col = items % EXTRADATA(node).columns; int cellHeight = 0; const Item* icItem = iterator.itemFound; /* skip items over and bellow the node view */ if (outOfNode || currentHeight < EXTRADATA(node).scrollY.viewPos) { int height; R_FontTextSize("f_verysmall", _(obj->name), cellWidth - 5, LONGLINES_WRAP, nullptr, &height, nullptr, nullptr); height += obj->sy * C_UNIT + 10; if (height > rowHeight) rowHeight = height; if (outOfNode || currentHeight + rowHeight < EXTRADATA(node).scrollY.viewPos) { if (col == EXTRADATA(node).columns - 1) { currentHeight += rowHeight; rowHeight = 0; } items++; continue; } } Vector2Copy(nodepos, pos); pos[0] += cellWidth * col; pos[1] += currentHeight - EXTRADATA(node).scrollY.viewPos; pos[2] = 0; if (highlightType) { if (obj->isAmmo()) isHighlight = obj->isLoadableInWeapon(highlightType); else isHighlight = highlightType->isLoadableInWeapon(obj); } if (icItem != nullptr) { if (isHighlight) color = colorLoadable; else color = colorDefault; } else { if (isHighlight) color = colorDisabledLoadable; else color = colorDisabledHiden; } if (icItem) amount = icItem->getAmount(); else amount = 0; /* draw item */ pos[0] += obj->sx * C_UNIT / 2.0; pos[1] += obj->sy * C_UNIT / 2.0; UI_DrawItem(node, pos, &tempItem, -1, -1, scale, color); UI_DrawString("f_verysmall", ALIGN_LC, pos[0] + obj->sx * C_UNIT / 2.0, pos[1] + obj->sy * C_UNIT / 2.0, pos[0] + obj->sx * C_UNIT / 2.0, cellWidth - 5, /* maxWidth */ 0, va("x%i", amount)); pos[0] -= obj->sx * C_UNIT / 2.0; pos[1] += obj->sy * C_UNIT / 2.0; cellHeight += obj->sy * C_UNIT; /* save position for ammo */ Vector2Copy(pos, ammopos); ammopos[2] = 0; ammopos[0] += obj->sx * C_UNIT + 10; /* draw the item name. */ cellHeight += UI_DrawString("f_verysmall", ALIGN_UL, pos[0], pos[1], pos[0], cellWidth - 5, /* max width */ 0, _(obj->name)); /* draw ammos of weapon */ if (obj->weapon && EXTRADATA(node).displayAmmoOfWeapon) { for (int ammoIdx = 0; ammoIdx < obj->numAmmos; ammoIdx++) { tempItem.setDef(obj->ammos[ammoIdx]); /* skip weapos that are their own ammo -- oneshot and such */ if (obj == tempItem.def()) continue; /* skip unusable ammo */ if (!GAME_ItemIsUseable(tempItem.def())) continue; /* find and skip none existing ammo */ icItem = UI_ContainerNodeGetExistingItem(node, tempItem.def(), (itemFilterTypes_t) EXTRADATA(node).filterEquipType); if (!icItem) continue; /* Calculate the center of the item model/image. */ ammopos[0] += icItem->def()->sx * C_UNIT / 2.0; ammopos[1] -= icItem->def()->sy * C_UNIT / 2.0; UI_DrawItem(node, ammopos, &tempItem, -1, -1, scale, colorDefault); UI_DrawString("f_verysmall", ALIGN_LC, ammopos[0] + icItem->def()->sx * C_UNIT / 2.0, ammopos[1] + icItem->def()->sy * C_UNIT / 2.0, ammopos[0] + icItem->def()->sx * C_UNIT / 2.0, cellWidth - 5 - ammopos[0], /* maxWidth */ 0, va("x%i", icItem->getAmount())); ammopos[0] += icItem->def()->sx * C_UNIT / 2.0; ammopos[1] += icItem->def()->sy * C_UNIT / 2.0; } } cellHeight += 10; if (cellHeight > rowHeight) { rowHeight = cellHeight; } /* add a marge between rows */ if (col == EXTRADATA(node).columns - 1) { currentHeight += rowHeight; rowHeight = 0; if (currentHeight - EXTRADATA(node).scrollY.viewPos >= node->box.size[1]) outOfNode = true; } /* count items */ items++; } if (rowHeight != 0) { currentHeight += rowHeight; } return currentHeight; }
/** * @brief Draw a container which only contains one item * @param node Context node * @param highlightType Current selected object */ static void UI_ContainerNodeDrawSingle (uiNode_t *node, const objDef_t *highlightType) { vec4_t color; vec3_t pos; UI_GetNodeAbsPos(node, pos); pos[0] += node->box.size[0] / 2.0; pos[1] += node->box.size[1] / 2.0; pos[2] = 0; /* Single item container (special case for left hand). */ if (INV_IsLeftDef(EXTRADATA(node).container) && !ui_inventory->c[csi.idLeft]) { if (ui_inventory->c[csi.idRight]) { const item_t *item = &ui_inventory->c[csi.idRight]->item; assert(item); assert(item->item); if (item->item->holdTwoHanded) { if (highlightType && INVSH_LoadableInWeapon(highlightType, item->item)) memcpy(color, colorLoadable, sizeof(vec4_t)); else memcpy(color, colorDefault, sizeof(vec4_t)); color[3] = 0.5; UI_DrawItem(node, pos, item, -1, -1, scale, color); } } } else if (ui_inventory->c[EXTRADATA(node).container->id]) { bool disabled = false; const item_t *item; if (ui_inventory->c[csi.idRight]) { item = &ui_inventory->c[csi.idRight]->item; /* If there is a weapon in the right hand that needs two hands to shoot it * and there is a weapon in the left, then draw a disabled marker for the * fireTwoHanded weapon. */ assert(item); assert(item->item); if (INV_IsRightDef(EXTRADATA(node).container) && item->item->fireTwoHanded && ui_inventory->c[csi.idLeft]) { disabled = true; UI_DrawDisabled(node); } } item = &ui_inventory->c[EXTRADATA(node).container->id]->item; assert(item); assert(item->item); if (highlightType && INVSH_LoadableInWeapon(highlightType, item->item)) { if (disabled) Vector4Copy(colorDisabledLoadable, color); else Vector4Copy(colorLoadable, color); } else { if (disabled) Vector4Copy(colorDisabled, color); else Vector4Copy(colorDefault, color); } if (disabled) color[3] = 0.5; UI_DrawItem(node, pos, item, -1, -1, scale, color); } }