Author Topic: MODULE: SpeechBubble v0.8.0  (Read 14094 times)

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: MODULE: SpeechBubble v0.8.0
« Reply #80 on: 24 Mar 2020, 14:29 »
Yup, merged.

What I want to happen:
1. Buddhist speaks, speech bubble appears
2. The sound sample 1 is over; delete this speech bubble, and create the second one; start the second bit of speech
3. When that's over, delete speechbubble, speech sample 2 has obviously stopped because it's non-blocking
4. Fade out screen

I'm not quite sure I understand this description. What do you mean that "speech sample 2 has obviously stopped because it's non-blocking"? Is the behavior you're after different in any way from normal speech behavior? (Show speech text and play speech clip, then show next speech text and next speech clip.)

but what is blocking/non-blocking?
Should I just write 'Wait(the length of time for the 2 speech samples)', and included it at the beginning/end of the block of code?

No, definitely not. But again, what do you mean "what is blocking/non-blocking"?

The speech bubbles are obviously ending early because they estimate a shorter amount of time to read the bubble than the speech sample has to end;

Well, if you're providing a voice clip it should be using the length of the clip automatically. In fact, it's not calculating anything, just displaying the speech bubble, then calling the AGS Character.Say() function with the speech clip ID as the line and waiting until it's finished.

I think I recall from testing your game before that these lines are extremely long, though. Like, around a minute or so? And you're using the LipSync module as well, right? I seem to remember that there is some limitation somewhere that they overflow (either somewhere in the modules or in AGS). I would first try cutting them down to a more reasonable length and see if that solves things.

Another thing you could test is to replace these SayBubble() calls with Say(). If you still have the problem then it's not an issue with the module.

bx83

  • Get 'Er Doooooone
Re: MODULE: SpeechBubble v0.8.0
« Reply #81 on: 25 Mar 2020, 00:53 »
Solved: made sound files shorter.

bx83

  • Get 'Er Doooooone
Re: MODULE: SpeechBubble v0.8.0
« Reply #82 on: 06 Apr 2020, 11:11 »
I am having a compile error on this line:

Code: [Select]
void SB_sayImpl(this Character*, String message)
{
//BLR ADDED
  this.SaySync(message);
}

I'm getting the error:
Code: [Select]
SpeechBubble_0.8.0.asc(19): Error (line 19): '.SaySync' is not a public member of 'Character'. Are you sure you spelt it correctly (remember, capital letters are important)?
...but it is. SaySync is most definitely a member of characters.

However I think I've made a typo around this code, but I can't find it.
It's just shot this error now, after months of not updating it.

here's the scripts:
https://redrom.ltd/filez/speechbubble.zip
« Last Edit: 06 Apr 2020, 11:25 by bx83 »

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: MODULE: SpeechBubble v0.8.0
« Reply #83 on: 06 Apr 2020, 11:24 »
Have you reordered the modules so that TotalLipSync is no longer above SpeechBubble? That's the only explanation I can think of.

bx83

  • Get 'Er Doooooone
Re: MODULE: SpeechBubble v0.8.0
« Reply #84 on: 06 Apr 2020, 11:59 »
SOLVED!

I didn't even know the order in the right-column for Scripts had a meaning - you learn something every day :D

bx83

  • Get 'Er Doooooone
Re: MODULE: SpeechBubble v0.8.0
« Reply #85 on: 21 Apr 2020, 12:12 »
I'm using SayAtBubble to position the bubble as I want. I've put two defines into the global.ash to  set x and y coordinates:

in global.ash:
Code: [Select]
#define hare_x 590
#define hare_y 12

in a conversation with the Hare character:
Code: [Select]
@6
  cJulius.SayAtBubble(hare_x,hare_y,"&615 How did you get invited to this animal party village green thing?");
  cHare.SayBubble("&16 How'd *you* get invited? You an animal?");
...

...BUT the X coordinate does nothing. It always positions the bubble in the centre of Julius head:



Here's the function code:

Code: [Select]
void realSayAtBubble(this Character*, int x, int y, String message, GUI* bubbleGui, DynamicSprite* bubbleSprite)
{
  // Render and display the speech bubble
  if(bubbleSprite == null)
    bubbleSprite = this.renderBubble32(message, true);
  Overlay* bubbleOverlay;
  if(bubbleGui == null && _defaultGui == null)
    bubbleOverlay = Overlay.CreateGraphical(x, y, bubbleSprite.Graphic, true);
  else
  {
    if(bubbleGui == null)
      bubbleGui = _defaultGui;
     
    bubbleGui.Clickable = false;
    bubbleGui.X = _clampInt(x, 0, System.ViewportWidth - bubbleSprite.Width);
    bubbleGui.Y = _clampInt(y, 0, System.ViewportHeight - bubbleSprite.Height);
    bubbleGui.Width = bubbleSprite.Width;
    bubbleGui.Height = bubbleSprite.Height;
    bubbleGui.BackgroundGraphic = bubbleSprite.Graphic;
    bubbleGui.Transparency = 0;
    bubbleGui.Visible = true;
  }
  SpeechBubble* bubble = SpeechBubble.Create(this, message, bubbleSprite, bubbleGui, bubbleOverlay);
 
  bubble.setX(x);
  bubble.setY(y);
  bubble.setBackgroundSpeech(false);
  bubble.setThinking(false);
  _addBubbleChar(this);
 
  // Play speech (this chunk blocks until speech is complete)

  String lineNumber = getLineNumber(message);
  // If we have set an invisible font, just call Say() - or whatever custom Say() implementation we have
  if(SpeechBubble.get_InvisibleFont() != -1)
  {
    FontType speechFont = Game.SpeechFont;
    Game.SpeechFont = _invisibleFont;
    this.SB_sayImpl(message);
    Game.SpeechFont = speechFont;
  }
  // Else if we're going to play a voice clip, call Say() with the clip number and a blank line of text
  // (takes care of animation and doesn't display any text). This doesn't work with text-based lip-sync,
  // so if you're using text-based lip-sync, you MUST set an invisible font to get lip-sync to work
  else if(lineNumber != null && Speech.VoiceMode != eSpeechTextOnly) // && !GetGameOption(OPT_LIPSYNCTEXT))
  {
    String s = lineNumber;
    while(s.Length < message.Length)
      s = s.AppendChar(' ');
    this.SB_sayImpl(s);
  }
  // Otherwise we have to do it manually...
  else
  {
    bubble.setAnimating(true);
    this.animateSpeech(message);
  }
 
 
  // Remove the bubble
  bubble.Remove();
}

...

void SayAtBubble(this Character*, int x, int y, String message, GUI* bubbleGui)
{
  if(message == null) return;
  if(!game.bgspeech_stay_on_display)
    _stopAllBackgroundBubbles();
  if((Speech.VoiceMode == eSpeechVoiceOnly && hasVoiceClip(message)) || message == "...") {
    this.SB_sayImpl(message);
  } else {
    DynamicSprite* bubbleSprite = this.renderBubble32(message, true);
    x = this.x - GetViewportX() - bubbleSprite.Width/2;
    x = _clampInt(x, 0, System.ViewportWidth - bubbleSprite.Width);
   
    this.realSayAtBubble(x, y, message, bubbleGui, null);
  }
}

...


// 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;
 
  SpeechBubbleHeight_blr=totalHeight;//BLR
 
  // 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;
  if(_backgroundTransparency == 0)
  {
    bgSprite = bubbleSprite;
    bgSurface = bubbleSurface;
  }
  else
  {
    bgSprite = DynamicSprite.Create(totalWidth, totalHeight, true);
    bgSurface = bgSprite.GetDrawingSurface();
  }
  if(_borderTransparency == 0)
  {
    borderSprite = bubbleSprite;
    borderSurface = bubbleSurface;
  }
  else
  {
    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;
  bgSurface.DrawRectangle(1, 1, totalWidth-2, bubbleHeight-1);
  drawRoundedCorners32(bgSurface, borderSurface, borderColor, 0, bubbleHeight);
  String tail[]; int tailWidth; int tailHeight;
  if(talkTail)
  {
    tail = _talkTail; tailWidth = _talkTailWidth; tailHeight = _talkTailHeight;
  }
  else
  {
    tail = _thinkTail; tailWidth = _thinkTailWidth; tailHeight = _thinkTailHeight;
  }
  bgSurface.DrawingColor = bgColor;
  bgSurface.drawPixelArray(tail, totalWidth/2-tailWidth, bubbleHeight, tailWidth, tailHeight, 'O', false, false);
  borderSurface.DrawingColor = borderColor;
  borderSurface.drawPixelArray(tail, totalWidth/2-tailWidth, bubbleHeight, tailWidth, tailHeight, 'X', false, false);
  borderSurface.DrawLine(_cornerRoundingRadius, 0, totalWidth - _cornerRoundingRadius, 0);
  // Left Line
  borderSurface.DrawLine(0, _cornerRoundingRadius, 0, bubbleHeight - _cornerRoundingRadius);
  // Right Line
  borderSurface.DrawLine(totalWidth-1, _cornerRoundingRadius, totalWidth-1, bubbleHeight - _cornerRoundingRadius);
  // Bottom Lines
  borderSurface.DrawLine(_cornerRoundingRadius, bubbleHeight, totalWidth/2 - tailWidth, bubbleHeight);
  borderSurface.DrawLine(totalWidth/2, bubbleHeight, totalWidth - _cornerRoundingRadius, bubbleHeight);
 
  if(_backgroundTransparency != 0)
  {
    bgSurface.Release();
    bubbleSurface.DrawImage(0, 0, bgSprite.Graphic, _backgroundTransparency);
    bgSprite.Delete();
  }
  if(_borderTransparency != 0)
  {
    borderSurface.Release();
    bubbleSurface.DrawImage(0, 0, borderSprite.Graphic, _borderTransparency);
    borderSprite.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;
}

I can include more functions; I've altered like 10 lines of code in this module, but the above *looks* okay...???

bx83

  • Get 'Er Doooooone
Re: MODULE: SpeechBubble v0.8.0
« Reply #86 on: 21 Apr 2020, 12:34 »

Snarky

  • Global Moderator
  • Global Moderator
  • Mittens Lord
  • Private Insultant
    • Best Innovation Award Winner 2018, for his numerous additions to the AGS open source ecosystem including the new Awards Ceremony client and modules
    • Snarky worked on one or more games that won an AGS Award!
    •  
    • Snarky worked on one or more games that was nominated for an AGS Award!
Re: MODULE: SpeechBubble v0.8.0
« Reply #87 on: 21 Apr 2020, 13:08 »
It's because of one of the lines you've added to SayAtBubble():

Code: Adventure Game Studio
  1.     x = this.x - GetViewportX() - bubbleSprite.Width/2;

Why have you changed the module code?

bx83

  • Get 'Er Doooooone
Re: MODULE: SpeechBubble v0.8.0
« Reply #88 on: 22 Apr 2020, 02:24 »
I don't know... :/
I'll test it.

bx83

  • Get 'Er Doooooone
Re: MODULE: SpeechBubble v0.8.0
« Reply #89 on: 22 Apr 2020, 03:26 »
Solved.