UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ui_node_container.cpp
Go to the documentation of this file.
1 
14 /*
15 Copyright (C) 2002-2020 UFO: Alien Invasion.
16 
17 This program is free software; you can redistribute it and/or
18 modify it under the terms of the GNU General Public License
19 as published by the Free Software Foundation; either version 2
20 of the License, or (at your option) any later version.
21 
22 This program is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25 
26 See the GNU General Public License for more details.
27 
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 
32 */
33 
34 #include "../ui_main.h"
35 #include "../ui_parse.h"
36 #include "../ui_behaviour.h"
37 #include "../ui_actions.h"
38 #include "../ui_dragndrop.h"
39 #include "../ui_tooltip.h"
40 #include "../ui_nodes.h"
41 #include "../ui_input.h"
42 #include "../ui_render.h"
43 #include "../ui_lua.h"
44 
45 #include "ui_node_model.h"
46 #include "ui_node_container.h"
47 #include "ui_node_abstractnode.h"
48 
49 #include "../../client.h"
50 #include "../../renderer/r_draw.h"
51 #include "../../renderer/r_mesh.h"
52 #include "../../cgame/cl_game.h"
53 #include "../../battlescape/cl_actor.h"
54 #include "../../cl_inventory.h"
55 
56 #include "../../../common/scripts_lua.h"
57 
63 
64 #define EXTRADATA_TYPE containerExtraData_t
65 #define EXTRADATA(node) UI_EXTRADATA(node, EXTRADATA_TYPE)
66 #define EXTRADATACONST(node) UI_EXTRADATACONST(node, EXTRADATA_TYPE)
67 
72 static int dragInfoFromX = -1;
73 static int dragInfoFromY = -1;
74 
79 static int dragInfoToX = -1;
80 static int dragInfoToY = -1;
81 
86 static const Item* dragInfoIC;
87 
88 static inline bool UI_IsScrollContainerNode (const uiNode_t* const node)
89 {
90  return EXTRADATACONST(node).container && EXTRADATACONST(node).container->scroll;
91 }
92 
103 {
104  /* make a copy, because we are not really using these items,
105  * but only putting them into a temp container */
106  int* const numItems = Mem_Dup(int, ed->numItems, lengthof(ed->numItems));
107 
108  /* a 'tiny hack' to add the remaining equipment (not carried)
109  * correctly into buy categories, reloading at the same time;
110  * it is valid only due to the following property: */
111  assert(MAX_CONTAINERS >= FILTER_AIRCRAFT);
112 
113  for (int i = 0; i < csi.numODs; i++) {
114  const objDef_t* od = INVSH_GetItemByIDX(i);
115  /* Don't allow to show unuseable items. */
116  if (!GAME_ItemIsUseable(od))
117  continue;
118 
119  while (numItems[i]) {
120  const Item item(od);
121  if (!cls.i.addToInventory(inv, &item, INVDEF(CID_EQUIP), NONE, NONE, 1)) {
122  /* no space left in the inventory */
123  break;
124  }
125  numItems[item.def()->idx]--;
126  }
127  }
128 
129  Mem_Free(numItems);
130 
131  /* First-time linking of ui_inventory. */
132  if (ui_inventory && !ui_inventory->getEquipContainer()) {
133  ui_inventory->setContainer(CID_EQUIP, inv->getEquipContainer());
134  }
135 }
136 
149 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)
150 {
151  const objDef_t* od = item->def();
152  vec4_t col;
153  vec3_t origin;
154 
155  assert(od);
156  assert(org[2] > -1000 && org[2] < 1000); /*< prevent use of vec2_t for org */
157 
158  Vector4Copy(color, col);
159  /* no ammo in this weapon - highlight this item */
160  if (od->weapon && item->mustReload()) {
161  col[1] *= 0.5;
162  col[2] *= 0.5;
163  }
164 
165  VectorCopy(org, origin);
166 
167  /* Calculate correct location of the image or the model (depends on rotation) */
170  if (x >= 0 || y >= 0) {
171  /* Add offset of location in container. */
172  origin[0] += x * C_UNIT;
173  origin[1] += y * C_UNIT;
174 
175  /* Add offset for item-center (depends on rotation). */
176  if (item->rotated) {
177  origin[0] += od->sy * C_UNIT / 2.0;
178  origin[1] += od->sx * C_UNIT / 2.0;
183  } else {
184  origin[0] += od->sx * C_UNIT / 2.0;
185  origin[1] += od->sy * C_UNIT / 2.0;
186  }
187  }
188 
189  /* don't handle the od->tech->image here - it's very ufopedia specific in most cases */
190  if (od->image[0] != '\0') {
191  const int imgWidth = od->sx * C_UNIT;
192  const int imgHeight = od->sy * C_UNIT;
193  origin[0] -= od->sx * C_UNIT / 2.0;
194  origin[1] -= od->sy * C_UNIT / 2.0;
195 
196  /* Draw the image. */
197  R_Color(color);
198  UI_DrawNormImageByName(false, origin[0], origin[1], imgWidth, imgHeight, 0, 0, 0, 0, od->image);
199  R_Color(nullptr);
200  } else {
201  uiModel_t* model = nullptr;
202  const char* modelName = GAME_GetModelForItem(od, &model);
203 
204  /* no model definition in the tech struct, not in the fallback object definition */
205  if (Q_strnull(modelName)) {
206  Com_Printf("UI_DrawItem: No model given for item: '%s'\n", od->id);
207  return;
208  }
209 
210  if (model && node) {
211  UI_DrawModelNode(node, modelName);
212  } else {
213  modelInfo_t mi;
214  vec3_t angles = {-10, 160, 70};
215  vec3_t size = {scale[0], scale[1], scale[2]};
216  vec3_t center;
217 
218  if (item->rotated)
219  angles[0] -= 90;
220 
221  if (od->scale)
222  VectorScale(size, od->scale, size);
223 
224  VectorNegate(od->center, center);
225 
226  OBJZERO(mi);
227  mi.origin = origin;
228  mi.angles = angles;
229  mi.center = center;
230  mi.scale = size;
231  mi.color = col;
232  mi.name = modelName;
233 
234  /* draw the model */
235  R_DrawModelDirect(&mi, nullptr, nullptr);
236  }
237  }
238 }
239 
247 void UI_GetItemTooltip (const Item& item, char* tooltipText, size_t stringMaxLength)
248 {
249  assert(item.def());
250 
251  if (item.getAmount() > 1)
252  Com_sprintf(tooltipText, stringMaxLength, "%i x %s\n", item.getAmount(), _(item.def()->name));
253  else
254  Com_sprintf(tooltipText, stringMaxLength, "%s\n", _(item.def()->name));
255 
256  /* Only display further info if item.t is researched */
257  if (GAME_ItemIsUseable(item.def())) {
258  if (item.isWeapon()) {
259  /* Get info about used ammo (if there is any) */
260  if (item.def() == item.ammoDef()) {
261  /* Item has no ammo but might have shot-count */
262  if (item.getAmmoLeft()) {
263  Q_strcat(tooltipText, stringMaxLength, _("Ammo: %i\n"), item.getAmmoLeft());
264  }
265  } else if (item.ammoDef()) {
266  /* Search for used ammo and display name + ammo count */
267  Q_strcat(tooltipText, stringMaxLength, _("%s loaded\n"), _(item.ammoDef()->name));
268  Q_strcat(tooltipText, stringMaxLength, _("Ammo: %i\n"), item.getAmmoLeft());
269  }
270  } else if (item.def()->numWeapons) {
271  /* Check if this is a non-weapon and non-ammo item */
272  if (!(item.def()->numWeapons == 1 && item.def()->weapons[0] == item.def())) {
273  /* If it's ammo get the weapon names it can be used in */
274  Q_strcat(tooltipText, stringMaxLength, _("Usable in:\n"));
275  for (int i = 0; i < item.def()->numWeapons; i++) {
276  const objDef_t* weapon = item.def()->weapons[i];
277  if (GAME_ItemIsUseable(weapon)) {
278  Q_strcat(tooltipText, stringMaxLength, "* %s\n", _(weapon->name));
279  }
280  }
281  }
282  }
283  }
284 }
285 
290 uiNode_t* UI_GetContainerNodeByContainerIDX (const uiNode_t* const parent, const int index)
291 {
292  const invDef_t* const container = INVDEF(index);
293  uiNode_t* containerNode = UI_GetNode(parent, container->name);
294  return containerNode;
295 }
296 
300 static void UI_DrawDisabled (const uiNode_t* node)
301 {
302  const vec4_t color = { 0.3f, 0.3f, 0.3f, 0.7f };
303  vec2_t nodepos;
304 
305  UI_GetNodeAbsPos(node, nodepos);
306  UI_DrawFill(nodepos[0], nodepos[1], node->box.size[0], node->box.size[1], color);
307 }
308 
312 static void UI_DrawFree (containerIndex_t container, const uiNode_t* node, int posx, int posy, int sizex, int sizey, bool showTUs)
313 {
314  const vec4_t color = { 0.0f, 1.0f, 0.0f, 0.7f };
315  invDef_t* inv = INVDEF(container);
316  vec2_t nodepos;
317 
318  UI_GetNodeAbsPos(node, nodepos);
319  UI_DrawFill(posx, posy, sizex, sizey, color);
320 
321  /* if showTUs is true (only the first time in none single containers)
322  * and we are connected to a game */
323  if (showTUs && CL_BattlescapeRunning()) {
324  UI_DrawString("f_verysmall", ALIGN_UL, nodepos[0] + 3, nodepos[1] + 3,
325  nodepos[0] + 3, node->box.size[0] - 6, 0,
326  va(_("In: %i Out: %i"), inv->in, inv->out));
327  }
328 }
329 
335 {
336  const objDef_t* od = UI_DNDGetItem()->def();
337  vec2_t nodepos;
338 
339  /* Draw only in dragging-mode and not for the equip-floor */
340  assert(UI_DNDIsDragging());
341  assert(inv);
342 
343  UI_GetNodeAbsPos(node, nodepos);
344  /* if single container (hands, headgear) */
345  if (EXTRADATA(node).container->single) {
346  /* if container is free or the dragged-item is in it */
347  if (UI_DNDIsSourceNode(node) || inv->canHoldItem(EXTRADATA(node).container, od, 0, 0, dragInfoIC))
348  UI_DrawFree(EXTRADATA(node).container->id, node, nodepos[0], nodepos[1], node->box.size[0], node->box.size[1], true);
349  } else {
350  /* The shape of the free positions. */
351  uint32_t free[SHAPE_BIG_MAX_HEIGHT];
352  bool showTUs = true;
353 
354  OBJZERO(free);
355 
356  for (int y = 0; y < SHAPE_BIG_MAX_HEIGHT; y++) {
357  for (int x = 0; x < SHAPE_BIG_MAX_WIDTH; x++) {
358  /* Check if the current position is usable (topleft of the item). */
359 
360  /* Add '1's to each position the item is 'blocking'. */
361  const int checkedTo = inv->canHoldItem(EXTRADATA(node).container, od, x, y, dragInfoIC);
362  if (checkedTo & INV_FITS) /* Item can be placed normally. */
363  INVSH_MergeShapes(free, od->shape, x, y);
364  if (checkedTo & INV_FITS_ONLY_ROTATED) /* Item can be placed rotated. */
365  INVSH_MergeShapes(free, od->getShapeRotated(), x, y);
366 
367  /* Only draw on existing positions. */
368  if (INVSH_CheckShape(EXTRADATA(node).container->shape, x, y)) {
369  if (INVSH_CheckShape(free, x, y)) {
370  UI_DrawFree(EXTRADATA(node).container->id, node, nodepos[0] + x * C_UNIT, nodepos[1] + y * C_UNIT, C_UNIT, C_UNIT, showTUs);
371  showTUs = false;
372  }
373  }
374  }
375  }
376  }
377 }
378 
385 {
386  const char* name;
387  const invDef_t* container;
388 
390  name = node->name;
391  if (Q_strstart(node->name, "equip_"))
392  name = "equip";
393 
394  container = INVSH_GetInventoryDefinitionByID(name);
395  if (container == nullptr)
396  return;
397 
398  EXTRADATA(node).container = container;
399 
400  if (UI_IsScrollContainerNode(node)) {
401  /* No need to compute the size, the script provide it */
402  } else {
403  int i, j;
404  /* Start on the last bit of the shape mask. */
405  for (i = SHAPE_BIG_MAX_WIDTH - 1; i >= 0; i--) {
406  for (j = 0; j < SHAPE_BIG_MAX_HEIGHT; j++)
407  if (container->shape[j] & (1 << i))
408  break;
409  if (j < SHAPE_BIG_MAX_HEIGHT)
410  break;
411  }
412  node->box.size[0] = C_UNIT * (i + 1) + 0.01;
413 
414  /* start on the lower row of the shape mask */
415  for (i = SHAPE_BIG_MAX_HEIGHT - 1; i >= 0; i--)
416  if (container->shape[i] & ~0x0)
417  break;
418  node->box.size[1] = C_UNIT * (i + 1) + 0.01;
419  }
420 }
421 
422 static const vec3_t scale = {3.5, 3.5, 3.5};
424 static const vec4_t colorDefault = {1, 1, 1, 1};
425 static const vec4_t colorLoadable = {0.5, 1, 0.5, 1};
426 static const vec4_t colorDisabled = {0.5, 0.5, 0.5, 1};
427 static const vec4_t colorDisabledLoadable = {0.5, 0.25, 0.25, 1.0};
428 static const vec4_t colorPreview = { 0.5, 0.5, 1, 1 };
435 static void UI_ContainerNodeDrawSingle (uiNode_t* node, const objDef_t* highlightType)
436 {
437  vec4_t color;
438  vec3_t pos;
439 
440  UI_GetNodeAbsPos(node, pos);
441  pos[0] += node->box.size[0] / 2.0;
442  pos[1] += node->box.size[1] / 2.0;
443  pos[2] = 0;
444 
445  /* Single item container (special case for left hand). */
446  const invDef_t* contType = EXTRADATA(node).container;
447  if (contType->isLeftDef() && !ui_inventory->getLeftHandContainer()) {
448  if (ui_inventory->getRightHandContainer()) {
449  const Item* item = ui_inventory->getRightHandContainer();
450  assert(item);
451  assert(item->def());
452 
453  if (item->isHeldTwoHanded()) {
454  if (highlightType && highlightType->isLoadableInWeapon(item->def()))
455  memcpy(color, colorLoadable, sizeof(vec4_t));
456  else
457  memcpy(color, colorDefault, sizeof(vec4_t));
458  color[3] = 0.5;
459  UI_DrawItem(node, pos, item, -1, -1, scale, color);
460  }
461  }
462  } else if (ui_inventory->getContainer2(contType->id)) {
463  bool disabled = false;
464  const Item* item;
465 
466  if (ui_inventory->getRightHandContainer()) {
467  item = ui_inventory->getRightHandContainer();
468  /* If there is a weapon in the right hand that needs two hands to shoot it
469  * and there is a weapon in the left, then draw a disabled marker for the
470  * fireTwoHanded weapon. */
471  assert(item);
472  assert(item->def());
473  if (contType->isRightDef() && item->def()->fireTwoHanded && ui_inventory->getLeftHandContainer()) {
474  disabled = true;
475  UI_DrawDisabled(node);
476  }
477  }
478 
479  item = ui_inventory->getContainer2(contType->id);
480  assert(item);
481  assert(item->def());
482  if (highlightType && highlightType->isLoadableInWeapon(item->def())) {
483  if (disabled)
485  else
486  Vector4Copy(colorLoadable, color);
487  } else {
488  if (disabled)
489  Vector4Copy(colorDisabled, color);
490  else
491  Vector4Copy(colorDefault, color);
492  }
493  if (disabled)
494  color[3] = 0.5;
495  UI_DrawItem(node, pos, item, -1, -1, scale, color);
496  }
497 }
498 
502 static void UI_ContainerNodeDrawGrid (uiNode_t* node, const objDef_t* highlightType)
503 {
504  vec3_t pos;
505 
506  UI_GetNodeAbsPos(node, pos);
507  pos[2] = 0;
508 
509  const Container& cont = ui_inventory->getContainer(EXTRADATA(node).container->id);
510  Item* item = nullptr;
511  while ((item = cont.getNextItem(item))) {
512  assert(item->def());
513  if (highlightType && highlightType->isLoadableInWeapon(item->def()))
514  UI_DrawItem(node, pos, item, item->getX(), item->getY(), scale, colorLoadable);
515  else
516  UI_DrawItem(node, pos, item, item->getX(), item->getY(), scale, colorDefault);
517  }
518 }
519 
524 {
525  Item previewItem;
526  int checkedTo;
527  vec3_t origine;
528 
529  /* no preview into scrollable list */
530  if (UI_IsScrollContainerNode(target))
531  return;
532 
533  /* copy the DND item to not change the original one */
534  previewItem = *UI_DNDGetItem();
535  previewItem.rotated = false;
536  checkedTo = ui_inventory->canHoldItem(EXTRADATA(target).container, previewItem.def(), dragInfoToX, dragInfoToY, dragInfoIC);
537  switch (checkedTo) {
538  case INV_DOES_NOT_FIT:
539  return;
540  case INV_FITS:
541  break;
542  case INV_FITS_BOTH:
545  break;
546  /* else fits rotated, fall through */
548  previewItem.rotated = true;
549  }
550 
551  /* Hack, no preview for armour, we don't want it out of the armour container (and armour container is not visible) */
552  if (previewItem.isArmour())
553  return;
554 
555  UI_GetNodeAbsPos(target, origine);
556  origine[2] = -40;
557 
558  /* Get center of single container for placement of preview item */
559  if (EXTRADATA(target).container->single) {
560  origine[0] += target->box.size[0] / 2.0;
561  origine[1] += target->box.size[1] / 2.0;
562  /* This is a "grid" container - we need to calculate the item-position
563  * (on the screen) from stored placement in the container and the
564  * calculated rotation info. */
565  } else {
566  if (previewItem.rotated) {
567  origine[0] += (dragInfoToX + previewItem.def()->sy / 2.0) * C_UNIT;
568  origine[1] += (dragInfoToY + previewItem.def()->sx / 2.0) * C_UNIT;
569  } else {
570  origine[0] += (dragInfoToX + previewItem.def()->sx / 2.0) * C_UNIT;
571  origine[1] += (dragInfoToY + previewItem.def()->sy / 2.0) * C_UNIT;
572  }
573  }
574 
575  UI_DrawItem(nullptr, origine, &previewItem, -1, -1, scale, colorPreview);
576 }
577 
582 {
583  const objDef_t* highlightType = nullptr;
584 
585  if (!EXTRADATA(node).container)
586  return;
587  if (!ui_inventory)
588  return;
589  /* is container invisible */
590  if (node->color[3] < 0.001)
591  return;
592 
593  /* Highlight weapons that the dragged ammo (if it is one) can be loaded into. */
594  if (UI_DNDIsDragging() && UI_DNDGetType() == DND_ITEM) {
595  highlightType = UI_DNDGetItem()->def();
596  }
597 
598  if (EXTRADATA(node).container->single) {
599  UI_ContainerNodeDrawSingle(node, highlightType);
600  } else {
601  if (UI_IsScrollContainerNode(node)) {
602  assert(false);
603  } else {
604  UI_ContainerNodeDrawGrid(node, highlightType);
605  }
606  }
607 
608  /* Draw free space if dragging - but not for CID_EQUIP */
609  if (UI_DNDIsDragging() && EXTRADATA(node).container->id != CID_EQUIP)
610  UI_ContainerNodeDrawFreeSpace(node, ui_inventory);
611 
612  if (UI_DNDIsTargetNode(node))
614 }
615 
625 static Item* UI_ContainerNodeGetItemAtPosition (const uiNode_t* const node, int mouseX, int mouseY, int* contX = nullptr, int* contY = nullptr)
626 {
627  if (!ui_inventory)
628  return nullptr;
629 
630  /* Get coordinates inside a scrollable container (if it is one). */
631  if (UI_IsScrollContainerNode(node)) {
632  Sys_Error("UI_ContainerNodeGetItemAtPosition is not usable for scrollable containers!");
633  }
634 
635  vec2_t nodepos;
636  UI_GetNodeAbsPos(node, nodepos);
637  /* Normalize screen coordinates to container coordinates. */
638  const int fromX = (int) (mouseX - nodepos[0]) / C_UNIT;
639  const int fromY = (int) (mouseY - nodepos[1]) / C_UNIT;
640  if (contX)
641  *contX = fromX;
642  if (contY)
643  *contY = fromY;
644 
645  Item* result = ui_inventory->getItemAtPos(EXTRADATACONST(node).container, fromX, fromY);
646  return result;
647 }
648 
654 void uiContainerNode::drawTooltip (const uiNode_t* node, int x, int y) const
655 {
656  /* Find out where the mouse is. */
657  const Item* itemHover = UI_ContainerNodeGetItemAtPosition(node, x, y);
658 
659  if (itemHover) {
660  static char tooltiptext[MAX_VAR * 2];
661  const int itemToolTipWidth = 250;
662 
663  /* Get name and info about item */
664  UI_GetItemTooltip(*itemHover, tooltiptext, sizeof(tooltiptext));
665 #ifdef DEBUG
666  /* Display stored container-coordinates of the item. */
667  Q_strcat(tooltiptext, sizeof(tooltiptext), "\n%i/%i", itemHover->getX(), itemHover->getY());
668 #endif
669  UI_DrawTooltip(tooltiptext, x, y, itemToolTipWidth);
670  }
671 }
672 
673 static bool UI_ContainerNodeAddItem (const invDef_t* container, Item* ic, containerIndex_t containerID, Item** icp)
674 {
675  int px, py;
676  const invDef_t* target = INVDEF(containerID);
677  ui_inventory->findSpace(target, ic, &px, &py, nullptr);
678  return INV_MoveItem(ui_inventory, target, px, py, container, ic, icp);
679 }
680 
688 {
689  containerIndex_t target;
690  bool ammoChanged = false;
691  const invDef_t* container = EXTRADATA(node).container;
692 
693  /* Right click: automatic item assignment/removal. */
694  if (container->id != CID_EQUIP) {
695  target = CID_EQUIP;
696  if (ic->ammoDef()) {
697  /* Remove ammo on removing weapon from a soldier */
698  ammoChanged = INV_UnloadWeapon(ic, ui_inventory, INVDEF(target));
699  }
700  if (!ammoChanged && !ic->ammoDef()) {
701  /* Move back to CID_EQUIP (ground, floor) container. */
702  INV_MoveItem(ui_inventory, INVDEF(target), NONE, NONE, container, ic, nullptr);
703  }
704  } else {
705  bool packed = false;
706  assert(ic->def());
707  /* armour can only have one target */
708  if (ic->isArmour()) {
709  target = CID_ARMOUR;
710  packed = INV_MoveItem(ui_inventory, INVDEF(target), 0, 0, container, ic, nullptr);
711  /* ammo or item */
712  } else if (ic->def()->isAmmo()) {
713  /* Finally try left and right hand. There is no other place to put it now. */
715  const size_t size = lengthof(idxArray);
716  for (int i = 0; i < size; i++) {
717  target = idxArray[i];
718  packed = UI_ContainerNodeAddItem(container, ic, target, nullptr);
719  if (packed)
720  break;
721  }
722  } else if (ic->def()->headgear) {
723  target = CID_HEADGEAR;
724  packed = UI_ContainerNodeAddItem(container, ic, target, nullptr);
725  } else if (ic->def()->implant) {
726  target = CID_IMPLANT;
727  packed = UI_ContainerNodeAddItem(container, ic, target, nullptr);
728  } else {
729  /* left and right are single containers, but this might change - it's cleaner to check
730  * for available space here, too */
732  const size_t size = lengthof(idxArray);
733  Item* tItem = nullptr;
734  for (int i = 0; i < size; i++) {
735  target = idxArray[i];
736  packed = UI_ContainerNodeAddItem(container, ic, target, &tItem);
737  if (packed) {
738  if ((ic->isWeapon() && !ic->getAmmoLeft()) || ic->def()->weapons[0])
739  ammoChanged = INV_LoadWeapon(tItem, ui_inventory, container, INVDEF(target));
740  break;
741  }
742  }
743  }
744  /* no need to continue here - placement wasn't successful at all */
745  if (!packed)
746  return;
747  }
748 
749  EXTRADATA(node).lastSelectedId = ic->def()->idx;
750  if (EXTRADATA(node).onSelect) {
751  UI_ExecuteEventActions(node, EXTRADATA(node).onSelect);
752  }
753  if (EXTRADATA(node).lua_onSelect != LUA_NOREF) {
754  UI_ExecuteLuaEventScript(node, EXTRADATA(node).lua_onSelect);
755  }
756  /* Run onChange events */
758  if (node->onChange) {
759  UI_ExecuteEventActions(node, node->onChange);
760  }
761  if (node->lua_onChange != LUA_NOREF) {
763  }
764  if (targetNode != nullptr && node != targetNode) {
765  if (targetNode->onChange) {
766  UI_ExecuteEventActions(targetNode, targetNode->onChange);
767  }
768  if (targetNode->lua_onChange != LUA_NOREF) {
769  UI_ExecuteLuaEventScript(targetNode, targetNode->lua_onChange);
770  }
771  }
772  /* Also call onChange for equip_ammo if ammo moved
773  * Maybe there's a better way to do this? */
774  if (ic->def()->isAmmo() || ammoChanged) {
776  uiNode_t* ammoNode = UI_GetNode(node->root, "equip_ammo");
777  if (ammoNode != nullptr && node != ammoNode) {
778  if (ammoNode->onChange) {
779  UI_ExecuteEventActions(ammoNode, ammoNode->onChange);
780  }
781  if (ammoNode->lua_onChange != LUA_NOREF) {
782  UI_ExecuteLuaEventScript(ammoNode, ammoNode->lua_onChange);
783  }
784  }
785  }
786 }
787 
795 static void UI_ContainerNodeAutoPlace (uiNode_t* node, int mouseX, int mouseY)
796 {
797  if (!ui_inventory)
798  return;
799 
800  /* don't allow this in tactical missions */
801  if (CL_BattlescapeRunning())
802  return;
803 
804  const int sel = cl_selected->integer;
805  if (sel < 0)
806  return;
807 
808  assert(EXTRADATA(node).container);
809 
810  Item* ic = UI_ContainerNodeGetItemAtPosition(node, mouseX, mouseY);
811  if (!ic)
812  return;
814 }
815 
816 static int oldMouseX = 0;
817 static int oldMouseY = 0;
818 
820 {
821  const int delta = abs(oldMouseX - x) + abs(oldMouseY - y);
822  if (delta > 15) {
823  UI_DNDDragItem(node, dragInfoIC);
824  UI_MouseRelease();
825  }
826 }
827 
828 void uiContainerNode::onMouseDown (uiNode_t* node, int x, int y, int button)
829 {
830  switch (button) {
831  case K_MOUSE1:
832  {
833  /* start drag and drop */
834  int fromX, fromY;
835  dragInfoIC = UI_ContainerNodeGetItemAtPosition(node, x, y, &fromX, &fromY);
836  if (dragInfoIC) {
837  dragInfoFromX = fromX;
838  dragInfoFromY = fromY;
839  oldMouseX = x;
840  oldMouseY = y;
841  UI_SetMouseCapture(node);
842  EXTRADATA(node).lastSelectedId = dragInfoIC->def()->idx;
843  if (EXTRADATA(node).onSelect) {
844  UI_ExecuteEventActions(node, EXTRADATA(node).onSelect);
845  }
846  if (EXTRADATA(node).lua_onSelect != LUA_NOREF) {
847  UI_ExecuteLuaEventScript(node, EXTRADATA(node).lua_onSelect);
848  }
849  }
850  break;
851  }
852  case K_MOUSE2:
853  if (UI_DNDIsDragging()) {
854  UI_DNDAbort();
855  } else {
856  /* auto place */
857  UI_ContainerNodeAutoPlace(node, x, y);
858  }
859  break;
860  default:
861  break;
862  }
863 }
864 
865 void uiContainerNode::onMouseUp (uiNode_t* node, int x, int y, int button)
866 {
867  if (button != K_MOUSE1)
868  return;
869  if (UI_GetMouseCapture() == node) {
870  UI_MouseRelease();
871  }
872  if (UI_DNDIsDragging()) {
873  UI_DNDDrop();
874  }
875 }
876 
878  /* initialize lua events */
880  EXTRADATA(node).lua_onSelect = LUA_NOREF;
881 }
882 
884 {
885  EXTRADATA(node).container = nullptr;
886  node->color[3] = 1.0;
887 }
888 
893 {
894  /* accept items only, if we have a container */
895  return UI_DNDGetType() == DND_ITEM && EXTRADATA(target).container && (!UI_IsScrollContainerNode(target) || UI_DNDGetSourceNode() != target);
896 }
897 
902 bool uiContainerNode::onDndMove (uiNode_t* target, int x, int y)
903 {
904  vec2_t nodepos;
905  bool exists;
906  int itemX = 0;
907  int itemY = 0;
908  Item* dragItem = UI_DNDGetItem();
909 
910  /* we already check it when the node accept the DND */
911  assert(EXTRADATA(target).container);
912  const invDef_t* containerType = EXTRADATA(target).container;
913 
914  UI_GetNodeAbsPos(target, nodepos);
915 
921  if (dragItem->def()) {
922  itemX = C_UNIT * dragItem->def()->sx / 2; /* Half item-width. */
923  itemY = C_UNIT * dragItem->def()->sy / 2; /* Half item-height. */
924 
925  /* Place relative center in the middle of the square. */
926  itemX -= C_UNIT / 2;
927  itemY -= C_UNIT / 2;
928  }
929 
930  dragInfoToX = (mousePosX - nodepos[0] - itemX) / C_UNIT;
931  dragInfoToY = (mousePosY - nodepos[1] - itemY) / C_UNIT;
932 
933  /* Check if the items already exists in the container. i.e. there is already at least one item. */
934  exists = false;
935  if ((containerType->isFloorDef() || containerType->isEquipDef())
936  && (dragInfoToX < 0 || dragInfoToY < 0 || dragInfoToX >= SHAPE_BIG_MAX_WIDTH || dragInfoToY >= SHAPE_BIG_MAX_HEIGHT)
937  && ui_inventory->containsItem(containerType->id, dragItem)) {
938  exists = true;
939  }
940 
941  /* Search for a suitable position to render the item at if
942  * the container is "single", the cursor is out of bound of the container. */
943  if (!exists && dragItem->def() && (containerType->single
944  || dragInfoToX < 0 || dragInfoToY < 0
946 #if 0
947 /* ... or there is something in the way. */
948 /* We would need to check for weapon/ammo as well here, otherwise a preview would be drawn as well when hovering over the correct weapon to reload. */
949  || (ui_inventory->canHoldItem(containerType, dragItem->item, dragInfoToX, dragInfoToY) == INV_DOES_NOT_FIT)) {
950 #endif
951  ui_inventory->findSpace(containerType, dragItem, &dragInfoToX, &dragInfoToY, dragInfoIC);
952  }
953 
954  /* we can drag every thing */
955  if (UI_IsScrollContainerNode(target)) {
956  return true;
957  }
958 
959  {
960  Item* fItem;
961 
962  /* is there empty slot? */
963  const int checkedTo = ui_inventory->canHoldItem(containerType, dragItem->def(), dragInfoToX, dragInfoToY, dragInfoIC);
964  if (checkedTo != INV_DOES_NOT_FIT)
965  return true;
966 
967  /* can we equip dragging item into the target item? */
968  fItem = ui_inventory->getItemAtPos(containerType, dragInfoToX, dragInfoToY);
969  if (!fItem)
970  return false;
971  if (containerType->single)
972  return true;
973  return dragItem->def()->isLoadableInWeapon(fItem->def());
974  }
975 }
976 
981 {
982  dragInfoToX = -1;
983  dragInfoToY = -1;
984 }
985 
989 bool uiContainerNode::onDndFinished (uiNode_t* source, bool isDropped)
990 {
991  Item* dragItem = UI_DNDGetItem();
992  const invDef_t* sourceContainer = EXTRADATACONST(source).container;
993 
994  /* if the target can't finalize the DND we stop */
995  if (!isDropped) {
996  return false;
997  }
998 
999  assert(sourceContainer);
1000 
1001  /* on tactical mission */
1002  if (CL_BattlescapeRunning()) {
1003  const uiNode_t* target = UI_DNDGetTargetNode();
1004  const invDef_t* targetContainer = EXTRADATACONST(target).container;
1005  assert(targetContainer);
1007  targetContainer->id, dragInfoToX, dragInfoToY);
1008  } else {
1009  uiNode_t* target = UI_DNDGetTargetNode();
1010  if (target) {
1011  Item* fItem;
1012  Item* tItem;
1013  bool moved = false;
1014  const invDef_t* targetContainer = EXTRADATACONST(target).container;
1015  assert(targetContainer);
1016  if (UI_IsScrollContainerNode(source)) {
1017  fItem = INV_SearchInInventoryWithFilter(ui_inventory, sourceContainer, dragItem->def(), MAX_FILTERTYPES);
1018  } else
1019  fItem = ui_inventory->getItemAtPos(sourceContainer, dragInfoFromX, dragInfoFromY);
1020  assert(fItem);
1021 
1023  /* Remove ammo on removing weapon from a soldier */
1024  if (UI_IsScrollContainerNode(target) && fItem->ammoDef())
1025  INV_UnloadWeapon(fItem, ui_inventory, targetContainer);
1026 
1027  /* Save rotation: in case the move fails we don't want the item overlapping other items or
1028  * ending partially out of the container due to changed rotation */
1029  const bool rotated = fItem->rotated;
1030  /* rotate on Shift */
1033 
1034  /* move the item */
1035  moved = INV_MoveItem(ui_inventory, targetContainer, dragInfoToX, dragInfoToY, sourceContainer, fItem, &tItem);
1036 
1037  /* No need to continue move wasn't successful */
1038  if (!moved) {
1039  fItem->rotated = rotated;
1040  return false;
1041  }
1042 
1043  /* Add ammo on adding weapon to a soldier */
1044  if (UI_IsScrollContainerNode(source) && ((fItem->isWeapon() && !fItem->getAmmoLeft())
1045  || (fItem->def()->weapons[0] && !fItem->def()->isAmmo())))
1046  INV_LoadWeapon(tItem, ui_inventory, sourceContainer, targetContainer);
1047 
1048  /* Run onChange events */
1049  if (source->onChange) {
1050  UI_ExecuteEventActions(source, source->onChange);
1051  }
1052  if (source->lua_onChange != LUA_NOREF) {
1053  UI_ExecuteLuaEventScript(source, source->lua_onChange);
1054  }
1055 
1056  if (source != target) {
1057  if (target->onChange) {
1058  UI_ExecuteEventActions(target, target->onChange);
1059  }
1060  if (target->lua_onChange != LUA_NOREF) {
1061  UI_ExecuteLuaEventScript(target, target->lua_onChange);
1062  }
1063  }
1064  }
1065  }
1066 
1067  dragInfoFromX = -1;
1068  dragInfoFromY = -1;
1069  return true;
1070 }
1071 
1073 {
1074  behaviour->name = "container";
1075  behaviour->manager = UINodePtr(new uiContainerNode());
1076  behaviour->extraDataSize = sizeof(EXTRADATA_TYPE);
1077  behaviour->lua_SWIG_typeinfo = UI_SWIG_TypeQuery("uiContainerNode_t *");
1078 
1079  /* Callback value set before calling onSelect. It is used to know the item selected */
1080  UI_RegisterExtradataNodeProperty(behaviour, "lastselectedid", V_INT, containerExtraData_t, lastSelectedId);
1081  /* Callback event called when the user select an item */
1082  UI_RegisterExtradataNodeProperty(behaviour, "onselect", V_UI_ACTION, containerExtraData_t, onSelect);
1083 }
#define EXTRADATACONST(node)
bool Q_strnull(const char *string)
Definition: shared.h:138
void onCapturedMouseMove(uiNode_t *node, int x, int y) override
static void UI_ContainerNodeDrawFreeSpace(uiNode_t *node, Inventory *inv)
Draws the free and usable inventory positions when dragging an item.
#define SHAPE_BIG_MAX_HEIGHT
defines the max height of an inventory container
Definition: inv_shared.h:188
vec2_t size
Definition: ui_nodes.h:52
bool mustReload() const
Definition: inv_shared.h:483
byte sx
Definition: inv_shared.h:326
#define VectorCopy(src, dest)
Definition: vector.h:51
int UI_DNDGetType(void)
Return the current type of the dragging object, else DND_NOTHING.
uiNode_t * UI_DNDGetTargetNode(void)
Return target of the DND.
void Sys_Error(const char *error,...)
Definition: g_main.cpp:421
#define CID_EQUIP
Definition: inv_shared.h:56
void CL_ActorInvMove(const le_t *le, containerIndex_t fromContainer, int fromX, int fromY, containerIndex_t toContainer, int toX, int toY)
Sends an inventory move event to the server.
Definition: cl_actor.cpp:1004
void initNode(uiNode_t *node) override
void onDndLeave(uiNode_t *node) override
Call when a DND enter into the node.
bool implant
Definition: inv_shared.h:282
uiNode_t * parent
Definition: ui_nodes.h:92
LUA_EVENT lua_onChange
Definition: ui_nodes.h:162
float * origin
Definition: cl_renderer.h:61
static int dragInfoToY
bool isArmour() const
Definition: inv_shared.h:489
static const vec4_t colorDisabledLoadable
float * color
Definition: cl_renderer.h:71
static const vec4_t colorDisabled
static int dragInfoFromX
InventoryInterface i
Definition: client.h:101
Item * UI_DNDGetItem(void)
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
const char * name
Definition: ui_behaviour.h:41
struct uiAction_s * onChange
Definition: ui_nodes.h:143
int getAmmoLeft() const
Definition: inv_shared.h:466
const char * name
Definition: cl_renderer.h:59
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 _(String)
Definition: cl_shared.h:43
void UI_DNDDragItem(uiNode_t *node, const Item *item)
Start to drag an item.
Item * getContainer2(const containerIndex_t idx) const
Definition: inv_shared.h:546
voidpf uLong int origin
Definition: ioapi.h:45
csi_t csi
Definition: common.cpp:39
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
void UI_DrawModelNode(uiNode_t *node, const char *source)
void UI_DNDAbort(void)
Drop the object at the current position.
#define VectorNegate(src, dest)
Definition: vector.h:58
void drawTooltip(const uiNode_t *node, int x, int y) const override
Custom tooltip for container node.
char name[MAX_VAR]
Definition: ui_nodes.h:82
Item * getLeftHandContainer() const
Definition: inv_shared.cpp:960
UINodePtr manager
Definition: ui_behaviour.h:43
bool isRightDef() const
Checks whether the inventory definition is the right Hand.
Definition: inv_shared.cpp:57
bool UI_ExecuteLuaEventScript(uiNode_t *node, LUA_EVENT event)
Executes a lua event handler.
Definition: ui_lua.cpp:71
const objDef_t * def(void) const
Definition: inv_shared.h:469
#define CID_ARMOUR
Definition: inv_shared.h:54
bool onDndEnter(uiNode_t *node) override
Call when a DND enter into the node.
void onMouseDown(uiNode_t *node, int x, int y, int button) override
bool isLeftDef() const
Checks whether a given inventory definition is of special type.
Definition: inv_shared.cpp:66
static const Item * dragInfoIC
static uiNode_t * targetNode
void UI_ContainerNodeUpdateEquipment(Inventory *inv, const equipDef_t *ed)
Fills the ground container of the ui_inventory with unused items from a given equipment definition...
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
int numODs
Definition: q_shared.h:518
static int dragInfoToX
Defines all attributes of objects used in the inventory.
Definition: inv_shared.h:264
char name[MAX_VAR]
Definition: inv_shared.h:372
int integer
Definition: cvar.h:81
#define VectorScale(in, scale, out)
Definition: vector.h:79
void UI_MouseRelease(void)
Release the captured node.
Definition: ui_input.cpp:526
#define CID_BELT
Definition: inv_shared.h:52
uiNode_t * UI_DNDGetSourceNode(void)
Return source of the DND.
#define UI_RegisterExtradataNodeProperty(BEHAVIOUR, NAME, TYPE, EXTRADATATYPE, ATTRIBUTE)
Initialize a property from extradata of node.
Definition: ui_behaviour.h:109
void R_Color(const vec4_t rgba)
Change the color to given value.
Definition: r_state.cpp:1011
bool isWeapon() const
Definition: inv_shared.h:486
void R_DrawModelDirect(modelInfo_t *mi, modelInfo_t *pmi, const char *tagname)
Draws a model in 2d mode (for rendering model data from the ui)
Definition: r_mesh.cpp:306
bool containsItem(const containerIndex_t contId, const Item *const item) const
Searches if there is a specific item already in the inventory&container.
Definition: inv_shared.h:572
bool headgear
Definition: inv_shared.h:280
#define CID_LEFT
Definition: inv_shared.h:48
bool fireTwoHanded
Definition: inv_shared.h:279
client_static_t cls
Definition: cl_main.cpp:83
item instance data, with linked list capability
Definition: inv_shared.h:402
float * angles
Definition: cl_renderer.h:62
const char * image
Definition: inv_shared.h:270
uiNode_t * root
Definition: ui_nodes.h:93
inventory definition with all its containers
Definition: inv_shared.h:525
void INVSH_MergeShapes(uint32_t *shape, const uint32_t itemShape, const int x, const int y)
Will merge the second shape (=itemShape) into the first one (=big container shape) on the position x/...
Definition: inv_shared.cpp:402
const char * GAME_GetModelForItem(const objDef_t *od, uiModel_t **uiModel)
Get a model for an item.
Definition: cl_game.cpp:1725
#define CID_HEADGEAR
Definition: inv_shared.h:50
#define C_UNIT
One unit in the containers is 25x25.
extradata for container widget
#define MAX_CONTAINERS
Definition: inv_shared.h:394
#define CID_RIGHT
Definition: inv_shared.h:47
const image_t * UI_DrawNormImageByName(bool flip, float x, float y, float w, float h, float sh, float th, float sl, float tl, const char *name)
Draws an image or parts of it.
Definition: ui_render.cpp:203
float * center
Definition: cl_renderer.h:64
GLsizei size
Definition: r_gl.h:152
#define SHAPE_BIG_MAX_WIDTH
32 bit mask
Definition: inv_shared.h:190
#define OBJZERO(obj)
Definition: shared.h:178
uint32_t shape
Definition: inv_shared.h:273
void findSpace(const invDef_t *container, const Item *item, int *const px, int *const py, const Item *ignoredItem) const
Finds space for item in inv at container.
Definition: inv_shared.cpp:876
#define MAX_VAR
Definition: shared.h:36
Item * getRightHandContainer() const
Definition: inv_shared.cpp:955
int mousePosY
Definition: cl_input.cpp:80
#define EXTRADATA_TYPE
bool single
Definition: inv_shared.h:375
vec3_t center
Definition: inv_shared.h:276
static const vec4_t colorLoadable
uiNode_t * UI_GetContainerNodeByContainerIDX(const uiNode_t *const parent, const int index)
Search a child container node by the given container id.
int numWeapons
Definition: inv_shared.h:317
SharedPtr< uiNode > UINodePtr
const invDef_t * INVSH_GetInventoryDefinitionByID(const char *id)
Definition: inv_shared.cpp:340
bool isAmmo() const
Definition: inv_shared.h:343
int UI_DrawTooltip(const char *string, int x, int y, int maxWidth)
Generic tooltip function.
Definition: ui_tooltip.cpp:40
#define CID_IMPLANT
Definition: inv_shared.h:49
void * lua_SWIG_typeinfo
Definition: ui_behaviour.h:57
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition: shared.cpp:587
void UI_SetMouseCapture(uiNode_t *node)
Captured the mouse into a node.
Definition: ui_input.cpp:516
bool UI_DNDIsTargetNode(uiNode_t *node)
Return true if the requested node is the current target of the DND.
int canHoldItem(const invDef_t *container, const objDef_t *od, const int x, const int y, const Item *ignoredItem) const
Definition: inv_shared.cpp:761
uint32_t getShapeRotated() const
Rotates a shape definition 90 degree to the left (CCW)
Definition: inv_shared.cpp:472
bool weapon
Definition: inv_shared.h:277
void UI_ExecuteEventActions(uiNode_t *source, const uiAction_t *firstAction)
Definition: ui_actions.cpp:726
uiNode_t * UI_GetMouseCapture(void)
Return the captured node.
Definition: ui_input.cpp:508
int getAmount() const
Definition: inv_shared.h:463
#define INVDEF(containerID)
Definition: cl_shared.h:47
Item * getEquipContainer() const
Definition: inv_shared.cpp:980
Item * getNextItem(const Item *prev) const
Definition: inv_shared.cpp:671
Atomic structure used to define most of the UI.
Definition: ui_nodes.h:80
bool INV_MoveItem(Inventory *inv, const invDef_t *toContainer, int toX, int toY, const invDef_t *fromContainer, Item *fItem, Item **uponItem)
Move item between containers.
void * UI_SWIG_TypeQuery(const char *name)
This function queries the SWIG type table for a type information structure. It is used in combination...
const char * name
Definition: inv_shared.h:267
#define CID_HOLSTER
Definition: inv_shared.h:53
bool CL_BattlescapeRunning(void)
Check whether we already have actors spawned on the battlefield.
void UI_GetNodeAbsPos(const uiNode_t *node, vec2_t pos)
Returns the absolute position of a node.
Definition: ui_node.cpp:514
#define CID_BACKPACK
Definition: inv_shared.h:51
static Item * UI_ContainerNodeGetItemAtPosition(const uiNode_t *const node, int mouseX, int mouseY, int *contX=nullptr, int *contY=nullptr)
Gets location of the item the mouse is over.
QGL_EXTERN GLuint index
Definition: r_gl.h:110
static const vec3_t scale
const Container & getContainer(const containerIndex_t idx) const
Definition: inv_shared.h:537
void UI_ContainerNodeAutoPlaceItem(uiNode_t *node, Item *ic)
Try to autoplace an item from a container.
int32_t containerIndex_t
Definition: inv_shared.h:46
static void UI_DrawDisabled(const uiNode_t *node)
Draws the rectangle in a 'free' style on position posx/posy (pixel) in the size sizex/sizey (pixel) ...
uint32_t shape[SHAPE_BIG_MAX_HEIGHT]
Definition: inv_shared.h:384
bool isFloorDef() const
Checks whether the inventory definition is the floor.
Definition: inv_shared.cpp:48
bool isLoadableInWeapon(const objDef_s *weapon) const
Checks if an item can be used to reload a weapon.
Definition: inv_shared.cpp:356
cvar_t * cl_selected
Definition: cl_main.cpp:73
static const vec4_t colorPreview
Item * addToInventory(Inventory *const inv, const Item *const item, const invDef_t *container, int x, int y, int amount) __attribute__((warn_unused_result))
Add an item to a specified container in a given inventory.
Definition: inventory.cpp:91
bool Key_IsDown(unsigned int key)
Checks whether a given key is currently pressed.
Definition: cl_keys.cpp:214
static void UI_ContainerNodeDrawSingle(uiNode_t *node, const objDef_t *highlightType)
Draw a container which only contains one item.
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...
#define EXTRADATA(node)
le_t * selActor
Definition: cl_actor.cpp:49
static int oldMouseY
virtual void initNode(uiNode_t *node)
static void UI_DrawFree(containerIndex_t container, const uiNode_t *node, int posx, int posy, int sizex, int sizey, bool showTUs)
Draws the rectangle in a 'free' style on position posx/posy (pixel) in the size sizex/sizey (pixel) ...
Inventory * ui_inventory
void UI_GetItemTooltip(const Item &item, char *tooltipText, size_t stringMaxLength)
Generate tooltip text for an item.
float scale
Definition: inv_shared.h:275
intptr_t extraDataSize
Definition: ui_behaviour.h:54
static bool UI_IsScrollContainerNode(const uiNode_t *const node)
QGL_EXTERN GLint i
Definition: r_gl.h:113
static int dragInfoFromY
uiNode_t * UI_GetNode(const uiNode_t *node, const char *name)
Search a child node by given name.
Definition: ui_node.cpp:702
node behaviour, how a node work
Definition: ui_behaviour.h:39
bool onDndMove(uiNode_t *node, int x, int y) override
Call into the target when the DND hover it.
int numItems[MAX_OBJDEFS]
Definition: inv_shared.h:608
static int oldMouseX
void UI_RegisterContainerNode(uiBehaviour_t *behaviour)
float * scale
Definition: cl_renderer.h:63
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
vec4_t color
Definition: ui_nodes.h:127
void onMouseUp(uiNode_t *node, int x, int y, int button) override
Item * getItemAtPos(const invDef_t *container, const int x, const int y) const
Searches if there is an item at location (x,y) in a container.
Definition: inv_shared.cpp:844
bool UI_DNDIsSourceNode(uiNode_t *node)
Return true if the requested node is the source of the DND.
#define Mem_Free(ptr)
Definition: mem.h:35
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
static const vec4_t colorDefault
bool isHeldTwoHanded() const
Definition: inv_shared.h:476
const objDef_t * ammoDef(void) const
Definition: inv_shared.h:460
vec_t vec3_t[3]
Definition: ufotypes.h:39
inventory definition for our menus
Definition: inv_shared.h:371
vec_t vec2_t[2]
Definition: ufotypes.h:38
Definition: scripts.h:52
const objDef_t * INVSH_GetItemByIDX(int index)
Returns the item that belongs to the given index or nullptr if the index is invalid.
Definition: inv_shared.cpp:266
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)
Definition: ui_render.cpp:371
int getX() const
Definition: inv_shared.h:454
bool INVSH_CheckShape(const uint32_t *shape, const int x, const int y)
Checks the shape if there is a 1-bit on the position x/y.
Definition: inv_shared.cpp:414
containerIndex_t id
Definition: inv_shared.h:373
bool isEquipDef() const
Checks whether a given inventory definition is of special type.
Definition: inv_shared.cpp:75
#define lengthof(x)
Definition: shared.h:105
void onLoading(uiNode_t *node) override
int rotated
Definition: inv_shared.h:412
#define V_UI_ACTION
Definition: ui_parse.h:54
#define NONE
Definition: defines.h:68
uiBox_t box
Definition: ui_nodes.h:96
byte sy
Definition: inv_shared.h:326
bool GAME_ItemIsUseable(const objDef_t *od)
Definition: cl_game.cpp:1295
void UI_DrawFill(int x, int y, int w, int h, const vec4_t color)
Fills a box of pixels with a single color.
Definition: ui_render.cpp:37
Model that have more than one part (top and down part of an aircraft)
Definition: ui_node_model.h:47
bool UI_DNDIsDragging(void)
Return true if we are dragging something.
int mousePosX
Definition: cl_input.cpp:80
bool INV_LoadWeapon(const Item *weaponList, Inventory *inv, const invDef_t *srcContainer, const invDef_t *destContainer)
Load a weapon with ammo.
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...
static void UI_ContainerNodeDrawGrid(uiNode_t *node, const objDef_t *highlightType)
Draw a grip 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.
#define Mem_Dup(type, in, n)
Definition: mem.h:47
#define Vector4Copy(src, dest)
Definition: vector.h:53
static void UI_ContainerNodeDrawDropPreview(uiNode_t *target)
Draw a preview of the DND item dropped into the node.
void UI_DNDDrop(void)
Drop the object at the current position.
bool INV_UnloadWeapon(Item *weapon, Inventory *inv, const invDef_t *container)
Unload a weapon and put the ammo in a container.
static bool UI_ContainerNodeAddItem(const invDef_t *container, Item *ic, containerIndex_t containerID, Item **icp)
void setContainer(const containerIndex_t idx, Item *cont)
Definition: inv_shared.h:550
const char * id
Definition: inv_shared.h:268
int getY() const
Definition: inv_shared.h:457
const struct objDef_s * weapons[MAX_WEAPONS_PER_OBJDEF]
Definition: inv_shared.h:311
void draw(uiNode_t *node) override
Main function to draw a container node.
bool onDndFinished(uiNode_t *node, bool isDroped) override
Call into the source when the DND end.
vec_t vec4_t[4]
Definition: ufotypes.h:40