Yeah, that's not possible in the module as of now. I suppose I could extend it to support it, but it's not a high priority.
For now, it's easier to hack the render function to do what you want. Try replacing the
drawRoundedCorners32() and
renderBubble32() functions in the module with these versions:
Spoiler
// Round off the corners of the bubble by erasing to transparent
void drawRoundedCorners32(DrawingSurface* background, int left, int top, int right, int bottom)
{
// Uses Bresenham's circle formula, found online
int r = _cornerRoundingRadius;
int x = 0;
int y = r;
int p = 3 - 2 * r;
int dc = background.DrawingColor;
background.DrawingColor = COLOR_TRANSPARENT;
while (y >= x) // only formulate 1/8 of circle
{
// Erase background corners
// Top Left
background.DrawLine(left + r - x, top+r - y, left + r - x, top);
background.DrawLine(left + r - y, top+r - x, left + r - y, top);
// Top Right
background.DrawLine(right - r + y, top+r - x, right - r + y, top);
background.DrawLine(right - r + x, top+r - y, right - r + x, top);
// Bottom Left
background.DrawLine(left + r - x, bottom-r + y, left + r - x, bottom);
background.DrawLine(left + r - y, bottom-r + x, left + r - y, bottom);
// Bottom Right
background.DrawLine(right - r + y, bottom-r + x, right - r + y, bottom);
background.DrawLine(right - r + x, bottom-r + y, right - r + x, bottom);
if (p < 0)
{
p += 4*x + 6;
x++;
}
else
{
p += 4*(x - y) + 10;
x++;
y--;
}
}
background.DrawingColor = dc;
}
// Draw a speech bubble in 32-bit (using transparency)
DynamicSprite* renderBubble32(this Character*, String message, bool talkTail)
{
// Calculate text dimensions
int textWidth = _maxTextWidth;
if(textWidth <= 0)
textWidth = calculateDefaultTextWidth(this);
textWidth = _minInt(textWidth, System.ViewportWidth - _paddingLeft - _paddingRight);
int textHeight = GetTextHeight(message, Game.SpeechFont, textWidth);
textWidth = calculateExactTextWidth(message, Game.SpeechFont, textWidth, textHeight);
// Calculate bubble dimensions
int totalWidth = textWidth + _paddingLeft + _paddingRight;
int bubbleHeight = textHeight + _paddingTop + _paddingBottom;
int totalHeight;
if(talkTail)
totalHeight = bubbleHeight + _talkTailHeight;
else
totalHeight = bubbleHeight + _thinkTailHeight;
// Set up the canvases
DynamicSprite* bubbleSprite = DynamicSprite.Create(totalWidth, totalHeight, true);
DrawingSurface* bubbleSurface = bubbleSprite.GetDrawingSurface();
//bubbleSurface.Clear();
DynamicSprite* bgSprite; DrawingSurface* bgSurface;
DynamicSprite* borderSprite; DrawingSurface* borderSurface;
bgSprite = DynamicSprite.Create(totalWidth, totalHeight, true);
bgSurface = bgSprite.GetDrawingSurface();
borderSprite = DynamicSprite.Create(totalWidth, totalHeight, true);
borderSurface = borderSprite.GetDrawingSurface();
int bgColor = mixColors(this.SpeechColor, _backgroundColor, _backgroundSpeechTint);
int borderColor = mixColors(this.SpeechColor, _borderColor, _borderSpeechTint);
// Draw!
bgSurface.DrawingColor = bgColor;
borderSurface.DrawingColor = borderColor;
bgSurface.DrawRectangle(0, 0, totalWidth-2, bubbleHeight-2);
borderSurface.DrawRectangle(1, 1, totalWidth-1, bubbleHeight-1);
drawRoundedCorners32(bgSurface, 0, 0, totalWidth-1, bubbleHeight);
drawRoundedCorners32(borderSurface, 1, 1, totalWidth, bubbleHeight+1);
String tail[]; int tailWidth; int tailHeight;
if(talkTail)
{
tail = _talkTail; tailWidth = _talkTailWidth; tailHeight = _talkTailHeight;
}
else
{
tail = _thinkTail; tailWidth = _thinkTailWidth; tailHeight = _thinkTailHeight;
}
bgSurface.drawPixelArray(tail, totalWidth/2-tailWidth, bubbleHeight-1, tailWidth, tailHeight, 'O', false, false);
borderSurface.drawPixelArray(tail, totalWidth/2-tailWidth+1, bubbleHeight, tailWidth, tailHeight, 'O', false, false);
borderSurface.Release();
bubbleSurface.DrawImage(0, 0, borderSprite.Graphic, _borderTransparency);
borderSprite.Delete();
bgSurface.Release();
bubbleSurface.DrawImage(0, 0, bgSprite.Graphic, _backgroundTransparency);
bgSprite.Delete();
bubbleSurface.DrawingColor = this.SpeechColor;
int outlineColor = mixColors(this.SpeechColor, _textOutlineColor, _textOutlineSpeechTint);
if(_textOutlineWidth > 0)
bubbleSurface.drawStringWrappedOutline(_paddingLeft, _paddingTop, textWidth, _textOutlineStyle, Game.SpeechFont, _textAlign, message, _textTransparency, outlineColor, _textOutlineWidth);
else
bubbleSurface.drawStringWrappedAA(_paddingLeft, _paddingTop, textWidth, Game.SpeechFont, _textAlign, message, _textTransparency);
bubbleSurface.Release();
return bubbleSprite;
}
(This won't work correctly if you set the speech bubble background to be semi-transparent. You can make the border/shadow transparent, though.)
That's good, but 'closer'? Doesn't it give exactly the result in your example?
No, the mistake was mine. (I
was a little drunk when I wrote it.) Try this for the two functions:
Spoiler
// Round off the corners of the bubble by erasing to transparent
void drawRoundedCorners32(DrawingSurface* background, int left, int top, int right, int bottom)
{
// Uses Bresenham's circle formula, found online
int r = _cornerRoundingRadius - 1;
int x = 0;
int y = r;
int p = 3 - 2 * r;
int dc = background.DrawingColor;
background.DrawingColor = COLOR_TRANSPARENT;
while (y >= x) // only formulate 1/8 of circle
{
// Erase background corners
// Top Left
background.DrawLine(left + r - x, top+r - y, left + r - x, top);
background.DrawLine(left + r - y, top+r - x, left + r - y, top);
// Top Right
background.DrawLine(right - r + y, top+r - x, right - r + y, top);
background.DrawLine(right - r + x, top+r - y, right - r + x, top);
// Bottom Left
background.DrawLine(left + r - x, bottom-r + y, left + r - x, bottom);
background.DrawLine(left + r - y, bottom-r + x, left + r - y, bottom);
// Bottom Right
background.DrawLine(right - r + y, bottom-r + x, right - r + y, bottom);
background.DrawLine(right - r + x, bottom-r + y, right - r + x, bottom);
if (p < 0)
{
p += 4*x + 6;
x++;
}
else
{
p += 4*(x - y) + 10;
x++;
y--;
}
}
background.DrawingColor = dc;
}
// Draw a speech bubble in 32-bit (using transparency)
DynamicSprite* renderBubble32(this Character*, String message, bool talkTail)
{
// Calculate text dimensions
int textWidth = _maxTextWidth;
if(textWidth <= 0)
textWidth = calculateDefaultTextWidth(this);
textWidth = _minInt(textWidth, System.ViewportWidth - _paddingLeft - _paddingRight);
int textHeight = GetTextHeight(message, Game.SpeechFont, textWidth);
textWidth = calculateExactTextWidth(message, Game.SpeechFont, textWidth, textHeight);
// Calculate bubble dimensions
int totalWidth = textWidth + _paddingLeft + _paddingRight;
int bubbleHeight = textHeight + _paddingTop + _paddingBottom;
int totalHeight;
if(talkTail)
totalHeight = bubbleHeight + _talkTailHeight;
else
totalHeight = bubbleHeight + _thinkTailHeight;
// Set up the canvases
DynamicSprite* bubbleSprite = DynamicSprite.Create(totalWidth, totalHeight, true);
DrawingSurface* bubbleSurface = bubbleSprite.GetDrawingSurface();
//bubbleSurface.Clear();
DynamicSprite* bgSprite; DrawingSurface* bgSurface;
DynamicSprite* borderSprite; DrawingSurface* borderSurface;
bgSprite = DynamicSprite.Create(totalWidth, totalHeight, true);
bgSurface = bgSprite.GetDrawingSurface();
borderSprite = DynamicSprite.Create(totalWidth, totalHeight, true);
borderSurface = borderSprite.GetDrawingSurface();
int bgColor = mixColors(this.SpeechColor, _backgroundColor, _backgroundSpeechTint);
int borderColor = mixColors(this.SpeechColor, _borderColor, _borderSpeechTint);
// Draw!
bgSurface.DrawingColor = bgColor;
borderSurface.DrawingColor = borderColor;
bgSurface.DrawRectangle(0, 0, totalWidth-2, bubbleHeight-2);
borderSurface.DrawRectangle(1, 1, totalWidth-1, bubbleHeight-1);
if(_cornerRoundingRadius > 0)
{
drawRoundedCorners32(bgSurface, 0, 0, totalWidth-2, bubbleHeight-2);
drawRoundedCorners32(borderSurface, 1, 1, totalWidth-1, bubbleHeight-1);
}
String tail[]; int tailWidth; int tailHeight;
if(talkTail)
{
tail = _talkTail; tailWidth = _talkTailWidth; tailHeight = _talkTailHeight;
}
else
{
tail = _thinkTail; tailWidth = _thinkTailWidth; tailHeight = _thinkTailHeight;
}
bgSurface.drawPixelArray(tail, totalWidth/2-tailWidth, bubbleHeight-1, tailWidth, tailHeight, 'O', false, false);
borderSurface.drawPixelArray(tail, totalWidth/2-tailWidth+1, bubbleHeight, tailWidth, tailHeight, 'O', false, false);
borderSurface.Release();
bubbleSurface.DrawImage(0, 0, borderSprite.Graphic, _borderTransparency);
borderSprite.Delete();
bgSurface.Release();
bubbleSurface.DrawImage(0, 0, bgSprite.Graphic, _backgroundTransparency);
bgSprite.Delete();
bubbleSurface.DrawingColor = this.SpeechColor;
int outlineColor = mixColors(this.SpeechColor, _textOutlineColor, _textOutlineSpeechTint);
if(_textOutlineWidth > 0)
bubbleSurface.drawStringWrappedOutline(_paddingLeft, _paddingTop, textWidth, _textOutlineStyle, Game.SpeechFont, _textAlign, message, _textTransparency, outlineColor, _textOutlineWidth);
else
bubbleSurface.drawStringWrappedAA(_paddingLeft, _paddingTop, textWidth, Game.SpeechFont, _textAlign, message, _textTransparency);
bubbleSurface.Release();
return bubbleSprite;
}
Note that I've also adjusted how the corner rounding parameter is used: you might want to increase it by 1 to get the same results as with the original version.
One thing: it looks like you're editing the
initSpeechBubble() function in order to configure the module. This is not how it's meant to be used: You're not supposed to edit the module code at all (except as otherwise instructed). Rather, as the header documentation explains, you're supposed to configure it from outside, e.g. in your game's GlobalScript. For your settings, that would be something like:
Spoiler
// in GlobalScript.asc
function game_start()
{
// Setup SpeechBubble module
SpeechBubble.CornerRoundingRadius = 3;
SpeechBubble.PaddingTop = 5;
SpeechBubble.PaddingBottom = 4;
SpeechBubble.PaddingLeft = 9;
SpeechBubble.PaddingRight =9;
// (You don't need the shadow any more, it's now drawn automatically)
String tail[] = new String[5];
tail[0] = " OOOO";
tail[1] = " OOO";
tail[2] = " OO";
tail[3] = " O";
tail[4] = null;
SpeechBubble.TalkTail = tail;
}
However, when I test, I see that that last line doesn't work â€" an AGS limitation I wasn't aware of. I will fix it so you can write:
SpeechBubble.SetTalkTail(tail);
In the mean time you can leave the setup as you have it.