void uiTextEntryNode::draw (uiNode_t* node) { const float* textColor; vec2_t pos; const char* font = UI_GetFontFromNode(node); uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; if (node->disabled) { textColor = node->disabledColor; iconStatus = SPRITE_STATUS_DISABLED; } else if (node->state) { textColor = node->color; iconStatus = SPRITE_STATUS_HOVER; } else { textColor = node->color; } if (UI_HasFocus(node)) { textColor = node->selectedColor; } UI_GetNodeAbsPos(node, pos); if (EXTRADATA(node).background) { UI_DrawSpriteInBox(false, EXTRADATA(node).background, iconStatus, pos[0], pos[1], node->box.size[0], node->box.size[1]); } if (char const* const text = UI_GetReferenceString(node, node->text)) { char buf[MAX_VAR]; if (EXTRADATA(node).isPassword) { size_t size = UTF8_strlen(text); if (size > MAX_VAR - 2) size = MAX_VAR - 2; memset(buf, HIDECHAR, size); buf[size] = '\0'; } else { /* leave one byte empty for the text-based cursor */ UTF8_strncpyz(buf, text, sizeof(buf) - 1); } /** @todo Make the cursor into a real graphical object instead of using a text character. */ if (UI_HasFocus(node)) { if (CL_Milliseconds() % 1000 < 500) { UTF8_insert_char_at(buf, sizeof(buf), EXTRADATA(node).cursorPosition, (int)CURSOR_ON); } else { UTF8_insert_char_at(buf, sizeof(buf), EXTRADATA(node).cursorPosition, (int)CURSOR_OFF); } } if (*buf != '\0') { R_Color(textColor); UI_DrawStringInBox(font, (align_t)node->contentAlign, pos[0] + node->padding, pos[1] + node->padding, node->box.size[0] - node->padding - node->padding, node->box.size[1] - node->padding - node->padding, buf); R_Color(nullptr); } } }
/** * @brief Handles CustomButton draw */ static void UI_CustomButtonNodeDraw (uiNode_t *node) { const char *text; int texY; const float *textColor; const char *image; vec2_t pos; static vec4_t disabledColor = {0.5, 0.5, 0.5, 1.0}; uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; const char *font = UI_GetFontFromNode(node); if (!node->onClick || node->disabled) { /** @todo need custom color when button is disabled */ textColor = disabledColor; texY = UI_CUSTOMBUTTON_TEX_HEIGHT * 2; iconStatus = SPRITE_STATUS_DISABLED; } else if (node->state) { textColor = node->selectedColor; texY = UI_CUSTOMBUTTON_TEX_HEIGHT; iconStatus = SPRITE_STATUS_HOVER; } else { textColor = node->color; texY = 0; } UI_GetNodeAbsPos(node, pos); image = UI_GetReferenceString(node, node->image); if (image) { const int texX = rint(EXTRADATA(node).texl[0]); texY += EXTRADATA(node).texl[1]; UI_DrawNormImageByName(qfalse, pos[0], pos[1], node->size[0], node->size[1], texX + node->size[0], texY + node->size[1], texX, texY, image); } if (EXTRADATA(node).background) { UI_DrawSpriteInBox(qfalse, EXTRADATA(node).background, iconStatus, pos[0], pos[1], node->size[0], node->size[1]); } if (EXTRADATA(node).super.icon) { UI_DrawSpriteInBox(EXTRADATA(node).super.flipIcon, EXTRADATA(node).super.icon, iconStatus, pos[0], pos[1], node->size[0], node->size[1]); } text = UI_GetReferenceString(node, node->text); if (text != NULL && *text != '\0') { R_Color(textColor); UI_DrawStringInBox(font, node->contentAlign, pos[0] + node->padding, pos[1] + node->padding, node->size[0] - node->padding - node->padding, node->size[1] - node->padding - node->padding, text, LONGLINES_PRETTYCHOP); R_Color(NULL); } }
void uiWindowNode::draw (uiNode_t* node) { const char* text; vec2_t pos; const char* font = UI_GetFontFromNode(node); UI_GetNodeAbsPos(node, pos); /* black border for anamorphic mode */ /** @todo it should be over the window */ /** @todo why not using glClear here with glClearColor set to black here? */ if (UI_WindowIsFullScreen(node)) { /* top */ if (pos[1] != 0) UI_DrawFill(0, 0, viddef.virtualWidth, pos[1], anamorphicBorder); /* left-right */ if (pos[0] != 0) UI_DrawFill(0, pos[1], pos[0], node->box.size[1], anamorphicBorder); if (pos[0] + node->box.size[0] < viddef.virtualWidth) { const int width = viddef.virtualWidth - (pos[0] + node->box.size[0]); UI_DrawFill(viddef.virtualWidth - width, pos[1], width, node->box.size[1], anamorphicBorder); } /* bottom */ if (pos[1] + node->box.size[1] < viddef.virtualHeight) { const int height = viddef.virtualHeight - (pos[1] + node->box.size[1]); UI_DrawFill(0, viddef.virtualHeight - height, viddef.virtualWidth, height, anamorphicBorder); } } /* hide background if window is modal */ if (EXTRADATA(node).modal && ui_global.windowStack[ui_global.windowStackPos - 1] == node) UI_DrawFill(0, 0, viddef.virtualWidth, viddef.virtualHeight, modalBackground); if (EXTRADATA(node).background) { UI_DrawSpriteInBox(false, EXTRADATA(node).background, SPRITE_STATUS_NORMAL, pos[0], pos[1], node->box.size[0], node->box.size[1]); } /* draw the title */ text = UI_GetReferenceString(node, node->text); if (text) UI_DrawStringInBox(font, ALIGN_CC, pos[0] + node->padding, pos[1] + node->padding, node->box.size[0] - node->padding - node->padding, TOP_HEIGHT + 10 - node->padding - node->padding, text); }
/** * @sa CMod_GetMapSize * @note we only need to handle the 2d plane and can ignore the z level * @param[in] node Node description of the radar */ void uiRadarNode::draw (uiNode_t* node) { vec2_t pos; vec2_t screenPos; #ifdef RADARSIZE_DEBUG int textposy = 40; static const vec4_t red = {1, 0, 0, 0.5}; #endif static const vec4_t backgroundColor = {0.0, 0.0, 0.0, 1}; const float mapWidth = cl.mapData->mapBox.getWidthX(); const float mapHeight = cl.mapData->mapBox.getWidthY(); /** @todo use the same coef for x and y */ const float mapCoefX = (float) node->box.size[0] / (float) mapWidth; const float mapCoefY = (float) node->box.size[1] / (float) mapHeight; if (cls.state != ca_active) return; UI_GetNodeAbsPos(node, pos); UI_GetNodeScreenPos(node, screenPos); R_CleanupDepthBuffer(pos[0], pos[1], node->box.size[0], node->box.size[1]); UI_DrawFill(pos[0], pos[1], mapWidth * mapCoefX, mapHeight * mapCoefY, backgroundColor); #ifndef RADARSIZE_DEBUG UI_PushClipRect(screenPos[0], screenPos[1], node->box.size[0], node->box.size[1]); #endif /* the cl struct is wiped with every new map */ if (!cl.radarInitialized) { UI_InitRadar(node); cl.radarInitialized = true; } /* update context */ radar.x = pos[0]; radar.y = pos[1]; radar.w = node->box.size[0]; radar.h = node->box.size[1]; if (radar.gridWidth < 6) radar.gridWidth = 6; if (radar.gridHeight < 6) radar.gridHeight = 6; #ifdef RADARSIZE_DEBUG UI_DrawStringInBox("f_small", ALIGN_UL, 50, textposy, 500, 25, va("%fx%f %fx%f map", cl.mapData->mapBox.getMinX(), cl.mapData->mapBox.getMinY(), cl.mapData->getMaxX(), cl.mapData->getMaxY())); textposy += 25; UI_DrawStringInBox("f_small", ALIGN_UL, 50, textposy, 500, 25, va("%fx%f map", mapWidth, mapHeight)); textposy += 25; #endif /* draw background */ for (int i = 0; i < radar.numImages; i++) { vec2_t imagePos; hudRadarImage_t* tile = &radar.images[i]; int maxlevel = cl_worldlevel->integer; /* check the max level value for this map tile */ if (maxlevel >= tile->maxlevel) maxlevel = tile->maxlevel - 1; assert(tile->path[maxlevel]); imagePos[0] = radar.x + mapCoefX * (tile->mapX - cl.mapData->mapBox.getMinX()); imagePos[1] = radar.y + mapCoefY * (tile->mapY - cl.mapData->mapBox.getMinY()); UI_DrawNormImageByName(false, imagePos[0], imagePos[1], mapCoefX * tile->mapWidth, mapCoefY * tile->mapHeight, 0, 0, 0, 0, tile->path[maxlevel]); #ifdef RADARSIZE_DEBUG UI_DrawStringInBox("f_small", ALIGN_UL, 50, textposy, 500, 25, va("%dx%d %dx%d %s", tile->x, tile->y, tile->width, tile->height, tile->path[maxlevel])); textposy += 25; UI_DrawStringInBox("f_small", ALIGN_UL, imagePos[0], imagePos[1], 500, 25, va("%dx%d", tile->gridX, tile->gridY)); #endif } #ifdef RADARSIZE_DEBUG UI_DrawFill(pos[0], pos[1], 100.0f * mapCoefX, 100.0f * mapCoefY, red); UI_DrawFill(pos[0], pos[1], UNIT_SIZE * mapCoefX, UNIT_SIZE * mapCoefY, red); #endif le_t* le = nullptr; while ((le = LE_GetNextInUse(le))) { vec3_t itempos; if (LE_IsInvisible(le)) continue; /* convert to radar area coordinates */ itempos[0] = pos[0] + (le->origin[0] - cl.mapData->mapBox.getMinX()) * mapCoefX; itempos[1] = pos[1] + (mapHeight - (le->origin[1] - cl.mapData->mapBox.getMinY())) * mapCoefY; switch (le->type) { case ET_ACTOR: case ET_ACTOR2x2: UI_RadarNodeDrawActor(le, itempos); break; case ET_ITEM: UI_RadarNodeDrawItem(le, itempos); break; default: break; } #ifdef RADARSIZE_DEBUG UI_DrawStringInBox("f_small", ALIGN_UL, 50, textposy, 500, 25, va("%fx%f %dx%d actor", le->origin[0], le->origin[1], le->pos[0], le->pos[1])); textposy += 25; UI_DrawFill(itempos[0], itempos[1], UNIT_SIZE * mapCoefX, 1, red); UI_DrawFill(itempos[0], itempos[1], 1, UNIT_SIZE * mapCoefY, red); #endif } #ifndef RADARSIZE_DEBUG UI_PopClipRect(); #endif }
/** * @brief Handles line breaks and drawing for shared data text * @param[in] node The context node * @param[in] list The text list to draw */ static void UI_TextLineNodeDrawText (uiNode_t* node, const linkedList_t* list) { vec4_t colorHover; vec4_t colorSelectedHover; int count; /* variable x position */ const char *font = UI_GetFontFromNode(node); vec2_t pos; int currentY; int viewSizeY; int lineHeight; int maxHeight; lineHeight = EXTRADATA(node).lineHeight; if (lineHeight == 0) lineHeight = UI_FontGetHeight(font); if (UI_AbstractScrollableNodeIsSizeChange(node)) viewSizeY = node->size[1] / lineHeight; else viewSizeY = EXTRADATA(node).super.scrollY.viewSize; /* text box */ UI_GetNodeAbsPos(node, pos); pos[0] += node->padding; pos[1] += node->padding; /* prepare colors */ VectorScale(node->color, 0.8, colorHover); colorHover[3] = node->color[3]; VectorScale(node->selectedColor, 0.8, colorSelectedHover); colorSelectedHover[3] = node->selectedColor[3]; /* skip lines over the scroll */ count = 0; while (list && count < EXTRADATA(node).super.scrollY.viewPos) { list = list->next; count++; } currentY = pos[1]; maxHeight = currentY + node->size[1] - node->padding - node->padding - node->padding - lineHeight; while (list) { const int width = node->size[0] - node->padding - node->padding; const char* text = (const char*) list->data; if (currentY > maxHeight) break; /* highlight selected line */ if (count == EXTRADATA(node).textLineSelected && EXTRADATA(node).textLineSelected >= 0) R_Color(node->selectedColor); else R_Color(node->color); /* highlight line under mouse */ if (node->state && count == EXTRADATA(node).lineUnderMouse) { if (count == EXTRADATA(node).textLineSelected && EXTRADATA(node).textLineSelected >= 0) R_Color(colorSelectedHover); else R_Color(colorHover); } UI_DrawStringInBox(font, node->contentAlign, pos[0], currentY, width, lineHeight, text, LONGLINES_PRETTYCHOP); /* next entries' position */ currentY += lineHeight; list = list->next; count++; } /* count all elements */ while (list) { list = list->next; count++; } /* update scroll status */ UI_AbstractScrollableNodeSetY(node, -1, viewSizeY, count); R_Color(NULL); }
static void UI_TextEntryNodeDraw (uiNode_t *node) { static const int panelTemplate[] = { CORNER_SIZE, MID_SIZE, CORNER_SIZE, CORNER_SIZE, MID_SIZE, CORNER_SIZE, MARGE }; const char *text; int texX, texY; const float *textColor; const char *image; vec2_t pos; static vec4_t disabledColor = {0.5, 0.5, 0.5, 1.0}; const char *font = UI_GetFontFromNode(node); if (node->disabled) { /** @todo need custom color when node is disabled */ textColor = disabledColor; texX = TILE_SIZE; texY = TILE_SIZE; } else if (node->state) { textColor = node->color; texX = TILE_SIZE; texY = 0; } else { textColor = node->color; texX = 0; texY = 0; } if (UI_HasFocus(node)) textColor = node->selectedColor; UI_GetNodeAbsPos(node, pos); image = UI_GetReferenceString(node, node->image); if (image) UI_DrawPanel(pos, node->size, image, texX, texY, panelTemplate); text = UI_GetReferenceString(node, node->text); if (text != NULL) { /** @todo we don't need to edit the text to draw the cursor */ if (UI_HasFocus(node)) { if (CL_Milliseconds() % 1000 < 500) { text = va("%s%c", text, CURSOR); } } if (EXTRADATA(node).isPassword) { char *c = va("%s", text); int size = UTF8_strlen(c); text = c; /* hide the text with a special char */ assert(strlen(c) >= size); /* trustable, but it can't be false */ while (size) { *c++ = HIDECHAR; size--; } /* readd the cursor */ if (UI_HasFocus(node)) { if (CL_Milliseconds() % 1000 < 500) { c--; *c++ = CURSOR; } } *c = '\0'; } if (*text != '\0') { R_Color(textColor); UI_DrawStringInBox(font, node->textalign, pos[0] + node->padding, pos[1] + node->padding, node->size[0] - node->padding - node->padding, node->size[1] - node->padding - node->padding, text, LONGLINES_PRETTYCHOP); R_Color(NULL); } } }
static void UI_KeyBindingNodeDraw (uiNode_t *node) { static const int panelTemplate[] = { CORNER_SIZE, MID_SIZE, CORNER_SIZE, CORNER_SIZE, MID_SIZE, CORNER_SIZE, MARGE }; const char *binding, *description, *command; int texX, texY; const float *textColor; const char *image; vec2_t pos; const char *font = UI_GetFontFromNode(node); const int bindingWidth = EXTRADATA(node).bindingWidth; const int descriptionWidth = node->size[0] - bindingWidth; vec2_t descriptionPos, descriptionSize; vec2_t bindingPos, bindingSize; if (node->state) { textColor = node->color; texX = TILE_SIZE; texY = 0; } else { textColor = node->color; texX = 0; texY = 0; } if (UI_HasFocus(node)) textColor = node->selectedColor; UI_GetNodeAbsPos(node, pos); Vector2Set(descriptionSize, descriptionWidth, node->size[1]); Vector2Set(bindingSize, bindingWidth, node->size[1]); Vector2Set(descriptionPos, pos[0], pos[1]); Vector2Set(bindingPos, pos[0] + descriptionWidth + node->padding, pos[1]); image = UI_GetReferenceString(node, node->image); if (image) { UI_DrawPanel(descriptionPos, descriptionSize, image, texX, texY, panelTemplate); UI_DrawPanel(bindingPos, bindingSize, image, texX, texY, panelTemplate); } binding = UI_GetReferenceString(node, node->text); if (Q_strnull(binding)) binding = _("NONE"); /** @todo check that this is a keybinding value (with macro expansion) */ command = node->text + 9; description = Cmd_GetCommandDesc(command); if (description[0] == '\0') description = command; R_Color(textColor); UI_DrawStringInBox(font, node->contentAlign, descriptionPos[0] + node->padding, descriptionPos[1] + node->padding, descriptionSize[0] - node->padding - node->padding, descriptionSize[1] - node->padding - node->padding, description, LONGLINES_PRETTYCHOP); UI_DrawStringInBox(font, node->contentAlign, bindingPos[0] + node->padding, bindingPos[1] + node->padding, bindingSize[0] - node->padding - node->padding, bindingSize[1] - node->padding - node->padding, binding, LONGLINES_PRETTYCHOP); R_Color(NULL); }
/** * @brief Handles Button draw */ static void UI_ButtonNodeDraw (uiNode_t *node) { static const int panelTemplate[] = { CORNER_SIZE, MID_SIZE, CORNER_SIZE, CORNER_SIZE, MID_SIZE, CORNER_SIZE, MARGE }; const char *text; int texX, texY; const float *textColor; const char *image; vec2_t pos; static vec4_t disabledColor = {0.5, 0.5, 0.5, 1.0}; int iconPadding = 0; uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; const char *font = UI_GetFontFromNode(node); if (!node->onClick || node->disabled) { /** @todo need custom color when button is disabled */ textColor = disabledColor; texX = TILE_SIZE; texY = TILE_SIZE; iconStatus = SPRITE_STATUS_DISABLED; } else if (node->state) { textColor = node->selectedColor; texX = TILE_SIZE; texY = 0; iconStatus = SPRITE_STATUS_HOVER; } else { textColor = node->color; texX = 0; texY = 0; } UI_GetNodeAbsPos(node, pos); image = UI_GetReferenceString(node, node->image); if (image) UI_DrawPanel(pos, node->size, image, texX, texY, panelTemplate); /* display the icon at the left */ /** @todo should we move it according to the text align? */ if (EXTRADATA(node).icon) { /* use at least a box size equals to button height */ int size = node->size[1] - node->padding - node->padding; if (size < EXTRADATA(node).icon->size[0]) size = EXTRADATA(node).icon->size[0]; UI_DrawSpriteInBox(EXTRADATA(node).flipIcon, EXTRADATA(node).icon, iconStatus, pos[0] + node->padding, pos[1] + node->padding, size, node->size[1] - node->padding - node->padding); iconPadding = size + node->padding; } text = UI_GetReferenceString(node, node->text); if (text != NULL && *text != '\0') { R_Color(textColor); text = _(text); UI_DrawStringInBox(font, node->contentAlign, pos[0] + node->padding + iconPadding, pos[1] + node->padding, node->size[0] - node->padding - node->padding - iconPadding, node->size[1] - node->padding - node->padding, text, LONGLINES_PRETTYCHOP); R_Color(NULL); } }