static void UI_CheckBoxNodeDraw (uiNode_t* node) { const float value = UI_GetReferenceFloat(node, EXTRADATA(node).value); vec2_t pos; const char *image = UI_GetReferenceString(node, node->image); int texx, texy; /* image set? */ if (Q_strnull(image)) return; /* outer status */ if (node->disabled) { texy = 96; } else if (node->state) { texy = 32; } else { texy = 0; } /* inner status */ if (value == 0) { texx = 0; } else if (value > 0) { texx = 32; } else { /* value < 0 */ texx = 64; } UI_GetNodeAbsPos(node, pos); UI_DrawNormImageByName(qfalse, pos[0], pos[1], node->size[0], node->size[1], texx + node->size[0], texy + node->size[1], texx, texy, image); }
static void UI_TBarNodeDraw (uiNode_t *node) { /* dataImageOrModel is the texture name */ float shx; vec2_t nodepos; const char* ref = UI_GetReferenceString(node, node->image); float pointWidth; float width; if (Q_strnull(ref)) return; UI_GetNodeAbsPos(node, nodepos); pointWidth = TEXTURE_WIDTH / 100.0; /* relative to the texture */ { float ps; const float min = UI_GetReferenceFloat(node, EXTRADATA(node).super.min); const float max = UI_GetReferenceFloat(node, EXTRADATA(node).super.max); float value = UI_GetReferenceFloat(node, EXTRADATA(node).super.value); /* clamp the value */ if (value > max) value = max; if (value < min) value = min; ps = (value - min) / (max - min) * 100; shx = EXTRADATA(node).texl[0]; /* left gap to the texture */ shx += round(ps * pointWidth); /* add size from 0..TEXTURE_WIDTH */ } width = (shx * node->size[0]) / TEXTURE_WIDTH; UI_DrawNormImageByName(qfalse, nodepos[0], nodepos[1], width, node->size[1], shx, EXTRADATA(node).texh[1], EXTRADATA(node).texl[0], EXTRADATA(node).texl[1], ref); }
/** * @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); } }
/** * @param[in] status The state of the sprite node * @param[in] sprite Context sprite * @param[in] posX Absolute X position of the top-left corner * @param[in] posY Absolute Y position of the top-left corner * @param[in] sizeX Width of the bounded box * @param[in] sizeY Height of the bounded box * @todo use named const for status */ void UI_DrawSpriteInBox (const uiSprite_t* sprite, uiSpriteStatus_t status, int posX, int posY, int sizeX, int sizeY) { int texX; int texY; const char* image; /** @todo Add warning */ if (status >= SPRITE_STATUS_MAX) return; /** @todo merge all this cases */ if (sprite->single || sprite->blend) { texX = sprite->pos[SPRITE_STATUS_NORMAL][0]; texY = sprite->pos[SPRITE_STATUS_NORMAL][1]; image = sprite->image[SPRITE_STATUS_NORMAL]; } else if (sprite->pack64) { texX = sprite->pos[SPRITE_STATUS_NORMAL][0]; texY = sprite->pos[SPRITE_STATUS_NORMAL][1] + (64 * status); image = sprite->image[SPRITE_STATUS_NORMAL]; } else { texX = sprite->pos[status][0]; texY = sprite->pos[status][1]; image = sprite->image[status]; if (!image) { texX = sprite->pos[SPRITE_STATUS_NORMAL][0]; texY = sprite->pos[SPRITE_STATUS_NORMAL][1]; image = sprite->image[SPRITE_STATUS_NORMAL]; } } if (!image) return; posX += (sizeX - sprite->size[0]) / 2; posY += (sizeY - sprite->size[1]) / 2; if (sprite->blend) { const vec_t *color; color = sprite->color[status]; R_Color(color); } UI_DrawNormImageByName(posX, posY, sprite->size[0], sprite->size[1], texX + sprite->size[0], texY + sprite->size[1], texX, texY, image); if (sprite->blend) R_Color(NULL); }
/** * @brief Handles RadioButton draw * @todo need to implement image. We can't do everything with only one icon (or use another icon) */ static void UI_RadioButtonNodeDraw (uiNode_t *node) { vec2_t pos; uiSpriteStatus_t iconStatus; const qboolean disabled = node->disabled || node->parent->disabled; int texY; const char *image; const qboolean isSelected = UI_RadioButtonNodeIsSelected(node); if (disabled) { iconStatus = SPRITE_STATUS_DISABLED; texY = UI_4STATUS_TEX_HEIGHT * 2; } else if (isSelected) { iconStatus = SPRITE_STATUS_CLICKED; texY = UI_4STATUS_TEX_HEIGHT * 3; } else if (node->state) { iconStatus = SPRITE_STATUS_HOVER; texY = UI_4STATUS_TEX_HEIGHT; } else { iconStatus = SPRITE_STATUS_NORMAL; texY = 0; } UI_GetNodeAbsPos(node, pos); image = UI_GetReferenceString(node, node->image); if (image) { const int texX = 0; 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).icon) { UI_DrawSpriteInBox(EXTRADATA(node).flipIcon, EXTRADATA(node).icon, iconStatus, pos[0], pos[1], node->size[0], node->size[1]); } }
/** * @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 Normalized access to the texture structure of tab to display a junction between each tabs * @param[in] image The normalized tab texture to use * @param[in] x The upper-left position of the screen to draw the texture * @param[in] y The upper-left position of the screen to draw the texture * @param[in] leftType The status of the left tab of the junction we display * @param[in] rightType The status of the right tab of the junction we display */ static inline void UI_TabNodeDrawJunction (const char *image, int x, int y, ui_tabStatus_t leftType, ui_tabStatus_t rightType) { UI_DrawNormImageByName(false, x, y, TILE_WIDTH, TILE_HEIGHT, TILE_WIDTH + TILE_SIZE * (1 + rightType), TILE_HEIGHT + TILE_SIZE * leftType, 0 + TILE_SIZE * (1 + rightType), 0 + TILE_SIZE * leftType, image); }
/** * @brief Normalized access to the texture structure of tab to display the plain part of a tab * @param[in] image The normalized tab texture to use * @param[in] x The upper-left position of the screen to draw the texture * @param[in] y The upper-left position of the screen to draw the texture * @param[in] width The width size of the screen to use (stretch) * @param[in] type The status of the tab we display */ static inline void UI_TabNodeDrawPlain (const char *image, int x, int y, int width, ui_tabStatus_t type) { /* Hack sl=1 to not use the pixel on the left border on the texture (create graphic bug) */ UI_DrawNormImageByName(false, x, y, width, TILE_HEIGHT, TILE_WIDTH + TILE_SIZE * 0, TILE_HEIGHT + TILE_SIZE * type, 1 + TILE_SIZE * 0, 0 + TILE_SIZE * type, image); }
/** * @brief Draws a base. */ static void UI_BaseMapNodeDraw (uiNode_t * node) { int width, height, row, col; const building_t *building; const base_t *base = B_GetCurrentSelectedBase(); qboolean used[MAX_BUILDINGS]; if (!base) { UI_PopWindow(qfalse); return; } /* reset the used flag */ OBJZERO(used); width = node->size[0] / BASE_SIZE; height = node->size[1] / BASE_SIZE + BASE_IMAGE_OVERLAY; for (row = 0; row < BASE_SIZE; row++) { const char *image = NULL; for (col = 0; col < BASE_SIZE; col++) { vec2_t pos; UI_GetNodeAbsPos(node, pos); pos[0] += col * width; pos[1] += row * (height - BASE_IMAGE_OVERLAY); /* base tile */ if (B_IsTileBlocked(base, col, row)) { building = NULL; image = "base/invalid"; } else if (B_GetBuildingAt(base, col, row) == NULL) { building = NULL; image = "base/grid"; } else { building = B_GetBuildingAt(base, col, row); assert(building); if (building->image) image = building->image; /* some buildings are drawn with two tiles - e.g. the hangar is no square map tile. * These buildings have the needs parameter set to the second building part which has * its own image set, too. We are searching for this second building part here. */ if (B_BuildingGetUsed(used, building->idx)) continue; B_BuildingSetUsed(used, building->idx); } /* draw tile */ if (image != NULL) UI_DrawNormImageByName(qfalse, pos[0], pos[1], width * (building ? building->size[0] : 1), height * (building ? building->size[1] : 1), 0, 0, 0, 0, image); if (building) { switch (building->buildingStatus) { case B_STATUS_DOWN: case B_STATUS_CONSTRUCTION_FINISHED: break; case B_STATUS_UNDER_CONSTRUCTION: { const float time = max(0.0, B_GetConstructionTimeRemain(building)); UI_DrawString("f_small", ALIGN_UL, pos[0] + 10, pos[1] + 10, pos[0] + 10, node->size[0], 0, va(ngettext("%3.1f day left", "%3.1f days left", time), time), 0, 0, NULL, qfalse, 0); break; } default: break; } } } } if (!node->state) return; UI_BaseMapGetCellAtPos(node, mousePosX, mousePosY, &col, &row); if (col == -1) return; /* if we are building */ if (ccs.baseAction == BA_NEWBUILDING) { int y, x; int xCoord, yCoord, widthRect, heigthRect; vec2_t pos; assert(base->buildingCurrent); for (y = row; y < row + base->buildingCurrent->size[1]; y++) { for (x = col; x < col + base->buildingCurrent->size[0]; x++) { if (!B_MapIsCellFree(base, x, y)) return; } } UI_GetNodeAbsPos(node, pos); xCoord = pos[0] + col * width; yCoord = pos[1] + row * (height - BASE_IMAGE_OVERLAY); widthRect = base->buildingCurrent->size[0] * width; heigthRect = base->buildingCurrent->size[1] * (height - BASE_IMAGE_OVERLAY); R_DrawRect(xCoord, yCoord, widthRect, heigthRect, white, 3, 1); } }
/** * @param[in] flip Flip the icon rendering (horizontal) * @param[in] sprite Context sprite * @param[in] status The state of the sprite node * @param[in] posX,posY Absolute X/Y position of the top-left corner * @param[in] sizeX,sizeY Width/height of the bounding box */ void UI_DrawSpriteInBox (bool flip, const uiSprite_t* sprite, uiSpriteStatus_t status, int posX, int posY, int sizeX, int sizeY) { float texX; float texY; const char* image; /** @todo Add warning */ if (status >= SPRITE_STATUS_MAX) return; /** @todo merge all this cases */ if (sprite->single || sprite->blend) { texX = sprite->pos[SPRITE_STATUS_NORMAL][0]; texY = sprite->pos[SPRITE_STATUS_NORMAL][1]; image = sprite->image[SPRITE_STATUS_NORMAL]; } else if (sprite->pack64) { texX = sprite->pos[SPRITE_STATUS_NORMAL][0]; texY = sprite->pos[SPRITE_STATUS_NORMAL][1] + (64 * status); image = sprite->image[SPRITE_STATUS_NORMAL]; } else { texX = sprite->pos[status][0]; texY = sprite->pos[status][1]; image = sprite->image[status]; if (!image) { if (texX == 0 && texY == 0) { texX = sprite->pos[SPRITE_STATUS_NORMAL][0]; texY = sprite->pos[SPRITE_STATUS_NORMAL][1]; image = sprite->image[SPRITE_STATUS_NORMAL]; } else { image = sprite->image[SPRITE_STATUS_NORMAL]; } } } if (!image) return; if (sprite->blend) { const vec_t* color = sprite->color[status]; R_Color(color); } if (sprite->tiled_17_1_3) { const vec2_t pos = Vector2FromInt(posX, posY); const vec2_t size = Vector2FromInt(sizeX, sizeY); UI_DrawPanel(pos, size, image, texX, texY, tile_template_17_1_3); } else if (sprite->tiled_25_1_3) { const vec2_t pos = Vector2FromInt(posX, posY); const vec2_t size = Vector2FromInt(sizeX, sizeY); UI_DrawPanel(pos, size, image, texX, texY, tile_template_25_1_3); } else if (sprite->tiled_popup) { const vec2_t pos = Vector2FromInt(posX, posY); const vec2_t size = Vector2FromInt(sizeX, sizeY); UI_DrawPanel(pos, size, image, texX, texY, tile_template_popup); } else if (sprite->border != 0) { const vec2_t pos = Vector2FromInt(posX, posY); const vec2_t size = Vector2FromInt(sizeX, sizeY); UI_DrawBorderedPanel(pos, size, image, texX, texY, sprite->size[0], sprite->size[1], sprite->border); } else { posX += (sizeX - sprite->size[0]) / 2; posY += (sizeY - sprite->size[1]) / 2; UI_DrawNormImageByName(flip, posX, posY, sprite->size[0], sprite->size[1], texX + sprite->size[0], texY + sprite->size[1], texX, texY, image); } if (sprite->blend) R_Color(nullptr); }
/** * @brief Draws an item to the screen * @param[in] node Context node * @param[in] org Node position on the screen (pixel). Single nodes: Use the center of the node. * @param[in] item The item to draw. * @param[in] x Position in container. Set this to -1 if it's drawn in a single container. * @param[in] y Position in container. Set this to -1 if it's drawn in a single container. * @param[in] scale * @param[in] color * @sa SCR_DrawCursor * Used to draw an item to the equipment containers. First look whether the objDef_t * includes an image - if there is none then draw the model */ void UI_DrawItem (uiNode_t *node, const vec3_t org, const item_t *item, int x, int y, const vec3_t scale, const vec4_t color) { const objDef_t *od = item->item; vec4_t col; vec3_t origin; assert(od); assert(org[2] > -1000 && org[2] < 1000); /*< prevent use of vec2_t for org */ Vector4Copy(color, col); /* no ammo in this weapon - highlight this item */ if (od->weapon && od->reload && !item->ammoLeft) { col[1] *= 0.5; col[2] *= 0.5; } VectorCopy(org, origin); /* Calculate correct location of the image or the model (depends on rotation) */ /** @todo Change the rotation of the image as well, right now only the location is changed. * How is image-rotation handled right now? */ if (x >= 0 || y >= 0) { /* Add offset of location in container. */ origin[0] += x * C_UNIT; origin[1] += y * C_UNIT; /* Add offset for item-center (depends on rotation). */ if (item->rotated) { origin[0] += od->sy * C_UNIT / 2.0; origin[1] += od->sx * C_UNIT / 2.0; /** @todo Image size calculation depends on handling of image-rotation. imgWidth = od->sy * C_UNIT; imgHeight = od->sx * C_UNIT; */ } else { origin[0] += od->sx * C_UNIT / 2.0; origin[1] += od->sy * C_UNIT / 2.0; } } /* don't handle the od->tech->image here - it's very ufopedia specific in most cases */ if (od->image[0] != '\0') { const int imgWidth = od->sx * C_UNIT; const int imgHeight = od->sy * C_UNIT; origin[0] -= od->sx * C_UNIT / 2.0; origin[1] -= od->sy * C_UNIT / 2.0; /* Draw the image. */ R_Color(color); UI_DrawNormImageByName(false, origin[0], origin[1], imgWidth, imgHeight, 0, 0, 0, 0, od->image); R_Color(NULL); } else { uiModel_t *model = NULL; const char *modelName = GAME_GetModelForItem(od, &model); /* no model definition in the tech struct, not in the fallback object definition */ if (Q_strnull(modelName)) { Com_Printf("UI_DrawItem: No model given for item: '%s'\n", od->id); return; } if (model && node) { UI_DrawModelNode(node, modelName); } else { modelInfo_t mi; vec3_t angles = {-10, 160, 70}; vec3_t size = {scale[0], scale[1], scale[2]}; vec3_t center; if (item->rotated) angles[0] -= 90; if (od->scale) VectorScale(size, od->scale, size); VectorNegate(od->center, center); OBJZERO(mi); mi.origin = origin; mi.angles = angles; mi.center = center; mi.scale = size; mi.color = col; mi.name = modelName; /* draw the model */ R_DrawModelDirect(&mi, NULL, NULL); } } }