Drawn text on hud

Discussions about Coding and Scripting
User avatar
>@tack!<
Adept
Posts: 338
Joined: Sat Apr 17, 2010 4:51 pm
Personal rank: lol?

Drawn text on hud

Post by >@tack!< »

Hey i have this weird thing.
Whenever i pick something up, ammo, weapon, if i have text drawn on my hud like the scale of the sniperzoom, it gets a bit bigger and then goes back to normal in a sec, this is very annoying since i want to draw text on the hud with my own sniper too.. my friend says that he had this too and he fixed it somehow but doesnt know anymore how. Is it something in the advanced options??
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Drawn text on hud

Post by Feralidragon »

Before the text drawing, add this:

Code: Select all

Canvas.Font = Canvas.default.Font;
The way your friend may have fixed was by forcing a font in the canvas before drawing any text, as what happens in the regular sniper is that no font is defined before the text drawing, and if a bigger or smaller font was already defined earlier in another canvas (since the Canvas is all pretty much the same), that value is retained and passed down and therefore affecting any text drawing with no font change.

Also, before doing anything on Canvas, is a good practise to make perhaps this instead:

Code: Select all

Canvas.Reset();
That resets all the canvas values to their defaults, and is used for these same reasons.
User avatar
>@tack!<
Adept
Posts: 338
Joined: Sat Apr 17, 2010 4:51 pm
Personal rank: lol?

Re: Drawn text on hud

Post by >@tack!< »

Ok thankyou verymuch
dot
Average
Posts: 59
Joined: Tue Oct 30, 2018 3:41 am

Re: Drawn text on hud

Post by dot »

Feralidragon wrote:Before the text drawing, add this:

Code: Select all

Canvas.Font = Canvas.default.Font;
It is crash my UT. Because Canvas.Default.Font is None.
Feralidragon wrote: Also, before doing anything on Canvas, is a good practise to make perhaps this instead:

Code: Select all

Canvas.Reset();
That resets all the canvas values to their defaults, and is used for these same reasons.
Same issue. Maybe by same reason. Also it can result not render text at all if Style not set properly.

My solution - store Font for first time and restore for all other calls. It is always safe.
1. Add field:

Code: Select all

var Font FirstFont;
2. In code make lazy init and set if font different.

Code: Select all

if (FirstFont == None) FirstFont = Canvas.Font;
if (FirstFont != Canvas.Font) Canvas.Font = FirstFont;
It must work always. Moreover it will respect any (even custom) used fonts and their sizes. And respect game types fonts. For example UT fonts or U1 fonts).
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Drawn text on hud

Post by Feralidragon »

Yeah, the default font is non-existent, I didn't realize that 7 years ago. :lol2:

Having that said, what you're suggesting doesn't solve the problem the OP asked about at all, it only worsens it given that then you pick up whichever font is set at the time of that first call and force it forever, meaning that such a solution is non-deterministic.
In other words, if the canvas ends up having at huge font at first for whichever reason, you're doomed to always see everything else from there in that context using that font and not the desired one.

Hence, all you need to actually do is simply this:

Code: Select all

Canvas.Reset();
Canvas.Font = <the font that you want>;
Canvas.Style = <the style that you want>;
The Canvas.Reset() is only meant to ensure that you start over from a clean slate canvas-wise, but it stands to reason that anything you want to set up you should just set it up after the reset.
dot
Average
Posts: 59
Joined: Tue Oct 30, 2018 3:41 am

Re: Drawn text on hud

Post by dot »

Yep. I know that. But you can set your Font very early.
Because you do not know which font is really used.
Because if you used fix font then it big on small screens and small on big.
I investigate this issue before make this solution.

You can use
Canvas.MedFont
https://github.com/Slipyx/UT99/blob/a26 ... as.uc#L107
And get green Font from U1.

Here example how it usually works in UT:

Code: Select all

static function font GetHugeFont(UWindowRootWindow Root)
{
	if (Root.WinWidth*Root.GUIScale < 512)
		return Font(DynamicLoadObject("LadderFonts.UTLadder12", class'Font'));
	else if (Root.WinWidth*Root.GUIScale < 640)
		return Font(DynamicLoadObject("LadderFonts.UTLadder16", class'Font'));
	else if (Root.WinWidth*Root.GUIScale < 800)
		return Font(DynamicLoadObject("LadderFonts.UTLadder20", class'Font'));
	else if (Root.WinWidth*Root.GUIScale < 1024)
		return Font(DynamicLoadObject("LadderFonts.UTLadder22", class'Font'));
	else
		return Font(DynamicLoadObject("LadderFonts.UTLadder30", class'Font'));
}
So you can not know which fonts really used. Because in settings can be set anything. Include double HUD size.
So this solution is good. Of course with some caveats.

But in any case Font always will be same, even if bigger from default. And it respect all customization. Any customization.

If you need, you can make special code, run it as more early, get here Canvas in some way and get Font from it.

Usually HUD mutators register on PostPlay. After that it receive PostRender on each frame. Very rare in first frame something change default font. Then you can get Font here.

About 7 years - I need place this code somewhere. I can create new topic if you want.

Maybe need use FontInfo if you really need some font:
https://github.com/Slipyx/UT99/blob/a26 ... ontInfo.uc
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Drawn text on hud

Post by Feralidragon »

Sure, but you can put anything in:

Code: Select all

Canvas.Font = <the font that you want>;
It doesn't necessarily have to be a fixed hardcoded font, this could as easily be a function call, using the Canvas as an argument, which would return the right font to use, and it would work 100% of the time, unlike what you're proposing.
You shouldn't assign state to something that can be stateless, or in other words, you shouldn't save things in vars when you can achieve the same by calling a deterministic function (except in cases where the function is heavy, and there you use a var for caching purposes only: memoization).
dot wrote:About 7 years - I need place this code somewhere. I can create new topic if you want.
I didn't mean anything big with it, it was mostly to make sure that you actually saw the date of this topic. :)

It's up to the moderators/admins how they prefer to go with this, but for what's worth, in my own personal opinion you should just check the date of the post and ask yourself if what you want to post is valuable enough to resurrect topics with almost a decade, or if it should be better to make a post with an aggregation of the ideas and solutions that you have in a more generic way, maybe by referencing these topics.

If it's just to give a very specific small alternate solution for a very old topic for a very specific small problem, maybe it's not worth it.

In this case I don't really see a big problem in posting in this one, but just make sure you don't resurrect too many old topics, otherwise the visibility of new posts may get lost between ancient topics, and other posters may not check the previous post dates and think these are recent things, which are not. :)
This forum should probably just have an automatic archival of old topics though.
dot
Average
Posts: 59
Joined: Tue Oct 30, 2018 3:41 am

Re: Drawn text on hud

Post by dot »

Need worked solution.

UT have big problem with documentation.
For write simple mutator I spent very lot of the time. It is not good.

You can obtain Font statically from FontInfo and screen Width:

Code: Select all

FirstFont = class'FontInfo'.Static.GetStaticMediumFont(Canvas.ClipX);
scr_1541367576.jpg
or

Code: Select all

FirstFont = class'FontInfo'.Static.GetStaticSmallFont(Canvas.ClipX);
scr_1541367633.jpg
Also you can use any FontInfo from system objects, because it can be override here.
For example ServerInfo.MyFonts, TournamentScoreBoard.MyFonts, ChallengeHUD.MyFonts.
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Drawn text on hud

Post by Feralidragon »

Picking up your example, I could just do this:

Code: Select all

Canvas.Font = class'FontInfo'.Static.GetStaticMediumFont(Canvas.ClipX);
Why store it in a variable?
Especially when doing so may cause issues, whereas a direct call does not? What's the advantage?

The best solutions are often the simplest ones.
dot
Average
Posts: 59
Joined: Tue Oct 30, 2018 3:41 am

Re: Drawn text on hud

Post by dot »

What kind of issues?

Read from cache faster usually. This code can be called on every frame so do not good make it heavy.
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Drawn text on hud

Post by Feralidragon »

For example: when you change the resolution in mid-game, your font will be bigger or smaller than intended.
And it's not as infrequent as it may sound, I can just Alt+Enter to window mode with a different resolution.

Like I said above: you shouldn't assign a state to something which doesn't have to be stateful, since it brings all sorts of edge cases and whatnot like the one above, unnecessarily so.
Any performance gains that you're trying to get there are negligible, and make the code be worse and more complicated overall than it should be.

There's a saying: "premature optimization is the root of all evil".
dot
Average
Posts: 59
Joined: Tue Oct 30, 2018 3:41 am

Re: Drawn text on hud

Post by dot »

Then need save width of Canvas and if it changed get Font from scratch. Else use cache.
This is from UT code.
https://github.com/Slipyx/UT99/blob/a26 ... ontInfo.uc
I do not think they do this without reason.
And I do not think create new Font on every frame is good idea,
Maybe better be make own FontInfo and use non-static methods from it.
It is already use cache.

Let's summarize code:

Code: Select all

var Font CacheFont;
var float CacheWidth;

if (CacheFont == None || CacheWidth != Canvas.ClipX) {
	CacheFont = class'FontInfo'.Static.GetStaticSmallFont(Canvas.ClipX);
	CacheWidth = Canvas.ClipX;
}
if (CacheFont != Canvas.Font) Canvas.Font = CacheFont;
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Drawn text on hud

Post by Feralidragon »

Notice that no actual "new" fonts are created, it's just a class reference, and always the same class reference in the end, although looking into the function itself (which I didn't at the time) it has DynamicLoadObject calls, which are indeed slow, and should indeed be taken into consideration.

What you pointed out was exactly what I was mentioning before: that's memoization, caching the results of function calls into vars, so that the heavy parts of a function do not need to run again in the subsequent calls.

But notice that still doesn't invalidate what I mentioned overall.
While it would indeed be a bad idea to call this function directly every frame, all that actually needs to be done is to just instantiate the FontInfo itself, either directly or through a similar way as TournamentScoreBoard:

Code: Select all

FI = spawn(Class'FontInfo');
// or
FI = FontInfo(spawn(Class<Actor>(DynamicLoadObject(class'ChallengeHUD'.default.FontInfoClass, class'Class'))));
and then:

Code: Select all

Canvas.Font = FI.GetMediumFont(Canvas.ClipX);
and you get the same thing, but memoized for free already in the FontInfo actor instance itself. :)

By the way, in this example it is assumed that you spawn the FontInfo only once, and keep the FI as a var.
In a way, this is similar to your proposed solution, except that here rather than saving the font itself, you save the actor which actually provides the fonts, and this way you have no issues whatsoever for 100% of the use-cases, and you also get all the caching/performance benefits you want.
dot
Average
Posts: 59
Joined: Tue Oct 30, 2018 3:41 am

Re: Drawn text on hud

Post by dot »

Solution with two variables is more easy, clear and light.
Because new Actor need more memory and use more resources. And for it called tick method and so on.
But if you need not one Font this can be not good solution rather reinvented wheel and make same code in your class.
But for one Font it can be overhead.
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Drawn text on hud

Post by Feralidragon »

You're worried about spawning a single actor, which is spawned only once and lasts the entire game lifetime, when the standard game itself spawns hundreds of actors constantly, some of which actually run code every single tick.
That's like worrying about a big lake flooding a village only because you dropped a single drop of water on it, it doesn't make any sense.

I understand that you want your code to be efficient, everyone wants the same, but you're putting optimization ahead of design, and that approach has been proven over and over again to cause much bigger problems either immediately or later on in the code, in the form of code that no one will want to use because it will break all sorts of stuff or have all sorts of weird hardcoded behaviors.

The moment you're just replicating code around just to avoid to spawn an actor, that's a dead end as far as maintainable code goes, and shifts your own focus from what you should actually paying attention to in the first place, which is how all the pieces actually fit together overall.
Post Reply