Esempio n. 1
0
/**
 * @brief Get the line number under an absolute position
 * @param[in] node a text node
 * @param[in] x,y position on the screen
 * @return The line number under the position (0 = first line)
 */
static int UI_TextNodeGetLine (const uiNode_t* node, int x, int y)
{
	int lineHeight;
	int line;
	assert(UI_NodeInstanceOf(node, "text"));

	lineHeight = EXTRADATACONST(node).lineHeight;
	if (lineHeight == 0) {
		const char* font = UI_GetFontFromNode(node);
		lineHeight = UI_FontGetHeight(font);
	}

	UI_NodeAbsoluteToRelativePos(node, &x, &y);
	y -= node->padding;

	/* skip position over the first line */
	if (y < 0)
		 return -1;
	line = (int) (y / lineHeight) + EXTRADATACONST(node).super.scrollY.viewPos;

	/* skip position under the last line */
	if (line >= EXTRADATACONST(node).super.scrollY.fullSize)
		return -1;

	return line;
}
Esempio n. 2
0
/**
 * @brief Use a container node to init an item iterator
 */
static void UI_ContainerItemIteratorInit (containerItemIterator_t *iterator, const uiNode_t* const node)
{
	int groupID = 0;
	iterator->itemID = -1;
	iterator->groupID = 0;
	iterator->node = node;
	iterator->filterEquipType = (itemFilterTypes_t) EXTRADATACONST(node).filterEquipType;

	if (EXTRADATACONST(node).displayAvailableOnTop) {
		/* available items */
		if (EXTRADATACONST(node).displayWeapon)
			iterator->groupSteps[groupID++] = CII_WEAPONONLY | CII_AVAILABLEONLY;
		if (EXTRADATACONST(node).displayAmmo)
			iterator->groupSteps[groupID++] = CII_AMMOONLY | CII_AVAILABLEONLY;
		/* unavailable items */
		if (EXTRADATACONST(node).displayUnavailableItem) {
			if (EXTRADATACONST(node).displayWeapon)
				iterator->groupSteps[groupID++] = CII_WEAPONONLY | CII_NOTAVAILABLEONLY;
			if (EXTRADATACONST(node).displayAmmo)
				iterator->groupSteps[groupID++] = CII_AMMOONLY | CII_NOTAVAILABLEONLY;
		}
	} else {
		const int filter = (EXTRADATACONST(node).displayUnavailableItem) ? 0 : CII_AVAILABLEONLY;
		if (EXTRADATACONST(node).displayWeapon)
			iterator->groupSteps[groupID++] = CII_WEAPONONLY | filter;
		if (EXTRADATACONST(node).displayAmmo)
			iterator->groupSteps[groupID++] = CII_AMMOONLY | filter;
	}
	iterator->groupSteps[groupID++] = CII_END;

	/* find the first item */
	UI_ContainerItemIteratorNext(iterator);
}
Esempio n. 3
0
/**
 * @brief Get the line number under an absolute position
 * @param[in] node a text node
 * @param[in] x position x on the screen
 * @param[in] y position y on the screen
 * @return The line number under the position (0 = first line)
 */
static int UI_TextListNodeGetLine (const uiNode_t *node, int x, int y)
{
	int lineHeight = EXTRADATACONST(node).lineHeight;
	if (lineHeight == 0) {
		const char *font = UI_GetFontFromNode(node);
		lineHeight = UI_FontGetHeight(font);
	}

	UI_NodeAbsoluteToRelativePos(node, &x, &y);
	y -= node->padding;
	return (int) (y / lineHeight) + EXTRADATACONST(node).super.scrollY.viewPos;
}
Esempio n. 4
0
/**
 * @brief Gets location of the item the mouse is over
 * @param[in] node The container-node.
 * @param[in] mouseX X location of the mouse.
 * @param[in] mouseY Y location of the mouse.
 * @param[out] contX X location in the container (index of item in row).
 * @param[out] contY Y location in the container (row).
 * @sa UI_ContainerNodeSearchInScrollableContainer
 */
static invList_t *UI_ContainerNodeGetItemAtPosition (const uiNode_t* const node, int mouseX, int mouseY, int* contX = NULL, int* contY = NULL)
{
	invList_t *result = NULL;

	if (!ui_inventory)
		return NULL;

	/* Get coordinates inside a scrollable container (if it is one). */
	if (UI_IsScrollContainerNode(node)) {
		Sys_Error("UI_ContainerNodeGetItemAtPosition is not usable for scrollable containers!");
	} else {
		vec2_t nodepos;
		int fromX, fromY;

		UI_GetNodeAbsPos(node, nodepos);
		/* Normalize screen coordinates to container coordinates. */
		fromX = (int) (mouseX - nodepos[0]) / C_UNIT;
		fromY = (int) (mouseY - nodepos[1]) / C_UNIT;
		if (contX)
			*contX = fromX;
		if (contY)
			*contY = fromY;

		result = INVSH_SearchInInventory(ui_inventory, EXTRADATACONST(node).container, fromX, fromY);
	}
	return result;
}
Esempio n. 5
0
/**
 * @brief Return a tab located at a screen position
 * @param[in] node A tab node
 * @param[in] x The x position of the screen to test
 * @param[in] y The x position of the screen to test
 * @return A uiNode_t, or NULL if nothing.
 * @todo improve test when we are on a junction
 * @todo improve test when we are on a chopped tab
 */
static uiNode_t* UI_TabNodeTabAtPosition (const uiNode_t *node, int x, int y)
{
    const char *font;
    uiNode_t* option;
    uiNode_t* prev = NULL;
    int allowedWidth;

    UI_NodeAbsoluteToRelativePos(node, &x, &y);

    /** @todo this dont work when an option is hidden */
    allowedWidth = node->size[0] - TILE_WIDTH * (EXTRADATACONST(node).count + 1);

    /* Bounded box test (shound not need, but there are problem) */
    if (x < 0 || y < 0 || x >= node->size[0] || y >= node->size[1])
        return NULL;

    font = UI_GetFontFromNode(node);

    /* Text box test */
    for (option = node->firstChild; option; option = option->next) {
        int tabWidth;
        const char *label;
        assert(option->behaviour == ui_optionBehaviour);

        /* skip hidden options */
        if (option->invis)
            continue;

        if (x < TILE_WIDTH / 2)
            return prev;

        label = OPTIONEXTRADATA(option).label;
        if (label[0] == '_')
            label = _(label + 1);

        R_FontTextSize(font, label, 0, LONGLINES_PRETTYCHOP, &tabWidth, NULL, NULL, NULL);
        if (OPTIONEXTRADATA(option).icon && OPTIONEXTRADATA(option).icon->size[0] < allowedWidth) {
            tabWidth += OPTIONEXTRADATA(option).icon->size[0];
        }
        if (tabWidth > allowedWidth) {
            if (allowedWidth > 0)
                tabWidth = allowedWidth;
            else
                tabWidth = 0;
        }

        if (x < tabWidth + TILE_WIDTH)
            return option;

        allowedWidth -= tabWidth;
        x -= tabWidth + TILE_WIDTH;
        prev = option;
    }
    if (x < TILE_WIDTH / 2)
        return prev;
    return NULL;
}
Esempio n. 6
0
/**
 * @brief Custom tooltip
 * @param[in] node Node we request to draw tooltip
 * @param[in] x Position x of the mouse
 * @param[in] y Position y of the mouse
 */
void uiBaseMapNode::drawTooltip (uiNode_t *node, int x, int y)
{
	int col, row;

	getCellAtPos(node, x, y, &col, &row);
	if (col == -1)
		return;

	GAME_DrawBaseTooltip(EXTRADATACONST(node).baseid, x, y, col, row);
}
Esempio n. 7
0
/**
 * @brief Search a a key binding from a window node.
 * Window node store key bindings for his node child.
 * @param node A window node
 * @param key A key code, either K_ value or lowercase ascii
 */
uiKeyBinding_t* UI_WindowNodeGetKeyBinding (uiNode_t const* const node, unsigned int key)
{
	uiKeyBinding_t* binding = EXTRADATACONST(node).keyList;
	assert(UI_NodeInstanceOf(node, "window"));
	while (binding) {
		if (binding->key == key)
			break;
		binding = binding->next;
	}
	return binding;
}
Esempio n. 8
0
/**
 * @brief Middle click on the basemap
 * @sa UI_BaseMapNodeClick
 * @param[in] node Node definition for the base map
 * @param[in] x The x screen coordinate
 * @param[in] y The y screen coordinate
 * @note relies on @c baseCurrent
 */
void uiBaseMapNode::onMiddleClick (uiNode_t *node, int x, int y)
{
	assert(node);
	assert(node->root);

	int row, col;
	getCellAtPos(node, x, y, &col, &row);
	if (col == -1)
		return;

	GAME_HandleBaseClick(EXTRADATACONST(node).baseid, K_MOUSE3, col, row);
}
Esempio n. 9
0
/**
 * @brief True if the window is a modal.
 * @param node A window node
 * @return True if the window is a modal.
 */
bool UI_WindowIsModal(uiNode_t const* const node)
{
	return EXTRADATACONST(node).modal;
}
Esempio n. 10
0
/**
 * @brief True if the window is a drop down.
 * @param node A window node
 * @return True if the window is a drop down.
 */
bool UI_WindowIsDropDown(uiNode_t const* const node)
{
	return EXTRADATACONST(node).dropdown;
}
Esempio n. 11
0
/**
 * @brief Check if a window is fullscreen or not
 */
bool UI_WindowIsFullScreen (const uiNode_t* const node)
{
	assert(UI_NodeInstanceOf(node, "window"));
	return EXTRADATACONST(node).isFullScreen;
}
Esempio n. 12
0
static void UI_PanelNodeGetClientPosition (const uiNode_t *node, vec2_t position)
{
	position[0] = -EXTRADATACONST(node).super.scrollX.viewPos;
	position[1] = -EXTRADATACONST(node).super.scrollY.viewPos;
}
Esempio n. 13
0
/**
 * @brief Searches if there is an item at location (x/y) in a scrollable container. You can also provide an item to search for directly (x/y is ignored in that case).
 * @note x = x-th item in a row, y = row. i.e. x/y does not equal the "grid" coordinates as used in those containers.
 * @param[in] node Context node
 * @param[in] item Item requested
 * @param[in] filterType Filter used.
 * @todo Remove filter it is not a generic concept, and here it mean nothing
 * @return Item Pointer to the Item/item that is located at x/y or equals "item".
 * @sa Inventory::getItemAtPos
 */
static Item* UI_ContainerNodeGetExistingItem (const uiNode_t* node, const objDef_t* item, const itemFilterTypes_t filterType)
{
	return INV_SearchInInventoryWithFilter(ui_inventory, EXTRADATACONST(node).super.container, item, filterType);
}
Esempio n. 14
0
/**
 * @note this function is a copy-paste of UI_ContainerNodeDrawItems (with remove of unneeded code)
 */
static Item* UI_BaseInventoryNodeGetItem (const uiNode_t* const node, int mouseX, int mouseY, int* contX, int* contY)
{
	bool outOfNode = false;
	vec2_t nodepos;
	int items = 0;
	int rowHeight = 0;
	const int cellWidth = node->box.size[0] / EXTRADATACONST(node).columns;
	int tempX, tempY;
	containerItemIterator_t iterator;
	int currentHeight = 0;

	if (!contX)
		contX = &tempX;
	if (!contY)
		contY = &tempY;

	UI_GetNodeAbsPos(node, nodepos);

	UI_ContainerItemIteratorInit(&iterator, node);
	for (; iterator.itemID < csi.numODs; UI_ContainerItemIteratorNext(&iterator)) {
		const int id = iterator.itemID;
		const objDef_t* obj = INVSH_GetItemByIDX(id);
		vec2_t pos;
		vec2_t ammopos;
		const int col = items % EXTRADATACONST(node).columns;
		int cellHeight = 0;
		Item* icItem = iterator.itemFound;
		int height;

		/* skip items over and bellow the node view */
		if (outOfNode || currentHeight < EXTRADATACONST(node).scrollY.viewPos) {
			int outHeight;
			R_FontTextSize("f_verysmall", _(obj->name),
				cellWidth - 5, LONGLINES_WRAP, nullptr, &outHeight, nullptr, nullptr);
			outHeight += obj->sy * C_UNIT + 10;
			if (outHeight > rowHeight)
				rowHeight = outHeight;

			if (outOfNode || currentHeight + rowHeight < EXTRADATACONST(node).scrollY.viewPos) {
				if (col == EXTRADATACONST(node).columns - 1) {
					currentHeight += rowHeight;
					rowHeight = 0;
				}
				items++;
				continue;
			}
		}

		Vector2Copy(nodepos, pos);
		pos[0] += cellWidth * col;
		pos[1] += currentHeight - EXTRADATACONST(node).scrollY.viewPos;

		/* check item */
		if (mouseY < pos[1])
			break;
		if (mouseX >= pos[0] && mouseX < pos[0] + obj->sx * C_UNIT
		 && mouseY >= pos[1] && mouseY < pos[1] + obj->sy * C_UNIT) {
			if (icItem) {
				*contX = icItem->getX();
				*contY = icItem->getY();
				return icItem;
			}
			return nullptr;
		}
		pos[1] += obj->sy * C_UNIT;
		cellHeight += obj->sy * C_UNIT;

		/* save position for ammo */
		Vector2Copy(pos, ammopos);
		ammopos[0] += obj->sx * C_UNIT + 10;

		/* draw the item name. */
		R_FontTextSize("f_verysmall", _(obj->name),
			cellWidth - 5, LONGLINES_WRAP, nullptr, &height, nullptr, nullptr);
		cellHeight += height;

		/* draw ammos of weapon */
		if (obj->weapon && EXTRADATACONST(node).displayAmmoOfWeapon) {
			for (int ammoIdx = 0; ammoIdx < obj->numAmmos; ammoIdx++) {
				const objDef_t* objammo = obj->ammos[ammoIdx];

				/* skip unusable ammo */
				if (!GAME_ItemIsUseable(objammo))
					continue;

				/* find and skip none existing ammo */
				icItem = UI_ContainerNodeGetExistingItem(node, objammo, (itemFilterTypes_t) EXTRADATACONST(node).filterEquipType);
				if (!icItem)
					continue;

				/* check ammo (ammopos in on the left-lower corner) */
				if (mouseX < ammopos[0] || mouseY >= ammopos[1])
					break;
				if (mouseX >= ammopos[0] && mouseX < ammopos[0] + objammo->sx * C_UNIT
				 && mouseY >= ammopos[1] - objammo->sy * C_UNIT && mouseY < ammopos[1]) {
					*contX = icItem->getX();
					*contY = icItem->getY();
					return icItem;
				}
				ammopos[0] += objammo->sx * C_UNIT;
			}
		}
		cellHeight += 10;

		if (cellHeight > rowHeight) {
			rowHeight = cellHeight;
		}

		/* add a margin between rows */
		if (col == EXTRADATACONST(node).columns - 1) {
			currentHeight += rowHeight;
			rowHeight = 0;
			if (currentHeight - EXTRADATACONST(node).scrollY.viewPos >= node->box.size[1])
				return nullptr;
		}

		/* count items */
		items++;
	}

	*contX = NONE;
	*contY = NONE;
	return nullptr;
}
Esempio n. 15
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;
}
Esempio n. 16
0
static inline bool UI_IsScrollContainerNode (const uiNode_t* const node)
{
	return EXTRADATACONST(node).container && EXTRADATACONST(node).container->scroll;
}