UFO: Alien Invasion
Loading...
Searching...
No Matches
ui_node_baseinventory.cpp
Go to the documentation of this file.
1
7
8/*
9Copyright (C) 2002-2025 UFO: Alien Invasion.
10
11This program is free software; you can redistribute it and/or
12modify it under the terms of the GNU General Public License
13as published by the Free Software Foundation; either version 2
14of the License, or (at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
20See the GNU General Public License for more details.
21
22You should have received a copy of the GNU General Public License
23along with this program; if not, write to the Free Software
24Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26*/
27
28#include "../ui_main.h"
29#include "../ui_parse.h"
30#include "../ui_behaviour.h"
31#include "../ui_actions.h"
32#include "../ui_dragndrop.h"
33#include "../ui_tooltip.h"
34#include "../ui_nodes.h"
35#include "../ui_input.h"
36#include "../ui_render.h"
37#include "../ui_lua.h"
38
40#include "ui_node_model.h"
41#include "ui_node_container.h"
44
45#include "../../cl_shared.h"
46#include "../../cgame/cl_game.h"
47#include "../../input/cl_keys.h"
48#include "../../cl_inventory.h"
49
51
52#define EXTRADATA_TYPE baseInventoryExtraData_t
53#define EXTRADATA(node) UI_EXTRADATA(node, EXTRADATA_TYPE)
54#define EXTRADATACONST(node) UI_EXTRADATACONST(node, EXTRADATA_TYPE)
55
56extern bool CL_BattlescapeRunning(void);
57extern cvar_t* cl_selected;
58
63static int dragInfoFromX = -1;
64static int dragInfoFromY = -1;
65
70static const Item* dragInfoIC;
71
82static Item* UI_ContainerNodeGetExistingItem (const uiNode_t* node, const objDef_t* item, const itemFilterTypes_t filterType)
83{
84 if (ui_inventory == nullptr) {
85 Com_Printf("ERROR: UI Inventory is not initialized in UI_ContainerNodeGetExistingItem!\n");
86 return nullptr;
87 }
88 return INV_SearchInInventoryWithFilter(ui_inventory, EXTRADATACONST(node).super.container, item, filterType);
89}
90
94#define CII_AMMOONLY 0x01
95#define CII_WEAPONONLY 0x02
96#define CII_AVAILABLEONLY 0x04
97#define CII_NOTAVAILABLEONLY 0x08
98#define CII_IMPLANTONLY 0x10
99#define CII_END 0x80
100
110
118{
119 assert(iterator->groupSteps[iterator->groupID] != CII_END);
120
121 /* iterate each groups */
122 for (; iterator->groupSteps[iterator->groupID] != CII_END; iterator->groupID++) {
123 int filter = iterator->groupSteps[iterator->groupID];
124 /* next */
125 iterator->itemID++;
126
127 /* iterate all item type*/
128 for (;iterator->itemID < csi.numODs; iterator->itemID++) {
129 const objDef_t* obj = INVSH_GetItemByIDX(iterator->itemID);
130
131 /* gameplay filter */
132 if (!GAME_ItemIsUseable(obj))
133 continue;
134
135 /* type filter */
137 const bool isArmour = obj->isArmour();
138 const bool isAmmo = obj->numWeapons != 0 && obj->isAmmo();
139 const bool isWeapon = obj->weapon || obj->isMisc || isArmour;
140 const bool isImplant = obj->implant;
141
142 if ((filter & CII_WEAPONONLY) && !isWeapon)
143 continue;
144 if ((filter & CII_AMMOONLY) && !isAmmo)
145 continue;
146 if ((filter & CII_IMPLANTONLY) && !isImplant)
147 continue;
148 if (!INV_ItemMatchesFilter(obj, iterator->filterEquipType))
149 continue;
150
151 /* exists in inventory filter */
152 iterator->itemFound = UI_ContainerNodeGetExistingItem(iterator->node, obj, iterator->filterEquipType);
153 if ((filter & CII_AVAILABLEONLY) && iterator->itemFound == nullptr)
154 continue;
155 if ((filter & CII_NOTAVAILABLEONLY) && iterator->itemFound != nullptr)
156 continue;
157
158 /* we found something */
159 return;
160 }
161
162 /* can we search into another group? */
163 if (iterator->groupSteps[iterator->groupID + 1] != CII_END)
164 iterator->itemID = -1;
165 }
166
167 /* clean up */
168 iterator->itemFound = nullptr;
169}
170
174static void UI_ContainerItemIteratorInit (containerItemIterator_t* iterator, const uiNode_t* const node)
175{
176 int groupID = 0;
177 iterator->itemID = -1;
178 iterator->groupID = 0;
179 iterator->node = node;
180 iterator->filterEquipType = (itemFilterTypes_t) EXTRADATACONST(node).filterEquipType;
181
182 if (EXTRADATACONST(node).displayAvailableOnTop) {
183 /* available items */
184 if (EXTRADATACONST(node).displayWeapon)
185 iterator->groupSteps[groupID++] = CII_WEAPONONLY | CII_AVAILABLEONLY;
186 if (EXTRADATACONST(node).displayAmmo)
187 iterator->groupSteps[groupID++] = CII_AMMOONLY | CII_AVAILABLEONLY;
188 if (EXTRADATACONST(node).displayImplant)
189 iterator->groupSteps[groupID++] = CII_IMPLANTONLY | CII_AVAILABLEONLY;
190 /* unavailable items */
191 if (EXTRADATACONST(node).displayUnavailableItem) {
192 if (EXTRADATACONST(node).displayWeapon)
193 iterator->groupSteps[groupID++] = CII_WEAPONONLY | CII_NOTAVAILABLEONLY;
194 if (EXTRADATACONST(node).displayAmmo)
195 iterator->groupSteps[groupID++] = CII_AMMOONLY | CII_NOTAVAILABLEONLY;
196 if (EXTRADATACONST(node).displayImplant)
197 iterator->groupSteps[groupID++] = CII_IMPLANTONLY | CII_NOTAVAILABLEONLY;
198 }
199 } else {
200 const int filter = (EXTRADATACONST(node).displayUnavailableItem) ? 0 : CII_AVAILABLEONLY;
201 if (EXTRADATACONST(node).displayWeapon)
202 iterator->groupSteps[groupID++] = CII_WEAPONONLY | filter;
203 if (EXTRADATACONST(node).displayAmmo)
204 iterator->groupSteps[groupID++] = CII_AMMOONLY | filter;
205 if (EXTRADATACONST(node).displayImplant)
206 iterator->groupSteps[groupID++] = CII_IMPLANTONLY | filter;
207 }
208 iterator->groupSteps[groupID++] = CII_END;
209
210 /* find the first item */
212}
213
219{
220 if (EXTRADATA(node).onViewChange) {
221 UI_ExecuteEventActions(node, EXTRADATA(node).onViewChange);
222 }
223 else if (EXTRADATA(node).lua_onViewChange != LUA_NOREF) {
224 UI_ExecuteLuaEventScript (node, EXTRADATA(node).lua_onViewChange);
225 }
226}
227
234{
235 EXTRADATA(node).super.container = INVSH_GetInventoryDefinitionByID("equip");
236}
237
238static const vec3_t scale = {3.5, 3.5, 3.5};
240static const vec4_t colorDefault = {1, 1, 1, 1};
241static const vec4_t colorLoadable = {0.5, 1, 0.5, 1};
242static const vec4_t colorDisabledHiden = {0.5, 0.5, 0.5, 0.5};
243static const vec4_t colorDisabledLoadable = {0.5, 0.25, 0.25, 1.0};
244
249static int UI_BaseInventoryNodeDrawItems (uiNode_t* node, const objDef_t* highlightType)
250{
251 bool outOfNode = false;
252 vec2_t nodepos;
253 int items = 0;
254 int rowHeight = 0;
255 const int cellWidth = node->box.size[0] / EXTRADATA(node).columns;
257 int currentHeight = 0;
258 UI_GetNodeAbsPos(node, nodepos);
259
260 UI_ContainerItemIteratorInit(&iterator, node);
261 for (; iterator.itemID < csi.numODs; UI_ContainerItemIteratorNext(&iterator)) {
262 const int id = iterator.itemID;
263 const objDef_t* obj = INVSH_GetItemByIDX(id);
264 Item tempItem(obj, nullptr, 1);
265 vec3_t pos;
266 vec3_t ammopos;
267 const float* color;
268 bool isHighlight = false;
269 int amount;
270 const int col = items % EXTRADATA(node).columns;
271 int cellHeight = 0;
272 const Item* icItem = iterator.itemFound;
273
274 /* skip items over and bellow the node view */
275 if (outOfNode || currentHeight < EXTRADATA(node).scrollY.viewPos) {
276 int height;
277 R_FontTextSize("f_verysmall", _(obj->name),
278 cellWidth - 5, LONGLINES_WRAP, nullptr, &height, nullptr, nullptr);
279 height += obj->sy * C_UNIT + 10;
280 if (height > rowHeight)
281 rowHeight = height;
282
283 if (outOfNode || currentHeight + rowHeight < EXTRADATA(node).scrollY.viewPos) {
284 if (col == EXTRADATA(node).columns - 1) {
285 currentHeight += rowHeight;
286 rowHeight = 0;
287 }
288 items++;
289 continue;
290 }
291 }
292
293 Vector2Copy(nodepos, pos);
294 pos[0] += cellWidth * col;
295 pos[1] += currentHeight - EXTRADATA(node).scrollY.viewPos;
296 pos[2] = 0;
297
298 if (highlightType) {
299 if (obj->isAmmo())
300 isHighlight = obj->isLoadableInWeapon(highlightType);
301 else
302 isHighlight = highlightType->isLoadableInWeapon(obj);
303 }
304
305 if (icItem != nullptr) {
306 if (isHighlight)
307 color = colorLoadable;
308 else
309 color = colorDefault;
310 } else {
311 if (isHighlight)
312 color = colorDisabledLoadable;
313 else
314 color = colorDisabledHiden;
315 }
316
317 if (icItem)
318 amount = icItem->getAmount();
319 else
320 amount = 0;
321
322 /* draw item */
323 pos[0] += obj->sx * C_UNIT / 2.0;
324 pos[1] += obj->sy * C_UNIT / 2.0;
325 UI_DrawItem(node, pos, &tempItem, -1, -1, scale, color);
326 UI_DrawString("f_verysmall", ALIGN_LC,
327 pos[0] + obj->sx * C_UNIT / 2.0, pos[1] + obj->sy * C_UNIT / 2.0,
328 pos[0] + obj->sx * C_UNIT / 2.0, cellWidth - 5, /* maxWidth */
329 0, va("x%i", amount));
330 pos[0] -= obj->sx * C_UNIT / 2.0;
331 pos[1] += obj->sy * C_UNIT / 2.0;
332 cellHeight += obj->sy * C_UNIT;
333
334 /* save position for ammo */
335 Vector2Copy(pos, ammopos);
336 ammopos[2] = 0;
337 ammopos[0] += obj->sx * C_UNIT + 10;
338
339 /* draw the item name. */
340 cellHeight += UI_DrawString("f_verysmall", ALIGN_UL,
341 pos[0], pos[1],
342 pos[0], cellWidth - 5, /* max width */
343 0, _(obj->name));
344
345 /* draw ammos of weapon */
346 if (obj->weapon && EXTRADATA(node).displayAmmoOfWeapon) {
347 for (int ammoIdx = 0; ammoIdx < obj->numAmmos; ammoIdx++) {
348 tempItem.setDef(obj->ammos[ammoIdx]);
349
350 /* skip weapos that are their own ammo -- oneshot and such */
351 if (obj == tempItem.def())
352 continue;
353
354 /* skip unusable ammo */
355 if (!GAME_ItemIsUseable(tempItem.def()))
356 continue;
357
358 /* find and skip none existing ammo */
359 icItem = UI_ContainerNodeGetExistingItem(node, tempItem.def(), (itemFilterTypes_t) EXTRADATA(node).filterEquipType);
360 if (!icItem)
361 continue;
362
363 /* Calculate the center of the item model/image. */
364 ammopos[0] += icItem->def()->sx * C_UNIT / 2.0;
365 ammopos[1] -= icItem->def()->sy * C_UNIT / 2.0;
366 UI_DrawItem(node, ammopos, &tempItem, -1, -1, scale, colorDefault);
367 UI_DrawString("f_verysmall", ALIGN_LC,
368 ammopos[0] + icItem->def()->sx * C_UNIT / 2.0, ammopos[1] + icItem->def()->sy * C_UNIT / 2.0,
369 ammopos[0] + icItem->def()->sx * C_UNIT / 2.0, cellWidth - 5 - ammopos[0], /* maxWidth */
370 0, va("x%i", icItem->getAmount()));
371 ammopos[0] += icItem->def()->sx * C_UNIT / 2.0;
372 ammopos[1] += icItem->def()->sy * C_UNIT / 2.0;
373 }
374 }
375 cellHeight += 10;
376
377 if (cellHeight > rowHeight) {
378 rowHeight = cellHeight;
379 }
380
381 /* add a marge between rows */
382 if (col == EXTRADATA(node).columns - 1) {
383 currentHeight += rowHeight;
384 rowHeight = 0;
385 if (currentHeight - EXTRADATA(node).scrollY.viewPos >= node->box.size[1])
386 outOfNode = true;
387 }
388
389 /* count items */
390 items++;
391 }
392
393 if (rowHeight != 0) {
394 currentHeight += rowHeight;
395 }
396 return currentHeight;
397}
398
402static void UI_BaseInventoryNodeDraw2 (uiNode_t* node, const objDef_t* highlightType)
403{
404 bool updateScroll = false;
405 int visibleHeight = 0;
406 int needHeight = 0;
407 vec2_t screenPos;
408
409 UI_GetNodeScreenPos(node, screenPos);
410 UI_PushClipRect(screenPos[0], screenPos[1], node->box.size[0], node->box.size[1]);
411
412 needHeight = UI_BaseInventoryNodeDrawItems(node, highlightType);
413
415 visibleHeight = node->box.size[1];
416
417#if 0
418 R_FontDrawString("f_verysmall", ALIGN_UL,
419 node->box.pos[0], node->box.pos[1], node->box.pos[0], node->box.pos[1],
420 0, 0, /* maxWidth/maxHeight */
421 0, va("%i %i/%i", EXTRADATA(node).scrollCur, visibleRows, totalRows), 0, 0, nullptr, false, 0);
422#endif
423
424 /* Update display of scroll buttons if something changed. */
425 if (visibleHeight != EXTRADATA(node).scrollY.viewSize || needHeight != EXTRADATA(node).scrollY.fullSize) {
426 EXTRADATA(node).scrollY.fullSize = needHeight;
427 EXTRADATA(node).scrollY.viewSize = visibleHeight;
428 updateScroll = true;
429 }
430 if (EXTRADATA(node).scrollY.viewPos > needHeight - visibleHeight) {
431 EXTRADATA(node).scrollY.viewPos = needHeight - visibleHeight;
432 updateScroll = true;
433 }
434 if (EXTRADATA(node).scrollY.viewPos < 0) {
435 EXTRADATA(node).scrollY.viewPos = 0;
436 updateScroll = true;
437 }
438
439 if (updateScroll)
441}
442
445 EXTRADATA(node).lua_onViewChange = LUA_NOREF;
446}
447
452{
453 const objDef_t* highlightType = nullptr;
454
455 if (!EXTRADATA(node).super.container)
456 return;
457 if (!ui_inventory)
458 return;
459 /* is container invisible */
460 if (node->color[3] < 0.001)
461 return;
462
463 /* Highlight weapons that the dragged ammo (if it is one) can be loaded into. */
465 highlightType = UI_DNDGetItem()->def();
466 }
467
468 UI_BaseInventoryNodeDraw2(node, highlightType);
469}
470
474static Item* UI_BaseInventoryNodeGetItem (const uiNode_t* const node, int mouseX, int mouseY, int* contX, int* contY)
475{
476 bool outOfNode = false;
477 vec2_t nodepos;
478 int items = 0;
479 int rowHeight = 0;
480 const int cellWidth = node->box.size[0] / EXTRADATACONST(node).columns;
481 int tempX, tempY;
483 int currentHeight = 0;
484
485 if (!contX)
486 contX = &tempX;
487 if (!contY)
488 contY = &tempY;
489
490 UI_GetNodeAbsPos(node, nodepos);
491
492 UI_ContainerItemIteratorInit(&iterator, node);
493 for (; iterator.itemID < csi.numODs; UI_ContainerItemIteratorNext(&iterator)) {
494 const int id = iterator.itemID;
495 const objDef_t* obj = INVSH_GetItemByIDX(id);
496 vec2_t pos;
497 vec2_t ammopos;
498 const int col = items % EXTRADATACONST(node).columns;
499 int cellHeight = 0;
500 Item* icItem = iterator.itemFound;
501 int height;
502
503 /* skip items over and bellow the node view */
504 if (outOfNode || currentHeight < EXTRADATACONST(node).scrollY.viewPos) {
505 int outHeight;
506 R_FontTextSize("f_verysmall", _(obj->name),
507 cellWidth - 5, LONGLINES_WRAP, nullptr, &outHeight, nullptr, nullptr);
508 outHeight += obj->sy * C_UNIT + 10;
509 if (outHeight > rowHeight)
510 rowHeight = outHeight;
511
512 if (outOfNode || currentHeight + rowHeight < EXTRADATACONST(node).scrollY.viewPos) {
513 if (col == EXTRADATACONST(node).columns - 1) {
514 currentHeight += rowHeight;
515 rowHeight = 0;
516 }
517 items++;
518 continue;
519 }
520 }
521
522 Vector2Copy(nodepos, pos);
523 pos[0] += cellWidth * col;
524 pos[1] += currentHeight - EXTRADATACONST(node).scrollY.viewPos;
525
526 /* check item */
527 if (mouseY < pos[1])
528 break;
529 if (mouseX >= pos[0] && mouseX < pos[0] + obj->sx * C_UNIT
530 && mouseY >= pos[1] && mouseY < pos[1] + obj->sy * C_UNIT) {
531 if (icItem) {
532 *contX = icItem->getX();
533 *contY = icItem->getY();
534 return icItem;
535 }
536 return nullptr;
537 }
538 pos[1] += obj->sy * C_UNIT;
539 cellHeight += obj->sy * C_UNIT;
540
541 /* save position for ammo */
542 Vector2Copy(pos, ammopos);
543 ammopos[0] += obj->sx * C_UNIT + 10;
544
545 /* draw the item name. */
546 R_FontTextSize("f_verysmall", _(obj->name),
547 cellWidth - 5, LONGLINES_WRAP, nullptr, &height, nullptr, nullptr);
548 cellHeight += height;
549
550 /* draw ammos of weapon */
551 if (obj->weapon && EXTRADATACONST(node).displayAmmoOfWeapon) {
552 for (int ammoIdx = 0; ammoIdx < obj->numAmmos; ammoIdx++) {
553 const objDef_t* objammo = obj->ammos[ammoIdx];
554
555 /* skip unusable ammo */
556 if (!GAME_ItemIsUseable(objammo))
557 continue;
558
559 /* find and skip none existing ammo */
560 icItem = UI_ContainerNodeGetExistingItem(node, objammo, (itemFilterTypes_t) EXTRADATACONST(node).filterEquipType);
561 if (!icItem)
562 continue;
563
564 /* check ammo (ammopos in on the left-lower corner) */
565 if (mouseX < ammopos[0] || mouseY >= ammopos[1])
566 break;
567 if (mouseX >= ammopos[0] && mouseX < ammopos[0] + objammo->sx * C_UNIT
568 && mouseY >= ammopos[1] - objammo->sy * C_UNIT && mouseY < ammopos[1]) {
569 *contX = icItem->getX();
570 *contY = icItem->getY();
571 return icItem;
572 }
573 ammopos[0] += objammo->sx * C_UNIT;
574 }
575 }
576 cellHeight += 10;
577
578 if (cellHeight > rowHeight) {
579 rowHeight = cellHeight;
580 }
581
582 /* add a margin between rows */
583 if (col == EXTRADATACONST(node).columns - 1) {
584 currentHeight += rowHeight;
585 rowHeight = 0;
586 if (currentHeight - EXTRADATACONST(node).scrollY.viewPos >= node->box.size[1])
587 return nullptr;
588 }
589
590 /* count items */
591 items++;
592 }
593
594 *contX = NONE;
595 *contY = NONE;
596 return nullptr;
597}
598
604void uiBaseInventoryNode::drawTooltip (const uiNode_t* node, int x, int y) const
605{
606 /* Find out where the mouse is. */
607 const Item* itemHover = UI_BaseInventoryNodeGetItem(node, x, y, nullptr, nullptr);
608 if (!itemHover)
609 return;
610
611 static char tooltiptext[MAX_VAR * 2];
612 const int itemToolTipWidth = 250;
613
614 /* Get name and info about item */
615 UI_GetItemTooltip(*itemHover, tooltiptext, sizeof(tooltiptext));
616#ifdef DEBUG
617 /* Display stored container-coordinates of the item. */
618 Q_strcat(tooltiptext, sizeof(tooltiptext), "\n%i/%i", itemHover->getX(), itemHover->getY());
619#endif
620 UI_DrawTooltip(tooltiptext, x, y, itemToolTipWidth);
621}
622
630static void UI_ContainerNodeAutoPlace (uiNode_t* node, int mouseX, int mouseY)
631{
632 if (!ui_inventory)
633 return;
634
635 /* don't allow this in tactical missions */
637 return;
638
639 const int sel = cl_selected->integer;
640 if (sel < 0)
641 return;
642
643 assert(EXTRADATA(node).super.container);
644
645 int fromX, fromY;
646 Item* ic = UI_BaseInventoryNodeGetItem(node, mouseX, mouseY, &fromX, &fromY);
647 Com_DPrintf(DEBUG_CLIENT, "UI_ContainerNodeAutoPlace: item %i/%i selected from scrollable container.\n", fromX, fromY);
648 if (!ic)
649 return;
651
652 /* Update display of scroll buttons. */
654}
655
656static int oldMouseX = 0;
657static int oldMouseY = 0;
658
660{
661 const int delta = abs(oldMouseX - x) + abs(oldMouseY - y);
662 if (delta > 15) {
665 }
666}
667
668void uiBaseInventoryNode::onMouseDown (uiNode_t* node, int x, int y, int button)
669{
670 switch (button) {
671 case K_MOUSE1:
672 {
673 /* start drag and drop */
674 int fromX, fromY;
675 dragInfoIC = UI_BaseInventoryNodeGetItem(node, x, y, &fromX, &fromY);
676 if (dragInfoIC) {
677 dragInfoFromX = fromX;
678 dragInfoFromY = fromY;
679 oldMouseX = x;
680 oldMouseY = y;
681 UI_SetMouseCapture(node);
682 EXTRADATA(node).super.lastSelectedId = dragInfoIC->def()->idx;
683 if (EXTRADATA(node).super.onSelect) {
684 UI_ExecuteEventActions(node, EXTRADATA(node).super.onSelect);
685 }
686 if (EXTRADATA(node).super.lua_onSelect != LUA_NOREF) {
687 UI_ExecuteLuaEventScript(node, EXTRADATA(node).super.lua_onSelect);
688 }
689 }
690 break;
691 }
692 case K_MOUSE2:
693 if (UI_DNDIsDragging()) {
694 UI_DNDAbort();
695 } else {
696 /* auto place */
697 UI_ContainerNodeAutoPlace(node, x, y);
698 }
699 break;
700 default:
701 break;
702 }
703}
704
705void uiBaseInventoryNode::onMouseUp (uiNode_t* node, int x, int y, int button)
706{
707 if (button != K_MOUSE1)
708 return;
709 if (UI_GetMouseCapture() == node) {
711 }
712 if (UI_DNDIsDragging()) {
713 UI_DNDDrop();
714 }
715}
716
717bool uiBaseInventoryNode::onScroll (uiNode_t* node, int deltaX, int deltaY)
718{
719 if (deltaY == 0)
720 return false;
721
722 if (EXTRADATA(node).scrollY.moveDelta(deltaY * 20)) {
724 return true;
725 }
726 return false;
727}
728
730{
731 EXTRADATA(node).super.container = nullptr;
732 EXTRADATA(node).columns = 1;
733 node->color[3] = 1.0;
734}
735
740{
741 /* The node is invalid */
742 if (EXTRADATA(target).super.container == nullptr)
743 return false;
744 /* accept items only, if we have a container */
745 return UI_DNDGetType() == DND_ITEM && UI_DNDGetSourceNode() != target;
746}
747
752bool uiBaseInventoryNode::onDndMove (uiNode_t* target, int x, int y)
753{
754 return true;
755}
756
763
770
772{
773 behaviour->name = "baseinventory";
774 behaviour->extends = "container";
775 behaviour->manager = UINodePtr(new uiBaseInventoryNode());
776 behaviour->extraDataSize = sizeof(EXTRADATA_TYPE);
777 behaviour->lua_SWIG_typeinfo = UI_SWIG_TypeQuery("uiBaseInventoryNode_t *");
778
779 /* Display/hide weapons. */
780 UI_RegisterExtradataNodeProperty(behaviour, "displayweapon", V_BOOL, baseInventoryExtraData_t, displayWeapon);
781 /* Display/hide ammo. */
782 UI_RegisterExtradataNodeProperty(behaviour, "displayammo", V_BOOL, baseInventoryExtraData_t, displayAmmo);
783 /* Display/hide implants. */
784 UI_RegisterExtradataNodeProperty(behaviour, "displayimplant", V_BOOL, baseInventoryExtraData_t, displayImplant);
785 /* Display/hide out of stock items. */
786 UI_RegisterExtradataNodeProperty(behaviour, "displayunavailableitem", V_BOOL, baseInventoryExtraData_t, displayUnavailableItem);
787 /* Sort the list to display in stock items on top of the list. */
788 UI_RegisterExtradataNodeProperty(behaviour, "displayavailableontop", V_BOOL, baseInventoryExtraData_t, displayAvailableOnTop);
789 /* Display/hide ammo near weapons. */
790 UI_RegisterExtradataNodeProperty(behaviour, "displayammoofweapon", V_BOOL, baseInventoryExtraData_t, displayAmmoOfWeapon);
791 /* Display/hide out of stock ammo near weapons. <code>displayammoofweapon</code> must be activated first. */
792 UI_RegisterExtradataNodeProperty(behaviour, "displayunavailableammoofweapon", V_BOOL, baseInventoryExtraData_t, displayUnavailableAmmoOfWeapon);
793 /* Custom the number of column we must use to display items. */
794 UI_RegisterExtradataNodeProperty(behaviour, "columns", V_INT, baseInventoryExtraData_t, columns);
795 /* Filter items by a category. */
796 UI_RegisterExtradataNodeProperty(behaviour, "filter", V_INT, baseInventoryExtraData_t, filterEquipType);
797
798 /* Position of the vertical view (into the full number of elements the node contain) */
799 UI_RegisterExtradataNodeProperty(behaviour, "viewpos", V_INT, baseInventoryExtraData_t, scrollY.viewPos);
800 /* Size of the vertical view (proportional to the number of elements the node can display without moving) */
801 UI_RegisterExtradataNodeProperty(behaviour, "viewsize", V_INT, baseInventoryExtraData_t, scrollY.viewSize);
802 /* Full vertical size (proportional to the number of elements the node contain) */
803 UI_RegisterExtradataNodeProperty(behaviour, "fullsize", V_INT, baseInventoryExtraData_t, scrollY.fullSize);
804 /* Called when one of the properties viewpos/viewsize/fullsize change */
805 UI_RegisterExtradataNodeProperty(behaviour, "onviewchange", V_UI_ACTION, baseInventoryExtraData_t, onViewChange);
806
807 Com_RegisterConstInt("FILTER_S_PRIMARY", FILTER_S_PRIMARY);
808 Com_RegisterConstInt("FILTER_S_SECONDARY", FILTER_S_SECONDARY);
809 Com_RegisterConstInt("FILTER_S_HEAVY", FILTER_S_HEAVY);
810 Com_RegisterConstInt("FILTER_S_IMPLANT", FILTER_S_IMPLANT);
811 Com_RegisterConstInt("FILTER_S_MISC", FILTER_S_MISC);
812 Com_RegisterConstInt("FILTER_S_ARMOUR", FILTER_S_ARMOUR);
813 Com_RegisterConstInt("FILTER_CRAFTITEM", FILTER_CRAFTITEM);
814 Com_RegisterConstInt("FILTER_UGVITEM", FILTER_UGVITEM);
815 Com_RegisterConstInt("FILTER_AIRCRAFT", FILTER_AIRCRAFT);
816 Com_RegisterConstInt("FILTER_DUMMY", FILTER_DUMMY);
817 Com_RegisterConstInt("FILTER_DISASSEMBLY", FILTER_DISASSEMBLY);
818}
bool GAME_ItemIsUseable(const objDef_t *od)
Definition cl_game.cpp:1104
Shared game type headers.
Item * INV_SearchInInventoryWithFilter(const Inventory *const inv, const invDef_t *container, const objDef_t *itemType, const itemFilterTypes_t filterType)
Searches if there is an item at location (x/y) in a scrollable container. You can also provide an ite...
bool INV_ItemMatchesFilter(const objDef_t *obj, const itemFilterTypes_t filterType)
Checks if the given object/item matched the given filter type.
Header file for inventory handling and Equipment menu.
itemFilterTypes_t
A list of filter types in the market and production view.
@ FILTER_S_ARMOUR
@ FILTER_S_HEAVY
@ FILTER_CRAFTITEM
@ FILTER_S_PRIMARY
@ FILTER_AIRCRAFT
@ FILTER_S_MISC
@ FILTER_DUMMY
@ FILTER_S_IMPLANT
@ FILTER_S_SECONDARY
@ FILTER_DISASSEMBLY
@ FILTER_UGVITEM
Header file for keyboard handler.
@ K_MOUSE2
Definition cl_keys.h:47
@ K_MOUSE1
Definition cl_keys.h:46
cvar_t * cl_selected
Definition cl_main.cpp:73
void R_FontTextSize(const char *fontId, const char *text, int maxWidth, longlines_t method, int *width, int *height, int *lines, bool *isTruncated)
Supply information about the size of the text when it is linewrapped and rendered,...
Definition r_font.cpp:522
@ LONGLINES_WRAP
int R_FontDrawString(const char *fontId, align_t align, int x, int y, int absX, int maxWidth, int lineHeight, const char *c, int boxHeight, int scrollPos, int *curLine, longlines_t method)
Definition r_font.cpp:681
Share stuff between the different cgame implementations.
#define _(String)
Definition cl_shared.h:44
item instance data, with linked list capability
Definition inv_shared.h:402
int getX() const
Definition inv_shared.h:454
int getAmount() const
Definition inv_shared.h:463
void setDef(const objDef_t *objDef)
Definition inv_shared.h:444
const objDef_t * def(void) const
Definition inv_shared.h:469
int getY() const
Definition inv_shared.h:457
void drawTooltip(const uiNode_t *node, int x, int y) const override
Custom tooltip for container node.
void onCapturedMouseMove(uiNode_t *node, int x, int y) override
void onMouseDown(uiNode_t *node, int x, int y, int button) override
bool onDndMove(uiNode_t *node, int x, int y) override
Call into the target when the DND hover it.
bool onDndEnter(uiNode_t *node) override
Call when a DND enter into the node.
void draw(uiNode_t *node) override
Main function to draw a container node.
void onDndLeave(uiNode_t *node) override
Call when a DND enter into the node.
bool onScroll(uiNode_t *node, int deltaX, int deltaY) override
void initNode(uiNode_t *node) override
void onLoaded(uiNode_t *node) override
Calculates the size of a container node and links the container into the node (uses the invDef_t shap...
void onMouseUp(uiNode_t *node, int x, int y, int button) override
void onLoading(uiNode_t *node) override
void onWindowOpened(uiNode_t *node, linkedList_t *params) override
Call when we open the window containing the node.
void initNode(uiNode_t *node) override
csi_t csi
Definition common.cpp:39
void Com_DPrintf(int level, const char *fmt,...)
A Com_Printf that only shows up if the "developer" cvar is set.
Definition common.cpp:440
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define DEBUG_CLIENT
Definition defines.h:59
#define NONE
Definition defines.h:68
const objDef_t * INVSH_GetItemByIDX(int index)
Returns the item that belongs to the given index or nullptr if the index is invalid.
const invDef_t * INVSH_GetInventoryDefinitionByID(const char *id)
void Com_RegisterConstInt(const char *name, int value)
Register mappings between script strings and enum values for values of the type V_INT.
Definition scripts.cpp:198
@ ALIGN_LC
Definition scripts.h:97
@ ALIGN_UL
Definition scripts.h:90
@ V_BOOL
Definition scripts.h:50
@ V_INT
Definition scripts.h:52
Header for lua script functions.
#define MAX_VAR
Definition shared.h:36
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition shared.cpp:475
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
Definition cvar.h:71
Defines all attributes of objects used in the inventory.
Definition inv_shared.h:264
bool isAmmo() const
Definition inv_shared.h:343
const struct objDef_s * ammos[MAX_AMMOS_PER_OBJDEF]
Definition inv_shared.h:307
bool weapon
Definition inv_shared.h:277
bool isLoadableInWeapon(const objDef_s *weapon) const
Checks if an item can be used to reload a weapon.
int numAmmos
Definition inv_shared.h:308
bool implant
Definition inv_shared.h:282
bool isMisc
Definition inv_shared.h:288
bool isArmour() const
Definition inv_shared.h:346
int numWeapons
Definition inv_shared.h:317
const char * name
Definition inv_shared.h:267
node behaviour, how a node work
const char * name
void * lua_SWIG_typeinfo
UINodePtr manager
const char * extends
intptr_t extraDataSize
vec2_t size
Definition ui_nodes.h:52
vec2_t pos
Definition ui_nodes.h:51
Atomic structure used to define most of the UI.
Definition ui_nodes.h:80
vec4_t color
Definition ui_nodes.h:127
uiBox_t box
Definition ui_nodes.h:96
vec_t vec3_t[3]
Definition ufotypes.h:39
vec_t vec4_t[4]
Definition ufotypes.h:40
vec_t vec2_t[2]
Definition ufotypes.h:38
void UI_ExecuteEventActions(uiNode_t *source, const uiAction_t *firstAction)
#define UI_RegisterExtradataNodeProperty(BEHAVIOUR, NAME, TYPE, EXTRADATATYPE, ATTRIBUTE)
Initialize a property from extradata of node.
bool UI_DNDIsDragging(void)
Return true if we are dragging something.
void UI_DNDDrop(void)
Drop the object at the current position.
Item * UI_DNDGetItem(void)
void UI_DNDAbort(void)
Drop the object at the current position.
void UI_DNDDragItem(uiNode_t *node, const Item *item)
Start to drag an item.
int UI_DNDGetType(void)
Return the current type of the dragging object, else DND_NOTHING.
uiNode_t * UI_DNDGetSourceNode(void)
Return source of the DND.
@ DND_ITEM
void UI_SetMouseCapture(uiNode_t *node)
Captured the mouse into a node.
Definition ui_input.cpp:516
uiNode_t * UI_GetMouseCapture(void)
Return the captured node.
Definition ui_input.cpp:508
void UI_MouseRelease(void)
Release the captured node.
Definition ui_input.cpp:526
bool UI_ExecuteLuaEventScript(uiNode_t *node, LUA_EVENT event)
Executes a lua event handler.
Definition ui_lua.cpp:71
Basic lua initialization for the ui.
void * UI_SWIG_TypeQuery(const char *name)
This function queries the SWIG type table for a type information structure. It is used in combination...
void UI_GetNodeAbsPos(const uiNode_t *node, vec2_t pos)
Returns the absolute position of a node.
Definition ui_node.cpp:526
void UI_GetNodeScreenPos(const uiNode_t *node, vec2_t pos)
Returns the absolute position of a node in the screen. Screen position is not used for the node rende...
Definition ui_node.cpp:554
SharedPtr< uiNode > UINodePtr
#define EXTRADATA_TYPE
#define EXTRADATA(node)
base code for scrollable node
#define EXTRADATACONST(node)
static int UI_BaseInventoryNodeDrawItems(uiNode_t *node, const objDef_t *highlightType)
Draw the base inventory.
static int dragInfoFromY
static void UI_BaseInventoryNodeDraw2(uiNode_t *node, const objDef_t *highlightType)
Draw the inventory of the base.
#define CII_END
static void UI_ContainerItemIteratorNext(containerItemIterator_t *iterator)
Compute the next itemID.
#define EXTRADATA(node)
void UI_RegisterBaseInventoryNode(uiBehaviour_t *behaviour)
static const vec4_t colorLoadable
#define CII_AMMOONLY
Flag for containerItemIterator_t (CII) groupSteps.
static void UI_BaseInventoryNodeUpdateScroll(uiNode_t *node)
Update display of scroll buttons.
#define CII_WEAPONONLY
static const vec4_t colorDisabledHiden
static int dragInfoFromX
static const vec4_t colorDefault
static int oldMouseY
static Item * UI_BaseInventoryNodeGetItem(const uiNode_t *const node, int mouseX, int mouseY, int *contX, int *contY)
static int oldMouseX
static const vec4_t colorDisabledLoadable
static Item * UI_ContainerNodeGetExistingItem(const uiNode_t *node, const objDef_t *item, const itemFilterTypes_t filterType)
Searches if there is an item at location (x/y) in a scrollable container. You can also provide an ite...
#define CII_AVAILABLEONLY
#define CII_IMPLANTONLY
static void UI_ContainerNodeAutoPlace(uiNode_t *node, int mouseX, int mouseY)
Try to autoplace an item at a position when right-click was used in the inventory.
#define EXTRADATACONST(node)
#define CII_NOTAVAILABLEONLY
static const vec3_t scale
static const Item * dragInfoIC
bool CL_BattlescapeRunning(void)
Check whether we already have actors spawned on the battlefield.
static void UI_ContainerItemIteratorInit(containerItemIterator_t *iterator, const uiNode_t *const node)
Use a container node to init an item iterator.
Inventory * ui_inventory
void UI_ContainerNodeAutoPlaceItem(uiNode_t *node, Item *ic)
Try to autoplace an item from a container.
void UI_DrawItem(uiNode_t *node, const vec3_t org, const Item *item, int x, int y, const vec3_t scale, const vec4_t color)
Draws an item to the screen.
void UI_GetItemTooltip(const Item &item, char *tooltipText, size_t stringMaxLength)
Generate tooltip text for an item.
#define C_UNIT
One unit in the containers is 25x25.
#define V_UI_ACTION
Definition ui_parse.h:54
int UI_DrawString(const char *fontID, align_t align, int x, int y, int absX, int maxWidth, int lineHeight, const char *c, int boxHeight, int scrollPos, int *curLine, bool increaseLine, longlines_t method)
void UI_PushClipRect(int x, int y, int width, int height)
Definition ui_render.cpp:47
void UI_PopClipRect(void)
Definition ui_render.cpp:52
int UI_DrawTooltip(const char *string, int x, int y, int maxWidth)
Generic tooltip function.
#define Vector2Copy(src, dest)
Definition vector.h:52