00001
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "../ui_main.h"
00036 #include "../ui_parse.h"
00037 #include "../ui_actions.h"
00038 #include "../ui_dragndrop.h"
00039 #include "../ui_tooltip.h"
00040 #include "../ui_nodes.h"
00041 #include "../ui_input.h"
00042 #include "../ui_render.h"
00043 #include "ui_node_baseinventory.h"
00044 #include "ui_node_model.h"
00045 #include "ui_node_container.h"
00046 #include "ui_node_abstractnode.h"
00047
00048 #include "../../client.h"
00049 #include "../../renderer/r_draw.h"
00050 #include "../../renderer/r_mesh.h"
00051 #include "../../cl_game.h"
00052 #include "../../cl_team.h"
00053 #include "../../battlescape/cl_actor.h"
00054 #include "../../cl_inventory.h"
00055
00056 #define EXTRADATA_TYPE containerExtraData_t
00057 #define EXTRADATA(node) UI_EXTRADATA(node, EXTRADATA_TYPE)
00058 #define EXTRADATACONST(node) UI_EXTRADATACONST(node, EXTRADATA_TYPE)
00059
00064 static int dragInfoFromX = -1;
00065 static int dragInfoFromY = -1;
00066
00071 static const invList_t *dragInfoIC;
00072
00083 static invList_t *UI_ContainerNodeGetExistingItem (const uiNode_t *node, objDef_t *item, const itemFilterTypes_t filterType)
00084 {
00085 return INVSH_SearchInInventoryWithFilter(ui_inventory, EXTRADATACONST(node).container, NONE, NONE, item, filterType);
00086 }
00087
00091 #define CII_AMMOONLY 0x01
00092 #define CII_WEAPONONLY 0x02
00093 #define CII_AVAILABLEONLY 0x04
00094 #define CII_NOTAVAILABLEONLY 0x08
00095 #define CII_END 0x80
00096
00097 typedef struct {
00098 const uiNode_t* node;
00099 byte groupSteps[6];
00100 int groupID;
00101 itemFilterTypes_t filterEquipType;
00102
00103 int itemID;
00104 invList_t *itemFound;
00105 } containerItemIterator_t;
00106
00113 static void UI_ContainerItemIteratorNext (containerItemIterator_t *iterator)
00114 {
00115 assert(iterator->groupSteps[iterator->groupID] != CII_END);
00116
00117
00118 for (; iterator->groupSteps[iterator->groupID] != CII_END; iterator->groupID++) {
00119 int filter = iterator->groupSteps[iterator->groupID];
00120
00121 iterator->itemID++;
00122
00123
00124 for (;iterator->itemID < csi.numODs; iterator->itemID++) {
00125 qboolean isAmmo;
00126 qboolean isWeapon;
00127 qboolean isArmour;
00128 objDef_t *obj = INVSH_GetItemByIDX(iterator->itemID);
00129
00130
00131 if (!GAME_ItemIsUseable(obj))
00132 continue;
00133
00134
00136 isArmour = INV_IsArmour(obj);
00137 isAmmo = obj->numWeapons != 0 && INV_IsAmmo(obj);
00138 isWeapon = obj->weapon || obj->isMisc || isArmour;
00139
00140 if ((filter & CII_WEAPONONLY) && !isWeapon)
00141 continue;
00142 if ((filter & CII_AMMOONLY) && !isAmmo)
00143 continue;
00144 if (!INV_ItemMatchesFilter(obj, iterator->filterEquipType))
00145 continue;
00146
00147
00148 iterator->itemFound = UI_ContainerNodeGetExistingItem(iterator->node, obj, iterator->filterEquipType);
00149 if ((filter & CII_AVAILABLEONLY) && iterator->itemFound == NULL)
00150 continue;
00151 if ((filter & CII_NOTAVAILABLEONLY) && iterator->itemFound != NULL)
00152 continue;
00153
00154
00155 return;
00156 }
00157
00158
00159 if (iterator->groupSteps[iterator->groupID + 1] != CII_END)
00160 iterator->itemID = -1;
00161 }
00162
00163
00164 iterator->itemFound = NULL;
00165 }
00166
00170 static void UI_ContainerItemIteratorInit (containerItemIterator_t *iterator, const uiNode_t* const node)
00171 {
00172 int groupID = 0;
00173 iterator->itemID = -1;
00174 iterator->groupID = 0;
00175 iterator->node = node;
00176 iterator->filterEquipType = EXTRADATACONST(node).filterEquipType;
00177
00178 if (EXTRADATACONST(node).displayAvailableOnTop) {
00179
00180 if (EXTRADATACONST(node).displayWeapon)
00181 iterator->groupSteps[groupID++] = CII_WEAPONONLY | CII_AVAILABLEONLY;
00182 if (EXTRADATACONST(node).displayAmmo)
00183 iterator->groupSteps[groupID++] = CII_AMMOONLY | CII_AVAILABLEONLY;
00184
00185 if (EXTRADATACONST(node).displayUnavailableItem) {
00186 if (EXTRADATACONST(node).displayWeapon)
00187 iterator->groupSteps[groupID++] = CII_WEAPONONLY | CII_NOTAVAILABLEONLY;
00188 if (EXTRADATACONST(node).displayAmmo)
00189 iterator->groupSteps[groupID++] = CII_AMMOONLY | CII_NOTAVAILABLEONLY;
00190 }
00191 } else {
00192 const int filter = (EXTRADATACONST(node).displayUnavailableItem) ? 0 : CII_AVAILABLEONLY;
00193 if (EXTRADATACONST(node).displayWeapon)
00194 iterator->groupSteps[groupID++] = CII_WEAPONONLY | filter;
00195 if (EXTRADATACONST(node).displayAmmo)
00196 iterator->groupSteps[groupID++] = CII_AMMOONLY | filter;
00197 }
00198 iterator->groupSteps[groupID++] = CII_END;
00199
00200
00201 UI_ContainerItemIteratorNext(iterator);
00202 }
00203
00210 static void UI_BaseInventoryNodeUpdateScroll (uiNode_t* node)
00211 {
00212 if (EXTRADATA(node).onViewChange) {
00213 UI_ExecuteEventActions(node, EXTRADATA(node).onViewChange);
00214 }
00215 }
00216
00224 static void UI_GetItemTooltip (item_t item, char *tooltipText, size_t stringMaxLength)
00225 {
00226 objDef_t *weapon;
00227
00228 assert(item.t);
00229
00230 if (item.amount > 1)
00231 Com_sprintf(tooltipText, stringMaxLength, "%i x %s\n", item.amount, _(item.t->name));
00232 else
00233 Com_sprintf(tooltipText, stringMaxLength, "%s\n", _(item.t->name));
00234
00235
00236 if (GAME_ItemIsUseable(item.t)) {
00237 if (item.t->weapon) {
00238
00239 if (item.t == item.m) {
00240
00241 if (item.a) {
00242 Q_strcat(tooltipText, va(_("Ammo: %i\n"), item.a), stringMaxLength);
00243 }
00244 } else if (item.m) {
00245
00246 Q_strcat(tooltipText, va(_("%s loaded\n"), _(item.m->name)), stringMaxLength);
00247 Q_strcat(tooltipText, va(_("Ammo: %i\n"), item.a), stringMaxLength);
00248 }
00249 } else if (item.t->numWeapons) {
00250
00251 if (!(item.t->numWeapons == 1 && item.t->weapons[0] == item.t)) {
00252 int i;
00253
00254 Q_strcat(tooltipText, _("Usable in:\n"), stringMaxLength);
00255 for (i = 0; i < item.t->numWeapons; i++) {
00256 weapon = item.t->weapons[i];
00257 if (GAME_ItemIsUseable(weapon)) {
00258 Q_strcat(tooltipText, va("* %s\n", _(weapon->name)), stringMaxLength);
00259 }
00260 }
00261 }
00262 }
00263 }
00264 }
00265
00271 static void UI_BaseInventoryNodeLoaded (uiNode_t* const node)
00272 {
00273 EXTRADATA(node).container = INVSH_GetInventoryDefinitionByID("equip");
00274 }
00275
00276 static const vec3_t scale = {3.5, 3.5, 3.5};
00278 static const vec4_t colorDefault = {1, 1, 1, 1};
00279 static const vec4_t colorLoadable = {0.5, 1, 0.5, 1};
00280 static const vec4_t colorDisabled = {0.5, 0.5, 0.5, 1};
00281 static const vec4_t colorDisabledHiden = {0.5, 0.5, 0.5, 0.5};
00282 static const vec4_t colorDisabledLoadable = {0.5, 0.25, 0.25, 1.0};
00283 static const vec4_t colorPreview = { 0.5, 0.5, 1, 1 };
00289 static int UI_BaseInventoryNodeDrawItems (uiNode_t *node, objDef_t *highlightType)
00290 {
00291 qboolean outOfNode = qfalse;
00292 vec2_t nodepos;
00293 int items = 0;
00294 int rowHeight = 0;
00295 const int cellWidth = node->size[0] / EXTRADATA(node).columns;
00296 containerItemIterator_t iterator;
00297 int currentHeight = 0;
00298 UI_GetNodeAbsPos(node, nodepos);
00299
00300 UI_ContainerItemIteratorInit(&iterator, node);
00301 for (; iterator.itemID < csi.numODs; UI_ContainerItemIteratorNext(&iterator)) {
00302 const int id = iterator.itemID;
00303 objDef_t *obj = INVSH_GetItemByIDX(id);
00304 item_t tempItem = {1, NULL, obj, 0, 0};
00305 vec3_t pos;
00306 vec3_t ammopos;
00307 const float *color;
00308 qboolean isHighlight = qfalse;
00309 int amount;
00310 const int col = items % EXTRADATA(node).columns;
00311 int cellHeight = 0;
00312 invList_t *icItem = iterator.itemFound;
00313
00314
00315 if (outOfNode || currentHeight < EXTRADATA(node).scrollCur) {
00316 int height;
00317 R_FontTextSize("f_verysmall", _(obj->name),
00318 cellWidth - 5, LONGLINES_WRAP, NULL, &height, NULL, NULL);
00319 height += obj->sy * C_UNIT + 10;
00320 if (height > rowHeight)
00321 rowHeight = height;
00322
00323 if (outOfNode || currentHeight + rowHeight < EXTRADATA(node).scrollCur) {
00324 if (col == EXTRADATA(node).columns - 1) {
00325 currentHeight += rowHeight;
00326 rowHeight = 0;
00327 }
00328 items++;
00329 continue;
00330 }
00331 }
00332
00333 Vector2Copy(nodepos, pos);
00334 pos[0] += cellWidth * col;
00335 pos[1] += currentHeight - EXTRADATA(node).scrollCur;
00336 pos[2] = 0;
00337
00338 if (highlightType) {
00339 if (INV_IsAmmo(obj))
00340 isHighlight = INVSH_LoadableInWeapon(obj, highlightType);
00341 else
00342 isHighlight = INVSH_LoadableInWeapon(highlightType, obj);
00343 }
00344
00345 if (icItem != NULL) {
00346 if (isHighlight)
00347 color = colorLoadable;
00348 else
00349 color = colorDefault;
00350 } else {
00351 if (isHighlight)
00352 color = colorDisabledLoadable;
00353 else
00354 color = colorDisabledHiden;
00355 }
00356
00357 if (icItem)
00358 amount = icItem->item.amount;
00359 else
00360 amount = 0;
00361
00362
00363 pos[0] += obj->sx * C_UNIT / 2.0;
00364 pos[1] += obj->sy * C_UNIT / 2.0;
00365 UI_DrawItem(node, pos, &tempItem, -1, -1, scale, color);
00366 UI_DrawString("f_verysmall", ALIGN_LC,
00367 pos[0] + obj->sx * C_UNIT / 2.0, pos[1] + obj->sy * C_UNIT / 2.0,
00368 pos[0] + obj->sx * C_UNIT / 2.0, cellWidth - 5,
00369 0, va("x%i", amount), 0, 0, NULL, qfalse, 0);
00370 pos[0] -= obj->sx * C_UNIT / 2.0;
00371 pos[1] += obj->sy * C_UNIT / 2.0;
00372 cellHeight += obj->sy * C_UNIT;
00373
00374
00375 Vector2Copy(pos, ammopos);
00376 ammopos[2] = 0;
00377 ammopos[0] += obj->sx * C_UNIT + 10;
00378
00379
00380 cellHeight += UI_DrawString("f_verysmall", ALIGN_UL,
00381 pos[0], pos[1],
00382 pos[0], cellWidth - 5,
00383 0, _(obj->name), 0, 0, NULL, qfalse, LONGLINES_WRAP);
00384
00385
00386 if (obj->weapon && EXTRADATA(node).displayAmmoOfWeapon) {
00387 int ammoIdx;
00388 for (ammoIdx = 0; ammoIdx < obj->numAmmos; ammoIdx++) {
00389 tempItem.t = obj->ammos[ammoIdx];
00390
00391
00392 if (!GAME_ItemIsUseable(tempItem.t))
00393 continue;
00394
00395
00396 icItem = UI_ContainerNodeGetExistingItem(node, tempItem.t, EXTRADATA(node).filterEquipType);
00397 if (!icItem)
00398 continue;
00399
00400
00401 ammopos[0] += icItem->item.t->sx * C_UNIT / 2.0;
00402 ammopos[1] -= icItem->item.t->sy * C_UNIT / 2.0;
00403 UI_DrawItem(node, ammopos, &tempItem, -1, -1, scale, colorDefault);
00404 UI_DrawString("f_verysmall", ALIGN_LC,
00405 ammopos[0] + icItem->item.t->sx * C_UNIT / 2.0, ammopos[1] + icItem->item.t->sy * C_UNIT / 2.0,
00406 ammopos[0] + icItem->item.t->sx * C_UNIT / 2.0, cellWidth - 5 - ammopos[0],
00407 0, va("x%i", icItem->item.amount), 0, 0, NULL, qfalse, 0);
00408 ammopos[0] += icItem->item.t->sx * C_UNIT / 2.0;
00409 ammopos[1] += icItem->item.t->sy * C_UNIT / 2.0;
00410 }
00411 }
00412 cellHeight += 10;
00413
00414 if (cellHeight > rowHeight) {
00415 rowHeight = cellHeight;
00416 }
00417
00418
00419 if (col == EXTRADATA(node).columns - 1) {
00420 currentHeight += rowHeight;
00421 rowHeight = 0;
00422 if (currentHeight - EXTRADATA(node).scrollCur >= node->size[1])
00423 outOfNode = qtrue;
00424 }
00425
00426
00427 items++;
00428 }
00429
00430 if (rowHeight != 0) {
00431 currentHeight += rowHeight;
00432 }
00433 return currentHeight;
00434 }
00435
00439 static void UI_BaseInventoryNodeDraw2 (uiNode_t *node, objDef_t *highlightType)
00440 {
00441 qboolean updateScroll = qfalse;
00442 int visibleHeight = 0;
00443 int needHeight = 0;
00444 vec2_t pos;
00445
00446 UI_GetNodeAbsPos(node, pos);
00447 R_PushClipRect(pos[0], pos[1], node->size[0], node->size[1]);
00448
00449 needHeight = UI_BaseInventoryNodeDrawItems(node, highlightType);
00450
00451 R_PopClipRect();
00452 visibleHeight = node->size[1];
00453
00454 #if 0
00455 R_FontDrawString("f_verysmall", ALIGN_UL,
00456 node->pos[0], node->pos[1], node->pos[0], node->pos[1],
00457 0, 0,
00458 0, va("%i %i/%i", EXTRADATA(node).scrollCur, visibleRows, totalRows), 0, 0, NULL, qfalse, 0);
00459 #endif
00460
00461
00462 if (visibleHeight != EXTRADATA(node).scrollNum || needHeight != EXTRADATA(node).scrollTotalNum) {
00463 EXTRADATA(node).scrollTotalNum = needHeight;
00464 EXTRADATA(node).scrollNum = visibleHeight;
00465 updateScroll = qtrue;
00466 }
00467 if (EXTRADATA(node).scrollCur > needHeight - visibleHeight) {
00468 EXTRADATA(node).scrollCur = needHeight - visibleHeight;
00469 updateScroll = qtrue;
00470 }
00471 if (EXTRADATA(node).scrollCur < 0) {
00472 EXTRADATA(node).scrollCur = 0;
00473 updateScroll = qtrue;
00474 }
00475
00476 if (updateScroll)
00477 UI_BaseInventoryNodeUpdateScroll(node);
00478 }
00479
00483 static void UI_BaseInventoryNodeDraw (uiNode_t *node)
00484 {
00485 objDef_t *highlightType = NULL;
00486
00487 if (!EXTRADATA(node).container)
00488 return;
00489 if (!ui_inventory)
00490 return;
00491
00492 if (node->color[3] < 0.001)
00493 return;
00494
00495
00496 if (UI_DNDIsDragging() && UI_DNDGetType() == DND_ITEM) {
00497 highlightType = UI_DNDGetItem()->t;
00498 }
00499
00500 UI_BaseInventoryNodeDraw2(node, highlightType);
00501 }
00502
00506 static invList_t *UI_BaseInventoryNodeGetItem (const uiNode_t* const node,
00507 int mouseX, int mouseY, int* contX, int* contY)
00508 {
00509 qboolean outOfNode = qfalse;
00510 vec2_t nodepos;
00511 int items = 0;
00512 int rowHeight = 0;
00513 const int cellWidth = node->size[0] / EXTRADATACONST(node).columns;
00514 int tempX, tempY;
00515 containerItemIterator_t iterator;
00516 int currentHeight = 0;
00517
00518 if (!contX)
00519 contX = &tempX;
00520 if (!contY)
00521 contY = &tempY;
00522
00523 UI_GetNodeAbsPos(node, nodepos);
00524
00525 UI_ContainerItemIteratorInit(&iterator, node);
00526 for (; iterator.itemID < csi.numODs; UI_ContainerItemIteratorNext(&iterator)) {
00527 const int id = iterator.itemID;
00528 objDef_t *obj = INVSH_GetItemByIDX(id);
00529 vec2_t pos;
00530 vec2_t ammopos;
00531 const int col = items % EXTRADATACONST(node).columns;
00532 int cellHeight = 0;
00533 invList_t *icItem = iterator.itemFound;
00534 int height;
00535
00536
00537 if (outOfNode || currentHeight < EXTRADATACONST(node).scrollCur) {
00538 int height;
00539 R_FontTextSize("f_verysmall", _(obj->name),
00540 cellWidth - 5, LONGLINES_WRAP, NULL, &height, NULL, NULL);
00541 height += obj->sy * C_UNIT + 10;
00542 if (height > rowHeight)
00543 rowHeight = height;
00544
00545 if (outOfNode || currentHeight + rowHeight < EXTRADATACONST(node).scrollCur) {
00546 if (col == EXTRADATACONST(node).columns - 1) {
00547 currentHeight += rowHeight;
00548 rowHeight = 0;
00549 }
00550 items++;
00551 continue;
00552 }
00553 }
00554
00555 Vector2Copy(nodepos, pos);
00556 pos[0] += cellWidth * col;
00557 pos[1] += currentHeight - EXTRADATACONST(node).scrollCur;
00558
00559
00560 if (mouseY < pos[1])
00561 break;
00562 if (mouseX >= pos[0] && mouseX < pos[0] + obj->sx * C_UNIT
00563 && mouseY >= pos[1] && mouseY < pos[1] + obj->sy * C_UNIT) {
00564 if (icItem) {
00565 *contX = icItem->x;
00566 *contY = icItem->y;
00567 return icItem;
00568 } else {
00569 return NULL;
00570 }
00571 }
00572 pos[1] += obj->sy * C_UNIT;
00573 cellHeight += obj->sy * C_UNIT;
00574
00575
00576 Vector2Copy(pos, ammopos);
00577 ammopos[0] += obj->sx * C_UNIT + 10;
00578
00579
00580 R_FontTextSize("f_verysmall", _(obj->name),
00581 cellWidth - 5, LONGLINES_WRAP, NULL, &height, NULL, NULL);
00582 cellHeight += height;
00583
00584
00585 if (obj->weapon && EXTRADATACONST(node).displayAmmoOfWeapon) {
00586 int ammoIdx;
00587 for (ammoIdx = 0; ammoIdx < obj->numAmmos; ammoIdx++) {
00588 objDef_t *objammo = obj->ammos[ammoIdx];
00589
00590
00591 if (!GAME_ItemIsUseable(objammo))
00592 continue;
00593
00594
00595 icItem = UI_ContainerNodeGetExistingItem(node, objammo, EXTRADATACONST(node).filterEquipType);
00596 if (!icItem)
00597 continue;
00598
00599
00600 if (mouseX < ammopos[0] || mouseY >= ammopos[1])
00601 break;
00602 if (mouseX >= ammopos[0] && mouseX < ammopos[0] + objammo->sx * C_UNIT
00603 && mouseY >= ammopos[1] - objammo->sy * C_UNIT && mouseY < ammopos[1]) {
00604 *contX = icItem->x;
00605 *contY = icItem->y;
00606 return icItem;
00607 }
00608 ammopos[0] += objammo->sx * C_UNIT;
00609 }
00610 }
00611 cellHeight += 10;
00612
00613 if (cellHeight > rowHeight) {
00614 rowHeight = cellHeight;
00615 }
00616
00617
00618 if (col == EXTRADATACONST(node).columns - 1) {
00619 currentHeight += rowHeight;
00620 rowHeight = 0;
00621 if (currentHeight - EXTRADATACONST(node).scrollCur >= node->size[1])
00622 return NULL;
00623 }
00624
00625
00626 items++;
00627 }
00628
00629 *contX = NONE;
00630 *contY = NONE;
00631 return NULL;
00632 }
00633
00640 static void UI_BaseInventoryNodeDrawTooltip (uiNode_t *node, int x, int y)
00641 {
00642 static char tooltiptext[MAX_VAR * 2];
00643 const invList_t *itemHover;
00644 vec2_t nodepos;
00645
00646 UI_GetNodeAbsPos(node, nodepos);
00647
00648
00649 itemHover = UI_BaseInventoryNodeGetItem(node, x, y, NULL, NULL);
00650
00651 if (itemHover) {
00652 const int itemToolTipWidth = 250;
00653
00654
00655 UI_GetItemTooltip(itemHover->item, tooltiptext, sizeof(tooltiptext));
00656 #ifdef DEBUG
00657
00658 Q_strcat(tooltiptext, va("\n%i/%i", itemHover->x, itemHover->y), sizeof(tooltiptext));
00659 #endif
00660 UI_DrawTooltip(tooltiptext, x, y, itemToolTipWidth);
00661 }
00662 }
00663
00673 static void UI_ContainerNodeAutoPlace (uiNode_t* node, int mouseX, int mouseY)
00674 {
00675 int sel;
00676 #if 0
00677 int id;
00678 #endif
00679 invList_t *ic;
00680 int fromX, fromY;
00681
00682 if (!ui_inventory)
00683 return;
00684
00685
00686 if (CL_BattlescapeRunning())
00687 return;
00688
00689 sel = cl_selected->integer;
00690 if (sel < 0)
00691 return;
00692
00693 assert(EXTRADATA(node).container);
00694
00695 ic = UI_BaseInventoryNodeGetItem(node, mouseX, mouseY, &fromX, &fromY);
00696 Com_DPrintf(DEBUG_CLIENT, "UI_ContainerNodeAutoPlace: item %i/%i selected from scrollable container.\n", fromX, fromY);
00697 if (!ic)
00698 return;
00699 #if 0
00700 id = ic->item.t->idx;
00701 #endif
00702
00703
00704 if (EXTRADATA(node).container->id != csi.idEquip) {
00705 if (ic->item.m && ic->item.m != ic->item.t && ic->item.a) {
00706
00707 INV_UnloadWeapon(ic, ui_inventory, INVDEF(csi.idEquip));
00708 } else {
00709
00710 INV_MoveItem(ui_inventory, INVDEF(csi.idEquip), NONE, NONE, EXTRADATA(node).container, ic);
00711 }
00712 } else {
00713 qboolean packed = qfalse;
00714 int px, py;
00715 assert(ic->item.t);
00716
00717 if (INV_IsArmour(ic->item.t)) {
00718 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idArmour), 0, 0, EXTRADATA(node).container, ic);
00719
00720 } else if (INV_IsAmmo(ic->item.t)) {
00721 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idBelt), &px, &py, NULL);
00722 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idBelt), px, py, EXTRADATA(node).container, ic);
00723 if (!packed) {
00724 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idHolster), &px, &py, NULL);
00725 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idHolster), px, py, EXTRADATA(node).container, ic);
00726 }
00727 if (!packed) {
00728 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idBackpack), &px, &py, NULL);
00729 packed = INV_MoveItem( ui_inventory, INVDEF(csi.idBackpack), px, py, EXTRADATA(node).container, ic);
00730 }
00731
00732 if (!packed) {
00733 const invList_t *rightHand = INVSH_SearchInInventory(ui_inventory, INVDEF(csi.idRight), 0, 0);
00734
00735
00736 if (!rightHand || !rightHand->item.t->fireTwoHanded) {
00737 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idLeft), &px, &py, NULL);
00738 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idLeft), px, py, EXTRADATA(node).container, ic);
00739 }
00740 }
00741 if (!packed) {
00742 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idRight), &px, &py, NULL);
00743 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idRight), px, py, EXTRADATA(node).container, ic);
00744 }
00745 } else {
00746 if (ic->item.t->headgear) {
00747 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idHeadgear), &px, &py, NULL);
00748 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idHeadgear), px, py, EXTRADATA(node).container, ic);
00749 } else {
00750
00751
00752 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idRight), &px, &py, NULL);
00753 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idRight), px, py, EXTRADATA(node).container, ic);
00754 if (ic->item.t->weapon && !ic->item.a && packed)
00755 INV_LoadWeapon(ic, ui_inventory, EXTRADATA(node).container, INVDEF(csi.idRight));
00756 if (!packed) {
00757 const invList_t *rightHand = INVSH_SearchInInventory(ui_inventory, INVDEF(csi.idRight), 0, 0);
00758
00759
00760 if (!rightHand || (rightHand && !rightHand->item.t->fireTwoHanded)) {
00761 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idLeft), &px, &py, NULL);
00762 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idLeft), px, py, EXTRADATA(node).container, ic);
00763 if (ic->item.t->weapon && !ic->item.a && packed)
00764 INV_LoadWeapon(ic, ui_inventory, EXTRADATA(node).container, INVDEF(csi.idLeft));
00765 }
00766 }
00767 if (!packed) {
00768 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idBelt), &px, &py, NULL);
00769 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idBelt), px, py, EXTRADATA(node).container, ic);
00770 if (ic->item.t->weapon && !ic->item.a && packed)
00771 INV_LoadWeapon(ic, ui_inventory, EXTRADATA(node).container, INVDEF(csi.idBelt));
00772 }
00773 if (!packed) {
00774 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idHolster), &px, &py, NULL);
00775 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idHolster), px, py, EXTRADATA(node).container, ic);
00776 if (ic->item.t->weapon && !ic->item.a && packed)
00777 INV_LoadWeapon(ic, ui_inventory, EXTRADATA(node).container, INVDEF(csi.idHolster));
00778 }
00779 if (!packed) {
00780 INVSH_FindSpace(ui_inventory, &ic->item, INVDEF(csi.idBackpack), &px, &py, NULL);
00781 packed = INV_MoveItem(ui_inventory, INVDEF(csi.idBackpack), px, py, EXTRADATA(node).container, ic);
00782 if (ic->item.t->weapon && !ic->item.a && packed)
00783 INV_LoadWeapon(ic, ui_inventory, EXTRADATA(node).container, INVDEF(csi.idBackpack));
00784 }
00785 }
00786 }
00787
00788 if (!packed)
00789 return;
00790 }
00791
00797 if (INV_IsArmour(ic->item.t)) {
00798 uiNode_t *armour = UI_GetNode(node->root, "armour");
00799 if (armour && armour->onChange)
00800 UI_ExecuteEventActions(armour, armour->onChange);
00801 }
00802
00803
00804 UI_BaseInventoryNodeUpdateScroll(node);
00805 }
00806
00807 static int oldMouseX = 0;
00808 static int oldMouseY = 0;
00809
00810 static void UI_BaseInventoryNodeCapturedMouseMove (uiNode_t *node, int x, int y)
00811 {
00812 const int delta = abs(oldMouseX - x) + abs(oldMouseY - y);
00813 if (delta > 15) {
00814 UI_DNDDragItem(node, &(dragInfoIC->item));
00815 UI_MouseRelease();
00816 }
00817 }
00818
00819 static void UI_BaseInventoryNodeMouseDown (uiNode_t *node, int x, int y, int button)
00820 {
00821 switch (button) {
00822 case K_MOUSE1:
00823 {
00824
00825 int fromX, fromY;
00826 dragInfoIC = UI_BaseInventoryNodeGetItem(node, x, y, &fromX, &fromY);
00827 if (dragInfoIC) {
00828 dragInfoFromX = fromX;
00829 dragInfoFromY = fromY;
00830 oldMouseX = x;
00831 oldMouseY = y;
00832 UI_SetMouseCapture(node);
00833 EXTRADATA(node).lastSelectedId = dragInfoIC->item.t->idx;
00834 if (EXTRADATA(node).onSelect) {
00835 UI_ExecuteEventActions(node, EXTRADATA(node).onSelect);
00836 }
00837 }
00838 break;
00839 }
00840 case K_MOUSE2:
00841 if (UI_DNDIsDragging()) {
00842 UI_DNDAbort();
00843 } else {
00844
00845 UI_ContainerNodeAutoPlace(node, x, y);
00846 }
00847 break;
00848 default:
00849 break;
00850 }
00851 }
00852
00853 static void UI_BaseInventoryNodeMouseUp (uiNode_t *node, int x, int y, int button)
00854 {
00855 if (button != K_MOUSE1)
00856 return;
00857 if (UI_GetMouseCapture() == node) {
00858 UI_MouseRelease();
00859 }
00860 if (UI_DNDIsDragging()) {
00861 UI_DNDDrop();
00862 }
00863 }
00864 static void UI_BaseInventoryNodeWheel (uiNode_t *node, qboolean down, int x, int y)
00865 {
00866 const int delta = 20;
00867 if (down) {
00868 const int lenght = EXTRADATA(node).scrollTotalNum - EXTRADATA(node).scrollNum;
00869 if (EXTRADATA(node).scrollCur < lenght) {
00870 EXTRADATA(node).scrollCur += delta;
00871 if (EXTRADATA(node).scrollCur > lenght)
00872 EXTRADATA(node).scrollCur = lenght;
00873 UI_BaseInventoryNodeUpdateScroll(node);
00874 }
00875 } else {
00876 if (EXTRADATA(node).scrollCur > 0) {
00877 EXTRADATA(node).scrollCur -= delta;
00878 if (EXTRADATA(node).scrollCur < 0)
00879 EXTRADATA(node).scrollCur = 0;
00880 UI_BaseInventoryNodeUpdateScroll(node);
00881 }
00882 }
00883 }
00884
00885 static void UI_BaseInventoryNodeLoading (uiNode_t *node)
00886 {
00887 EXTRADATA(node).container = NULL;
00888 EXTRADATA(node).columns = 1;
00889 node->color[3] = 1.0;
00890 }
00891
00895 static qboolean UI_BaseInventoryNodeDNDEnter (uiNode_t *target)
00896 {
00897
00898 if (EXTRADATA(target).container == NULL)
00899 return qfalse;
00900
00901 return UI_DNDGetType() == DND_ITEM && UI_DNDGetSourceNode() != target;
00902 }
00903
00908 static qboolean UI_BaseInventoryNodeDNDMove (uiNode_t *target, int x, int y)
00909 {
00910 return qtrue;
00911 }
00912
00916 static void UI_BaseInventoryNodeDNDLeave (uiNode_t *node)
00917 {
00918 }
00919
00923 static void UI_BaseInventoryNodeInit (uiNode_t *node)
00924 {
00926 assert(!CL_BattlescapeRunning());
00927 }
00928
00929 void UI_RegisterBaseInventoryNode (uiBehaviour_t* behaviour)
00930 {
00931 behaviour->name = "baseinventory";
00932 behaviour->extends = "container";
00933 behaviour->draw = UI_BaseInventoryNodeDraw;
00934 behaviour->drawTooltip = UI_BaseInventoryNodeDrawTooltip;
00935 behaviour->mouseDown = UI_BaseInventoryNodeMouseDown;
00936 behaviour->mouseUp = UI_BaseInventoryNodeMouseUp;
00937 behaviour->mouseWheel = UI_BaseInventoryNodeWheel;
00938 behaviour->capturedMouseMove = UI_BaseInventoryNodeCapturedMouseMove;
00939 behaviour->init = UI_BaseInventoryNodeInit;
00940 behaviour->loading = UI_BaseInventoryNodeLoading;
00941 behaviour->loaded = UI_BaseInventoryNodeLoaded;
00942
00943 behaviour->dndEnter = UI_BaseInventoryNodeDNDEnter;
00944 behaviour->dndMove = UI_BaseInventoryNodeDNDMove;
00945 behaviour->dndLeave = UI_BaseInventoryNodeDNDLeave;
00946
00947 Com_RegisterConstInt("FILTER_S_PRIMARY", FILTER_S_PRIMARY);
00948 Com_RegisterConstInt("FILTER_S_SECONDARY", FILTER_S_SECONDARY);
00949 Com_RegisterConstInt("FILTER_S_HEAVY", FILTER_S_HEAVY);
00950 Com_RegisterConstInt("FILTER_S_MISC", FILTER_S_MISC);
00951 Com_RegisterConstInt("FILTER_S_ARMOUR", FILTER_S_ARMOUR);
00952 Com_RegisterConstInt("FILTER_CRAFTITEM", FILTER_CRAFTITEM);
00953 Com_RegisterConstInt("FILTER_UGVITEM", FILTER_UGVITEM);
00954 Com_RegisterConstInt("FILTER_AIRCRAFT", FILTER_AIRCRAFT);
00955 Com_RegisterConstInt("FILTER_DUMMY", FILTER_DUMMY);
00956 Com_RegisterConstInt("FILTER_DISASSEMBLY", FILTER_DISASSEMBLY);
00957 }