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 Yesterday 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 Yesterday 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 Yesterday 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 Yesterday 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.

eri0o

I will need to find some time to play with this but I think my blunt of clause should work.

Crimson Wizard

#27
There are definitely 2 opposite use cases of drawing a text:
1. When you draw a text on a prepared space, where the text must fit in that space.
2. When you draw a text (maybe limiting by some width), but then adjust the "space" to the text.

DrawingSurface API suits for the first purpose, and I could not figure out if it's possible to use for the second, unless it's an internal call where you already precalculated text size. But when I think more about this, there's another issue with DrawFancyString, as well as AGS own DrawStringWrapped: there's no way to limit by height.

And DrawingSurface does not expose "Clipping" feature either, which seems like an oversight.

Which means that if one needs to limit an output text by height, then they either have to get a precalculated text size first (Fancy module seem to have a FancyState for this, but it does not expose this atm, unless I missed anything), or draw on a intermediate sprite first, and then manipulate that sprite (crop or whatnot).

SMF spam blocked by CleanTalk