Einführung in GUI Skinning

Für ein Spiel ist es wichtig, seinen Spielern eine klare, informative und dennoch optisch ansprechende Benutzeroberfläche zu bieten. Während Control-Nodes von Haus aus mit einem anständig funktionalen Aussehen ausgestattet sind, gibt es immer Raum für Einzigartigkeit und fallspezifisches Tuning. Zu diesem Zweck enthält die Godot-Engine ein System für das GUI-Skinning (oder Themen), mit dem Sie das Aussehen jedes Steuerelements in Ihrer Benutzeroberfläche, einschließlich Ihrer benutzerdefinierten Steuerelemente, anpassen können.

Hier ist ein Beispiel für dieses System in Aktion - ein Spiel mit einer grafischen Benutzeroberfläche, die sich radikal vom Standard-UI-Thema der Engine unterscheidet:

../../_images/tank-kings-by-winterpixel-games.png

Ein "Ausrüsten!" Bildschirm in Tank Kings, mit freundlicher Genehmigung von Winterpixel Games

Mit diesem System können Sie nicht nur ein einzigartiges Aussehen für Ihr Spiel erzielen, sondern auch Anpassungsoptionen für die Endbenutzer bereitstellen, einschließlich Einstellungen für die Barrierefreiheit. UI-Themen werden kaskadierend angewendet (d. h. sie werden von übergeordneten Steuerelementen auf ihre untergeordneten Steuerelemente übertragen), was bedeutet, dass Schrifteinstellungen oder Anpassungen für farbenblinde Benutzer an einer einzigen Stelle vorgenommen werden können und den gesamten UI-Baum betreffen. Natürlich kann dieses System auch für Gameplay-Zwecke verwendet werden: Ihr heldenbasiertes Spiel kann seinen Stil für den ausgewählten Spielercharakter ändern, oder Sie können den Seiten in Ihrem teambasierten Projekt verschiedene Geschmacksrichtungen geben.

Themen-Grundlagen

Das Skinning-System wird durch die Ressource Theme gesteuert. Jedes Godot-Projekt hat ein vorgegebenes Standardthema, das die von den eingebauten Kontroll-Nodes verwendeten Einstellungen enthält. Dadurch erhalten die Steuerelemente ihr unverwechselbares Aussehen. Ein Thema beschreibt jedoch nur die Konfiguration, und es ist immer noch die Aufgabe jedes einzelnen Steuerelements, diese Konfiguration so zu verwenden, wie es für seine Darstellung erforderlich ist. Dies ist wichtig zu bedenken, wenn Sie Ihre eigenen benutzerdefinierten Steuerelemente implementieren.

Bemerkung

Sogar der Godot-Editor selbst basiert auf dem Standardthema. Aber er sieht nicht so aus wie ein Godot-Projekt, weil er sein eigenes, stark angepasstes Thema auf das Standard-Thema anwendet. Im Prinzip funktioniert das genau so wie in Ihrem Spiel, wie hier erklärt.

Themen-Elemente

Die Konfiguration, die in einem Thema gespeichert wird, besteht aus Themenelementen. Jedes Element hat einen eindeutigen Namen und muss einem der folgenden Datentypen entsprechen:

  • Color

    Ein color Wert, der oft für Schriftarten und Hintergründe verwendet wird. Farben können auch für die Anpassung von Steuerelementen und Symbolen verwendet werden.

  • Konstante

    Ein ganzzahliger Wert, der entweder für numerische Eigenschaften von Steuerelementen (z. B. den Elementabstand in einem BoxContainer) oder für boolesche Flags (z. B. das Zeichnen von Beziehungslinien in einem Tree) verwendet werden kann.

  • Font

    Eine font Ressource, die von Steuerelementen verwendet wird, die Text anzeigen. Schriftarten enthalten die meisten Einstellungen für die Textdarstellung, mit Ausnahme von Größe und Farbe. Darüber hinaus werden Ausrichtung und Textrichtung von einzelnen Steuerelementen gesteuert.

  • Icon

    Eine texture-Ressource, die normalerweise verwendet wird, um ein Symbol darzustellen (zum Beispiel auf einem Button).

  • StyleBox

    Eine StyleBox-Ressource, eine Sammlung von Konfigurationsoptionen, die festlegen, wie ein UI-Panel angezeigt werden soll. Dies ist nicht auf das Panel-Steuerelement beschränkt, da Styleboxen von vielen Steuerelementen für ihre Hintergründe und Overlays verwendet werden.

Themen-Typen

Um die Organisation der Elemente zu erleichtern, ist jedes Thema in Typen unterteilt, und jedes Element muss zu einem einzigen Typ gehören. Mit anderen Worten: Jedes Thema wird durch seinen Namen, seinen Datentyp und seinen Thementyp definiert. Diese Kombination muss innerhalb des Themas eindeutig sein. Zum Beispiel kann es nicht zwei Farbelemente mit dem Namen font_color in einem Typ namens Label geben, aber es kann ein weiteres font_color Element in einem Typ LineEdit geben.

Das Standard-Godot-Thema enthält mehrere bereits definierte Thementypen, einen für jeden eingebauten Kontroll-Node, der UI-Skinning verwendet. Das obige Beispiel enthält tatsächliche Themenelemente, die im Standardthema vorhanden sind. Sie können den Abschnitt Themen-Eigenschaften in der Klassenreferenz für jedes Steuerelement nachsehen, welche Elemente für dieses und seine untergeordneten Klassen verfügbar sind.

Bemerkung

Untergeordnete Klassen können Themenelemente verwenden, die für ihre Elternklasse definiert sind (Button und seine Derivate sind ein gutes Beispiel dafür). Tatsächlich kann jedes Steuerelement bei Bedarf jedes Themenelement eines beliebigen Thementyps verwenden (aber aus Gründen der Übersichtlichkeit und Vorhersehbarkeit versuchen wir, dies in der Engine zu vermeiden).

Es ist wichtig sich daran zu erinnern, dass dieser Prozess für untergeordnete Klassen automatisiert ist. Wann immer ein eingebautes Steuerelement ein Themenelement aus dem Thema anfordert, kann es den Thementyp weglassen, und stattdessen wird sein Klassenname verwendet. Darüber hinaus werden auch die Klassennamen der übergeordneten Klassen verwendet. Dies ermöglicht es, daß Änderungen an der übergeordneten Klasse, wie z.B. Button, sich auf alle abgeleiteten Klassen auswirken, ohne daß jede einzelne von ihnen angepaßt werden muß.

Sie können auch Ihre eigenen Thementypen definieren und zusätzlich sowohl die eingebauten als auch Ihre eigenen Steuerelemente anpassen. Da die eingebauten Steuerelemente keine Kenntnis von Ihren benutzerdefinierten Thementypen haben, müssen Sie Skripte verwenden, um auf diese Elemente zuzugreifen. Alle Steuerelement-Nodes verfügen über mehrere Methoden, die es ermöglichen, Themenelemente aus dem auf sie angewendeten Thema zu holen. Diese Methoden akzeptieren den Thementyp als eines der Argumente.

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

Anpassen eines Steuerelements

Jeder Kontroll-Node kann direkt ohne die Verwendung von Themen angepasst werden. Dies wird als lokale Überschreibungen bezeichnet. Jede Themen-Eigenschaft aus der Klassenreferenz des Steuerelements kann direkt auf dem Steuerelement selbst überschrieben werden, entweder über das Inspektor-Dock oder über Skripte. Dies ermöglicht es, granulare Änderungen an einem bestimmten Teil der Benutzeroberfläche vorzunehmen, ohne dass sich dies auf andere Teile des Projekts auswirkt, einschließlich der Kinder dieses Steuerelements.

../../_images/themecheck.png

Lokale Überschreibungen sind weniger nützlich für das visuelle Flair Ihrer Benutzeroberfläche, insbesondere wenn Sie auf Konsistenz achten. Für Layout-Node sind sie jedoch unerlässlich. Nodes wie BoxContainer und GridContainer verwenden Themenkonstanten zur Definition der Trennung zwischen ihren Kindern, und MarginContainer speichert seine anpassbaren Ränder in seinen Themenelementen.

Wenn ein Steuerelement ein lokales Themen-Element überschreibt, wird dieser Wert verwendet. Vom Thema bereitgestellte Werte werden ignoriert.

Anpassen eines Projekts

Jedes Projekt nimmt standardmäßig das von Godot bereitgestellte Projektthema an. Das Standardthema selbst ist fest und kann nicht geändert werden, aber seine Elemente können mit einem benutzerdefinierten Thema überschrieben werden. Benutzerdefinierte Themen können auf zwei Arten angewendet werden: als Projekteinstellung und als Node-Eigenschaft im gesamten Baum der Kontroll-Nodes.

Es gibt zwei Projekteinstellungen, die so angepasst werden können, dass sie das gesamte Projekt betreffen: gui/theme/custom ermöglicht es Ihnen, ein benutzerdefiniertes projektweites Thema festzulegen, und gui/theme/custom_font macht dasselbe mit der Standard-Ausweich-Schriftart. Wenn ein Themen-Element von einem Kontroll-Node angefordert wird, wird das benutzerdefinierte Projektthema, falls vorhanden, zuerst geprüft. Nur wenn das Element nicht vorhanden ist, wird das Standardthema geprüft.

Auf diese Weise können Sie das Standardaussehen jedes Godot-Steuerelements mit einer einzigen Designressource konfigurieren, aber Sie können detaillierter vorgehen. Jeder Steuerelement-Node verfügt außerdem über eine theme-Eigenschaft, mit der Sie ein benutzerdefiniertes Design für den Zweig von Nodes festlegen können, der mit diesem Steuerelement beginnt. Dies bedeutet, dass das Steuerelement und alle seine untergeordneten Elemente und deren untergeordneten Elemente zuerst diese benutzerdefinierte Designressource überprüfen, bevor sie auf das Projekt und die Standarddesigns zurückgreifen.

Bemerkung

Anstatt die Projekteinstellung zu ändern, können Sie die Ressource für das benutzerdefinierte Thema auf den obersten Kontroll-Node Ihres gesamten UI-Zweigs setzen, um fast denselben Effekt zu erzielen. Während es sich im laufenden Projekt wie erwartet verhält, werden einzelne Szenen immer noch mit dem Standardthema angezeigt, wenn sie in der Vorschau angezeigt oder direkt ausgeführt werden. Um dies zu beheben, können Sie dieselbe Themenressource auf das Wurzel-Steuerelement jeder einzelnen Szene setzen.

Sie können zum Beispiel einen bestimmten Stil für Schaltflächen in Ihrem Projektthema haben, aber ein anderes Aussehen für Schaltflächen innerhalb eines Popup-Dialogs wünschen. Sie können eine benutzerdefinierte Themenressource auf das Stammsteuerelement Ihres Popups setzen und einen anderen Stil für die Schaltflächen innerhalb dieser Ressource definieren. Solange die Kette der Steuerelement-Nodes zwischen der Wurzel des Popups und den Schaltflächen nicht unterbrochen ist, verwenden diese Schaltflächen die Stile, die in der Themenressource definiert sind, die ihnen am nächsten ist. Alle anderen Steuerelemente werden weiterhin mit dem projektweiten Thema und den Standardthemenstilen formatiert.

Zusammenfassend lässt sich sagen, dass für ein beliebiges Steuerelement das Aussehen der Themenelemente etwa so ablaufen würde:

  1. Prüfung auf lokale Überschreibungen desselben Datentyps und Namens.

  2. Verwendung des Klassennamens des Steuerelements und der Namen der übergeordneten Klassen:

    1. Überprüfen jedes Steuerelements, beginnend mit sich selbst, ob es eine Themeneigenschaft hat;

    2. Ist dies der Fall, wird dieses Thema nach dem passenden Element mit demselben Namen, denselben Daten und demselben Thementyp überprüft;

    3. Wenn es kein benutzerdefiniertes Thema gibt oder das Element nicht vorhanden ist, wird zum übergeordneten Steuerelement gewechselt;

    4. Die Schritte a-c wiederholen, bis die Wurzel des Baums erreicht ist oder ein Nicht-Kontroll-Node erreicht ist.

  3. Verwenden Sie den Klassennamen des Steuerelements, um das projektweite Thema zu überprüfen, falls es vorhanden ist.

  4. Verwenden Sie den Klassennamen des Steuerelements, um das Standardthema zu überprüfen.

Selbst wenn das Element in keinem Thema vorhanden ist, wird ein entsprechender Standardwert für diesen Datentyp zurückgegeben.

Jenseits von Kontrollen

Natürlich sind Themen eine ideale Art von Ressource, um die Konfiguration für etwas Visuelles zu speichern. Während die Unterstützung für das Thema in Steuer-Nodes integriert ist, können andere Nodes sie ebenfalls verwenden, genau wie jede andere Ressource.

Ein Beispiel für die Verwendung von Themen für etwas, das über die Steuerung hinausgeht, kann die Veränderung von Sprites für dieselben Einheiten in verschiedenen Teams in einem Strategiespiel sein. Eine Themen-Ressource kann eine Sammlung von Farben definieren, und Sprites können (mit Hilfe von Skripten) diese Farben verwenden, um die Textur zu zeichnen. Der Hauptvorteil besteht darin, dass man verschiedene Themen mit denselben Themenelementen für rote, blaue und grüne Teams erstellen und sie mit einer einzigen Ressourcenänderung austauschen kann.