Introduction to GUI skinning (2024)

It is essential for a game to provide clear, informative, and yet visuallypleasing user interface to its players. While Controlnodes come with a decently functional look out of the box, there is alwaysroom for uniqueness and case-specific tuning. For this purpose Godot engineincludes a system for GUI skinning (or theming), which allows you to customizethe look of every control in your user interface, including your custom controls.

Here is an example of this system in action — a game with the GUI that isradically different from the default UI theme of the engine:

Introduction to GUI skinning (1)

Beyond achieving a unique look for your game, this system also enables developersto provide customization options to the end users, including accessibility settings.UI themes are applied in a cascading manner (i.e. they propagate from parentcontrols to their children), which means that font settings or adjustments forcolorblind users can be applied in a single place and affect the entire UI tree.Of course this system can also be used for gameplay purposes: your hero-based gamecan change its style for the selected player character, or you can give differentflavors to the sides in your team-based project.

Basics of themes

The skinning system is driven by the Theme resource. EveryGodot project has an inherent default theme that contains the settings used bythe built-in control nodes. This is what gives the controls their distinct lookout of the box. A theme only describes the configuration, however, and it is stillthe job of each individual control to use that configuration in the way it requiresto display itself. This is important to remember when implementingyour own custom controls.

Note

Even the Godot editor itself relies on the default theme. But it doesn't look thesame as a Godot project, because it applies its own heavily customized theme on topof the default one. In principle, this works exactly like it would in your gameas explained below.

Theme items

The configuration that is stored in a theme consists of theme items. Each item hasa unique name and must be one of the following data types:

  • Color

    A color value, which is often used for fontsand backgrounds. Colors can also be used for modulation of controlsand icons.

  • Constant

    An integer value, which can be used either for numeric properties ofcontrols (such as the item separation in a BoxContainer),or for boolean flags (such as the drawing of relationship lines in a Tree).

  • Font

    A font resource, which is used by controls thatdisplay text. Fonts contain most text rendering settings, except forits size and color. On top of that, alignment and text direction arecontrolled by individual controls.

  • Font size

    An integer value, which is used alongside a font to determine thesize at which the text should be displayed.

  • Icon

    A texture resource, which is normally usedto display an icon (on a Button, for example).

  • StyleBox

    A StyleBox resource, a collection of configurationoptions which define the way a UI panel should be displayed. This isnot limited to the Panel control, as styleboxesare used by many controls for their backgrounds and overlays.

Theme types

To help with the organization of its items each theme is separated into types,and each item must belong to a single type. In other words, each theme itemis defined by its name, its data type and its theme type. This combinationmust be unique within the theme. For example, there cannot be two color items namedfont_color in a type called Label, but there can be another font_coloritem in a type LineEdit.

The default Godot theme comes with multiple theme types already defined,one for every built-in control node that uses UI skinning. The example abovecontains actual theme items present in the default theme. You can refer to theTheme Properties section in the class reference for each control to seewhich items are available to it and its child classes.

Note

Child classes can use theme items defined for their parent class (Buttonand its derivatives being a good example of that). In fact, every control canuse every theme item of any theme type, if it needs to (but for the clarity andpredictability we try to avoid that in the engine).

It is important to remember that for child classes that process is automated.Whenever a built-in control requests a theme item from the theme it can omitthe theme type, and its class name will be used instead. On top of that,the class names of its parent classes will also be used in turn. This allowschanges to the parent class, such as Button, to affect all derivedclasses without the need to customize every one of them.

You can also define your own theme types, and additionally customize both built-incontrols and your own controls. Because built-in controls have no knowledge ofyour custom theme types, you must utilize scripts to access those items. All controlnodes have several methods that allow to fetch theme items from the theme thatis applied to them. Those methods accept the theme type as one of the arguments.

var accent_color = get_theme_color("accent_color", "MyType")label.add_color_override("font_color", accent_color)

To give more customization opportunities types can also be linked together astype variations. This is another use-case for custom theme types. For example,a theme can contain a type Header which can be marked as a variation ofthe base Label type. An individual Label control can then be set touse the Header variation for its type, and every time a theme item isrequested from a theme this variation will be used before any other type. Thisallows to store various presets of theme items for the same class of thecontrol node in the single Theme resource.

Warning

Only variations available from the default theme or defined in the customproject theme are shown in the Inspector dock as options. You can stillinput manually the name of a variation that is defined outside of thosetwo places, but it is recommended to keep all variations to the project theme.

You can learn more about creating and using theme type variations in adedicated article.

Customizing a control

Each control node can be customized directly without the use of themes. Thisis called local overrides. Every theme property from the control's classreference can be overridden directly on the control itself, using eitherthe Inspector dock, or scripts. This allows to make granular changes to aparticular part of the UI, while not affecting anything else in the project,including this control's children.

Introduction to GUI skinning (2)

Local overrides are less useful for the visual flair of your user interface,especially if you aim for consistency. However, for layout nodes these areessential. Nodes such as BoxContainer andGridContainer use theme constants for definingseparation between their children, and MarginContainerstores its customizable margins in its theme items.

Whenever a control has a local theme item override, this is the value thatit uses. Values provided by the theme are ignored.

Customizing a project

Out of the box each project adopts the default project theme provided by Godot. Thedefault theme itself is constant and cannot be changed, but its items can be overriddenwith a custom theme. Custom themes can be applied in two ways: as a project setting,and as a node property throughout the tree of control nodes.

There are two project settings that can be adjusted to affect your entire project:gui/theme/custom allows you toset a custom project-wide theme, and gui/theme/custom_fontdoes the same to the default fallback font. When a theme item is requested by a controlnode the custom project theme, if present, is checked first. Only if it doesn't havethe item the default theme is checked.

This allows you to configure the default look of every Godot control with a singletheme resource, but you can go more granular than that. Every control node also hasa theme property, which allows you to set acustom theme for the branch of nodes starting with that control. This means that thecontrol and all of its children, and their children in turn, would first check thatcustom theme resource before falling back on the project and the default themes.

Note

Instead of changing the project setting you can set the custom theme resource to theroot-most control node of your entire UI branch to almost the same effect. While in therunning project it will behave as expected, individual scenes will still displayusing the default theme when previewing or running them directly. To fix that youcan set the same theme resource to the root control of each individual scene.

For example, you can have a certain style for buttons in your project theme, but wanta different look for buttons inside of a popup dialog. You can set a custom themeresource to the root control of your popup and define a different style for buttonswithin that resource. As long as the chain of control nodes between the root ofthe popup and the buttons is uninterrupted, those buttons will use the styles definedin the theme resource that is closest to them. All other controls will still be styledusing the project-wide theme and the default theme styles.

To sum it up, for an arbitrary control its theme item lookup would look somethinglike this:

  1. Check for local overrides of the same data type and name.

  2. Using control's type variation, class name and parent class names:

    1. Check every control starting from itself and see if it has a theme property set;

    2. If it does, check that theme for the matching item of the same name, data and theme type;

    3. If there is no custom theme or it doesn't have the item, move to the parent control;

    4. Repeat steps a-c. until the root of the tree is reached, or a non-control node is reached.

  3. Using control's type variation, class name and parent class names check the project-wide theme, if it's present.

  4. Using control's type variation, class name and parent class names check the default theme.

Even if the item doesn't exist in any theme, a corresponding default value for thatdata type will be returned.

Beyond controls

Naturally, themes are an ideal type of resource for storing configuration forsomething visual. While the support for theming is built into control nodes,other nodes can use them as well, just like any other resource.

An example of using themes for something beyond controls can be a modulationof sprites for the same units on different teams in a strategy game. A themeresource can define a collection of colors, and sprites (with a help from scripts)can use those colors to draw the texture. The main benefit being that youcould make different themes using the same theme items for red, blue, andgreen teams, and swap them with a single resource change.

Introduction to GUI skinning (2024)
Top Articles
Latest Posts
Article information

Author: Domingo Moore

Last Updated:

Views: 5950

Rating: 4.2 / 5 (73 voted)

Reviews: 80% of readers found this page helpful

Author information

Name: Domingo Moore

Birthday: 1997-05-20

Address: 6485 Kohler Route, Antonioton, VT 77375-0299

Phone: +3213869077934

Job: Sales Analyst

Hobby: Kayaking, Roller skating, Cabaret, Rugby, Homebrewing, Creative writing, amateur radio

Introduction: My name is Domingo Moore, I am a attractive, gorgeous, funny, jolly, spotless, nice, fantastic person who loves writing and wants to share my knowledge and understanding with you.