MODULE: Fancy 0.7.5

Started by eri0o, Mon 15/04/2024 19:53:49

Previous topic - Next topic

Akril15

#20
Hmm...that definitely changed things. Unfortunately, the text still isn't quite centered and gets cut off by the right edge of the GUI. There's still a big gap between the bottom of the text and the bottom of the GUI as well.

EDIT: Crimson Wizard was able to walk me through the various minutiae that resulted in the effect I was looking for. I've included the end result below, In case anyone finds it useful:
Code: ags
void SpeakFancy(this Character*, String message) {
  Label3.Text=this.Name;
  gSpeechLabel.Visible=true;
  labeltext.Height = GetTextHeight(message, labeltext.Font, labeltext.Width);
  gLabel.Width = labeltext.Width + (3*trans_textmargin);
  gLabel.Height = labeltext.Height + (4*trans_textmargin);
  labeltext.Text = message;
  speech_label.Y=gLabel.Y; //speech_label is an invisible label on gLabel,  but it helps with vertical alignment
  gLabel.X = (System.ViewportWidth-gLabel.Width)/2;
  gLabel.Y = (System.ViewportHeight-gLabel.Height)-trans_guibottommargin;
  gLabel.Visible = true;  
  gSpeechLabel.Y=gLabel.Y;
  this.Say(message);
  DynamicSprite *dspr = DynamicSprite.Create(gLabel.Width, gLabel.Height);
  DrawingSurface *ds = dspr.GetDrawingSurface();
  surf.DrawFancyString(0, 0, message);
  ds.Release();
  Overlay *text_over = Overlay.CreateGraphical(gLabel.X, gLabel.Y,  dspr.Graphic);
  text_over.ZOrder = gLabel.ZOrder + 1; // position overlay right above speech gui
  gLabel.Visible = false;
  gSpeechLabel.Visible=false;
  }
 

eri0o

I think that's fine since the width is adjusted before when it calculates the word wrapping.

@Akril15 , from your code I don't understand what you are trying to do, afaict if you don't maintain a global dynamic sprite and overlay I can't understand how they would show on screen.

Crimson Wizard

#22
We figured this out on Discord, using DynamicSprite.CreateFromFancyString instead, which allows to know the width and height occupied by the text, which in turn lets to align the resulting text on the background as the user wants.
(somehow this reminds me SDL_ttf which creates a bitmap with the text)

Quote from: eri0o on Today at 02:55:29I think that's fine since the width is adjusted before when it calculates the word wrapping.

If you are referring to the horizontal alignment, then it does not center it in the provided "max width", but (apparently) longest line's width? This makes the whole text aligned to some seemingly random horizontal point, which is not what a user would expect.

Quote from: eri0o on Today at 02:55:29@Akril15 , from your code I don't understand what you are trying to do, afaict if you don't maintain a global dynamic sprite and overlay I can't understand how they would show on screen.

There's a character.Say call right after that, which blocks the game and keeps created overlay displayed.

The code overall does following:
- displays a background GUI with some extra elements, such as character's name.
- creates a dynamic sprite with a Fancy text on it, makes a overlay and aligns over the background GUI.
- calls character.Say, so that the default lip-sync (and maybe voice) could work, and game blocks until speech is done.

eri0o

Uhm, I think then it could be if MaxTextWidth is infinite then it uses TextWidth, otherwise it uses MaxTextWidth.

Snarky

Quote from: Crimson Wizard on Today at 03:48:11If you are referring to the horizontal alignment, then it does not center it in the provided "max width", but (apparently) longest line's width? This makes the whole text aligned to some seemingly random horizontal point, which is not what a user would expect.

That sounds correct to me. Consider the case of a textbox that is resized to fit the text content: you don't want to center the text around the halfway point of the "max width," but around the halfway point of the actual longest line width.

Crimson Wizard

#25
Quote from: Snarky on Today at 16:59:59That sounds correct to me. Consider the case of a textbox that is resized to fit the text content: you don't want to center the text around the halfway point of the "max width," but around the halfway point of the actual longest line width.

There are 2 different cases:

Case 1. When the text is being drawn on a prepared surface of the fixed-sized text box. This is the case of DrawingSurface.DrawFancyString which we tried first, and that's what I reported above. In such case I expect it to center relative to the "max width" that I pass; because otherwise it does not make any sense. I do not have a way to know the width of the longest line beforehand, so that I could adjust the x position.

Compare it with DrawingSurface.DrawStringWrapped, which wraps in the "max width":
https://adventuregamestudio.github.io/ags-manual/DrawingSurface.html#drawingsurfacedrawstringwrapped

Quotewidth is the width of the virtual textbox enclosing the text, and is the point that the text will wrap at. You can use the alignment parameter to determine how the text is horizontally aligned.

Case 2. When the text is placed on a exclusive sprite, resized to fit just the text, which one may align with the text box as sees fit. This is the case of DynamicSprite.CreateFromFancyString, which we used in the end.

SMF spam blocked by CleanTalk