Drawn text on hud
-
- Adept
- Posts: 338
- Joined: Sat Apr 17, 2010 4:51 pm
- Personal rank: lol?
Drawn text on hud
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??
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??
-
- Godlike
- Posts: 5499
- Joined: Wed Feb 27, 2008 6:24 pm
- Personal rank: Work In Progress
- Location: Liandri
Re: Drawn text on hud
Before the text drawing, add this:
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:
That resets all the canvas values to their defaults, and is used for these same reasons.
Code: Select all
Canvas.Font = Canvas.default.Font;
Also, before doing anything on Canvas, is a good practise to make perhaps this instead:
Code: Select all
Canvas.Reset();
-
- Adept
- Posts: 338
- Joined: Sat Apr 17, 2010 4:51 pm
- Personal rank: lol?
-
- Average
- Posts: 59
- Joined: Tue Oct 30, 2018 3:41 am
Re: Drawn text on hud
It is crash my UT. Because Canvas.Default.Font is None.Feralidragon wrote:Before the text drawing, add this:Code: Select all
Canvas.Font = Canvas.default.Font;
Same issue. Maybe by same reason. Also it can result not render text at all if Style not set properly.Feralidragon wrote: Also, before doing anything on Canvas, is a good practise to make perhaps this instead:That resets all the canvas values to their defaults, and is used for these same reasons.Code: Select all
Canvas.Reset();
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;
Code: Select all
if (FirstFont == None) FirstFont = Canvas.Font;
if (FirstFont != Canvas.Font) Canvas.Font = FirstFont;
-
- Godlike
- Posts: 5499
- Joined: Wed Feb 27, 2008 6:24 pm
- Personal rank: Work In Progress
- Location: Liandri
Re: Drawn text on hud
Yeah, the default font is non-existent, I didn't realize that 7 years ago.
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:
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.
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>;
-
- Average
- Posts: 59
- Joined: Tue Oct 30, 2018 3:41 am
Re: Drawn text on hud
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:
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
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 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
-
- Godlike
- Posts: 5499
- Joined: Wed Feb 27, 2008 6:24 pm
- Personal rank: Work In Progress
- Location: Liandri
Re: Drawn text on hud
Sure, but you can put anything in:
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).
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.
Code: Select all
Canvas.Font = <the font that you want>;
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).
I didn't mean anything big with it, it was mostly to make sure that you actually saw the date of this topic.dot wrote:About 7 years - I need place this code somewhere. I can create new topic if you want.
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.
-
- Average
- Posts: 59
- Joined: Tue Oct 30, 2018 3:41 am
Re: Drawn text on hud
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:
or
Also you can use any FontInfo from system objects, because it can be override here.
For example ServerInfo.MyFonts, TournamentScoreBoard.MyFonts, ChallengeHUD.MyFonts.
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);
Code: Select all
FirstFont = class'FontInfo'.Static.GetStaticSmallFont(Canvas.ClipX);
For example ServerInfo.MyFonts, TournamentScoreBoard.MyFonts, ChallengeHUD.MyFonts.
You do not have the required permissions to view the files attached to this post.
-
- Godlike
- Posts: 5499
- Joined: Wed Feb 27, 2008 6:24 pm
- Personal rank: Work In Progress
- Location: Liandri
Re: Drawn text on hud
Picking up your example, I could just do this:
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.
Code: Select all
Canvas.Font = class'FontInfo'.Static.GetStaticMediumFont(Canvas.ClipX);
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.
-
- Average
- Posts: 59
- Joined: Tue Oct 30, 2018 3:41 am
Re: Drawn text on hud
What kind of issues?
Read from cache faster usually. This code can be called on every frame so do not good make it heavy.
Read from cache faster usually. This code can be called on every frame so do not good make it heavy.
-
- Godlike
- Posts: 5499
- Joined: Wed Feb 27, 2008 6:24 pm
- Personal rank: Work In Progress
- Location: Liandri
Re: Drawn text on hud
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".
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".
-
- Average
- Posts: 59
- Joined: Tue Oct 30, 2018 3:41 am
Re: Drawn text on hud
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:
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;
-
- Godlike
- Posts: 5499
- Joined: Wed Feb 27, 2008 6:24 pm
- Personal rank: Work In Progress
- Location: Liandri
Re: Drawn text on hud
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:
and then:
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.
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'))));
Code: Select all
Canvas.Font = FI.GetMediumFont(Canvas.ClipX);
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.
-
- Average
- Posts: 59
- Joined: Tue Oct 30, 2018 3:41 am
Re: Drawn text on hud
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.
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.
-
- Godlike
- Posts: 5499
- Joined: Wed Feb 27, 2008 6:24 pm
- Personal rank: Work In Progress
- Location: Liandri
Re: Drawn text on hud
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.
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.