Search code examples
godotgdscript

How to make custom fonts visible at runtime? or How to redraw/update/restart the project in code?


Imagine a simple settings window with an option to choose custom fonts. A function takes the value and passes it down the line setting the ProjectSettings gui/theme/custom_font value to the correct font's file path. The get_setting returns the correct value when asked. BUT there is no update after the change is made, i.e. I still see the default fonts being used (at runtime. To test it I just change fonts after key presses).

ProjectSettings.set_setting("gui/theme/custom_font", font_path)

As I understand what should happen after setting a new custom font is the project needs to be restarted (as indicated by the warning in the editor itself when you try to set it manually). So, how can I do it? I tried get_tree().reload_current_scene() but it only reloads the scene and not the whole project (I'd say it rather "resets" it to its initial values/parameters).


Solution

  • Restarting the game

    To completely restart the game, this is what you are supposed to do:

    • Call OS.set_restart_on_exit passing true, so the game restart the next time it exits.

      Be aware of this:

      Note: This method is only effective on desktop platforms, and only when the project isn't started from the editor. It will have no effect on mobile and Web platforms, or when the project is started from the editor.

    • Call get_tree().quit() to exit the game.

    However, this is a XY problem. You don't want to restart the game, you want to change the font.


    Changing fonts in runtime

    To change the font in runtime, do not work with the default font in project settings.

    Instead create a Theme. The Theme is a Resource (you can create it as a Theme resource file from the filesystem). And in it you configure the fonts and the rest of the UI appearance you want.

    Then on the root Controls of every scene, you configure the theme to your Theme... You do not need to set it on every Control because they will take the Theme from their parent, so you only need to set it on the top level Controls.

    Now, you should be able to change fonts of the Theme in runtime, and the change would be reflected on every Control that has it configured automatically. No restart needed.

    Note: If you have set the theme to your Theme resource file via the Inspector, or if you preload it form code, you should be getting the same instance. But if you use load you might or might not get the same instance (due to the object lifespan and caching), and if you don't get the same instance, its changes would not be reflected elsewhere (you would have essentially loaded a copy).


    The Theme has a default_font property that you can set. You can find it on the Inspector when you open your Theme resource file in the editor. And make sure to set the default_font_size too.

    And you can directly set these properties from code in runtime. Again, I remind you that you preload the Theme resource file to work with it from code.


    If you rather have more control, you can specify fonts (and font sizes) for different types...

    You can do this in the Theme panel when you open the Theme resource file in the editor.* So, for example, to change the font of Buttons, you specify the value "font" of the type "Button", which is different from the font for Labels which is "font" of the type "Label". *Inheritance apply, so by setting the font for "Button" but not the font for "CheckBox" the CheckBox gets the same font as Buttons.

    You need to keep that in mind to change the font from code. As you might guess, you need to set_font on the Theme (which I remind you that you get by preloading the Theme resource file). The set_font method wants three parameters:

    • name: the name of the value you are setting, e.g. "font".
    • theme_type: the type for which you are setting it, e.g. "Button".
    • font: The new font you want to set.

    Looking at my current Theme, the fonts I set are for "Button", "Label", "LineEdit", "PopupMenu", "ProgressBar", "TabContainer", "TextEdit", "Tree" and "Window".