Skip to content

Instantly share code, notes, and snippets.

@fire
Forked from toger5/godot adapted dpi.md
Last active May 9, 2019 14:09
Show Gist options
  • Save fire/3dc8b5d00aaf796fe50f9cda133883ce to your computer and use it in GitHub Desktop.
Save fire/3dc8b5d00aaf796fe50f9cda133883ce to your computer and use it in GitHub Desktop.

Implementation of dpi adaption in Godot

The theme is the master class that gets asked for style boxes, constants and fonts all the time. The theme is asked multiple times per node and hundreds of times a frame.

It's that simple. However, there is one great additional thing in Godot which makes the dpi addition easy to implement. There are two ways of accessing values in a theme. theme->get_styebox() and my_control->get_stylebox().

  • When asking the theme, it just calls the hash map with styles, and that's it.
  • When asking a control, it does some logic:
    1. font (cached) the next node up to the tree that has a theme assigned.
    2. check if the theme has the requested style. Yes: return it! No: go to the next Control with a theme. If nothing got found search with the next class name (if it was a Texture Button, search for styles for Button) and so on.

There is no better place than doing the dpi in that section. This way it can be a property of a node subtree and not for an entire theme!

So whenever a style is asked for the correct dpi gets calculated and an adapted sb gets returned. (This does not interfere with any inspector stuff since the inspector does not use the Control::get_stylebox method) That's it, almost ;)

How to use

Just add a theme to the Control you want to change the dpi. ALL CHILDREN WILL GET DPI SCALED AS WELL. You don't need to add any other theme property then the dpi_scale. For the Rest of the values (fonts styles icons), Godot will use the next theme in the tree (worst case the default theme).

Performance

It is already quite bad that each Control::get_stylebox request results in multiple while loops with hash map calls. However, with the dpi stuff I saw the opportunity to cache everything. So only on NOTIFICATION::THEME_CHANGED the while loop and the dpi adaption gets executed. Otherwise, it just calls a local hash map on the Control itself which only has the elements needed (Only a Ref actually to be more precise) So the performance should be better than without the dpi patch

Dpi adaption

I mentioned that the dpi gets adapted. What does that mean?

  • For Textures (icons) A new class got added. Scaled/Theme_texture (haven't decided on the name yet). This texture also stores a custom size value and fakes its size to be bigger than the texture res. The draw function is overridden and draws a stretched version of the texture. I Also have the plan to give that texture wrapper a modulate color. so that you can have multiple textures with the same Bitmap but with different colors. The editor could use white icons in many places and use those wrapped textures.
  • For Fonts Only dynamic fonts are supported atm. They just get duplicated, and the size gets changed. The font itself is a small class and uses the font data which is already designed to support multiple size versions. So basically it is the same than a wrapped font.
  • For style box flat/texture A wrapper class with a ref to the node that requested the style box. When the style box gets asked for margins, it scales it by the dpi environment of the Control. Whenever the style box draws, it uses the dpi value of the next theme in the controls (in the draw the get_current_drawn control function is used) tree.

So basically all the objects used by nodes are just wrappers which have the correct behavior in the right context. In addition to that also those wrappers are cached and the Control::get_stylebox/font/icon... functions perform much better now.

The improvement allows for an excellent performance. When not changing the dpi it should run faster than before thanks to the caching. If the dpi_scale gets changed it only reloads all controls which use the changed theme. That is as heavy as drawing was before since it will loop through the themes again as explained at the beginning. It is still fast enough to animate the dpi scale. I tweeted about that some time ago.

Created a dynamic dpi system for #GodotEngine. So no recreation of the theme is needed to provide multiple dpi lvls. The editor hacks for the dpi scale can get removed and all Godot projects can provide different dpi lvls without setting up multiple themes. pic.twitter.com/tGWFkSCvW9

— Timo K (@Toger50) March 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment