Merge branch 'master' into terencehill/weapon_panel_fix
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud.qc
index e33b9b0..024a076 100644 (file)
@@ -140,6 +140,12 @@ vector HUD_Get_Num_Color (float x, float maxvalue)
        return color;
 }
 
+float HUD_GetRowCount(float item_count, vector size, float item_aspect)
+{
+       float aspect = size_y / size_x;
+       return bound(1, floor((sqrt(4 * item_aspect * aspect * item_count + aspect * aspect) + aspect + 0.5) / 2), item_count);
+}
+
 float stringwidth_colors(string s, vector theSize)
 {
        return stringwidth(s, true, theSize);
@@ -424,16 +430,13 @@ void HUD_Weapons(void)
        float screen_ar;
        vector center = '0 0 0';
        float weapon_count, weapon_id;
-       float row, column, rows = 0, columns = 0;
+       float row, column, rows = 0, columns;
        float aspect = autocvar_hud_panel_weapons_aspect;
 
-       float panel_weapon_accuracy;
-
        float timeout = autocvar_hud_panel_weapons_timeout;
        float timein_effect_length = autocvar_hud_panel_weapons_timeout_speed_in; //? 0.375 : 0);
        float timeout_effect_length = autocvar_hud_panel_weapons_timeout_speed_out; //? 0.75 : 0);
 
-       float ammo_full;
        vector barsize = '0 0 0', baroffset = '0 0 0';
        vector ammo_color = '1 0 1';
        float ammo_alpha = 1;
@@ -497,15 +500,18 @@ void HUD_Weapons(void)
        if(!autocvar_hud_panel_weapons_complainbubble || autocvar__hud_configure || time - complain_weapon_time >= when + fadetime)
                complain_weapon = 0;
 
+       if(autocvar__hud_configure)
+       {
+               if(!weapons_stat)
+                       for(i = WEP_FIRST; i <= WEP_LAST; i += floor((WEP_LAST-WEP_FIRST)/5))
+                               weapons_stat |= WepSet_FromWeapon(i);
+       }
+
        // determine which weapons are going to be shown
        if (autocvar_hud_panel_weapons_onlyowned)
        {
                if(autocvar__hud_configure)
                {
-                       if (!weapons_stat)
-                               for(i = WEP_FIRST; i <= WEP_LAST; i += floor((WEP_LAST-WEP_FIRST)/5))
-                                       weapons_stat |= WepSet_FromWeapon(i);
-
                        if(menu_enabled != 2)
                                HUD_Panel_DrawBg(1); // also draw the bg of the entire panel
                }
@@ -513,13 +519,9 @@ void HUD_Weapons(void)
                // do we own this weapon?
                weapon_count = 0;
                for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
-                       if(weapons_stat & WepSet_FromWeapon(weaponorder[i].weapon))
+                       if((weapons_stat & WepSet_FromWeapon(weaponorder[i].weapon)) || (weaponorder[i].weapon == complain_weapon))
                                ++weapon_count;
 
-               // add it anyway if weaponcomplain is shown
-               if(complain_weapon)
-                       ++weapon_count;
-
                // might as well commit suicide now, no reason to live ;)
                if (weapon_count == 0)
                {
@@ -527,41 +529,36 @@ void HUD_Weapons(void)
                        return;
                }
 
-               vector max_panel_size = panel_size - '2 2 0' * panel_bg_padding;
+               vector old_panel_size = panel_size;
+               if(panel_bg_padding)
+                       old_panel_size -= '2 2 0' * panel_bg_padding;
 
-               // calculate distribution and size of table cells
-               if(max_panel_size.x > max_panel_size.y)
-               {
-                       while(weapon_count > columns * rows)
-                       {
-                               ++rows;
-                               columns = ceil(max_panel_size.x / (max_panel_size.y / rows * aspect));
-                       }
+               // NOTE: the goal is to use the all-weapons layout and remove unneeded cells
+               // this way weapon icons always have the same size regardless of owned weapon count
 
-                       weapon_size.x = max_panel_size.x / columns;
-                       weapon_size.y = max_panel_size.y / rows;
-                       columns = ceil(weapon_count / rows);
-               }
-               else
-               {
-                       while(weapon_count > columns * rows)
-                       {
-                               ++columns;
-                               rows = ceil(max_panel_size.y / (max_panel_size.x / columns / aspect));
-                       }
+               // get the all-weapons layout
+               rows = HUD_GetRowCount(WEP_COUNT, old_panel_size, aspect);
+               columns = ceil(WEP_COUNT/rows);
+               weapon_size.x = old_panel_size.x / columns;
+               weapon_size.y = old_panel_size.y / rows;
 
-                       weapon_size.x = max_panel_size.x / columns;
-                       weapon_size.y = max_panel_size.y / rows;
-                       rows = ceil(weapon_count / columns);
-               }
+               // reduce rows and columns as needed
+               columns = ceil(weapon_count / rows);
+               rows = ceil(weapon_count / columns);
+
+               // NOTE: although weapons should aways look the same even if onlyowned is disabled,
+               // we enlarge them a bit when possible to better match the desired aspect ratio
+               // as they look much better
+               weapon_size.x = min(old_panel_size.x / columns, aspect * weapon_size.y);
+               weapon_size.y = min(old_panel_size.y / rows, weapon_size.x / aspect);
 
                // reduce size of the panel
                panel_size.x = columns * weapon_size.x;
                panel_size.y = rows * weapon_size.y;
-               panel_pos.x += (max_panel_size.x - panel_size.x) / 2;
-               panel_pos.y += (max_panel_size.y - panel_size.y) / 2;
-
-               panel_size += '2 2 0' * panel_bg_padding;
+               panel_pos.x += (old_panel_size.x - panel_size.x) / 2;
+               panel_pos.y += (old_panel_size.y - panel_size.y) / 2;
+               if(panel_bg_padding)
+                       panel_size += '2 2 0' * panel_bg_padding;
        }
        else
                weapon_count = WEP_COUNT;
@@ -672,8 +669,7 @@ void HUD_Weapons(void)
 
        if(!rows) // if rows is > 0 onlyowned code has already updated these vars
        {
-               rows = panel_size.y/panel_size.x;
-               rows = bound(1, floor((sqrt(4 * aspect * rows * weapon_count + rows * rows) + rows + 0.5) / 2), weapon_count);
+               rows = HUD_GetRowCount(weapon_count, panel_size, aspect);
                columns = ceil(weapon_count/rows);
                weapon_size = eX * panel_size.x*(1/columns) + eY * panel_size.y*(1/rows);
        }
@@ -729,7 +725,7 @@ void HUD_Weapons(void)
                // draw the weapon accuracy
                if(autocvar_hud_panel_weapons_accuracy)
                {
-                       panel_weapon_accuracy = weapon_accuracy[self.weapon-WEP_FIRST];
+                       float panel_weapon_accuracy = weapon_accuracy[self.weapon-WEP_FIRST];
                        if(panel_weapon_accuracy >= 0)
                        {
                                color = Accuracy_GetColor(panel_weapon_accuracy);
@@ -765,6 +761,7 @@ void HUD_Weapons(void)
                        // draw ammo status bar
                        if(autocvar_hud_panel_weapons_ammo && (self.ammo_field != ammo_none))
                        {
+                               float ammo_full;
                                a = getstati(GetAmmoStat(self.ammo_field)); // how much ammo do we have?
 
                                if(a > 0)
@@ -1015,15 +1012,10 @@ void HUD_Ammo(void)
        else
                nade_prevstatus = nade_prevframe = nade_statuschange_time = 0;
 
-       rows = mySize.y/mySize.x;
-       rows = bound(1, floor((sqrt(4 * (3/1) * rows * (total_ammo_count) + rows * rows) + rows + 0.5) / 2), (total_ammo_count));
-       //                               ^^^ ammo item aspect goes here
-
+       rows = HUD_GetRowCount(total_ammo_count, mySize, 3);
        columns = ceil((total_ammo_count)/rows);
-
        ammo_size = eX * mySize.x*(1/columns) + eY * mySize.y*(1/rows);
 
-
        vector offset = '0 0 0'; // fteqcc sucks
        float newSize;
        if(ammo_size.x/ammo_size.y > 3)
@@ -2309,12 +2301,8 @@ void HUD_Score(void)
                }
                if(spectatee_status == -1)
                {
-                       rows = mySize.y/mySize.x;
-                       rows = bound(1, floor((sqrt(4 * (3/1) * rows * team_count + rows * rows) + rows + 0.5) / 2), team_count);
-                       //                               ^^^ ammo item aspect goes here
-
+                       rows = HUD_GetRowCount(team_count, mySize, 3);
                        columns = ceil(team_count/rows);
-
                        score_size = eX * mySize.x*(1/columns) + eY * mySize.y*(1/rows);
 
                        float newSize;
@@ -2742,9 +2730,8 @@ void HUD_Mod_CA(vector myPos, vector mySize)
        else //if(gametype == MAPINFO_TYPE_FREEZETAG)
                layout = autocvar_hud_panel_modicons_freezetag_layout;
        float rows, columns, aspect_ratio;
-       rows = mySize.y/mySize.x;
        aspect_ratio = (layout) ? 2 : 1;
-       rows = bound(1, floor((sqrt((4 * aspect_ratio * team_count + rows) * rows) + rows + 0.5) / 2), team_count);
+       rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
        columns = ceil(team_count/rows);
 
        int i;
@@ -3338,9 +3325,8 @@ void HUD_Mod_Dom(vector myPos, vector mySize)
 
        int layout = autocvar_hud_panel_modicons_dom_layout;
        float rows, columns, aspect_ratio;
-       rows = mySize.y/mySize.x;
        aspect_ratio = (layout) ? 3 : 1;
-       rows = bound(1, floor((sqrt((4 * aspect_ratio * team_count + rows) * rows) + rows + 0.5) / 2), team_count);
+       rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
        columns = ceil(team_count/rows);
 
        int i;