Download

Circular Progress HUD

I’m trying to figure out a way to render a circular progress bar that fills from 0 - 100%

My naive approach would just to have 30 different icon states that I would transition between, but I was hoping there is a better way?

I’ve reviewed the UCanvas documentation but nothing stands out at me as a way to draw/make an icon at a rotation so I could construct the progress bar dynamically from one small wedge piece.

Any suggestions?

Having 30 different icons for such thing is A VERY BAD IDEA. My suggestion is to use algo described here: http://www.gamedev.net/topic/621035-how-would-a-filling-clock-drawing-algorythm-work/?view=findpost&p=4917427
Or you can use shader based approach described here: http://www.gamedev.net/topic/603658-circular-health-bars/?view=findpost&p=4820385

Hope this helps

Oh, come on - it’s not that bad. Both of your links demonstrate much better ways, though.

@Mentos - Perhaps look at FCanvasNGonItem, it looks (upon cursory inspection) like it provides pretty much what you need to get started with the triangle fan method described in the first link provided by Peter. From the source comments:



/* 	 
	 * NGon item Several texture tris with a common central point with a fixed radius. 
	 ....
*/


You’ll find that in the UE4 source - not in the game project source - if you’re interested in examining the internals.

Hope that’s handy!

Is this the kind of thing you are after?

Hey Mentos!

Have you looked into sprite sheet style animation for the HUD class?

It means you don’t have to generate any NGon shapes,
and you can customize the look as much as you are capable in P/Shop or GIMP.

Say you have 100 different states of your Ring Health bar, make then evenly spaced in an image like so:

1 - 2 - 3 - 4 - 5
6 - 7 - etc, etc

I whipped up a quick function for you, a more basic version of an animation function from my objectified HUD system.

It can calculate what position it should be at based on the percentage given.
Doesn’t matter how many tiles there are, how wide or high it is, etc, etc, it’ll work. :3

All in all, it means you only need one texture, and you can set it’s LOD group to be ‘UI’ for better clarity!

YourHUD.h



/*
 * Draw a texture at a specific sprite tile position based on a passed percentage
 * @param Texture - The texture to be passed in with a sprite sheet image
 * @param X - The start horizontal position of the object in pixels
 * @param Y - The start vertical position of the object in pixels
 * @param W - The width of the object in pixels
 * @param H - The height of the object in pixels
 * @param RowsCols - The number of tiles wide and high the sprite sheet is
 * @param TotalTiles - This is available in case you have a 5x5 sheet but only 23 tiles altogether
 * @param PercentageAlong - The percentage through this animation you wish to be at
 */
 void DrawAnimatedTexture(UTexture2D* Texture, float X, float Y, float W, float H, FVector2D RowsCols = FVector2D(0, 0), int TotalTiles = 1, float PercentageAlong = 0);


YourHUD.cpp



void AYourHUD::DrawAnimatedTexture(UTexture2D* Texture, float X, float Y, float W, float H, FVector2D RowsCols, int TotalTiles, float PercentageAlong)
{
    //Calculate the width and height of each sprite tile
    float UWidth = 1 / RowsCols.X;
    float VHeight = 1 / RowsCols.Y;


    //Make easier to write int variables of the number of XY tiles
    int MaxX = (int)RowsCols.X;
    int MaxY = (int)RowsCols.Y;


    //Set up the current Tile
    int CurrentTile = 0;
    
    //Grab a float value of the percentage
    float TmpPercent = PercentageAlong / 100; 
    
    //If the percentage is greater than 0
    if (TmpPercent > 0)
    {
        //Set the current tile to be the percentage of tiles calculted
        CurrentTile = (int)(TotalTiles * TmpPercent);
    }//if


    //Default the current tile position
    FVector2D CurrentTilePos = FVector2D(0, 0);


    //Clamp the current tile so it can never go blank
    CurrentTile = FMath::Clamp<int>(CurrentTile, 0, TotalTiles - 1);


    //Set the X position
    CurrentTilePos.X = CurrentTile;


    //If we have exceeded the first row
    if (CurrentTile >= MaxX - 1)
    {
        //Calculate the rows
        CurrentTilePos.Y = (int)(CurrentTile / RowsCols.X);
        //Calculate the remainder 
        int TilesRemaining = (int)(CurrentTile - (RowsCols.X * CurrentTilePos.Y));
        //Set the remainder as the X position
        CurrentTilePos.X = TilesRemaining;
    }//if


    //Draw the texture with the given position, size and UV Coords
    DrawTexture(Texture, X, Y, W, H, CurrentTilePos.X * UWidth, CurrentTilePos.Y * VHeight, UWidth, VHeight);
}//DrawAnimatedTexture


Sorry it’s a bit long, and has far too many calculations per frame,
but you could always hold the positions or current tile elsewhere,
and only update everything else if it changes.

Although If you want to go down the material route,
Shockwave-peter’s second link is FARRRRRRRR better than this!

I hope it helps!

-Peace