I believe this is brought on forums every now and then, this is the earliest thread I found that gives a working solution, so I'd mention this for a reference here:
http://www.adventuregamestudio.co.uk/forums/index.php?topic=35731.0So, what is this all about. Imagine you want to create an Overlay having very particular width, precisely to let your text fit in. What do you do?
Basic example:
function MakeOverlay(String s, int x, int y, FontType font, int color, int wait)
{
int width = GetTextWidth(s, font);
Overlay *o = Overlay.CreateTextual(x, y, width, font, color, s);
Wait(wait);
}
That looks correct, right? Well, it should be. However, when you run the game, you find out that your text is split into more lines than you expected. Try calling this example with a short line, like "Welcome!". You may end up having "Welco" on one line and "me!" on another (depends on font).
Why the heck does it happen?
This is because when you call GetTextWidth - a correct width of text is calculated, however when AGS splits line for drawing (on overlay, on label, Display function, Say function, DrawStringWrapped function, etc), it does
additional and
undocumented changes to the width parameter:
1) First of all, it decreases width by (2 *
padding) pixels, where
padding is a specific value which depends on the type of GUI used for display (like TextWindow).
If no GUI is used for Display function (by default), then
padding = 3.
Some functions do not do this, like DrawStringWrapped, because it is drawn raw on a DrawingSurface. But even then, there is another thing:
2) When calculating how many characters fit into single line, AGS does a small mistake in condition:
// otherwise, see if we are too wide
else if (wgettextwidth_compensate(theline, fonnt) >= wii) {
Notice '>=' sign. It means that even if the text fits into the width
precisely, it will still will be split at that point, resulting in at least 2 lines where 1 would be enough.
In other words, to work around this issue, you script should look like:
function MakeOverlay(String s, int x, int y, FontType font, int color, int wait)
{
int width = GetTextWidth(s, font);
width = width + 2*3 + 1; // 2*3 is double default padding, and 1 pixel is to counter wrong condition
Overlay *o = Overlay.CreateTextual(x, y, width, font, color, s);
Wait(wait);
}
I think something must be done here. I am not yet sure what. There is no problem in modifying calculations, because we know how to detect old games and process them differently to keep backwards compatibility. Fixing the condition in line-split function is easy, but I am not sure how to deal with the padding.
EDITWhat I mean about padding. We certainly cannot remove it out of equation, because then the text will be drawn over TextWindow borders, and such. But then there should be two things:
1) Firstly, it should be clearly documented that overlay's and display window's "width" - that is not just text width, but text width + padding.
2) Secondly, user must have means to get that padding somehow, to use it when arranging stuff on screen.
PSWhile I am at this, there is another known issue that you should use "width + 1" in the call to GetTextHeight. Probably because of same line splitting mistake.