From 35984ceec8cd076bb3f6083864c5fbf299748ef5 Mon Sep 17 00:00:00 2001 From: k9er Date: Sun, 19 Jan 2025 11:57:30 +0000 Subject: [PATCH] Improve advanced menu tooltips --- qcsrc/menu/menu.qc | 105 ++++++++++++++---- qcsrc/menu/xonotic/commandbutton.qc | 2 +- .../xonotic/dialog_multiplayer_profile.qc | 8 +- qcsrc/menu/xonotic/dialog_settings_audio.qc | 4 +- .../xonotic/dialog_settings_game_weapons.qc | 2 +- qcsrc/menu/xonotic/dialog_settings_input.qc | 2 +- qcsrc/menu/xonotic/dialog_settings_misc.qc | 2 +- .../xonotic/dialog_settings_misc_reset.qc | 2 +- qcsrc/menu/xonotic/dialog_settings_video.qc | 14 +-- qcsrc/menu/xonotic/leavematchbutton.qc | 2 +- qcsrc/menu/xonotic/util.qc | 16 +-- qcsrc/menu/xonotic/util.qh | 15 +++ 12 files changed, 117 insertions(+), 57 deletions(-) diff --git a/qcsrc/menu/menu.qc b/qcsrc/menu/menu.qc index 4d2d6d450..2e941e614 100644 --- a/qcsrc/menu/menu.qc +++ b/qcsrc/menu/menu.qc @@ -502,11 +502,20 @@ entity m_findtooltipitem(entity root, vector pos) return best; } +string gettooltip_dependency_string_numeric(entity e, .string cvarStr, .float cvarMin, .float cvarMax) +{ + if (e.(cvarMin) == e.(cvarMax)) + return sprintf("^3%s^7 \"%s\"", e.(cvarStr), ftos_mindecimals(e.(cvarMin))); + else if (e.(cvarMin) < e.(cvarMax)) + return sprintf(_("^3%s^7 in range \"%s\" to \"%s\""), e.(cvarStr), ftos_mindecimals(e.(cvarMin)), ftos_mindecimals(e.(cvarMax))); + else + return sprintf(_("^3%s^7 outside range \"%s\" to \"%s\""), e.(cvarStr), ftos_mindecimals(e.(cvarMax)), ftos_mindecimals(e.(cvarMin))); +} string gettooltip() { + string s; if (menu_tooltips == 2) { - string s; if (menuTooltipItem.controlledCvar) { string cvar_list = getCvarsMulti(menuTooltipItem); @@ -514,23 +523,54 @@ string gettooltip() cvar_list = strcat(menuTooltipItem.controlledCvar, " ", cvar_list); else cvar_list = menuTooltipItem.controlledCvar; - s = strcat("[", cvar_list, " \"", cvar_string(menuTooltipItem.controlledCvar), "\"]"); + s = strcat("^3", cvar_list, + " ^7\"", cvar_string(menuTooltipItem.controlledCvar), "^7\" " + "^8[\"", cvar_defstring(menuTooltipItem.controlledCvar), "^8\"]^7"); } else if (menuTooltipItem.onClickCommand) - { - s = strcat("<", menuTooltipItem.onClickCommand, ">"); - } + s = strcat("<", menuTooltipItem.onClickCommand, "^7>"); else + s = ""; + + if (menuTooltipItem.tooltip) + s = strcat(rgb_to_hexcolor(SKINCOLOR_TOOLTIP), (s == "" ? menuTooltipItem.tooltip : strcat(menuTooltipItem.tooltip, "\n\n", s))); + + if (menuTooltipItem.disabled) { - return menuTooltipItem.tooltip; + if (menuTooltipItem.func_setDependent) + s = strcat(s, "\n\n", _("Has special requirements")); + else if (menuTooltipItem.cvarString_setDependent) + s = strcat(s, "\n\n", + sprintf(_("Requires ^3%s^7 not equal to \"%s^7\""), cvar_string(menuTooltipItem.cvarString_setDependent), menuTooltipItem.cvarValue_setDependent)); + else if (menuTooltipItem.cvar_setDependent) + { + s = strcat(s, "\n\n"); + string cvar1_s, cvar2_s, cvar3_s; + cvar1_s = gettooltip_dependency_string_numeric(menuTooltipItem, cvar_setDependent, cvarMin_setDependent, cvarMax_setDependent); + if (menuTooltipItem.cvar2_setDependent) + { + cvar2_s = gettooltip_dependency_string_numeric(menuTooltipItem, cvar2_setDependent, cvar2Min_setDependent, cvar2Max_setDependent); + if (menuTooltipItem.cvar3_setDependent) + { + cvar3_s = gettooltip_dependency_string_numeric(menuTooltipItem, cvar3_setDependent, cvar3Min_setDependent, cvar3Max_setDependent); + s = strcat(s, sprintf(_("Requires %s, %s, and %s"), cvar1_s, cvar2_s, cvar3_s)); + } + else + s = strcat(s, sprintf((menuTooltipItem.op_setDependent ? _("Requires %s or %s") : _("Requires %s and %s")), cvar1_s, cvar2_s)); + } + else + s = strcat(s, sprintf(_("Requires %s"), cvar1_s)); + } + // if this point is reached, it's disabled for some other unknown reason } - if (menuTooltipItem.tooltip) return strcat(menuTooltipItem.tooltip, " ", s); - return s; } - return menuTooltipItem.tooltip; + else + s = menuTooltipItem.tooltip; + return s; } void m_tooltip(vector pos) { + const float MAX_TOOLTIP_LINES = 16; static string prev_tooltip; entity it; menu_tooltips = cvar("menu_tooltips"); @@ -590,18 +630,27 @@ void m_tooltip(vector pos) strcpy(menuTooltipText, gettooltip()); - int i = 0; float w = 0; - for (getWrappedLine_remaining = menuTooltipText; getWrappedLine_remaining && i <= 16; ++i) + float lines = 0; + int n = tokenizebyseparator(menuTooltipText, "\n"); + for (int k = 0; k < n && lines <= MAX_TOOLTIP_LINES; ++k) { - string s = getWrappedLine(SKINWIDTH_TOOLTIP, fontsize, draw_TextWidth_WithoutColors); - if (i == 16) - s = "..."; - float f = draw_TextWidth(s, false, fontsize); - if (f > w) w = f; + if (argv(k) == "") + { + lines += 0.5; // insert a half-height separator between paragraphs (marked by 2 newlines) + continue; + } + for (getWrappedLine_remaining = argv(k); getWrappedLine_remaining && lines <= MAX_TOOLTIP_LINES; ++lines) + { + string s = getWrappedLine(SKINWIDTH_TOOLTIP, fontsize, draw_TextWidth_WithColors); + if (lines + 1 > MAX_TOOLTIP_LINES) + s = "..."; + float f = draw_TextWidth_WithColors(s, fontsize); + if (f > w) w = f; + } } menuTooltipSize.x = w + 2 * (SKINMARGIN_TOOLTIP_x / conwidth); - menuTooltipSize.y = i * fontsize.y + 2 * (SKINMARGIN_TOOLTIP_y / conheight); + menuTooltipSize.y = lines * fontsize.y + 2 * (SKINMARGIN_TOOLTIP_y / conheight); menuTooltipSize.z = 0; } break; @@ -662,13 +711,23 @@ void m_tooltip(vector pos) p = menuTooltipOrigin; p.x += SKINMARGIN_TOOLTIP_x / conwidth; p.y += SKINMARGIN_TOOLTIP_y / conheight; - int i = 0; - for (getWrappedLine_remaining = menuTooltipText; getWrappedLine_remaining && i <= 16; ++i, p.y += fontsize.y) + float lines = 0; + int n = tokenizebyseparator(menuTooltipText, "\n"); + for (int k = 0; k < n && lines <= MAX_TOOLTIP_LINES; ++k) { - string s = getWrappedLine(SKINWIDTH_TOOLTIP, fontsize, draw_TextWidth_WithoutColors); - if (i == 16) - s = "..."; - draw_Text(p, s, fontsize, SKINCOLOR_TOOLTIP, SKINALPHA_TOOLTIP * menuTooltipAlpha, false); + if (argv(k) == "") + { + p.y += fontsize.y / 2; + continue; + } + for (getWrappedLine_remaining = argv(k); getWrappedLine_remaining && lines <= MAX_TOOLTIP_LINES; ++lines) + { + string s = getWrappedLine(SKINWIDTH_TOOLTIP, fontsize, draw_TextWidth_WithColors); + if (lines + 1 > MAX_TOOLTIP_LINES) + s = "..."; + draw_Text(p, s, fontsize, '1 1 1', SKINALPHA_TOOLTIP * menuTooltipAlpha, true); + p.y += fontsize.y; + } } } } diff --git a/qcsrc/menu/xonotic/commandbutton.qc b/qcsrc/menu/xonotic/commandbutton.qc index ec03633eb..789f071df 100644 --- a/qcsrc/menu/xonotic/commandbutton.qc +++ b/qcsrc/menu/xonotic/commandbutton.qc @@ -17,7 +17,7 @@ void XonoticCommandButton_Click(entity me, entity other) { //if(me.flags & COMMANDBUTTON_APPLY) // saveAllCvars(me.parent); - cmd("\n", me.onClickCommand, "\n"); + localcmd("\n", me.onClickCommand, "\n"); //if(me.flags & COMMANDBUTTON_REVERT) // loadAllCvars(me.parent); if(me.flags & COMMANDBUTTON_CLOSE) diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_profile.qc b/qcsrc/menu/xonotic/dialog_multiplayer_profile.qc index ad3a3cbb5..564a6e9db 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_profile.qc +++ b/qcsrc/menu/xonotic/dialog_multiplayer_profile.qc @@ -36,10 +36,10 @@ void XonoticProfileTab_fill(entity me) entity e, pms, label, box; float i; entity profileApplyButton = makeXonoticCommandButton(_("Apply immediately"), '0 0 0', - "color -1 -1;" // apply colors contained in _cl_color - "name \"$_cl_name\";" - "playermodel $_cl_playermodel;" - "playerskin $_cl_playerskin;" + "color -1 -1; " // apply colors contained in _cl_color + "name \"$_cl_name\"; " + "playermodel $_cl_playermodel; " + "playerskin $_cl_playerskin" , COMMANDBUTTON_APPLY); profileApplyButton.disableOnClick = true; diff --git a/qcsrc/menu/xonotic/dialog_settings_audio.qc b/qcsrc/menu/xonotic/dialog_settings_audio.qc index 7f911c103..73181c6d9 100644 --- a/qcsrc/menu/xonotic/dialog_settings_audio.qc +++ b/qcsrc/menu/xonotic/dialog_settings_audio.qc @@ -20,8 +20,8 @@ void XonoticAudioSettingsTab_fill(entity me) { entity e, e2, s; entity audioApplyButton = makeXonoticCommandButton(_("Apply immediately"), '0 0 0', - "snd_restart;" - "snd_attenuation_method_${menu_snd_attenuation_method};" + "snd_restart; " + "snd_attenuation_method_${menu_snd_attenuation_method}" , COMMANDBUTTON_APPLY); audioApplyButton.disableOnClick = true; diff --git a/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc b/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc index e5adc9a80..310054b61 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game_weapons.qc @@ -24,7 +24,7 @@ void XonoticGameWeaponsSettingsTab_fill(entity me) { entity e; entity weaponsApplyButton = makeXonoticCommandButton(_("Apply immediately"), '0 0 0', - "sendcvar cl_weaponpriority;" + "sendcvar cl_weaponpriority" , COMMANDBUTTON_APPLY); weaponsApplyButton.disableOnClick = true; diff --git a/qcsrc/menu/xonotic/dialog_settings_input.qc b/qcsrc/menu/xonotic/dialog_settings_input.qc index 659e41533..535ec2b20 100644 --- a/qcsrc/menu/xonotic/dialog_settings_input.qc +++ b/qcsrc/menu/xonotic/dialog_settings_input.qc @@ -57,7 +57,7 @@ entity makeXonoticInputSettingsTab() void CheckBox_Click_Redisplay(entity me, entity checkbox) { CheckBox_Click(me, checkbox); - cmd("\ndefer 0.2 \"togglemenu 1\"\n"); + localcmd("\ndefer 0.2 \"togglemenu 1\"\n"); //m_display(); } void XonoticInputSettingsTab_fill(entity me) diff --git a/qcsrc/menu/xonotic/dialog_settings_misc.qc b/qcsrc/menu/xonotic/dialog_settings_misc.qc index 24c4c7ce4..875ef0040 100644 --- a/qcsrc/menu/xonotic/dialog_settings_misc.qc +++ b/qcsrc/menu/xonotic/dialog_settings_misc.qc @@ -24,7 +24,7 @@ void XonoticMiscSettingsTab_fill(entity me) entity e; //entity sk; - entity miscApplyButton = makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "menu_restart;", COMMANDBUTTON_APPLY); + entity miscApplyButton = makeXonoticCommandButton(_("Apply immediately"), '0 0 0', "menu_restart", COMMANDBUTTON_APPLY); miscApplyButton.disableOnClick = true; me.TR(me); diff --git a/qcsrc/menu/xonotic/dialog_settings_misc_reset.qc b/qcsrc/menu/xonotic/dialog_settings_misc_reset.qc index c0d064a7d..da9b4fe62 100644 --- a/qcsrc/menu/xonotic/dialog_settings_misc_reset.qc +++ b/qcsrc/menu/xonotic/dialog_settings_misc_reset.qc @@ -13,7 +13,7 @@ void XonoticResetDialog_fill(entity me) me.TD(me, 1, 2, makeXonoticTextLabel(0.5, _("This will create a backup config in your data directory"))); me.TR(me); me.TR(me); - me.TD(me, 1, 1, e = makeXonoticCommandButton(_("Yes"), '1 0 0', "saveconfig backup.cfg\n;\n exec default.cfg\n", 0)); + me.TD(me, 1, 1, e = makeXonoticCommandButton(_("Yes"), '1 0 0', "saveconfig backup.cfg; exec default.cfg", 0)); me.TD(me, 1, 1, e = makeXonoticButton(_("No"), '0 1 0')); e.onClick = Dialog_Close; e.onClickEntity = me; diff --git a/qcsrc/menu/xonotic/dialog_settings_video.qc b/qcsrc/menu/xonotic/dialog_settings_video.qc index ff236bc69..12786e13d 100644 --- a/qcsrc/menu/xonotic/dialog_settings_video.qc +++ b/qcsrc/menu/xonotic/dialog_settings_video.qc @@ -19,13 +19,13 @@ void XonoticVideoSettingsTab_fill(entity me) { entity e; entity videoApplyButton = makeXonoticCommandButton(_("Apply immediately"), '0 0 0', - "vid_width $_menu_vid_width;" - "vid_height $_menu_vid_height;" - "vid_pixelheight $_menu_vid_pixelheight;" - "vid_desktopfullscreen $_menu_vid_desktopfullscreen;" - "menu_cmd update_conwidths_before_vid_restart;" - "vid_restart;" - "menu_cmd sync;" + "vid_width $_menu_vid_width; " + "vid_height $_menu_vid_height; " + "vid_pixelheight $_menu_vid_pixelheight; " + "vid_desktopfullscreen $_menu_vid_desktopfullscreen; " + "menu_cmd update_conwidths_before_vid_restart; " + "vid_restart; " + "menu_cmd sync" , COMMANDBUTTON_APPLY); videoApplyButton.disableOnClick = true; diff --git a/qcsrc/menu/xonotic/leavematchbutton.qc b/qcsrc/menu/xonotic/leavematchbutton.qc index d2117356b..d25b1bfdd 100644 --- a/qcsrc/menu/xonotic/leavematchbutton.qc +++ b/qcsrc/menu/xonotic/leavematchbutton.qc @@ -4,7 +4,7 @@ // the delay is for allowing listening to the button sound (if enabled), since the disconnect command stops all sounds // menu_sync is also useful when leaving Instant Action mode // see also m_draw -const string LEAVEMATCH_CMD = "defer 0.4 disconnect; defer 0.4 wait; defer 0.4 \"g_campaign 0\"; defer 0.4 menu_sync\n"; +const string LEAVEMATCH_CMD = "defer 0.4 disconnect; defer 0.4 wait; defer 0.4 \"g_campaign 0\"; defer 0.4 menu_sync"; string leaveMatchButton_getText(entity me) { diff --git a/qcsrc/menu/xonotic/util.qc b/qcsrc/menu/xonotic/util.qc index e3bb5085c..937497e6d 100644 --- a/qcsrc/menu/xonotic/util.qc +++ b/qcsrc/menu/xonotic/util.qc @@ -112,20 +112,6 @@ void makeCallback(entity e, entity cbent, void(entity, entity) cbfunc) } .void(entity) draw_setDependent; -.string cvar_setDependent; -.float cvarMin_setDependent; -.float cvarMax_setDependent; -.string cvar2_setDependent; -.float cvar2Min_setDependent; -.float cvar2Max_setDependent; -.string cvar3_setDependent; -.float cvar3Min_setDependent; -.float cvar3Max_setDependent; -.float op_setDependent; -.string cvarString_setDependent; -.string cvarValue_setDependent; -.float(entity) func_setDependent; -.bool disabled; void setDependent_Check(entity e) { bool disabled_prev = e.disabled; @@ -838,7 +824,7 @@ void CheckSendCvars(entity me, string cvarnamestring) if(gamestatus & (GAME_CONNECTED | GAME_ISSERVER)) { LOG_INFOF("Sending cvar: %s -> %s", cvarnamestring, cvar_string(cvarnamestring)); - cmd(sprintf("\nsendcvar %s\n", cvarnamestring)); + localcmd(sprintf("\nsendcvar %s\n", cvarnamestring)); } } } diff --git a/qcsrc/menu/xonotic/util.qh b/qcsrc/menu/xonotic/util.qh index bb5de1b51..d93a7aa89 100644 --- a/qcsrc/menu/xonotic/util.qh +++ b/qcsrc/menu/xonotic/util.qh @@ -1,5 +1,20 @@ #pragma once +.string cvar_setDependent; +.float cvarMin_setDependent; +.float cvarMax_setDependent; +.string cvar2_setDependent; +.float cvar2Min_setDependent; +.float cvar2Max_setDependent; +.string cvar3_setDependent; +.float cvar3Min_setDependent; +.float cvar3Max_setDependent; +.float op_setDependent; +.string cvarString_setDependent; +.string cvarValue_setDependent; +.float(entity) func_setDependent; +.bool disabled; + float GL_CheckExtension(string ext); float GL_Have_TextureCompression(); -- 2.39.5