Changing HUD element positioning? Created 6 months ago2023-10-08 10:44:08 UTC by robokiller robokiller

Created 6 months ago2023-10-08 10:44:08 UTC by robokiller robokiller

Posted 6 months ago2023-10-08 10:44:08 UTC Post #347927
Hey all. I've been trying to change the X and Y coordinates of various parts of the HUD for a bit, both the numbers and icons, but I'm a bit lost on where exactly I could find the code for this, as I'm not seeing it anywhere in hud.cpp or battery.cpp.
I've modified the height and width of the icons via the hud.txt file, but I'm looking to change the position of which they actually show up on screen.
Posted 6 months ago2023-10-09 16:53:56 UTC Post #347931
Files like health.cpp, battery.cpp etc. implement their own HUD elements with exact coordinates in them.

I'll give you a bit of a detailed explanation so you mechanically know what's going on, if that makes sense.
For example, battery.cpp starts with:
//
// battery.cpp
//
// implementation of CHudBattery class
//
Implementation of CHudBattery huh... what's that?
It is defined in hud.h:
class CHudBattery : public CHudBase
{
public:
    bool Init() override;
    bool VidInit() override;
    bool Draw(float flTime) override;
    bool MsgFunc_Battery(const char* pszName, int iSize, void* pbuf);

private:
    HSPRITE m_hSprite1;
    HSPRITE m_hSprite2;
    Rect* m_prc1;
    Rect* m_prc2;
    int m_iBat;
    int m_iBatMax;
    float m_fFade;
    int m_iHeight; // width of the battery innards
};
Each of these HUD elements are C++ classes, which inherit from CHudBase. The HUD system contains a collection of these CHudBase based objects.

Now, here's the thing. When the HUD wants to actually draw itself onto the screen, it visits each of these elements and asks them to render themselves. This is what the Draw functions are for. If you want to find what coordinates are used, you would simply find, for instance, CHudBattery::Draw, like so:
bool CHudBattery::Draw(float flTime)
{
    if ((gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) != 0)
        return true;

    int r, g, b, x, y, a;
    Rect rc;

    rc = *m_prc2;
    rc.top += m_iHeight * ((float)(100 - (V_min(100, m_iBat))) * 0.01); // battery can go from 0 to 100 so * 0.01 goes from 0 to 1
    UnpackRGB(r, g, b, RGB_YELLOWISH);

    if (!gHUD.HasSuit())
        return true;
... // rest of the code
Scrolling down in the same function, we see this code:
y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
x = ScreenWidth / 4;

// make sure we have the right sprite handles
if (0 == m_hSprite1)
    m_hSprite1 = gHUD.GetSprite(gHUD.GetSpriteIndex("suit_empty"));
if (0 == m_hSprite2)
    m_hSprite2 = gHUD.GetSprite(gHUD.GetSpriteIndex("suit_full"));


SPR_Set(m_hSprite1, r, g, b);
SPR_DrawAdditive(0, x, y - iOffset, m_prc1);

if (rc.bottom > rc.top)
{
    SPR_Set(m_hSprite2, r, g, b);
    SPR_DrawAdditive(0, x, y - iOffset + (rc.top - m_prc2->top), &rc);
}
This says "Hey GoldSRC, please render a sprite at these coordinates here". SPR_Set tells the engine to use a certain sprite, and SPR_DrawAdditive tells the engine to draw it. So, now you might be wondering what's up with these x and y variable things. You can declare your own temporary variables to essentially "chain" HUD elements one after another, so you don't have to manually specify every single coordinate yourself. You can use it to say "the next one will be 5 pixels more" etc.

Now if you actually know C++ and stuff, woops! I tend to assume people don't know, and this may be useful to people in the future anyway, so yeah.

So, generally, it boils down to maths. You just gotta read the code really well to see where the coordinates are defined, and you'll be fine. You can change it to whatever you want, whether it's moving something from the bottom-left corner into a top-right corner, or make them bounce up'n'down through time and anything you can imagine.
Admer456 Admer456If it ain't broken, don't fox it!
You must be logged in to post a response.