Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Introduzione a GUI skinning
It is essential for a game to provide clear, informative, and yet visually pleasing user interface to its players. While Control nodes come with a decently functional look out of the box, there is always room for uniqueness and case-specific tuning. For this purpose Godot engine includes a system for GUI skinning (or theming), which allows you to customize the 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 is radically different from the default UI theme of the engine:
A "Gear Up!" screen in Tank Kings, courtesy of Winterpixel Games
Beyond achieving a unique look for your game, this system also enables developers to provide customization options to the end users, including accessibility settings. UI themes are applied in a cascading manner (i.e. they propagate from parent controls to their children), which means that font settings or adjustments for colorblind 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 game can change its style for the selected player character, or you can give different flavors to the sides in your team-based project.
Le basi dei temi
Il sistema di skinning è gestito dalla risorsa Theme. Ogni progetto Godot ha un tema predefinito intrinseco che contiene le impostazioni utilizzate dai nodi di controllo integrati. Questo è ciò che da ai controlli il loro aspetto distintivo fin da subito. Un tema, tuttavia, descrive solo la configurazione, ed è comunque compito di ogni singolo controllo utilizzare tale configurazione nel modo in cui si voglia visualizzare. Questo è importante da ricordare quando si implementano controlli personalizzati.
Nota
Anche l'editor Godot stesso dipende dal tema predefinito. Ma non ha lo stesso aspetto di un progetto Godot, perché applica un tema personalizzato a quello predefinito. In principio, funziona esattamente come in un gioco, come spiegato in seguito.
Elementi del tema
La configurazione memorizzata in un tema è composta da elementi del tema. Ogni elemento ha un nome univoco e deve essere uno dei seguenti tipi di dati:
Color
Un valore color, spesso utilizzato per font e sfondi. I colori si possono utilizzare anche per la modulazione di controlli e icone.
Costante
Un valore intero, che si può utilizzare per proprietà numeriche di controlli (ad esempio la separazione degli elementi in un BoxContainer) o per flag booleani (ad esempio il disegno di linee di relazione in un Tree).
Font
Una risorsa font, utilizzata dai controlli che visualizzano il testo. I font contengono gran parte delle impostazioni di rendering del testo, ad eccezione di dimensione e colore. Inoltre, l'allineamento e la direzione del testo sono controllati da controlli individuali.
Dimensione di font
Un valore intero, che viene utilizzato insieme a un font per determinare la dimensione alla quale deve essere visualizzato il testo.
Icona
Una risorsa texture, che normalmente è utilizzata per visualizzare un'icona (ad esempio su un Button).
StyleBox
Una risorsa StyleBox, una raccolta di opzioni di configurazione che definiscono il modo in cui un pannello dell'interfaccia si dovrebbe visualizzare. Questo non si limita al controllo Panel, poiché gli stylebox sono utilizzati da molti controlli per i loro sfondi e sovrapposizioni.
Controlli diversi applicheranno gli StyleBox diversamente. In particolare, gli stylebox
focussono disegnati come una sovrapposizione ad altri stylebox (comenormalopressed) per consentire allo stylebox di base di rimanere visibile. Ciò significa che lo stylebox di focus si dovrebbe progettare come un riquadro con contorno o semitrasparente, in modo che il suo sfondo rimanga visibile.
Tipi del tema
Per facilitare l'organizzazione dei suoi elementi, ogni tema è suddiviso in tipi e ogni elemento deve appartenere a un singolo tipo. In altre parole, ogni elemento del tema è definito dal suo nome, dal suo tipo di dati e dal suo tipo di tema. Questa combinazione deve essere univoca all'interno del tema. Ad esempio, non possono esserci due elementi di colore denominati font_color in un tipo denominato Label, ma può esserci un altro elemento font_color in un tipo LineEdit.
Il tema predefinito di Godot include diversi tipi di tema già definiti, uno per ogni nodo di controllo integrato che utilizza UI skinning. L'esempio precedente contiene elementi del tema effettivamente presenti nel tema predefinito. È possibile fare riferimento alla sezione Proprietà del tema nel riferimento alla classe di ciascun controllo per vedere quali elementi sono disponibili per esso e per le sue classi figlio.
Nota
Le classi figlie possono utilizzare gli elementi del tema definiti per la classe padre (Button e i suoi derivati ne sono un buon esempio). Infatti, ogni controllo può utilizzare qualsiasi elemento del tema di qualsiasi tipo, se necessario (ma per chiarezza e prevedibilità cerchiamo di evitarlo nel motore).
È importante ricordare che per le classi figlio questo processo è automatizzato. Ogni volta che un controllo integrato richiede un elemento del tema, può omettere il tipo di tema e sarà utilizzato il nome della sua classe. Inoltre, saranno utilizzati a loro volta anche i nomi delle classi padre. Questo consente alle modifiche apportate alla classe padre, come Button, di influire su tutte le classi derivate senza doverle personalizzare singolarmente.
È inoltre possibile definire i propri tipi del tema e personalizzare sia i controlli integrati sia controlli personalizzati. Poiché i controlli integrati non conoscono i tipi del tema personalizzati, è necessario utilizzare script per accedervi. Tutti i nodi di controllo dispongono di diversi metodi che consentono di recuperare gli elementi del tema dal tema a essi applicato. Questi metodi accettano il tipo del tema come uno degli argomenti.
var accent_color = get_theme_color("accent_color", "MyType")
label.add_theme_color_override("font_color", accent_color)
Color accentColor = GetThemeColor("accent_color", "MyType");
label.AddThemeColorOverride("font_color", accentColor);
Per offrire più opportunità di personalizzazione, i tipi si possono anche connettere tra loro come variazioni di tipo. Questo è un altro caso d'uso per i tipi di tema personalizzati. Ad esempio, un tema può contenere un tipo Header che può essere segnato come una variazione del tipo base Label. Un singolo controllo Label si può quindi configurare per utilizzare la variazione Header per il suo tipo, e ogni volta che un elemento del tema è richiesto da un tema, questa variazione sarà utilizzata prima di qualsiasi altro tipo. Ciò consente di memorizzare diverse preimpostazioni di elementi del tema per la stessa classe del nodo controllo in una sola risorsa Theme.
Avvertimento
Solo le variazioni disponibili nel tema predefinito o definite nel tema personalizzato del progetto sono visualizzate come opzioni nel pannello Ispettore. È comunque possibile inserire manualmente il nome di una variazione definita fuori queste due posizioni, ma si consiglia di mantenere tutte le variazioni nel tema del progetto.
Per ulteriori informazioni su come creare e utilizzare le variazioni di tipi del tema, consultare l'articolo dedicato.
Personalizzazione di un controllo
Ogni nodo controllo si può personalizzare direttamente senza l'utilizzo di temi. Questa operazione è detta sostituzione locale. Ogni proprietà del tema presente nel riferimento alla classe del controllo si può sovrascrivere direttamente sul controllo stesso, attraverso il pannello Ispettore o gli script. Questo consente di apportare modifiche granulari a una parte specifica dell'interfaccia utente, senza influire su altri elementi del progetto, inclusi gli elementi figlio di questo controllo.
Le sostituzioni locali sono meno utili per l'aspetto visivo dell'interfaccia utente, soprattutto se si desidera coerenza. Tuttavia, sono essenziali per i nodi di layout. Nodi come BoxContainer e GridContainer utilizzano costanti del tema per definire la separazione tra i loro elementi figlio, mentre MarginContainer memorizza i margini personalizzabili nei propri elementi del tema.
Ogni volta che un controllo ha una sostituzione di un elemento del tema locale, questo è il valore che utilizza. I valori forniti dal tema sono ignorati.
Customizing a project
Out of the box each project adopts the default project theme provided by Godot. The default theme itself is constant and cannot be changed, but its items can be overridden with 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 to set a custom project-wide theme, and GUI > Theme > Custom Font does the same to the default fallback font. When a theme item is requested by a control node the custom project theme, if present, is checked first. Only if it doesn't have the item the default theme is checked.
This allows you to configure the default look of every Godot control with a single theme resource, but you can go more granular than that. Every control node also has a theme property, which allows you to set a custom theme for the branch of nodes starting with that control. This means that the control and all of its children, and their children in turn, would first check that custom theme resource before falling back on the project and the default themes.
Nota
Instead of changing the project setting you can set the custom theme resource to the root-most control node of your entire UI branch to almost the same effect. While in the running project it will behave as expected, individual scenes will still display using the default theme when previewing or running them directly. To fix that you can 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 want a different look for buttons inside of a popup dialog. You can set a custom theme resource to the root control of your popup and define a different style for buttons within that resource. As long as the chain of control nodes between the root of the popup and the buttons is uninterrupted, those buttons will use the styles defined in the theme resource that is closest to them. All other controls will still be styled using the project-wide theme and the default theme styles.
Riassumendo, per un controllo arbitrario, la ricerca dell'elemento del tema assomiglierebbe a qualcosa del genere:
Verifica la presenza di sostituzioni locali dello stesso tipo di dati e nome.
Utilizzando la variazione di tipo del controllo, il nome della classe e i nomi della classe padre:
Controlla ogni controllo a partire da se stesso e verifica se ha una proprietà del tema impostata;
Se sì, verifica il tema per l'elemento corrispondente con lo stesso nome, dati e tipo di tema;
Se non è presente alcun tema personalizzato o non ha l'elemento, passa al controllo padre;
Ripeti i passaggi da a a c, fino a raggiungere la radice dell'albero o un nodo non di controllo.
Utilizzando la variazione di tipo del controllo, il nome della classe e i nomi delle classi padre, verifica il tema dell'intero progetto, se presente.
Utilizzando la variazione di tipo del controllo, il nome della classe e i nomi delle classi padre, verifica il tema predefinito.
Anche se l'elemento non esiste in alcun tema, sarà restituito un valore predefinito corrispondente per quel tipo di dati.
Beyond controls
Naturalmente, i temi sono una risorsa ideale per memorizzare la configurazione di qualcosa di visivo. Sebbene il supporto per i temi sia integrato nei nodi di controllo, anche altri nodi possono utilizzarli, proprio come qualsiasi altra risorsa.
An example of using themes for something beyond controls can be a modulation of sprites for the same units on different teams in a strategy game. A theme resource 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 you could make different themes using the same theme items for red, blue, and green teams, and swap them with a single resource change.