I'm replacing the Say function using overlays from DrawStringWrapped. I'm able to pretty accurately mimic the way the built-in Say option wraps and positions dialog, but I'm having trouble getting the dialog to align to the edge of the screen if the character is standing there.
(http://i.imgur.com/GIdcmSY.png)
For example, the text displayed by DrawStringWrapped is set to wrap to 160px wide. This results in text that's actually 130 pixels wide, but I can't figure out how to get that number in script, so it's aligned based on the 160px value, which results in awkward placement.
Here's how .Say normally displays it:
(http://i.imgur.com/gVT2Tc6.png)
(ignore the disembodied head)
Is there some way to do this?
Two ways I can think of:
Write a function that progressively measures the width of each line using GetTextWidth and mimics AGS' own text wrapping. Return the maximum value found for the width of a line.
Given that you know the line height (and the height of the text via GetTextHeight), write a function that scans blank pixels on the right of the surface until it finds a non-blank (not COLOR_TRANSPARENT) pixel. You could scan just the baseline of each line to find a black pixel, so in your example, that's two tests per column.
I don't think there's a built-in way. Older threads on similar subjects suggest the use of a StrCutByWidth function, similar to the first method I outlined.
Yeah, I just ended up writing a function doing exactly that.
function GetTextWidthX(String message, FontType whatfont, int wrapwidth) {
String line = "";
String remaining = message;
int maxwidth = 0;
int ind = remaining.IndexOf(" ");
if (GetTextWidth(message, whatfont) <= wrapwidth) return GetTextWidth(message, whatfont);
if (ind==-1) return GetTextWidth(message, whatfont);
while (ind!=-1) {
String newremaining = remaining.Truncate(ind+1);
line = line.Append(newremaining);
remaining = remaining.Substring(ind+1, remaining.Length);
int linewidth = GetTextWidth(line, whatfont);
if (linewidth >= wrapwidth) line = "";
else if (linewidth > maxwidth) maxwidth = linewidth;
ind = remaining.IndexOf(" ");
}
return maxwidth;
}
Seems to work well enough.