示例#1
0
/**
 * @brief Main function to draw a container node
 */
void uiContainerNode::draw (uiNode_t *node)
{
	const objDef_t *highlightType = NULL;

	if (!EXTRADATA(node).container)
		return;
	if (!ui_inventory)
		return;
	/* is container invisible */
	if (node->color[3] < 0.001)
		return;

	/* Highlight weapons that the dragged ammo (if it is one) can be loaded into. */
	if (UI_DNDIsDragging() && UI_DNDGetType() == DND_ITEM) {
		highlightType = UI_DNDGetItem()->item;
	}

	if (EXTRADATA(node).container->single) {
		UI_ContainerNodeDrawSingle(node, highlightType);
	} else {
		if (UI_IsScrollContainerNode(node)) {
			assert(false);
		} else {
			UI_ContainerNodeDrawGrid(node, highlightType);
		}
	}

	/* Draw free space if dragging - but not for idEquip */
	if (UI_DNDIsDragging() && EXTRADATA(node).container->id != csi.idEquip)
		UI_ContainerNodeDrawFreeSpace(node, ui_inventory);

	if (UI_DNDIsTargetNode(node))
		UI_ContainerNodeDrawDropPreview(node);
}
示例#2
0
/**
 * @brief Draw a preview of the DND item dropped into the node
 */
static void UI_ContainerNodeDrawDropPreview (uiNode_t *target)
{
	item_t previewItem;
	int checkedTo;
	vec3_t origine;

	/* no preview into scrollable list */
	if (UI_IsScrollContainerNode(target))
		return;

	/* copy the DND item to not change the original one */
	previewItem = *UI_DNDGetItem();
	previewItem.rotated = false;
	checkedTo = INVSH_CheckToInventory(ui_inventory, previewItem.item, EXTRADATA(target).container, dragInfoToX, dragInfoToY, dragInfoIC);
	switch (checkedTo) {
	case INV_DOES_NOT_FIT:
		return;
	case INV_FITS:
		break;
	case INV_FITS_BOTH:
		/** @todo enable Shift-rotate for battlescape too when issues are solved */
		if (!Key_IsDown(K_SHIFT) || CL_BattlescapeRunning())
			break;
	case INV_FITS_ONLY_ROTATED:
		previewItem.rotated = true;
	}

	/* Hack, no preview for armour, we don't want it out of the armour container (and armour container is not visible) */
	if (INV_IsArmour(previewItem.item))
		return;

	UI_GetNodeAbsPos(target, origine);
	origine[2] = -40;

	/* Get center of single container for placement of preview item */
	if (EXTRADATA(target).container->single) {
		origine[0] += target->box.size[0] / 2.0;
		origine[1] += target->box.size[1] / 2.0;
	/* This is a "grid" container - we need to calculate the item-position
	 * (on the screen) from stored placement in the container and the
	 * calculated rotation info. */
	} else {
		if (previewItem.rotated) {
			origine[0] += (dragInfoToX + previewItem.item->sy / 2.0) * C_UNIT;
			origine[1] += (dragInfoToY + previewItem.item->sx / 2.0) * C_UNIT;
		} else {
			origine[0] += (dragInfoToX + previewItem.item->sx / 2.0) * C_UNIT;
			origine[1] += (dragInfoToY + previewItem.item->sy / 2.0) * C_UNIT;
		}
	}

	UI_DrawItem(NULL, origine, &previewItem, -1, -1, scale, colorPreview);
}
示例#3
0
/**
 * @brief Draws the free and usable inventory positions when dragging an item.
 * @note Only call this function in dragging mode
 */
static void UI_ContainerNodeDrawFreeSpace (uiNode_t *node, inventory_t *inv)
{
	const objDef_t *od = UI_DNDGetItem()->item;	/**< Get the 'type' of the dragged item. */
	vec2_t nodepos;

	/* Draw only in dragging-mode and not for the equip-floor */
	assert(UI_DNDIsDragging());
	assert(inv);

	UI_GetNodeAbsPos(node, nodepos);
	/* if single container (hands, extension, headgear) */
	if (EXTRADATA(node).container->single) {
		/* if container is free or the dragged-item is in it */
		if (UI_DNDIsSourceNode(node) || INVSH_CheckToInventory(inv, od, EXTRADATA(node).container, 0, 0, dragInfoIC))
			UI_DrawFree(EXTRADATA(node).container->id, node, nodepos[0], nodepos[1], node->box.size[0], node->box.size[1], true);
	} else {
		/* The shape of the free positions. */
		uint32_t free[SHAPE_BIG_MAX_HEIGHT];
		bool showTUs = true;
		int x, y;

		OBJZERO(free);

		for (y = 0; y < SHAPE_BIG_MAX_HEIGHT; y++) {
			for (x = 0; x < SHAPE_BIG_MAX_WIDTH; x++) {
				/* Check if the current position is usable (topleft of the item). */

				/* Add '1's to each position the item is 'blocking'. */
				const int checkedTo = INVSH_CheckToInventory(inv, od, EXTRADATA(node).container, x, y, dragInfoIC);
				if (checkedTo & INV_FITS)				/* Item can be placed normally. */
					INVSH_MergeShapes(free, (uint32_t)od->shape, x, y);
				if (checkedTo & INV_FITS_ONLY_ROTATED)	/* Item can be placed rotated. */
					INVSH_MergeShapes(free, INVSH_ShapeRotate((uint32_t)od->shape), x, y);

				/* Only draw on existing positions. */
				if (INVSH_CheckShape(EXTRADATA(node).container->shape, x, y)) {
					if (INVSH_CheckShape(free, x, y)) {
						UI_DrawFree(EXTRADATA(node).container->id, node, nodepos[0] + x * C_UNIT, nodepos[1] + y * C_UNIT, C_UNIT, C_UNIT, showTUs);
						showTUs = false;
					}
				}
			}
		}
	}
}
示例#4
0
/**
 * @brief Main function to draw a container node
 */
void uiBaseInventoryNode::draw (uiNode_t* node)
{
	const objDef_t* highlightType = nullptr;

	if (!EXTRADATA(node).super.container)
		return;
	if (!ui_inventory)
		return;
	/* is container invisible */
	if (node->color[3] < 0.001)
		return;

	/* Highlight weapons that the dragged ammo (if it is one) can be loaded into. */
	if (UI_DNDIsDragging() && UI_DNDGetType() == DND_ITEM) {
		highlightType = UI_DNDGetItem()->def();
	}

	UI_BaseInventoryNodeDraw2(node, highlightType);
}
示例#5
0
/**
 * @brief Call into the source when the DND end
 */
bool uiContainerNode::onDndFinished (uiNode_t *source, bool isDropped)
{
	item_t *dragItem = UI_DNDGetItem();
	const invDef_t *sourceContainer = EXTRADATACONST(source).container;

	/* if the target can't finalize the DND we stop */
	if (!isDropped) {
		return false;
	}

	assert(sourceContainer);

	/* on tactical mission */
	if (CL_BattlescapeRunning()) {
		const uiNode_t *target = UI_DNDGetTargetNode();
		const invDef_t *targetContainer = EXTRADATACONST(target).container;
		assert(targetContainer);
		CL_ActorInvMove(selActor, sourceContainer->id, dragInfoFromX, dragInfoFromY,
				targetContainer->id, dragInfoToX, dragInfoToY);
	} else {
		uiNode_t *target = UI_DNDGetTargetNode();
		if (target) {
			invList_t *fItem;
			invList_t *tItem;
			bool moved = false;
			const invDef_t *targetContainer = EXTRADATACONST(target).container;
			assert(targetContainer);
			if (UI_IsScrollContainerNode(source)) {
				fItem = UI_ContainerNodeGetExistingItem(sourceContainer, dragItem->item, MAX_FILTERTYPES);
			} else
				fItem = INVSH_SearchInInventory(ui_inventory, sourceContainer, dragInfoFromX, dragInfoFromY);
			assert(fItem);

			/** @todo We must split the move in two. Here, we should not know how to add the item to the target (see dndDrop) */
			/* Remove ammo on removing weapon from a soldier */
			if (UI_IsScrollContainerNode(target) && fItem->item.ammo && fItem->item.ammo != fItem->item.item && fItem->item.ammoLeft)
				INV_UnloadWeapon(fItem, ui_inventory, targetContainer);

			/* rotate on Shift */
			/** @todo enable Shift-rotate for battlescape too when issues are solved */
			fItem->item.rotated = Key_IsDown(K_SHIFT) && !CL_BattlescapeRunning();

			/* move the item */
			moved = INV_MoveItem(ui_inventory, targetContainer, dragInfoToX, dragInfoToY, sourceContainer, fItem, &tItem);

			/* No need to continue move wasn't successful */
			if (!moved)
				return false;

			/* Add ammo on adding weapon to a soldier */
			if (UI_IsScrollContainerNode(source) && ((fItem->item.item->weapon && !fItem->item.ammoLeft) || fItem->item.item->oneshot))
				INV_LoadWeapon(tItem, ui_inventory, sourceContainer, targetContainer);

			/* Run onChange events */
			if (source->onChange)
				UI_ExecuteEventActions(source, source->onChange);
			if (source != target && target->onChange)
				UI_ExecuteEventActions(target, target->onChange);
		}
	}

	dragInfoFromX = -1;
	dragInfoFromY = -1;
	return true;
}
示例#6
0
/**
 * @brief Call into the target when the DND hover it
 * @return True if the DND is accepted
 */
bool uiContainerNode::onDndMove (uiNode_t *target, int x, int y)
{
	vec2_t nodepos;
	bool exists;
	int itemX = 0;
	int itemY = 0;
	item_t *dragItem = UI_DNDGetItem();

	/* we already check it when the node accept the DND */
	assert(EXTRADATA(target).container);

	UI_GetNodeAbsPos(target, nodepos);

	/** We calculate the position of the top-left corner of the dragged
	 * item in oder to compensate for the centered-drawn cursor-item.
	 * Or to be more exact, we calculate the relative offset from the cursor
	 * location to the middle of the top-left square of the item.
	 * @sa UI_LeftClick */
	if (dragItem->item) {
		itemX = C_UNIT * dragItem->item->sx / 2;	/* Half item-width. */
		itemY = C_UNIT * dragItem->item->sy / 2;	/* Half item-height. */

		/* Place relative center in the middle of the square. */
		itemX -= C_UNIT / 2;
		itemY -= C_UNIT / 2;
	}

	dragInfoToX = (mousePosX - nodepos[0] - itemX) / C_UNIT;
	dragInfoToY = (mousePosY - nodepos[1] - itemY) / C_UNIT;

	/* Check if the items already exists in the container. i.e. there is already at least one item. */
	exists = false;
	if ((INV_IsFloorDef(EXTRADATA(target).container) || INV_IsEquipDef(EXTRADATA(target).container))
		&& (dragInfoToX < 0 || dragInfoToY < 0 || dragInfoToX >= SHAPE_BIG_MAX_WIDTH || dragInfoToY >= SHAPE_BIG_MAX_HEIGHT)
		&& INVSH_ExistsInInventory(ui_inventory, EXTRADATA(target).container, dragItem)) {
		exists = true;
	}

	/* Search for a suitable position to render the item at if
	 * the container is "single", the cursor is out of bound of the container. */
	if (!exists && dragItem->item && (EXTRADATA(target).container->single
		|| dragInfoToX < 0 || dragInfoToY < 0
		|| dragInfoToX >= SHAPE_BIG_MAX_WIDTH || dragInfoToY >= SHAPE_BIG_MAX_HEIGHT)) {
#if 0
/* ... or there is something in the way. */
/* 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. */
		|| (INVSH_CheckToInventory(ui_inventory, dragItem->item, EXTRADATA(target).container, dragInfoToX, dragInfoToY) == INV_DOES_NOT_FIT)) {
#endif
		INVSH_FindSpace(ui_inventory, dragItem, EXTRADATA(target).container, &dragInfoToX, &dragInfoToY, dragInfoIC);
	}

	/* we can drag every thing */
	if (UI_IsScrollContainerNode(target)) {
		return true;
	}

	{
		invList_t *fItem;

		/* is there empty slot? */
		const int checkedTo = INVSH_CheckToInventory(ui_inventory, dragItem->item, EXTRADATA(target).container, dragInfoToX, dragInfoToY, dragInfoIC);
		if (checkedTo != INV_DOES_NOT_FIT)
			return true;

		/* can we equip dragging item into the target item? */
		fItem = INVSH_SearchInInventory(ui_inventory, EXTRADATA(target).container, dragInfoToX, dragInfoToY);
		if (!fItem)
			return false;
		if (EXTRADATA(target).container->single)
			return true;
		return INVSH_LoadableInWeapon(dragItem->item, fItem->item.item);
	}
}

/**
 * @brief Call when a DND enter into the node
 */
void uiContainerNode::onDndLeave (uiNode_t *node)
{
	dragInfoToX = -1;
	dragInfoToY = -1;
}