/** * @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; }
/** * @brief Handles selectboxes clicks */ static void UI_OptionTreeNodeClick (uiNode_t * node, int x, int y) { uiNode_t* option; int depth; if (UI_AbstractOptionGetCurrentValue(node) == NULL) return; /* select the right option */ option = UI_OptionTreeNodeGetOptionAtPosition(node, x, y, &depth); UI_NodeAbsoluteToRelativePos(node, &x, &y); /* extend/collapse*/ x -= depth * DEPTH_WIDTH; if (x >= 0 && x < COLLAPSEBUTTON_WIDTH) { if (option && option->firstChild) { OPTIONEXTRADATA(option).collapsed = !OPTIONEXTRADATA(option).collapsed; UI_OptionTreeNodeUpdateCache(node); } return; } /* update the status */ if (option) UI_AbstractOptionSetCurrentValue(node, OPTIONEXTRADATA(option).value); }
/** * @brief Return index of the image (r_images[i]) else NULL */ static int UI_MaterialEditorNodeGetImageAtPosition (uiNode_t *node, int x, int y) { int i; vec2_t pos; int cnt = 0; int cntView = 0; const int imagesPerLine = (node->box.size[0] - node->padding) / (IMAGE_WIDTH + node->padding); const int imagesPerColumn = (node->box.size[1] - node->padding) / (IMAGE_WIDTH + node->padding); int columnRequested; int lineRequested; UI_NodeAbsoluteToRelativePos(node, &x, &y); /* have we click between 2 images? */ if (((x % (IMAGE_WIDTH + node->padding)) < node->padding) || ((y % (IMAGE_WIDTH + node->padding)) < node->padding)) return -1; /* get column and line of the image */ columnRequested = x / (IMAGE_WIDTH + node->padding); lineRequested = y / (IMAGE_WIDTH + node->padding); /* have we click outside? */ if (columnRequested >= imagesPerLine || lineRequested >= imagesPerColumn) return -1; UI_GetNodeAbsPos(node, pos); /* check images */ for (i = 0; i < r_numImages; i++) { #ifndef ANYIMAGES /* filter */ image_t *image = R_GetImageAtIndex(i); if (image->type != it_world) continue; if (strstr(image->name, "tex_common")) continue; #endif /* skip images before the scroll position */ if (cnt / imagesPerLine < EXTRADATA(node).scrollY.viewPos) { cnt++; continue; } if (cntView % imagesPerLine == columnRequested && cntView / imagesPerLine == lineRequested) return i; /* vertical overflow */ if (cntView / imagesPerLine > lineRequested) break; cnt++; cntView++; } return -1; }
/** * @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; }
/** * @brief Get an element of the scrollbar at a position * @param[in] node Absolute position y * @param[in] description Size of each scroll bar elements (beginarrow, mid, scroll, mid, endarrow) * @param[in] x,y Absolute position */ static int UI_VScrollbarNodeGetElement (uiNode_t* node, int description[5], int x, int y) { UI_NodeAbsoluteToRelativePos(node, &x, &y); for (int i = 0; i < 5; i++) { if (y < description[i]) return i; y -= description[i]; } return -1; }
void uiControlNode::onMouseDown (uiNode_t* node, int x, int y, int button) { if (button == K_MOUSE1) { UI_SetMouseCapture(node); /* save position between mouse and node pos */ UI_NodeAbsoluteToRelativePos(node, &x, &y); deltaMouseX = x + node->box.pos[0]; deltaMouseY = y + node->box.pos[1]; } }
/** * @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; }
/** * @brief Return col and row of a cell, at an absolute position * @param[in] node Node definition for the base map * @param[in] x Absolute x-position requested * @param[in] y Absolute y-position requested * @param[out] col Col of the cell at the position (-1 if no cell) * @param[out] row Row of the cell at the position (-1 if no cell) */ void uiBaseMapNode::getCellAtPos (const uiNode_t *node, int x, int y, int *col, int *row) { assert(col); assert(row); UI_NodeAbsoluteToRelativePos(node, &x, &y); if (x < 0 || y < 0 || x >= node->box.size[0] || y >= node->box.size[1]) { *col = -1; *row = -1; return; } *col = x / (node->box.size[0] / BASE_SIZE); *row = y / (node->box.size[1] / BASE_SIZE); assert(*col >= 0 && *col < BASE_SIZE); assert(*row >= 0 && *row < BASE_SIZE); }
void uiSpinnerNode::onMouseDown (uiNode_t *node, int x, int y, int button) { const bool disabled = node->disabled || node->parent->disabled; if (disabled) return; if (button == K_MOUSE1) { UI_SetMouseCapture(node); UI_NodeAbsoluteToRelativePos(node, &x, &y); capturedDownButton = !isPositionIncrease(node, x, y); step(node, capturedDownButton); capturedTimer = UI_AllocTimer(node, 500, UI_SpinnerNodeRepeat); UI_TimerStart(capturedTimer); } }
/** * @brief call when the mouse move is the node is captured * @todo we can remove the loop if we save the current element in the node */ void uiSelectBoxNode::onCapturedMouseMove (uiNode_t* node, int x, int y) { UI_NodeAbsoluteToRelativePos(node, &x, &y); /* test bounded box */ if (x < 0 || y < 0 || x > node->box.size[0] || y > node->box.size[1] * (EXTRADATA(node).count + 1)) { return; } int posy = node->box.size[1]; for (uiNode_t* option = UI_AbstractOptionGetFirstOption(node); option; option = option->next) { if (option->invis) continue; OPTIONEXTRADATA(option).hovered = (posy <= y && y < posy + node->box.size[1]); posy += node->box.size[1]; } }
/** * @brief Called when the node is captured by the mouse */ void uiRadarNode::onCapturedMouseMove (uiNode_t* node, int x, int y) { const float mapWidth = cl.mapData->mapBox.getWidthX(); const float mapHeight = cl.mapData->mapBox.getWidthY(); const float mapCoefX = node->box.size[0] / mapWidth; const float mapCoefY = node->box.size[1] / mapHeight; vec3_t pos; /* from absolute to relative to node */ UI_NodeAbsoluteToRelativePos(node, &x, &y); /* from node to map */ pos[0] = cl.mapData->mapBox.getMinX() + x / mapCoefX; pos[1] = cl.mapData->mapBox.getMaxY() - y / mapCoefY; pos[2] = 0; VectorCopy(pos, cl.cam.origin); }
static uiNode_t* UI_OptionTreeNodeGetOptionAtPosition (uiNode_t * node, int x, int y, int *depth) { uiNode_t* option; const char *font; int fontHeight; int count; uiOptionIterator_t iterator; UI_NodeAbsoluteToRelativePos(node, &x, &y); font = UI_GetFontFromNode(node); fontHeight = EXTRADATA(node).lineHeight; if (fontHeight == 0) fontHeight = UI_FontGetHeight(font); option = UI_OptionTreeNodeGetFirstOption(node); count = EXTRADATA(node).scrollY.viewPos + (y - node->padding) / fontHeight; option = UI_InitOptionIteratorAtIndex(count, option, &iterator); *depth = iterator.depthPos; return option; }
/** * @brief Called when the node is captured by the mouse */ void uiBarNode::onCapturedMouseMove (uiNode_t* node, int x, int y) { UI_NodeAbsoluteToRelativePos(node, &x, &y); if (x < 0) x = 0; else if (x > node->box.size[0]) x = node->box.size[0]; if (y < 0) y = 0; else if (y > node->box.size[1]) y = node->box.size[1]; float frac; const float min = getMin(node); const float max = getMax(node); switch (EXTRADATA(node).orientation) { case ALIGN_UC: frac = (node->box.size[1] - (float) y) / node->box.size[1]; break; case ALIGN_LC: frac = (float) y / node->box.size[1]; break; case ALIGN_CR: frac = (float) x / node->box.size[0]; break; case ALIGN_CL: frac = (node->box.size[0] - (float) x) / node->box.size[0]; break; default: frac = 0; Com_Printf("UI_BarNodeCapturedMouseMove: Orientation %d not supported\n", EXTRADATA(node).orientation); break; } setValue(node, min + frac * (max - min)); }
static zoneNode_t UI_EditorNodeGetElementAtPosition (uiNode_t* node, int x, int y) { UI_NodeAbsoluteToRelativePos(anchoredNode, &x, &y); if (x > 0 && x < node->box.size[0] && y > 0 && y < node->box.size[1]) { return ZONE_BODY; } if (y > -anchorSize && y < 0) { if (x > -anchorSize && x < 0) { return ZONE_TOPLEFT_CORNER; } else if (x > node->box.size[0] && x < node->box.size[0] + anchorSize) { return ZONE_TOPRIGHT_CORNER; } } else if (y > node->box.size[1] && y < node->box.size[1] + anchorSize) { if (x > -anchorSize && x < 0) { return ZONE_BOTTOMLEFT_CORNER; } else if (x > node->box.size[0] && x < node->box.size[0] + anchorSize) { return ZONE_BOTTOMRIGHT_CORNER; } } return ZONE_NONE; }