/** * @brief Initializes an option with a very little set of values. * @param[in] option Context option * @param[in] label label displayed * @param[in] value value used when this option is selected */ static void UI_InitOption (uiNode_t* option, const char* label, const char* value) { assert(option); assert(option->behaviour == ui_optionBehaviour); Q_strncpyz(OPTIONEXTRADATA(option).label, label, sizeof(OPTIONEXTRADATA(option).label)); Q_strncpyz(OPTIONEXTRADATA(option).value, value, sizeof(OPTIONEXTRADATA(option).value)); }
/** * @brief Remove the higher element (in alphabet) from a list * @todo option should start with '_' if we need to translate it * @warning update parent */ static uiNode_t* UI_OptionNodeRemoveHigherOption (uiNode_t** option) { uiNode_t* prev = *option; uiNode_t* prevfind = nullptr; uiNode_t* search = (*option)->next; const char* label = CL_Translate(OPTIONEXTRADATA(*option).label); /* search the smaller element */ while (search) { const char* searchlabel = CL_Translate(OPTIONEXTRADATA(search).label); if (strcmp(label, searchlabel) < 0) { prevfind = prev; label = searchlabel; } prev = search; search = search->next; } /* remove the first element */ if (prevfind == nullptr) { uiNode_t* tmp = *option; *option = (*option)->next; return tmp; } else { uiNode_t* tmp = prevfind->next; prevfind->next = tmp->next; return tmp; } }
/** * @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); }
void uiSelectBoxNode::draw (uiNode_t* node) { uiNode_t* option; int selBoxX, selBoxY; const char* ref; const char* font; vec2_t nodepos; const char* imageName; const image_t* image; static vec4_t invisColor = {1.0, 1.0, 1.0, 0.7}; ref = UI_AbstractOptionGetCurrentValue(node); if (ref == nullptr) return; UI_GetNodeAbsPos(node, nodepos); imageName = UI_GetReferenceString(node, node->image); if (!imageName) imageName = "ui/selectbox"; image = UI_LoadImage(imageName); font = UI_GetFontFromNode(node); selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH; selBoxY = nodepos[1] + SELECTBOX_SPACER; /* left border */ UI_DrawNormImage(false, nodepos[0], nodepos[1], SELECTBOX_SIDE_WIDTH, node->box.size[1], SELECTBOX_SIDE_WIDTH, SELECTBOX_DEFAULT_HEIGHT, 0.0f, 0.0f, image); /* stretched middle bar */ UI_DrawNormImage(false, nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1], node->box.size[0]-SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, node->box.size[1], 12.0f, SELECTBOX_DEFAULT_HEIGHT, 7.0f, 0.0f, image); /* right border (arrow) */ UI_DrawNormImage(false, nodepos[0] + node->box.size[0] - SELECTBOX_RIGHT_WIDTH, nodepos[1], SELECTBOX_DEFAULT_HEIGHT, node->box.size[1], 12.0f + SELECTBOX_RIGHT_WIDTH, SELECTBOX_DEFAULT_HEIGHT, 12.0f, 0.0f, image); /* draw the label for the current selected option */ for (option = UI_AbstractOptionGetFirstOption(node); option; option = option->next) { if (!Q_streq(OPTIONEXTRADATA(option).value, ref)) continue; if (option->invis) R_Color(invisColor); const char* label = CL_Translate(OPTIONEXTRADATA(option).label); UI_DrawString(font, ALIGN_UL, selBoxX, selBoxY, selBoxX, node->box.size[0] - 4, 0, label, 0, 0, nullptr, false, LONGLINES_PRETTYCHOP); R_Color(nullptr); break; } /* must we draw the drop-down list */ if (UI_GetMouseCapture() == node) { UI_CaptureDrawOver(node); } }
/** * @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; }
static void UI_OptionTreeSetSelectedValue (uiNode_t *node, const uiCallContext_t *context) { uiOptionIterator_t iterator; uiNode_t *option; uiNode_t *firstOption; const char* value; int pos, i; if (UI_GetParamNumber(context) != 1) { Com_Printf("UI_OptionTreeSetSelectedValue: Invalide number of param\n"); return; } value = UI_GetParam(context, 1); /* is the option exists */ firstOption = UI_OptionTreeNodeGetFirstOption(node); UI_InitOptionIteratorAtIndex(0, firstOption, &iterator); /** @todo merge that into the Init iterator function */ iterator.skipCollapsed = qfalse; option = UI_FindOptionByValue(&iterator, value); /* update the selection */ if (option) { UI_AbstractOptionSetCurrentValue(node, OPTIONEXTRADATA(option).value); } else { Com_Printf("UI_OptionTreeSetSelectedValue: Option value \"%s\" not found\n", value); return; } /* expend parents */ for (i = 0; i < iterator.depthPos; i++) OPTIONEXTRADATA(iterator.depthCache[i]).collapsed = qfalse; UI_OptionTreeNodeUpdateCache(node); UI_OptionTreeNodeUpdateScroll(node); /* fix scroll bar */ firstOption = UI_OptionTreeNodeGetFirstOption(node); UI_InitOptionIteratorAtIndex(0, firstOption, &iterator); pos = UI_FindOptionPosition(&iterator, option); if (pos == -1) return; if (pos < EXTRADATA(node).scrollY.viewPos || pos >= EXTRADATA(node).scrollY.viewPos + EXTRADATA(node).scrollY.viewSize) { qboolean updated; updated = UI_SetScroll(&EXTRADATA(node).scrollY, pos, -1, -1); if (updated && EXTRADATA(node).onViewChange) UI_ExecuteEventActions(node, EXTRADATA(node).onViewChange); } }
/** * @brief Custom tooltip of tab node * @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 uiTabNode::drawTooltip (uiNode_t *node, int x, int y) { uiNode_t *option; const int tooltipWidth = 250; option = UI_TabNodeTabAtPosition(node, x, y); if (option == NULL) return; if (!OPTIONEXTRADATA(option).truncated) return; const char *label = CL_Translate(OPTIONEXTRADATA(option).label); UI_DrawTooltip(label, x, y, tooltipWidth); }
/** called when the window is pushed * check cvar then, reduce runtime check * @todo move cvar check to AbstractOption */ static void UI_TabNodeInit (uiNode_t *node, linkedList_t *params) { const char *cvarName; /* no cvar given? */ if (!(EXTRADATA(node).cvar)) return; /* not a cvar? */ if (!Q_strstart(EXTRADATA(node).cvar, "*cvar:")) { /* normalize */ Com_Printf("UI_TabNodeInit: node '%s' doesn't have a valid cvar assigned (\"%s\" read)\n", UI_GetPath(node), EXTRADATA(node).cvar); EXTRADATA(node).cvar = NULL; return; } /* cvar do not exists? */ cvarName = &EXTRADATA(node).cvar[6]; if (Cvar_FindVar(cvarName) == NULL) { /* search default value, if possible */ uiNode_t* option = node->firstChild; assert(option->behaviour == ui_optionBehaviour); Cvar_ForceSet(cvarName, OPTIONEXTRADATA(option).value); } }
/** * @brief Find the next element from the iterator * Iterator skipCollapsed and skipInvisible attribute can control the option flow */ uiNode_t* UI_OptionIteratorNextOption (uiOptionIterator_t* iterator) { uiNode_t* option; option = iterator->option; assert(iterator->depthPos < MAX_DEPTH_OPTIONITERATORCACHE); iterator->depthCache[iterator->depthPos] = option; iterator->depthPos++; if (OPTIONEXTRADATA(option).collapsed && iterator->skipCollapsed) option = NULL; else option = option->firstChild; while (qtrue) { while (option) { if (!option->invis || !iterator->skipInvisible) { iterator->option = option; return option; } option = option->next; } if (iterator->depthPos == 0) break; iterator->depthPos--; option = iterator->depthCache[iterator->depthPos]->next; } iterator->option = NULL; return NULL; }
/** * @brief Find an option (and all his parents) by is value. * @param[in,out] iterator If it found an option, the iterator contain all option parent * @param[in] value The value we search * @return The right option, else NULL */ uiNode_t* UI_FindOptionByValue (uiOptionIterator_t* iterator, const char* value) { while (iterator->option) { assert(iterator->option->behaviour == ui_optionBehaviour); if (Q_streq(OPTIONEXTRADATA(iterator->option).value, value)) return iterator->option; UI_OptionIteratorNextOption(iterator); } return NULL; }
/** * @brief Custom tooltip of tab node * @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 */ static void UI_TabNodeDrawTooltip (uiNode_t *node, int x, int y) { uiNode_t *option; const int tooltipWidth = 250; const char *label; option = UI_TabNodeTabAtPosition(node, x, y); if (option == NULL) return; if (!OPTIONEXTRADATA(option).truncated) return; label = OPTIONEXTRADATA(option).label; if (label[0] == '_') label = _(label + 1); UI_DrawTooltip(label, x, y, tooltipWidth); }
/** * @brief Handles selectboxes clicks */ static void UI_SelectBoxNodeClick (uiNode_t *node, int x, int y) { uiNode_t* option; int clickedAtOption; vec2_t pos; /* dropdown the node */ if (UI_GetMouseCapture() == NULL) { UI_SetMouseCapture(node); return; } UI_GetNodeAbsPos(node, pos); clickedAtOption = (y - pos[1]); /* we click outside */ if (x < pos[0] || y < pos[1] || x >= pos[0] + node->size[0] || y >= pos[1] + node->size[1] * (EXTRADATA(node).count + 1)) { UI_MouseRelease(); return; } /* we click on the head */ if (clickedAtOption < node->size[1]) { UI_MouseRelease(); return; } clickedAtOption = (clickedAtOption - node->size[1]) / node->size[1]; if (clickedAtOption < 0 || clickedAtOption >= EXTRADATA(node).count) return; if (UI_AbstractOptionGetCurrentValue(node) == NULL) return; /* select the right option */ option = UI_AbstractOptionGetFirstOption(node); for (; option; option = option->next) { if (option->invis) continue; if (clickedAtOption == 0) break; clickedAtOption--; } /* update the status */ if (option) UI_AbstractOptionSetCurrentValue(node, OPTIONEXTRADATA(option).value); /* close the dropdown */ UI_MouseRelease(); }
/** * @brief find an option why index (0 is the first option) * @param[in] index Requested index (0 is the first option) * @param[in] option First element of options (it can be a tree) * @param[in,out] iterator need an initialised iterator, and update it into the write index */ static uiNode_t* UI_FindOptionAtIndex (int index, uiNode_t* option, uiOptionIterator_t* iterator) { while (option) { assert(option->behaviour == ui_optionBehaviour); if (option->invis) { option = option->next; continue; } /* we are on the right element */ if (index == 0) { iterator->option = option; return option; } /* not the parent */ index--; if (OPTIONEXTRADATA(option).collapsed) { option = option->next; continue; } /* its a child */ if (index < OPTIONEXTRADATA(option).childCount) { if (iterator->depthPos >= MAX_DEPTH_OPTIONITERATORCACHE) assert(qfalse); iterator->depthCache[iterator->depthPos] = option; iterator->depthPos++; return UI_FindOptionAtIndex(index, option->firstChild, iterator); } index -= OPTIONEXTRADATA(option).childCount; option = option->next; } iterator->option = NULL; return NULL; }
/** * @brief Handles selectboxes clicks */ void uiOptionListNode::onLeftClick (uiNode_t* node, int x, int y) { uiNode_t* option; if (UI_AbstractOptionGetCurrentValue(node) == nullptr) return; /* select the right option */ option = UI_OptionListNodeGetOptionAtPosition(node, x, y); /* update the status */ if (option) UI_AbstractOptionSetCurrentValue(node, OPTIONEXTRADATA(option).value); }
/** * @brief update option cache about child, according to collapse and visible status * @note can be a common function for all option node * @return number of visible elements */ int UI_OptionUpdateCache (uiNode_t* option) { int count = 0; while (option) { int localCount = 0; assert(option->behaviour == ui_optionBehaviour); if (option->invis) { option = option->next; continue; } if (OPTIONEXTRADATA(option).collapsed) { OPTIONEXTRADATA(option).childCount = 0; option = option->next; count++; continue; } if (option->firstChild) localCount = UI_OptionUpdateCache(option->firstChild); OPTIONEXTRADATA(option).childCount = localCount; count += 1 + localCount; option = option->next; } return count; }
/** * @brief Function for menu buttons to update message settings. * @sa MSO_Set * @todo move this into scripts */ static void MSO_Toggle_f (void) { if (cgi->Cmd_Argc() != 3) Com_Printf("Usage: %s <listId> <pause|notify|sound>\n", cgi->Cmd_Argv(0)); else { uiOptionIterator_t iterator; const int listIndex = atoi(cgi->Cmd_Argv(1)); int idx; const msgCategoryEntry_t* selectedEntry; int optionType; bool activate; int type; uiNode_t* messageSetting = cgi->UI_GetOption(TEXT_MESSAGEOPTIONS); UI_InitOptionIteratorAtIndex(messageList_scroll + listIndex, messageSetting, &iterator); if (!iterator.option) return; idx = atoi(OPTIONEXTRADATA(iterator.option).value); selectedEntry = &ccs.msgCategoryEntries[idx]; if (!selectedEntry) return; if (selectedEntry->isCategory) { Com_Printf("Toggle command with selected category entry ignored.\n"); return; } for (type = 0; type < NT_NUM_NOTIFYTYPE; type++) { if (Q_streq(nt_strings[type], selectedEntry->notifyType)) break; } if (type == NT_NUM_NOTIFYTYPE) { Com_Printf("Unrecognized messagetype during toggle '%s' ignored\n", selectedEntry->notifyType); return; } if (Q_streq(cgi->Cmd_Argv(2), "pause")) { optionType = MSO_PAUSE; activate = !selectedEntry->settings->doPause; } else if (Q_streq(cgi->Cmd_Argv(2), "notify")) { optionType = MSO_NOTIFY; activate = !selectedEntry->settings->doNotify; } else { optionType = MSO_SOUND; activate = !selectedEntry->settings->doSound; } MSO_Set(listIndex, (notify_t)type, optionType, activate, true); } }
/** * @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]; } }
static void CL_SetRatioFilter_f (void) { uiNode_t* firstOption = UI_GetOption(OPTION_VIDEO_RESOLUTIONS); uiNode_t* option = firstOption; float requestedRation = atof(Cmd_Argv(1)); bool all = false; bool custom = false; const float delta = 0.01; if (Cmd_Argc() != 2) { Com_Printf("Usage: %s <all|floatration>\n", Cmd_Argv(0)); return; } if (Q_streq(Cmd_Argv(1), "all")) all = true; else if (Q_streq(Cmd_Argv(1), "custom")) custom = true; else requestedRation = atof(Cmd_Argv(1)); while (option) { int width; int height; bool visible = false; const int result = sscanf(OPTIONEXTRADATA(option).label, "%i x %i", &width, &height); if (result != 2) Com_Error(ERR_FATAL, "CL_SetRatioFilter_f: Impossible to decode resolution label.\n"); const float ratio = (float)width / (float)height; if (all) visible = true; else if (custom) /** @todo We should check the ratio list and remove matched resolutions, here it is a hack */ visible = ratio > 2 || (ratio > 1.7 && ratio < 1.76); else visible = ratio - delta < requestedRation && ratio + delta > requestedRation; option->invis = !visible; option = option->next; } /* the content change */ UI_RegisterOption(OPTION_VIDEO_RESOLUTIONS, firstOption); }
/** * @brief Handles tab clicks */ static void UI_TabNodeClick (uiNode_t * node, int x, int y) { uiNode_t* option; if (UI_AbstractOptionGetCurrentValue(node) == NULL) return; option = UI_TabNodeTabAtPosition(node, x, y); if (option == NULL) return; if (option->disabled) return; /* only execute the click stuff if the selectbox is active */ if (node->state) UI_AbstractOptionSetCurrentValue(node, OPTIONEXTRADATA(option).value); }
/** * @brief Generate a tree of option for all allowed chapters and articles * @note it update OPTION_UFOPEDIA */ static void UP_GenerateSummary (void) { uiNode_t* chapters = nullptr; int num = 0; numChaptersDisplayList = 0; for (int i = 0; i < ccs.numChapters; i++) { /* hide chapters without name */ pediaChapter_t* chapter = &ccs.upChapters[i]; if (chapter->name == nullptr) continue; /* Check if there are any researched or collected items in this chapter ... */ bool researchedEntries = false; upCurrentTech = chapter->first; while (upCurrentTech) { if (UP_TechGetsDisplayed(upCurrentTech)) { researchedEntries = true; break; } upCurrentTech = upCurrentTech->upNext; } /* .. and if so add them to the displaylist of chapters. */ if (researchedEntries) { uiNode_t* chapterOption; if (numChaptersDisplayList >= sizeof(upChaptersDisplayList)) cgi->Com_Error(ERR_DROP, "MAX_PEDIACHAPTERS hit"); upChaptersDisplayList[numChaptersDisplayList++] = chapter; /* chapter section*/ chapterOption = cgi->UI_AddOption(&chapters, chapter->id, va("_%s", chapter->name), va("%i", num)); /** @todo use a confunc */ OPTIONEXTRADATA(chapterOption).icon = cgi->UI_GetSpriteByName(va("icons/ufopedia_%s", chapter->id)); chapterOption->firstChild = UP_GenerateArticlesSummary(chapter); num++; } } cgi->UI_RegisterOption(OPTION_UFOPEDIA, chapters); cgi->Cvar_Set("mn_uptitle", _("UFOpaedia")); }
/** * @brief Handles tab clicks */ void uiTabNode::onLeftClick (uiNode_t* node, int x, int y) { uiNode_t* option; if (UI_AbstractOption_GetCurrentValue(node) == nullptr) return; option = UI_TabNodeTabAtPosition(node, x, y); if (option == nullptr) return; if (option->disabled) return; /* only execute the click stuff if the selectbox is active */ if (node->state) UI_AbstractOption_SetCurrentValue(node, OPTIONEXTRADATA(option).value); UI_PlaySound("click1"); }
/** called when the window is pushed * check cvar then, reduce runtime check * @todo move cvar check to AbstractOption */ void uiTabNode::onWindowOpened (uiNode_t* node, linkedList_t* params) { /* no cvar given? */ if (!(EXTRADATA(node).cvar)) return; /* not a cvar? */ char const* const cvarName = Q_strstart(EXTRADATA(node).cvar, "*cvar:"); if (!cvarName) { /* normalize */ Com_Printf("UI_TabNodeInit: node '%s' doesn't have a valid cvar assigned (\"%s\" read)\n", UI_GetPath(node), EXTRADATA(node).cvar); EXTRADATA(node).cvar = nullptr; return; } /* cvar does not exist? */ if (Cvar_FindVar(cvarName) == nullptr) { /* search default value, if possible */ uiNode_t* option = node->firstChild; assert(option->behaviour == ui_optionBehaviour); Cvar_ForceSet(cvarName, OPTIONEXTRADATA(option).value); } }
void uiOptionListNode::draw (uiNode_t* node) { uiNode_t* option; const char* ref; const char* font; int lineHeight; vec2_t pos; int currentY; const float* textColor; int count = 0; ref = UI_AbstractOptionGetCurrentValue(node); if (ref == nullptr) return; UI_GetNodeAbsPos(node, pos); 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]); } font = UI_GetFontFromNode(node); lineHeight = EXTRADATA(node).lineHeight; if (lineHeight == 0) lineHeight = UI_FontGetHeight(font); currentY = pos[1] + node->padding; /* skip option over current position */ option = UI_AbstractOptionGetFirstOption(node); while (option && count < EXTRADATA(node).scrollY.viewPos) { option = option->next; count++; } /* draw all available options for this selectbox */ for (; option; option = option->next) { int decX = pos[0] + node->padding; /* outside the node */ if (currentY + lineHeight > pos[1] + node->box.size[1] - node->padding) { count++; break; } /* draw the hover effect */ if (OPTIONEXTRADATA(option).hovered) UI_DrawFill(pos[0] + node->padding, currentY, node->box.size[0] - node->padding - node->padding, lineHeight, node->color); /* text color */ if (Q_streq(OPTIONEXTRADATA(option).value, ref)) { textColor = node->selectedColor; } else if (node->disabled || option->disabled) { textColor = node->disabledColor; } else if (option->color[3] == 0.0f) { textColor = node->color; } else { textColor = option->color; } if (OPTIONEXTRADATA(option).icon) { uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; if (option->disabled) iconStatus = SPRITE_STATUS_DISABLED; R_Color(nullptr); UI_DrawSpriteInBox(OPTIONEXTRADATA(option).flipIcon, OPTIONEXTRADATA(option).icon, iconStatus, decX, currentY, OPTIONEXTRADATA(option).icon->size[0], lineHeight); decX += OPTIONEXTRADATA(option).icon->size[0] + lineHeight / 4; } /* print the option label */ const char* label = CL_Translate(OPTIONEXTRADATA(option).label); R_Color(textColor); UI_DrawString(font, ALIGN_UL, decX, currentY, pos[0], node->box.size[0] - node->padding - node->padding, 0, label, 0, 0, nullptr, false, LONGLINES_PRETTYCHOP); /* next entries' position */ currentY += lineHeight; count++; } R_Color(nullptr); /* count number of options (current architecture doesn't allow to know if the data change) */ for (; option; option = option->next) { count++; } if (EXTRADATA(node).count != count) { EXTRADATA(node).count = count; } UI_OptionListNodeUpdateScroll(node); }
static void UI_OptionListNodeDraw (uiNode_t *node) { static const int panelTemplate[] = { CORNER_SIZE, MID_SIZE, CORNER_SIZE, CORNER_SIZE, MID_SIZE, CORNER_SIZE, MARGE }; uiNode_t* option; const char *ref; const char *font; int lineHeight; vec2_t pos; const char* image; int currentY; const float *textColor; static vec4_t disabledColor = {0.5, 0.5, 0.5, 1.0}; int count = 0; ref = UI_AbstractOptionGetCurrentValue(node); if (ref == NULL) return; UI_GetNodeAbsPos(node, pos); image = UI_GetReferenceString(node, node->image); if (image) UI_DrawPanel(pos, node->size, image, 0, 0, panelTemplate); font = UI_GetFontFromNode(node); lineHeight = EXTRADATA(node).lineHeight; if (lineHeight == 0) lineHeight = UI_FontGetHeight(font); currentY = pos[1] + node->padding; /* skip option over current position */ option = UI_AbstractOptionGetFirstOption(node); while (option && count < EXTRADATA(node).scrollY.viewPos) { option = option->next; count++; } /* draw all available options for this selectbox */ for (; option; option = option->next) { const char *label; int decX = pos[0] + node->padding; /* outside the node */ if (currentY + lineHeight > pos[1] + node->size[1] - node->padding) { count++; break; } /* draw the hover effect */ if (OPTIONEXTRADATA(option).hovered) UI_DrawFill(pos[0] + node->padding, currentY, node->size[0] - node->padding - node->padding, lineHeight, node->color); /* text color */ if (Q_streq(OPTIONEXTRADATA(option).value, ref)) { textColor = node->selectedColor; } else if (node->disabled || option->disabled) { textColor = disabledColor; } else if (option->color[3] == 0.0f) { textColor = node->color; } else { textColor = option->color; } if (OPTIONEXTRADATA(option).icon) { uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; if (option->disabled) iconStatus = SPRITE_STATUS_DISABLED; R_Color(NULL); UI_DrawSpriteInBox(OPTIONEXTRADATA(option).flipIcon, OPTIONEXTRADATA(option).icon, iconStatus, decX, currentY, OPTIONEXTRADATA(option).icon->size[0], lineHeight); decX += OPTIONEXTRADATA(option).icon->size[0] + lineHeight / 4; } /* print the option label */ label = OPTIONEXTRADATA(option).label; if (label[0] == '_') label = _(label + 1); R_Color(textColor); UI_DrawString(font, ALIGN_UL, decX, currentY, pos[0], node->size[0] - node->padding - node->padding, 0, label, 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP); /* next entries' position */ currentY += lineHeight; count++; } R_Color(NULL); /* count number of options (current architecture doesn't allow to know if the data change) */ for (; option; option = option->next) { count++; } if (EXTRADATA(node).count != count) { EXTRADATA(node).count = count; } UI_OptionListNodeUpdateScroll(node); }
static void UI_OptionTreeNodeDraw (uiNode_t *node) { static const int panelTemplate[] = { CORNER_SIZE, MID_SIZE, CORNER_SIZE, CORNER_SIZE, MID_SIZE, CORNER_SIZE, MARGE }; uiNode_t* option; const char *ref; const char *font; vec2_t pos; const char* image; int fontHeight; int currentY; int currentDecY = 0; const float *textColor; vec4_t disabledColor = {0.5, 0.5, 0.5, 1.0}; int count = 0; uiOptionIterator_t iterator; if (!systemExpand) systemExpand = UI_GetSpriteByName("icons/system_expand"); if (!systemCollapse) systemCollapse = UI_GetSpriteByName("icons/system_collapse"); ref = UI_AbstractOptionGetCurrentValue(node); if (ref == NULL) return; UI_GetNodeAbsPos(node, pos); image = UI_GetReferenceString(node, node->image); if (image) UI_DrawPanel(pos, node->size, image, 0, 0, panelTemplate); font = UI_GetFontFromNode(node); fontHeight = EXTRADATA(node).lineHeight; currentY = pos[1] + node->padding; if (fontHeight == 0) fontHeight = UI_FontGetHeight(font); else { const int height = UI_FontGetHeight(font); currentDecY = (fontHeight - height) / 2; } /* skip option over current position */ option = UI_OptionTreeNodeGetFirstOption(node); UI_OptionTreeNodeUpdateScroll(node); option = UI_InitOptionIteratorAtIndex(EXTRADATA(node).scrollY.viewPos, option, &iterator); /* draw all available options for this selectbox */ for (; option; option = UI_OptionIteratorNextOption(&iterator)) { int decX; const char *label; /* outside the node */ if (currentY + fontHeight > pos[1] + node->size[1] - node->padding) { count++; break; } /* draw the hover effect */ if (OPTIONEXTRADATA(option).hovered) UI_DrawFill(pos[0] + node->padding, currentY, node->size[0] - node->padding - node->padding, fontHeight, node->color); /* text color */ if (Q_streq(OPTIONEXTRADATA(option).value, ref)) { textColor = node->selectedColor; } else if (node->disabled || option->disabled) { textColor = disabledColor; } else if (option->color[3] == 0.0f) { textColor = node->color; } else { textColor = option->color; } /* print the option label */ decX = pos[0] + node->padding + iterator.depthPos * DEPTH_WIDTH; R_Color(NULL); if (option->firstChild) { uiSprite_t *icon = OPTIONEXTRADATA(option).collapsed ? systemExpand : systemCollapse; UI_DrawSpriteInBox(OPTIONEXTRADATA(option).flipIcon, icon, SPRITE_STATUS_NORMAL, decX, currentY, icon->size[0], fontHeight); } decX += COLLAPSEBUTTON_WIDTH; if (OPTIONEXTRADATA(option).icon) { uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; if (option->disabled) iconStatus = SPRITE_STATUS_DISABLED; UI_DrawSpriteInBox(OPTIONEXTRADATA(option).flipIcon, OPTIONEXTRADATA(option).icon, iconStatus, decX, currentY, OPTIONEXTRADATA(option).icon->size[0], fontHeight); decX += OPTIONEXTRADATA(option).icon->size[0] + fontHeight / 4; } label = OPTIONEXTRADATA(option).label; if (label[0] == '_') label = _(label + 1); R_Color(textColor); UI_DrawString(font, ALIGN_UL, decX, currentY + currentDecY, pos[0], node->size[0] - node->padding - node->padding, 0, label, 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP); /* next entries' position */ currentY += fontHeight; count++; } R_Color(NULL); }
static void UI_SelectBoxNodeDrawOverWindow (uiNode_t *node) { uiNode_t* option; int selBoxX, selBoxY; const char *ref; const char *font; vec2_t nodepos; const char* imageName; const image_t *image; ref = UI_AbstractOptionGetCurrentValue(node); if (ref == NULL) return; UI_GetNodeAbsPos(node, nodepos); imageName = UI_GetReferenceString(node, node->image); if (!imageName) imageName = "ui/selectbox"; image = UI_LoadImage(imageName); font = UI_GetFontFromNode(node); selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH; selBoxY = nodepos[1] + SELECTBOX_SPACER; selBoxY += node->size[1]; /* drop down list */ /* left side */ UI_DrawNormImage(nodepos[0], nodepos[1] + node->size[1], SELECTBOX_SIDE_WIDTH, node->size[1] * EXTRADATA(node).count, 7.0f, 28.0f, 0.0f, 21.0f, image); /* stretched middle bar */ UI_DrawNormImage(nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1] + node->size[1], node->size[0] -SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, node->size[1] * EXTRADATA(node).count, 16.0f, 28.0f, 7.0f, 21.0f, image); /* right side */ UI_DrawNormImage(nodepos[0] + node->size[0] -SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, nodepos[1] + node->size[1], SELECTBOX_SIDE_WIDTH, node->size[1] * EXTRADATA(node).count, 23.0f, 28.0f, 16.0f, 21.0f, image); /* now draw all available options for this selectbox */ for (option = UI_AbstractOptionGetFirstOption(node); option; option = option->next) { const char *label; if (option->invis) continue; /* draw the hover effect */ if (OPTIONEXTRADATA(option).hovered) UI_DrawFill(selBoxX, selBoxY, node->size[0] -SELECTBOX_SIDE_WIDTH - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH, SELECTBOX_DEFAULT_HEIGHT, node->color); /* print the option label */ label = OPTIONEXTRADATA(option).label; if (label[0] == '_') label = _(label + 1); UI_DrawString(font, ALIGN_UL, selBoxX, selBoxY, selBoxX, node->size[0] - 4, 0, label, 0, 0, NULL, qfalse, LONGLINES_PRETTYCHOP); /* next entries' position */ selBoxY += node->size[1]; } /* left side */ UI_DrawNormImage(nodepos[0], selBoxY - SELECTBOX_SPACER, SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT, 7.0f, 32.0f, 0.0f, 28.0f, image); /* stretched middle bar */ UI_DrawNormImage(nodepos[0] + SELECTBOX_SIDE_WIDTH, selBoxY - SELECTBOX_SPACER, node->size[0] - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH, SELECTBOX_BOTTOM_HEIGHT, 16.0f, 32.0f, 7.0f, 28.0f, image); /* right bottom side */ UI_DrawNormImage(nodepos[0] + node->size[0] - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH, selBoxY - SELECTBOX_SPACER, SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT, 23.0f, 32.0f, 16.0f, 28.0f, image); }
void uiSelectBoxNode::drawOverWindow (uiNode_t* node) { const char* ref = UI_AbstractOptionGetCurrentValue(node); if (ref == nullptr) return; vec2_t nodepos; UI_GetNodeAbsPos(node, nodepos); const char* imageName = UI_GetReferenceString(node, node->image); if (!imageName) imageName = "ui/selectbox"; const image_t* image = UI_LoadImage(imageName); const char* font = UI_GetFontFromNode(node); int selBoxX = nodepos[0] + SELECTBOX_SIDE_WIDTH; int selBoxY = nodepos[1] + SELECTBOX_SPACER; selBoxY += node->box.size[1]; /* drop down list */ /* left side */ UI_DrawNormImage(false, nodepos[0], nodepos[1] + node->box.size[1], SELECTBOX_SIDE_WIDTH, node->box.size[1] * EXTRADATA(node).count, 7.0f, 28.0f, 0.0f, 21.0f, image); /* stretched middle bar */ UI_DrawNormImage(false, nodepos[0] + SELECTBOX_SIDE_WIDTH, nodepos[1] + node->box.size[1], node->box.size[0] -SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, node->box.size[1] * EXTRADATA(node).count, 16.0f, 28.0f, 7.0f, 21.0f, image); /* right side */ UI_DrawNormImage(false, nodepos[0] + node->box.size[0] -SELECTBOX_SIDE_WIDTH-SELECTBOX_RIGHT_WIDTH, nodepos[1] + node->box.size[1], SELECTBOX_SIDE_WIDTH, node->box.size[1] * EXTRADATA(node).count, 23.0f, 28.0f, 16.0f, 21.0f, image); /* now draw all available options for this selectbox */ int check = 0; for (uiNode_t* option = UI_AbstractOptionGetFirstOption(node); option; option = option->next) { if (option->invis) continue; /* draw the hover effect */ if (OPTIONEXTRADATA(option).hovered) UI_DrawFill(selBoxX, selBoxY, node->box.size[0] -SELECTBOX_SIDE_WIDTH - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH, SELECTBOX_DEFAULT_HEIGHT, node->color); /* print the option label */ const char* label = CL_Translate(OPTIONEXTRADATA(option).label); UI_DrawString(font, ALIGN_UL, selBoxX, selBoxY, selBoxX, node->box.size[0] - 4, 0, label, 0, 0, nullptr, false, LONGLINES_PRETTYCHOP); /* next entries' position */ selBoxY += node->box.size[1]; check++; } /** detect inconsistency */ if (check != EXTRADATA(node).count) { /** force clean up cache */ Com_Printf("uiSelectBoxNode::drawOverWindow: Node '%s' contains unsynchronized option list. Fixed.\n", UI_GetPath(node)); EXTRADATA(node).versionId = 0; } /* left side */ UI_DrawNormImage(false, nodepos[0], selBoxY - SELECTBOX_SPACER, SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT, 7.0f, 32.0f, 0.0f, 28.0f, image); /* stretched middle bar */ UI_DrawNormImage(false, nodepos[0] + SELECTBOX_SIDE_WIDTH, selBoxY - SELECTBOX_SPACER, node->box.size[0] - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH, SELECTBOX_BOTTOM_HEIGHT, 16.0f, 32.0f, 7.0f, 28.0f, image); /* right bottom side */ UI_DrawNormImage(false, nodepos[0] + node->box.size[0] - SELECTBOX_SIDE_WIDTH - SELECTBOX_RIGHT_WIDTH, selBoxY - SELECTBOX_SPACER, SELECTBOX_SIDE_WIDTH, SELECTBOX_BOTTOM_HEIGHT, 23.0f, 32.0f, 16.0f, 28.0f, image); }
void uiTabNode::draw (uiNode_t *node) { ui_tabStatus_t lastStatus = UI_TAB_NOTHING; uiNode_t* option; uiNode_t* overMouseOption = NULL; const char *ref; const char *font; int currentX; int allowedWidth; vec2_t pos; const char* image = UI_GetReferenceString(node, node->image); if (!image) image = "ui/tab"; ref = UI_AbstractOptionGetCurrentValue(node); if (ref == NULL) return; font = UI_GetFontFromNode(node); if (node->state) { overMouseOption = UI_TabNodeTabAtPosition(node, mousePosX, mousePosY); } UI_GetNodeAbsPos(node, pos); currentX = pos[0]; option = node->firstChild; assert(option->behaviour == ui_optionBehaviour); /** @todo this dont work when an option is hidden */ allowedWidth = node->box.size[0] - TILE_WIDTH * (EXTRADATA(node).count + 1); while (option) { int fontHeight; int fontWidth; int tabWidth; int textPos; bool drawIcon = false; ui_tabStatus_t status = UI_TAB_NORMAL; assert(option->behaviour == ui_optionBehaviour); /* skip hidden options */ if (option->invis) { option = option->next; continue; } /* Check the status of the current tab */ if (Q_streq(OPTIONEXTRADATA(option).value, ref)) { status = UI_TAB_SELECTED; } else if (option->disabled || node->disabled) { status = UI_TAB_DISABLED; } else if (option == overMouseOption) { status = UI_TAB_HIGHLIGHTED; } /* Display */ UI_TabNodeDrawJunction(image, currentX, pos[1], lastStatus, status); currentX += TILE_WIDTH; const char *label = CL_Translate(OPTIONEXTRADATA(option).label); R_FontTextSize(font, label, 0, LONGLINES_PRETTYCHOP, &fontWidth, &fontHeight, NULL, NULL); tabWidth = fontWidth; if (OPTIONEXTRADATA(option).icon && OPTIONEXTRADATA(option).icon->size[0] < allowedWidth) { tabWidth += OPTIONEXTRADATA(option).icon->size[0]; drawIcon = true; } if (tabWidth > allowedWidth) { if (allowedWidth > 0) tabWidth = allowedWidth; else tabWidth = 0; } if (tabWidth > 0) { UI_TabNodeDrawPlain(image, currentX, pos[1], tabWidth, status); } textPos = currentX; if (drawIcon) { uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; if (status == UI_TAB_DISABLED) { iconStatus = SPRITE_STATUS_DISABLED; } UI_DrawSpriteInBox(OPTIONEXTRADATA(option).flipIcon, OPTIONEXTRADATA(option).icon, iconStatus, currentX, pos[1], OPTIONEXTRADATA(option).icon->size[0], TILE_HEIGHT); textPos += OPTIONEXTRADATA(option).icon->size[0]; } /** @todo fontWidth can be =0, maybe a bug from the font cache */ OPTIONEXTRADATA(option).truncated = tabWidth < fontWidth || tabWidth == 0; UI_DrawString(font, ALIGN_UL, textPos, pos[1] + ((node->box.size[1] - fontHeight) / 2), textPos, tabWidth + 1, 0, label, 0, 0, NULL, false, LONGLINES_PRETTYCHOP); currentX += tabWidth; allowedWidth -= tabWidth; /* Next */ lastStatus = status; option = option->next; } /* Display last junction and end of header */ UI_TabNodeDrawJunction(image, currentX, pos[1], lastStatus, UI_TAB_NOTHING); currentX += TILE_WIDTH; if (currentX < pos[0] + node->box.size[0]) UI_TabNodeDrawPlain(image, currentX, pos[1], pos[0] + node->box.size[0] - currentX, UI_TAB_NOTHING); }