Spritefont plugin not working properly in AGS 3.6

Started by Honza, Tue 28/02/2023 08:31:00

Previous topic - Next topic

Honza

I'm using Calin Leafshade's spritefont plugin and ever since switching to AGS 3.6, I've been having some issues with it (at least I *think* it started with AGS 3.6, but it could be a coincidence). What seems to be happening is that the game treats the font as if the first line had minimum height. When I disable the sprite font, the text appears normally. I've tried experimenting with various import sizes and combinations of the "TTF fonts adjustment defaults" and "TTF fonts height used in the game logic" settings, but none of it seems to affect the sprite font. The only settings that have an effect on it are line spacing and offset - so far I've managed to use those to work around the issue in text windows, but it doesn't help in lists, such as dialogue options or the savegame window below:




To make things more confusing, this list was messed up before similar to the savegame one, and now it seems to be working fine - and I have no idea what I did to achieve that  ???.



Will be thankful for any help, I would really like to keep using the plugin. I'm using AGS 3.6.0.39. Thank you!

Honza

Update: It seems the normal font has the same issue as the sprite font with "resize ascender to nominal height" switched off? So this setting fixes the issue with standard fonts but doesn't affect the spritefont plugin? Honestly, I have no idea how it works exactly and why "do nothing" changes the font's height to 4 - I've been fumbling through this by trial and error :-[.


Crimson Wizard

Quote from: Honza on Tue 28/02/2023 09:04:33Update: It seems the normal font has the same issue as the sprite font with "resize ascender to nominal height" switched off? So this setting fixes the issue with standard fonts but doesn't affect the spritefont plugin?

Of course, as it's called "TTF font adjustment" it only affects TTF fonts. Sprite fonts are not TTF fonts and should not be affected by this setting (if they are - that's a mistake).

Honza

Quote from: Crimson Wizard on Tue 28/02/2023 09:44:14Of course, as it's called "TTF font adjustment" it only affects TTF fonts. Sprite fonts are not TTF fonts and should not be affected by this setting (if they are - that's a mistake).

Sure, I wasn't trying to point out a mistake in the setting, just to clarify the issue. I suppose my question is why this setting is necessary in the first place and what can be done for the sprite font to work properly?

Crimson Wizard

#4
Quote from: Honza on Tue 28/02/2023 09:49:08I suppose my question is why this setting is necessary in the first place and what can be done for the sprite font to work properly?

This setting is for backwards compatibility; some TTF fonts require automatic adjustment in order to be displayed "correctly" in AGS. More information about this may be found in the manual: https://adventuregamestudio.github.io/ags-manual/UpgradeTo36.html#ttf-fonts-behavior

I don't know why exactly the sprite font is not working properly, but my guess is that something got broken in the engine. Because plugin's fonts replace original fonts, some settings may have remained from the original fonts, for example (this is only a guess), or maybe something does not initialize correctly. Judging by the screenshots, the font height is not calculated right. I would need to investigate this in a test game.

eri0o

@Honza which sprite font binary are you using? If you built, how was it built?

Honza

Quote from: Crimson Wizard on Tue 28/02/2023 09:53:20This setting is for backwards compatibility; some TTF fonts require automatic adjustment in order to be displayed "correctly" in AGS. More information about this may be found in the manual: https://adventuregamestudio.github.io/ags-manual/UpgradeTo36.html#ttf-fonts-behavior

I had read this part of the manual before I posted. What confused me was that the font I'm using isn't a "TTF font specifically created or adjusted for older versions of AGS" and it still required the setting to display correctly. For some reason, when I import this font at nominal size 19, the "do nothing" option assigns height 4 to it. I've now experimented with more fonts and they don't seem to have the same issue, but the problem with the sprite font persists.

Quote from: Crimson Wizard on Tue 28/02/2023 09:53:20Judging by the screenshots, the font height is not calculated right. I would need to investigate this in a test game.

Is this an offer? :) I can upload the game somewhere and share it if you'd be willing to look into it, but I don't want to waste too much of your time, so also feel totally free to ignore me.

Honza

Quote from: eri0o on Tue 28/02/2023 10:07:20@Honza which sprite font binary are you using? If you built, how was it built?

Apologies for my non-coder ignorance, but I don't know what you mean by sprite font binary :-[. I'm using this plugin, I simply follow the instructions given in the thread.

Crimson Wizard

Quote from: Honza on Tue 28/02/2023 10:39:42I had read this part of the manual before I posted. What confused me was that the font I'm using isn't a "TTF font specifically created or adjusted for older versions of AGS" and it still required the setting to display correctly.

Perhaps this is not worded well; apparently this applies to certain fonts but not the others. I do not know alot about the reasons. We're using a very old font rendering library, which may have its own mistakes, or miss support for certain font kinds.

Quote from: Honza on Tue 28/02/2023 10:39:42
Quote from: Crimson Wizard on Tue 28/02/2023 09:53:20Judging by the screenshots, the font height is not calculated right. I would need to investigate this in a test game.

Is this an offer? :) I can upload the game somewhere and share it if you'd be willing to look into it, but I don't want to waste too much of your time, so also feel totally free to ignore me.

I would like to get to the bottom of this, because if this is a error in the engine, or broken compatibility with this plugin, then I must fix it.

If you can send a game, that would be wonderful; if not, maybe I could try emulating this case in dummy game (but I would need to know some specifics about the font setups).

Honza

Quote from: Crimson Wizard on Tue 28/02/2023 11:37:45If you can send a game, that would be wonderful; if not, maybe I could try emulating this case in dummy game (but I would need to know some specifics about the font setups).

Great, thank you! I can't do it right now, but I'll upload the game later in the day and DM you. Is it ok if I share the current build of the full game or do you want me to make a test game just to show the problem?

Crimson Wizard

Quote from: Honza on Tue 28/02/2023 13:15:23I can't do it right now, but I'll upload the game later in the day and DM you. Is it ok if I share the current build of the full game or do you want me to make a test game just to show the problem?

Hmm, a test game is usually better, since it lets to narrow a problem down, but in case of fonts, I think, both variants will work, as the fonts setup is not too complicated.

Crimson Wizard

#11
Alright, so I remembered what the problem is now.

There has been a change in the 3.6.0 engine:
Before 3.6.0 the font's height was calculated anew each time any text is drawn. This was inefficient and also seemed redundant, as the font's height actually never should depend on a text itself, it's a fixed value. Maybe there were other reasons connected to all the changes to fonts made in 3.6.0 (i may have forgotten them).

In a nutshell, 3.6.0 only remembers the font's height once the font is registered. The new plugin API, introduced for 3.6.0, actually allows the font plugin to notify the engine if the font changes, and that forces engine to recalculate the font params. But old plugins did not have such capability.

So, in case of the old SpriteFont plugin, font's height must be known at the time when **SetSpriteFont** and **SetVariableSpriteFont** are called.
But your script registers a sprite font before it's been assigned any glyphs yet, and thus its height is equal to zero.

There are two ways to solve this problem:
1) Use an updated version of plugin, built anew from our sources. It does not have any changes in API (script functions), but has an enhanced "conversation" with the engine.
2) As a workaround: call SetVariableSpriteFont AFTER you set the glyphs. This does not seem to cause any problems, as the plugin is smart and creates a new font internally if it was not created with "SetSpriteFont" yet. But because the SetVariableSpriteFont is called afterwards, the plugin already knows the glyph metrics and so can already calculate text height upon registration.

NOTE: it looks like this is only an issue with Variable sprite fonts, as the regular sprite fonts require to pass a "height" parameter upon creation.

eri0o

@Crimson Wizard in Kathy Rain, there is a small part of the text being cut at the bottom for letters that go down the text line (like g and y), do you think this change you mentioned could be related to that observed behavior?

Crimson Wizard

Quote from: eri0o on Wed 01/03/2023 00:16:24@Crimson Wizard in Kathy Rain, there is a small part of the text being cut at the bottom for letters that go down the text line (like g and y), do you think this change you mentioned could be related to that observed behavior?

Depends on which version of the plugin you are running it with; but judging from what I've seen it is probably something else.
If you look closer, it seems that the letters themselves are drawn correctly (in greyish colors), but the outline is missing in these parts.

Honza

Quote from: Crimson Wizard on Wed 01/03/2023 00:06:252) As a workaround: call SetVariableSpriteFont AFTER you set the glyphs. This does not seem to cause any problems, as the plugin is smart and creates a new font internally if it was not created with "SetSpriteFont" yet. But because the SetVariableSpriteFont is called afterwards, the plugin already knows the glyph metrics and so can already calculate text height upon registration.

Great, I did this and it works fine now. A very quick fix, thank you!

Crimson Wizard

#15
I think we need to distribute a new version of SpriteFont ourselves, perhaps from a separate repository.

And additionally add API to explicitly choose newer font renderers which we had to support for "Clifftop Games". Since they are in our plugin anyway. Right now they are selected using a game-detection hack, which is only suitable for built-in compatibility feature.

eri0o

#16
@Crimson Wizard if you want an extra plugin pack in the ags release I could do that, I haven't gone through that route yet because some plugins I believe are more legacy and not necessary currently like AGSflashlight, and some are too hard to do currently (like AGSlua), but perhaps we could start with the AGS sprite font plugin.

Overall, in separate repository it would need it's own CI, and CI is something that can take a while for AGS constraints (unsupported version of Windows, 32-bit Linux, ...). For the web and Android platform, it's also easier to have a minor selection of plugins supported or built-in than setting up CI individually - specific to the web, the existing dlopen implementation is quite different from the other platforms, which is why I opted to just throw some plugins builtin, which is the case for the mentioned SpriteFont plugin.

OTOH, I think the SpriteFont plugin is probably the only one still relevant we maintain, so perhaps some of it's functionality should be a feature in the engine?

Crimson Wizard

#17
The situation with AGS plugins is not critical, but remains annoying. The idea of a plugin system assumes that it's something you may "plug-in" and "unplug" easily, but, even if we forget compatibility mode, with AGS we have to 1) built-in a selection of common plugins for particular platforms, 2) add hardcoded stubs for "optional" plugins (ones that are not required to complete the game). An alternative to this is probably to let game authors make custom engine builds, combining "official" engine code and plugin together (example: I have a suspicion that "Kathy Rain"'s steam version has a steam plugin built-in, because it's not present in the game folder). Maybe the latter could be achieved by distributing a template CMake script that allows to easily extend the engine with plugin sources. As the cloud building services become widespread now, some things probably may be achieved even by the unexperienced people without programming background.

For another instance, right now the SpriteFont in our repository has a hardcoded behavior switch based on the game GUID. The reason for this is that a separate game team created their own variant of this plugin without changing the name*. So when we support running that game, we cannot rely on the plugin's name. So our plugin's code literally sais: for certain selection of games - do something special; this contradicts to the concept of a plugin and API.

(* - unfortunately, I noticed that people like to make custom versions of the engine or plugins without indicating that, by e.g. changing a version number or an internal name. This commonly leads to problems in the future.)

Personally, I prefer to distinguish a "proper plugin" and "engine's workaround", at least in theory. For that reason I also imagine that there could be a separate repository with this plugin (or a collection of plugins), with their own dedicated maintainers. If it's necessary to produce engine with this plugin built-in, we might either have a copy of the source, or a submodule. If there is a need to have some additional hacks (like the aforementioned hack in our SF plugin now), then we might have either a copy of plugin with these changes, or work around somehow else, by linking files from a submodule with our own sources that "inject" these hacks.

I know that sounds like extra work, but in my opinion the project goal should be to clean the repository, and the engine, up from the bits that do not directly relate to it. And, eventually, find a solution for having to hardcode something every time a plugin is added (like stubs).


Quote from: eri0o on Wed 01/03/2023 13:10:41OTOH, I think the SpriteFont plugin is probably the only one still relevant we maintain, so perhaps some of it's functionality should be a feature in the engine?

In case of SpriteFont, I think - yes, and it's been suggested before. So long as a good API is designed for this; like a Font class, with extensions, etc (we should not blindly take plugin's API as-is).

The primary reason for the SpriteFont being a plugin and not a script overall was that it's easier this way, as there are no script callbacks for "draw a text" that would replace all the speech and GUI. And also, previously, iirc there have been some issues with 32-bit alpha transparency in old AGS.

Snarky

I think I've said this before, but I don't see why AGS should even attempt to be backwards compatible with unofficial, undocumented engine/plugin modifications by random game devs. If Clifftop Games (or whoever else) want their games to run in new versions of the engine, they can submit their changes to the official repo, or make a new build using the official APIs, no?

Sure, backwards compatibility is nice, when it makes sense, but not at any cost. AGS shouldn't try to be ScummVM—some kind of universal adventure game platform that will run anything you throw at it.

SMF spam blocked by CleanTalk