Custom font loading issues with GUI

Hi everyone!

Quick question on the GUI and custom font loading. How to ensure that fonts loaded OR make sure that the GUI refreshes with fonts after they are loaded.

Currently when I am not caching stuff my fonts load with the default font and their position is totally wrong. This is with “disable cache” option in the browser devtools. Without the option, the custom font seems to load fine. It is a bit puzzling since this font is base64 encoded to the html itself but unknown are the ways of the code…

If I hover over the ui buttons, they seem to correct themselves, but the positioning is still wrong, and things like titles don’t work of course:

And finally, this is how it should look:

So, is there a way to at least manually trigger the GUI to recalculate itself or build itself from the scratch? Is this known issue? Or how to ensure browser has properly loaded the fonts?

Thank you in advance :smiling_face_with_three_hearts:

1 Like

cc @georgie

1 Like

Hi there @Panuchka can you please provide a playground link that I can use to debug?

Without seeing the code I am not sure if this will help, but if you are referring to a textBlock whose font is changing, try setting resizeToFit = true on the textblock (this will help with layout recalculations)

1 Like

Unfortunately I’m using this currently already, was the topic of a previous thread I had where the text wobbled a bit :smiley:

I’ll try to make a repro on the playground, I’ve been reluctant because I’m afraid I cannot use the custom font in playground similar way… We will see!

Lol ok it was easier to reproduce than I thought! :nerd_face:

So, here is the playground with custom font base64 encoded in it:
gui problem | Babylon.js Playground

On the first load it might be wrong, but if it is not you should go to browsers network tab and disable cache + reload the page. It should look like this (wrong):

Then, if you enable caching again and refresh it should look like this (right):

Also the GUI is loaded from a json which is embedded in the playground, and that is exactly what I use in my game.

hi @Panuchka to answer your first question, you can manually recalculate via the markAsDirty function, so in your playground call this.guiTexture.markAsDirty() after loading the texture.

However I agree this shouldn’t be something you should need to do manually (in fact we’d advise against it as it is an expensive operation). I will look into why in this case we aren’t detecting fonts being loaded and applying font to the GUI automatically

1 Like

The problem seems to still persist with the `markAsDirty`, if I do a full page refresh with cache disabled. And I mean like actual browser refresh, not the play button :smiley:
gui problem | Babylon.js Playground

ah yes I can reproduce with the hard refresh - i also could reproduce with a simple textblock in playground as well as a simple loaded texture from gui-editor (see Babylon.js Playground) so narrowed down to issue w how the font is loaded or issue w how we are handling setting font relative to when it is loaded.

will continue to investigate further! thank you for your patience

3 Likes

hi there, for some reason document.fonts is not capturing the font you load above via style tag. however you can achieve the desired behavior using the font-face API programatically, (vs injecting into style tag) and things work as expected, here is updated playground .gui problem | Babylon.js Playground

let me know if the above solution works for you!

1 Like

This is because loading of the font isn’t synchronous to the document. In a prod environment you could add the App/bjs loading logic to the window load event listener. It probably works in script because it may have loaded by this time.

it is true loading the font is done async, however i would still expect font API to detect that loading occuring and include the fontset promise in document.fonts, so that awaiting document.fonts.ready would be sufficient

perhaps that is the case if the font is embedded in the document html directly vs being added via html styleTag programatically in playground?

@Panuchka are you adding the font to document the way you are doing in the playground? or directly in page HTML? if the latter, if u use await document.fonts.ready before loading the gui snippet does that solve? based on my testing so far / understanding of the issue i don’t think it will. @j-te that is also a fair suggestion!

1 Like

@Panuchka are you unblocked with the proposal above?

Yeah hi sorry for late reply!

I’ve read the comments from above and I have found an adequate solution for now. I want the font to be embedded to style tag so it can be used with regular html as well, not just js/ts code.

So, with a bit of more researching I fixed the problematic pg above:
gui problem | Babylon.js Playground

Basically I added these two lines that ensure that fonts are being loaded:

await Promise.all([document.fonts.load(“16px ‘press-start-2p’”)])

await document.fonts.ready

The real reason why the font is not loading might be that the browser only starts to load them when the font appears somewhere in the dom or in js. Maybe…

May have to fine tune this in the future so that the loading of the game is not blocked by this but it seems to work! :kissing_face_with_smiling_eyes: Thank you for helping!

1 Like

If you don’t want to await and block (ie: allow fallback font) - what I have done previously is:

if (document.fonts.check(“16px FontAwesome”) === false) {
  document.fonts.load(“16px FontAwesome”).then(() => {
     // trigger markAsDirty here
  }
}

Anyway, you can flow the event through and update your GUI like here:
create-react-app-typescript-babylonjs/src/BouncySphere.tsx at master · brianzinn/create-react-app-typescript-babylonjs

My suggestion a few years ago was that if we could pass in a list of fonts that they could be loaded and the GUI would mark itself as dirty automatically. It’s browser specific though, too. I think there are a few other threads in the forum on this.

1 Like