HUD Overview and Canvas Functions

From Oldunreal-Wiki
Jump to navigation Jump to search

Who this tutorial is for

This tutorial is a detailed overview of all the wonderful things you can do with HUDs and the Canvas class. Although I do mention some things on how to create a simple HUD, this tutorial is geared more towards advanced coders that want to find out a few more tricks about making good HUDs. If you've never made a HUD before you may find yourself a little confused. This is normal. Feel free to mail me any questions you may have at lsergey@home.com.

Canvas and where it all begins

First off, whenever you're making a HUD, you should remember that everyone a HUD draws is drawn on the Canvas. The Canvas is basically an object that draws thing directly on the player's screen. If you've ever coded Java applets, the Graphics object is probably the closest thing to the UT Canvas I can think of. The HUD is basically a set of instructions that tell the Canvas object what to draw and where. The HUD is redrawn as often as possible (every tick I believe). Whenever the HUD is redrawn, the "PostRender(Canvas Canvas)" function is called. This function is called by the PlayerPawn and gives you access to the Canvas class so you can draw things on it. The PlayerPawn also calls the PostRender function of weapons for things like custom crosshairs (like for the rocket launcher), but we'll focus on just the HUD for now. Another thing to keep in mind about the HUD is that in multiplayer games it exists client-side (since there is no need for the server to know what the player has going on with his HUD), so you should put "simulated" before all the functions to ensure your own well being.

"What this all means to me"

If you don't feel like figuring out what I said above, here is a summary of what all that means to you, a guy that just wants to make a custom HUD: The whole HUD process starts with the "PostRender(Canvas Canvas)" function which is called about every tick (in other words, as often as possible). All the drawing is done by the Canvas object. You should put "simulated" before all your functions in your HUD. Simple enough, right? Good.

Making and using the HUD

Before I go into detail about how to actually draw pictures and text on the HUD, I want to explain where and how you can use this HUD. The best place to use new HUD objects is in a new gametype. I'm not sure about mutators however, as it may be possible to modify the HUD with a mutator without having to create a new HUD object. If, however, you want to use your HUD in a new gametype just set the HUDType property of your new gametype to the class name of your HUD. For most UT modifications, you'll want to subclass ChallengeHUD, although if you're making a more total conversion you might want to subclass the HUD class.

Basic functions and variables

As stated before, all the drawing is done by the Canvas object, sent to the HUD through the PostRender(Canvas Canvas) function. Note that if you want to draw things on the HUD with other functions besides PostRender, be sure to send the Canvas object to them too so they actually have something to draw on. Now without any further comments, here is my list of all the important functions and variables in the Canvas class:

font Font - this is the font that the Canvas will use when it draws text. I will explain more about fonts later on.

float OrgX, OrgY - these are the coordinates of the point (0,0). Usually you won't alter these, but there are situations (explained later on) where altering these values can be helpful.

float ClipX, ClipY - this is the bottom right corner of the drawing region. Depending on the resolution, these values will vary. Again, usually you won't alter these, but there are situations where it may be helpful.

float CurX, CurY - the current location for drawing. If you draw something, this is where it will be drawn.

byte Style - the style in which pictures or text will be drawn (transparent, masked, etc.). So if you want to draw a masked icon, make sure that the Style variable is set to STY_Masked.

color DrawColor - the color in which something will be drawn. The default is gray (127,127,127). If you draw a picture while the DrawColor is not white, that picture's colors WILL be altered. To alter the color, simply enter Canvas.DrawColor.r = REDVALUE; Canvas.DrawColor.g = GREENVALUE; Canvas.DrawColor.b = BLUEVALUE; where REDVALUE, GREENVALUE, and BLUEVALUE are the amounts of red green and blue you want in that color (255 is the max amount you can set per color).

function StrLen( coerce string String, out float XL, out float YL ) - return the dimensions of the string String (XL and YL) based on the currently selected font.

function DrawText( coerce string Text, optional bool CR) - draws the string Text at (CurX,CurY) with the font Font.

function DrawTile( texture Tex, float XL, float YL, float U, float V, float UL, float VL) - used for drawing parts of an icon or drawing an icon with irregular dimensions. This function will be discussed later on.

function DrawActor( Actor A, bool WireFrame, optional bool ClearZ ) - draws the actor A on the player's screen. This only makes sense if the actor A is normally hidden. The only place I've seen this used is by the weapon class for drawing the first person model.

function DrawPortal( int X, int Y, int Width, int Height, actor CamActor, vector CamLocation, rotator CamRotation, optional int FOV, optional bool ClearZ ) - draws a rectangular area that displays the view from another actor. Most of the values are pretty obvious. In my own experience I've noticed that this function doesn't always work. If you are having trouble, make sure FOV is set to 90.

event Reset() - resests all the variables to their defaults. Useful for cleaning up after you do something messy (more below).

function SetPos( float X, float Y ) - sets CurX to X and CurY to Y, just like writing CurX = X; CurY = Y; only faster.

function SetOrigin( float X, float Y ) - sets OrgX to X and OrgY to Y, just like writing OrgX = X; OrgY = Y; only faster.

function SetClip( float X, float Y ) - sets ClipX to X and ClipY to Y, just like writing ClipX = X; ClipY = Y; only faster.

function DrawPattern ( texture Tex, float XL, float YL, float Scale ) - draws a repeating pattern with sizes XL and YL and with a scale Scale (that scale is applied to each "picture" in the pattern). Note that the pattern is drawn as if it started at (0,0), so if you're drawing in around the middle of the screen don't be surprised if you don't have the upper-left hand corner of Tex in the upper-left hand corner of your pattern (if you want to know what I mean, test this function out for yourself). Also, keep in mind that the scale is reversed, so if you enter 0.5 the images will be 2x BIGGER, and with scale 2 they will be 2x SMALLER.

function DrawIcon ( texture Tex, float Scale ) - draws the icon Tex with a scale factor Scale. You will probably be using this a lot.

function DrawRectangle ( texture Tex, float RectX, float RectY ) - draws the icon Tex with a horizontal scale of RectX and a vertical scale for RectY.

Drawing from the bottom-right

This is really a beginner thing, but just so you know, if you want to draw an icon along the bottom of the screen, since the coordinates of the bottom will change with the resolution (as well as the coordinates for the right edge), you should use ClipX and ClipY (that is after all what they're there for). So if you want to draw a 64x64 pixel icon in the lower right-hand corner, you would set the CurX to ClipX-64 and CurY to ClipY-64.

Fonts

The Font variable in the Canvas class represents the font with which a text string will be drawn. You can set this to any Font you want, but there are some predefined Fonts in ChallengeHUD you should be aware of. Since the UT HUD, unlike the Unreal HUD, changes depending on a player's resolution (so if you increase the resolution the icons will be made bigger so as to compensate), the fonts have to change with the resolution too. So if you are making a HUD that changes with the resolution, you may want to use the predefined font functions. The FontInfo class is a UT class that determines what font you should use depending on the player's current resolution. In the ChallengeHUD class, there is a FontInfo variable named "MyFonts". This class contains a lot of functions that return the font you want. Below is a list of all these functions. Note that you should enter the current horizontal resolution, ClipX, for Width:

function font GetHugeFont(float Width) - returns a HUGE font. function font GetBigFont(float Width) - returns a big font. function font GetMediumFont(float Width) - returns a medium font. function font GetSmallFont(float Width) - returns a small font. function font GetSmallestFont(float Width) - returns an even smaller font. function font GetAReallySmallFont(float Width) - returns a really small font. function font GetACompletelyUnreadableFont(float Width) - returns a completely unreadable font. Note that some of the smaller fonts may not have a full character set and you might only be able to use numbers.

Text wrapping and the use of origins and clips

By default, if you draw some text at the edge of the screen it will be automatically wrapped to the opposite edge. Of course, this doesn't look very good and sometimes you need to draw a sort of "text box" with wrapped text (like the Unreal translator). I have some good news - you CAN do this.

The text wrapping is based on ClipX and OrgX. The Canvas class assumes these are the edges of the screen, but as I mentioned earlier, these variables can be changed. However, be sure never to lose the original value of ClipX and ClipY, unless you want to be drawing the rest of your HUD in a rather small portion of the screen. To start off, you'll want to have two local variables in your function for storing the original values of ClipX and ClipY. For this part of the tutorial, we'll call these variables TempX and TempY. Before you do anything, make sure TempX = ClipX and TempY = ClipY. Now that the original clip values are safe and sound, we can start messing around with them.

First you'll want to use the setOrigin function to set the upper left-hand corner of our text box, then you'll want to use the setClip function to determine the lower right-hand corner. Now you'll want to enter setPos(0,0) so that the text starts in the upper left-hand corner of the box, and your text box is all set. Now you can set the font, make sure the colors are set right, etc. etc. and draw your text (with a single DrawText function). After you're done with that, we have to clean things up so that we can draw other stuff on the Canvas after this. First of all you'll want to call Canvas.Reset() to clean things up, and then you'll want to set ClipX and ClipY back to TempX and TempY. That's it, you're done!

The Scale factor

NOTE: This section only applies to people subclassing the ChallengeHUD class.

As I mentioned before in the Fonts section, the UT HUD changes in size depending on the resolution to give the impression that it stays the same. It uses the floating point Scale, set in the SetupHUD() function, to control the size of just about everything, so you'll want to multiply the scale of your icons and the locations you enter by Scale. You may also want to multiply it by StatusScale, which is the scale of the HUD set in the menu (so it would be YourScaleOrLocation*Scale*StatusScale).

The almighty tile

The DrawTile function is a native function in the Canvas class that actually draws an image. All those DrawIcon and DrawPattern are just UnrealScript functions that use the DrawTile function. However, the DrawTile function can be used to do a lot of fun things. Here is a description of all the arguments of that function:

native(466) final function DrawTile( texture Tex, // this is the actual image you want to draw, simple enough float XL, // the horizontal length of the thing we're drawing, in pixels float YL, // the vertical length of the thing we're drawing, in pixels float U, // The horizontal offset of the image (so if we're drawing an image 128 in length with XL 128 and UL 128 and we enter 64 here, it will look like 2 halves of the image on opposite sides. Still confused? Here is my ASCII art to the rescue:

//
//XL = 128, UL = 128, U = 0 ("before"):
//[op]
//
//XL = 128, UL = 128, U = 64 ("after"):
//p][o
//

float V, // The vertical offset of the image (so if we're drawing an image 128 in height with YL 128 and VL 128 and we enter 64 here, it will look like 2 halves of the image on opposite sides. Still confused? Imagine the above ASCII art but rotated 90 degrees... float UL, // how much of the image Tex to draw (so if the image is 128 in length and we enter 64, we will draw half) float VL // how much of the image Tex to draw (so if the image is 128 in height and we enter 64, we will draw half) );

So, if our image is 128 in length and we have UL set to 64 and XL set to 64, we will draw half of the image.

If, under the same setup, we have XL set to 128, we will draw half of that image with 2x the horizontal scale (so half the image will cover the same area as the whole image with UL 128).

Also, there are a few things to keep in mind about U and V. First of all, remember that it has nothing to do with XL and YL, so if you have an image 128 in length and enter UL = 128 and XL = 64, entering U = 32 will NOT result in the image being cut in half as described in the above ASCII art (it will be cut into 1/4 and 3/4). Think of XL and YL as a scale applied after all the other stuff is done. Another thing to keep in mind is that the image will be moved to the left for U and up for V, not right and down as would seem to make sense.