Rename GUI to User Interface (UI)
353
tutorials/ui/bbcode_in_richtextlabel.rst
Normal file
@@ -0,0 +1,353 @@
|
||||
.. _doc_bbcode_in_richtextlabel:
|
||||
|
||||
BBCode in RichTextLabel
|
||||
=======================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Label nodes are great for displaying basic text, but they have limits. If you want
|
||||
to change the color of the text, or its alignment, that change affects all of the
|
||||
text in the Label node. You can't have only one part of the text be one color, or
|
||||
only one part of the text be centered. To get around this limitation you would use
|
||||
a :ref:`class_RichTextLabel`.
|
||||
|
||||
:ref:`class_RichTextLabel` allows the display of complex text markup in a Control.
|
||||
It has a built-in API for generating the markup, but can also parse a BBCode.
|
||||
|
||||
Note that the BBCode tags can also be used, to some extent, in the
|
||||
:ref:`XML source of the class reference <doc_updating_the_class_reference>`.
|
||||
|
||||
Using BBCode
|
||||
------------
|
||||
|
||||
For uniformly formatted text you can write in the "Text" property, but if you want
|
||||
to use BBCode markup you should use the "Text" property in the "Bb Code" section
|
||||
instead (``bbcode_text``). Writing to this property will trigger the parsing of your
|
||||
markup to format the text as requested. Before this happens, you need to toggle the
|
||||
"Enabled" checkbox in the "Bb Code" section (``bbcode_enabled``).
|
||||
|
||||
.. image:: img/bbcodeText.png
|
||||
|
||||
For example, ``BBCode [color=blue]blue[/color]`` would render the word "blue" with
|
||||
a blue color.
|
||||
|
||||
.. image:: img/bbcodeDemo.png
|
||||
|
||||
You'll notice that after writing in the BBCode "Text" property the regular "Text"
|
||||
property now has the text without the BBCode. While the text property will be updated
|
||||
by the BBCode property, you can't edit the text property or you'll lose the BBCode
|
||||
markup. All changes to the text must be done in the BBCode parameter.
|
||||
|
||||
.. note::
|
||||
|
||||
For BBCode tags such as ``[b]`` (bold), ``[i]`` (italics) or ``[code]`` to
|
||||
work, you must set up custom fonts for the RichTextLabel node first.
|
||||
|
||||
There are no BBCode tags to control vertical centering of text yet.
|
||||
|
||||
Reference
|
||||
---------
|
||||
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| Command | Tag | Description |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **bold** | ``[b]{text}[/b]`` | Makes {text} bold. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **italics** | ``[i]{text}[/i]`` | Makes {text} italics. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **underline** | ``[u]{text}[/u]`` | Makes {text} underline. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **strikethrough** | ``[s]{text}[/s]`` | Makes {text} strikethrough. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **code** | ``[code]{text}[/code]`` | Makes {text} use the code font (which is typically monospace). |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **center** | ``[center]{text}[/center]`` | Makes {text} horizontally centered. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **right** | ``[right]{text}[/right]`` | Makes {text} horizontally right-aligned. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **fill** | ``[fill]{text}[/fill]`` | Makes {text} fill the RichTextLabel's width. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **indent** | ``[indent]{text}[/indent]`` | Increase the indentation level of {text}. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **url** | ``[url]{url}[/url]`` | Show {url} as such, underline it and make it clickable. |
|
||||
| | | **Must be handled with the "meta_clicked" signal to have an effect.** |
|
||||
| | | See :ref:`doc_bbcode_in_richtextlabel_handling_url_tag_clicks`. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **url (ref)** | ``[url=<url>]{text}[/url]`` | Makes {text} reference <url> (underlined and clickable). |
|
||||
| | | **Must be handled with the "meta_clicked" signal to have an effect.** |
|
||||
| | | See :ref:`doc_bbcode_in_richtextlabel_handling_url_tag_clicks`. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **image** | ``[img]{path}[/img]`` | Insert image at resource {path}. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **resized image** | ``[img=<width>]{path}[/img]`` | Insert image at resource {path} using <width> (keeps ratio). |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **resized image** | ``[img=<width>x<height>]{path}[/img]`` | Insert image at resource {path} using <width>×<height>. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **font** | ``[font=<path>]{text}[/font]`` | Use custom font at <path> for {text}. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **color** | ``[color=<code/name>]{text}[/color]`` | Change {text} color; use name or # format, such as ``#ff00ff``. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **table** | ``[table=<number>]{cells}[/table]`` | Creates a table with <number> of columns. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
| **cell** | ``[cell]{text}[/cell]`` | Adds cells with the {text} to the table. |
|
||||
+-----------------------+-----------------------------------------------------------+--------------------------------------------------------------------------+
|
||||
|
||||
Built-in color names
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
List of valid color names for the [color=<name>] tag:
|
||||
|
||||
- aqua
|
||||
- black
|
||||
- blue
|
||||
- fuchsia
|
||||
- gray
|
||||
- green
|
||||
- lime
|
||||
- maroon
|
||||
- navy
|
||||
- purple
|
||||
- red
|
||||
- silver
|
||||
- teal
|
||||
- white
|
||||
- yellow
|
||||
|
||||
Hexadecimal color codes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For opaque RGB colors, any valid 6-digit hexadecimal code is supported, e.g. ``[color=#ffffff]white[/color]``.
|
||||
Short RGB color codes such as ``#6f2`` (equivalent to ``#66ff22``) are also supported.
|
||||
|
||||
For transparent RGB colors, any 8-digit hexadecimal code can be used, e.g. ``[color=#88ffffff]translucent white[/color]``.
|
||||
In this case, note that the alpha channel is the **first** component of the color code, not the last one.
|
||||
Short RGBA color codes such as ``#86f2`` (equivalent to ``#8866ff22``) are also supported.
|
||||
|
||||
.. _doc_bbcode_in_richtextlabel_handling_url_tag_clicks:
|
||||
|
||||
Handling ``[url]`` tag clicks
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, ``[url]`` tags do nothing when clicked. This is to allow flexible use
|
||||
of ``[url]`` tags rather than limiting them to opening URLs in a web browser.
|
||||
|
||||
To handle clicked ``[url]`` tags, connect the RichTextLabel node's
|
||||
:ref:`meta_clicked <class_RichTextLabel_signal_meta_clicked>` signal to a script function.
|
||||
|
||||
For example, the following method can be connected to ``meta_clicked`` to open
|
||||
clicked URLs using the user's default web browser::
|
||||
|
||||
# This assumes RichTextLabel's `meta_clicked` signal was connected to
|
||||
# the function below using the signal connection dialog.
|
||||
func _richtextlabel_on_meta_clicked(meta):
|
||||
# `meta` is not guaranteed to be a String, so convert it to a String
|
||||
# to avoid script errors at run-time.
|
||||
OS.shell_open(str(meta))
|
||||
|
||||
For more advanced use cases, it's also possible to store JSON in an ``[url]``
|
||||
tag's option and parse it in the function that handles the ``meta_clicked`` signal.
|
||||
For example: ``[url={"example": "value"}]JSON[/url]``
|
||||
|
||||
Image vertical offset
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You use a custom font for your image in order to align it vertically.
|
||||
|
||||
1. Create a ``BitmapFont`` resource
|
||||
2. Set this bitmap font with a positive value for the ``ascent`` property, that's your height offset
|
||||
3. Set the BBCode tag this way: ``[font=<font-path>][img]{image-path}[/img][/font]``
|
||||
|
||||
Animation effects
|
||||
-----------------
|
||||
|
||||
BBCode can also be used to create different text animation effects. Five customizable
|
||||
effects are provided out of the box, and you can easily create your own.
|
||||
|
||||
Wave
|
||||
~~~~
|
||||
|
||||
.. image:: img/wave.png
|
||||
|
||||
Wave makes the text go up and down. Its tag format is ``[wave amp=50 freq=2][/wave]``.
|
||||
``amp`` controls how high and low the effect goes, and ``freq`` controls how fast the
|
||||
text goes up and down.
|
||||
|
||||
Tornado
|
||||
~~~~~~~
|
||||
|
||||
.. image:: img/tornado.png
|
||||
|
||||
Tornao makes the text move around in a circle. Its tag format is
|
||||
``[tornado radius=5 freq=2][/tornado]``.
|
||||
``radius`` is the radius of the circle that controls the offset, ``freq`` is how
|
||||
fast the text moves in a circle.
|
||||
|
||||
Shake
|
||||
~~~~~
|
||||
|
||||
.. image:: img/shake.png
|
||||
|
||||
Shake makes the text shake. Its tag format is ``[shake rate=5 level=10][/shake]``.
|
||||
``rate`` controls how fast the text shakes, ``level`` controls how far the text is
|
||||
offset from the origin.
|
||||
|
||||
Fade
|
||||
~~~~
|
||||
|
||||
.. image:: img/fade.png
|
||||
|
||||
Fade creates a fade effect over the text that is not animated. Its tag format is
|
||||
``[fade start=4 length=14][/fade]``.
|
||||
``start`` controls the starting position of the falloff relative to where the fade
|
||||
command is inserted, ``length`` controls over how many characters should the fade
|
||||
out take place.
|
||||
|
||||
Rainbow
|
||||
~~~~~~~
|
||||
|
||||
.. image:: img/rainbow.png
|
||||
|
||||
Rainbow gives the text a rainbow color that changes over time. Its tag format is
|
||||
``[rainbow freq=0.2 sat=10 val=20][/rainbow]``.
|
||||
``freq`` is the number of full rainbow cycles per second, ``sat`` is the saturation
|
||||
of the rainbow, ``val`` is the value of the rainbow.
|
||||
|
||||
Custom BBCode tags and text effects
|
||||
-----------------------------------
|
||||
|
||||
You can extend the :ref:`class_RichTextEffect` resource type to create your own custom
|
||||
BBCode tags. You begin by extending the :ref:`class_RichTextEffect` resource type. Add
|
||||
the ``tool`` prefix to your GDScript file if you wish to have these custom effects run
|
||||
within the editor itself. The RichTextLabel does not need to have a script attached,
|
||||
nor does it need to be running in ``tool`` mode. The new effect will be activable in
|
||||
the Inspector through the **Custom Effects** property.
|
||||
|
||||
There is only one function that you need to extend: ``_process_custom_fx(char_fx)``.
|
||||
Optionally, you can also provide a custom BBCode identifier simply by adding a member
|
||||
name ``bbcode``. The code will check the ``bbcode`` property automatically or will
|
||||
use the name of the file to determine what the BBCode tag should be.
|
||||
|
||||
``_process_custom_fx``
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is where the logic of each effect takes place and is called once per character
|
||||
during the draw phase of text rendering. This passes in a :ref:`class_CharFXTransform`
|
||||
object, which holds a few variables to control how the associated character is rendered:
|
||||
|
||||
- ``identity`` specifies which custom effect is being processed. You should use that for
|
||||
code flow control.
|
||||
- ``relative_index`` tells you how far into a given custom effect block you are in as an
|
||||
index.
|
||||
- ``absolute_index`` tells you how far into the entire text you are as an index.
|
||||
- ``elapsed_time`` is the total amount of time the text effect has been running.
|
||||
- ``visible`` will tell you whether the character is visible or not and will also allow you
|
||||
to hide a given portion of text.
|
||||
- ``offset`` is an offset position relative to where the given character should render under
|
||||
normal circumstances.
|
||||
- ``color`` is the color of a given character.
|
||||
- Finally, ``env`` is a :ref:`class_Dictionary` of parameters assigned to a given custom
|
||||
effect. You can use :ref:`get() <class_Dictionary_method_get>` with an optional default value
|
||||
to retrieve each parameter, if specified by the user. For example ``[custom_fx spread=0.5
|
||||
color=#FFFF00]test[/custom_fx]`` would have a float ``spread`` and Color ``color``
|
||||
parameters in its ` `env`` Dictionary. See below for more usage examples.
|
||||
|
||||
The last thing to note about this function is that it is necessary to return a boolean
|
||||
``true`` value to verify that the effect processed correctly. This way, if there's a problem
|
||||
with rendering a given character, it will back out of rendering custom effects entirely until
|
||||
the user fixes whatever error cropped up in their custom effect logic.
|
||||
|
||||
Here are some examples of custom effects:
|
||||
|
||||
Ghost
|
||||
~~~~~
|
||||
|
||||
::
|
||||
|
||||
tool
|
||||
extends RichTextEffect
|
||||
class_name RichTextGhost
|
||||
|
||||
# Syntax: [ghost freq=5.0 span=10.0][/ghost]
|
||||
|
||||
# Define the tag name.
|
||||
var bbcode = "ghost"
|
||||
|
||||
func _process_custom_fx(char_fx):
|
||||
# Get parameters, or use the provided default value if missing.
|
||||
var speed = char_fx.env.get("freq", 5.0)
|
||||
var span = char_fx.env.get("span", 10.0)
|
||||
|
||||
var alpha = sin(char_fx.elapsed_time * speed + (char_fx.absolute_index / span)) * 0.5 + 0.5
|
||||
char_fx.color.a = alpha
|
||||
return true
|
||||
|
||||
Pulse
|
||||
~~~~~
|
||||
|
||||
::
|
||||
|
||||
tool
|
||||
extends RichTextEffect
|
||||
class_name RichTextPulse
|
||||
|
||||
# Syntax: [pulse color=#00FFAA height=0.0 freq=2.0][/pulse]
|
||||
|
||||
# Define the tag name.
|
||||
var bbcode = "pulse"
|
||||
|
||||
func _process_custom_fx(char_fx):
|
||||
# Get parameters, or use the provided default value if missing.
|
||||
var color = char_fx.env.get("color", char_fx.color)
|
||||
var height = char_fx.env.get("height", 0.0)
|
||||
var freq = char_fx.env.get("freq", 2.0)
|
||||
|
||||
var sined_time = (sin(char_fx.elapsed_time * freq) + 1.0) / 2.0
|
||||
var y_off = sined_time * height
|
||||
color.a = 1.0
|
||||
char_fx.color = char_fx.color.linear_interpolate(color, sined_time)
|
||||
char_fx.offset = Vector2(0, -1) * y_off
|
||||
return true
|
||||
|
||||
Matrix
|
||||
~~~~~~
|
||||
|
||||
::
|
||||
|
||||
tool
|
||||
extends RichTextEffect
|
||||
class_name RichTextMatrix
|
||||
|
||||
# Syntax: [matrix clean=2.0 dirty=1.0 span=50][/matrix]
|
||||
|
||||
# Define the tag name.
|
||||
var bbcode = "matrix"
|
||||
|
||||
func _process_custom_fx(char_fx):
|
||||
# Get parameters, or use the provided default value if missing.
|
||||
var clear_time = char_fx.env.get("clean", 2.0)
|
||||
var dirty_time = char_fx.env.get("dirty", 1.0)
|
||||
var text_span = char_fx.env.get("span", 50)
|
||||
|
||||
var value = char_fx.character
|
||||
|
||||
var matrix_time = fmod(char_fx.elapsed_time + (char_fx.absolute_index / float(text_span)), \
|
||||
clear_time + dirty_time)
|
||||
|
||||
matrix_time = 0.0 if matrix_time < clear_time else \
|
||||
(matrix_time - clear_time) / dirty_time
|
||||
|
||||
if value >= 65 && value < 126 && matrix_time > 0.0:
|
||||
value -= 65
|
||||
value = value + int(1 * matrix_time * (126 - 65))
|
||||
value %= (126 - 65)
|
||||
value += 65
|
||||
char_fx.character = value
|
||||
return true
|
||||
|
||||
This will add a few new BBCode commands, which can be used like so:
|
||||
|
||||
::
|
||||
|
||||
[center][ghost]This is a custom [matrix]effect[/matrix][/ghost] made in
|
||||
[pulse freq=5.0 height=2.0][pulse color=#00FFAA freq=2.0]GDScript[/pulse][/pulse].[/center]
|
||||
9
tutorials/ui/control_node_gallery.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
Control node gallery
|
||||
====================
|
||||
|
||||
Here is a list of common Control nodes with their name next to them:
|
||||
|
||||
.. image:: /img/control_gallery.png
|
||||
|
||||
The Control Gallery demo pictured above can be found
|
||||
`on GitHub <https://github.com/godotengine/godot-demo-projects/tree/master/gui/control_gallery>`__.
|
||||
228
tutorials/ui/custom_gui_controls.rst
Normal file
@@ -0,0 +1,228 @@
|
||||
.. _doc_custom_gui_controls:
|
||||
|
||||
Custom GUI controls
|
||||
===================
|
||||
|
||||
So many controls...
|
||||
-------------------
|
||||
|
||||
Yet there are never enough. Creating your own custom controls that act
|
||||
just the way you want them to is an obsession of almost every GUI
|
||||
programmer. Godot provides plenty of them, but they may not work exactly
|
||||
the way you want. Before contacting the developers with a pull-request
|
||||
to support diagonal scrollbars, at least it will be good to know how to
|
||||
create these controls easily from script.
|
||||
|
||||
Drawing
|
||||
-------
|
||||
|
||||
For drawing, it is recommended to check the :ref:`doc_custom_drawing_in_2d` tutorial.
|
||||
The same applies. Some functions are worth mentioning due to their
|
||||
usefulness when drawing, so they will be detailed next:
|
||||
|
||||
Checking control size
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Unlike 2D nodes, "size" is important with controls, as it helps to
|
||||
organize them in proper layouts. For this, the
|
||||
:ref:`Control.rect_size <class_Control_property_rect_size>`
|
||||
property is provided. Checking it during ``_draw()`` is vital to ensure
|
||||
everything is kept in-bounds.
|
||||
|
||||
Checking focus
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Some controls (such as buttons or text editors) might provide input
|
||||
focus for keyboard or joypad input. Examples of this are entering text
|
||||
or pressing a button. This is controlled with the
|
||||
:ref:`Control.focus_mode <class_Control_property_focus_mode>`
|
||||
property. When drawing, and if the control supports input focus, it is
|
||||
always desired to show some sort of indicator (highlight, box, etc.) to
|
||||
indicate that this is the currently focused control. To check for this
|
||||
status, the :ref:`Control.has_focus() <class_Control_method_has_focus>` method
|
||||
exists. Example
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _draw():
|
||||
if has_focus():
|
||||
draw_selected()
|
||||
else:
|
||||
draw_normal()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Draw()
|
||||
{
|
||||
if (HasFocus())
|
||||
{
|
||||
DrawSelected()
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawNormal();
|
||||
}
|
||||
}
|
||||
|
||||
Sizing
|
||||
------
|
||||
|
||||
As mentioned before, size is important to controls. This allows
|
||||
them to lay out properly, when set into grids, containers, or anchored.
|
||||
Controls, most of the time, provide a *minimum size* to help properly
|
||||
lay them out. For example, if controls are placed vertically on top of
|
||||
each other using a :ref:`VBoxContainer <class_VBoxContainer>`,
|
||||
the minimum size will make sure your custom control is not squished by
|
||||
the other controls in the container.
|
||||
|
||||
To provide this callback, just override
|
||||
:ref:`Control.get_minimum_size() <class_Control_method_get_minimum_size>`,
|
||||
for example:
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func get_minimum_size():
|
||||
return Vector2(30, 30)
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override Vector2 _GetMinimumSize()
|
||||
{
|
||||
return new Vector2(20, 20);
|
||||
}
|
||||
|
||||
Alternatively, set it using a function:
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _ready():
|
||||
set_custom_minimum_size(Vector2(30, 30))
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
SetCustomMinimumSize(new Vector2(20, 20));
|
||||
}
|
||||
|
||||
Input
|
||||
-----
|
||||
|
||||
Controls provide a few helpers to make managing input events much easier
|
||||
than regular nodes.
|
||||
|
||||
Input events
|
||||
~~~~~~~~~~~~
|
||||
|
||||
There are a few tutorials about input before this one, but it's worth
|
||||
mentioning that controls have a special input method that only works
|
||||
when:
|
||||
|
||||
- The mouse pointer is over the control.
|
||||
- The button was pressed over this control (control always
|
||||
captures input until button is released)
|
||||
- Control provides keyboard/joypad focus via
|
||||
:ref:`Control.focus_mode <class_Control_property_focus_mode>`.
|
||||
|
||||
This function is
|
||||
:ref:`Control._gui_input() <class_Control_method__gui_input>`.
|
||||
Simply override it in your control. No processing needs to be set.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends Control
|
||||
|
||||
func _gui_input(event):
|
||||
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.pressed:
|
||||
print("Left mouse button was pressed!")
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _GuiInput(InputEvent @event)
|
||||
{
|
||||
if (@event is InputEventMouseButton mbe && mbe.ButtonIndex == (int)ButtonList.Left && mbe.Pressed)
|
||||
{
|
||||
GD.Print("Left mouse button was pressed!");
|
||||
}
|
||||
}
|
||||
|
||||
For more information about events themselves, check the :ref:`doc_inputevent`
|
||||
tutorial.
|
||||
|
||||
Notifications
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Controls also have many useful notifications for which no dedicated callback
|
||||
exists, but which can be checked with the _notification callback:
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _notification(what):
|
||||
match what:
|
||||
NOTIFICATION_MOUSE_ENTER:
|
||||
pass # Mouse entered the area of this control.
|
||||
NOTIFICATION_MOUSE_EXIT:
|
||||
pass # Mouse exited the area of this control.
|
||||
NOTIFICATION_FOCUS_ENTER:
|
||||
pass # Control gained focus.
|
||||
NOTIFICATION_FOCUS_EXIT:
|
||||
pass # Control lost focus.
|
||||
NOTIFICATION_THEME_CHANGED:
|
||||
pass # Theme used to draw the control changed;
|
||||
# update and redraw is recommended if using a theme.
|
||||
NOTIFICATION_VISIBILITY_CHANGED:
|
||||
pass # Control became visible/invisible;
|
||||
# check new status with is_visible().
|
||||
NOTIFICATION_RESIZED:
|
||||
pass # Control changed size; check new size
|
||||
# with get_size().
|
||||
NOTIFICATION_MODAL_CLOSE:
|
||||
pass # For modal pop-ups, notification
|
||||
# that the pop-up was closed.
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Notification(int what)
|
||||
{
|
||||
switch (what)
|
||||
{
|
||||
case NotificationMouseEnter:
|
||||
// Mouse entered the area of this control.
|
||||
break;
|
||||
|
||||
case NotificationMouseExit:
|
||||
// Mouse exited the area of this control.
|
||||
break;
|
||||
|
||||
case NotificationFocusEnter:
|
||||
// Control gained focus.
|
||||
break;
|
||||
|
||||
case NotificationFocusExit:
|
||||
// Control lost focus.
|
||||
break;
|
||||
|
||||
case NotificationThemeChanged:
|
||||
// Theme used to draw the control changed;
|
||||
// update and redraw is recommended if using a theme.
|
||||
break;
|
||||
|
||||
case NotificationVisibilityChanged:
|
||||
// Control became visible/invisible;
|
||||
// check new status with is_visible().
|
||||
break;
|
||||
|
||||
case NotificationResized:
|
||||
// Control changed size; check new size with get_size().
|
||||
break;
|
||||
|
||||
case NotificationModalClose:
|
||||
// For modal pop-ups, notification that the pop-up was closed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
BIN
tutorials/ui/files/skin_assets.zip
Normal file
181
tutorials/ui/gui_containers.rst
Normal file
@@ -0,0 +1,181 @@
|
||||
.. _doc_gui_containers:
|
||||
|
||||
Using Containers
|
||||
================
|
||||
|
||||
:ref:`Anchors <doc_size_and_anchors>` are an efficient way to handle
|
||||
different aspect ratios for basic multiple resolution handling in GUIs,
|
||||
|
||||
For more complex user interfaces, they can become difficult to use.
|
||||
|
||||
This is often the case of games, such as RPGs, online chats, tycoons or simulations. Another
|
||||
common case where more advanced layout features may be required is in-game tools (or simply just tools).
|
||||
|
||||
All these situations require a more capable OS-like user interface, with advanced layout and formatting.
|
||||
For that, :ref:`Containers <class_container>` are more useful.
|
||||
|
||||
Container layout
|
||||
----------------
|
||||
|
||||
Containers provide a huge amount of layout power (as an example, the Godot editor user interface is entirely done using them):
|
||||
|
||||
.. image:: img/godot_containers.png
|
||||
|
||||
When a :ref:`Container <class_Container>`-derived node is used, all children :ref:`Control <class_Control>` nodes give up their
|
||||
own positioning ability. This means the *Container* will control their positioning and any attempt to manually alter these
|
||||
nodes will be either ignored or invalidated the next time their parent is resized.
|
||||
|
||||
Likewise, when a *Container* derived node is resized, all its children will be re-positioned according to it,
|
||||
with a behavior based on the type of container used:
|
||||
|
||||
.. image:: img/container_example.gif
|
||||
|
||||
Example of *HBoxContainer* resizing children buttons.
|
||||
|
||||
The real strength of containers is that they can be nested (as nodes), allowing the creation of very complex layouts that resize effortlessly.
|
||||
|
||||
Size flags
|
||||
----------
|
||||
|
||||
When adding a node to a container, the way the container treats each child depends mainly on their *size flags*. These flags
|
||||
can be found by inspecting any control that is a child of a *Container*.
|
||||
|
||||
.. image:: img/container_size_flags.png
|
||||
|
||||
Size flags are independent for vertical and horizontal sizing and not all containers make use of them (but most do):
|
||||
|
||||
* **Fill**: Ensures the control *fills* the designated area within the container. No matter if
|
||||
a control *expands* or not (see below), it will only *fill* the designated area when this is toggled on (it is by default).
|
||||
* **Expand**: Attempts to use as much space as possible in the parent container (in each axis).
|
||||
Controls that don't expand will be pushed away by those that do. Between expanding controls, the
|
||||
amount of space they take from each other is determined by the *Ratio* (see below).
|
||||
* **Shrink Center** When expanding (and if not filling), try to remain at the center of the expanded
|
||||
area (by default it remains at the left or top).
|
||||
* **Ratio** Simple ratio of how much expanded controls take up the available space in relation to each
|
||||
other. A control with "2", will take up twice as much available space as one with "1".
|
||||
|
||||
Experimenting with these flags and different containers is recommended to get a better grasp on how they work.
|
||||
|
||||
Container types
|
||||
---------------
|
||||
|
||||
Godot provides several container types out of the box as they serve different purposes:
|
||||
|
||||
Box Containers
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Arranges child controls vertically or horizontally (via :ref:`HBoxContainer <class_HBoxContainer>` and
|
||||
:ref:`VBoxContainer <class_VBoxContainer>`). In the opposite of the designated direction
|
||||
(as in, vertical for an horizontal container), it just expands the children.
|
||||
|
||||
.. image:: img/containers_box.png
|
||||
|
||||
These containers make use of the *Ratio* property for children with the *Expand* flag set.
|
||||
|
||||
Grid Container
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Arranges child controls in a grid layout (via :ref:`GridContainer <class_GridContainer>`, amount
|
||||
of columns must be specified). Uses both the vertical and horizontal expand flags.
|
||||
|
||||
.. image:: img/containers_grid.png
|
||||
|
||||
Margin Container
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Child controls are expanded towards the bounds of this control (via
|
||||
:ref:`MarginContainer <class_MarginContainer>`). Padding will be added on the margins
|
||||
depending on the theme configuration.
|
||||
|
||||
.. image:: img/containers_margin.png
|
||||
|
||||
Again, keep in mind that the margins are a *Theme* value, so they need to be edited from the
|
||||
constants overrides section of each control:
|
||||
|
||||
.. image:: img/containers_margin_constants.png
|
||||
|
||||
Tab Container
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Allows you to place several child controls stacked on top of each other (via
|
||||
:ref:`TabContainer <class_TabContainer>`), with only the *current* one visible.
|
||||
|
||||
.. image:: img/containers_tab.png
|
||||
|
||||
Changing the *current* one is done via tabs located at the top of the container, via clicking:
|
||||
|
||||
.. image:: img/containers_tab_click.gif
|
||||
|
||||
The titles are generated from the node names by default (although they can be overridden via *TabContainer* API).
|
||||
|
||||
Settings such as tab placement and *StyleBox* can be modified in the *TabContainer* theme overrides.
|
||||
|
||||
Split Container
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Accepts only one or two children controls, then places them side to side with a divisor
|
||||
(via :ref:`HSplitContainer <class_HSplitContainer>` and :ref:`VSplitContainer <class_VSplitContainer>`).
|
||||
Respects both horizontal and vertical flags, as well as *Ratio*.
|
||||
|
||||
.. image:: img/containers_split.png
|
||||
|
||||
The divisor can be dragged around to change the size relation between both children:
|
||||
|
||||
.. image:: img/containers_split_drag.gif
|
||||
|
||||
|
||||
PanelContainer
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Simple container that draws a *StyleBox*, then expands children to cover its whole area
|
||||
(via :ref:`PanelContainer <class_PanelContainer>`, respecting the *StyleBox* margins).
|
||||
It respects both the horizontal and vertical size flags.
|
||||
|
||||
.. image:: img/containers_panel.png
|
||||
|
||||
This container is useful as top-level, or just to add custom backgrounds to sections of a layout.
|
||||
|
||||
ScrollContainer
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Accepts a single child node. If this node is bigger than the container, scrollbars will be added
|
||||
to allow panning the node around (via :ref:`ScrollContainer <class_ScrollContainer>`). Both
|
||||
vertical and horizontal size flags are respected, and the behavior can be turned on or off
|
||||
per axis in the properties.
|
||||
|
||||
.. image:: img/containers_scroll.png
|
||||
|
||||
Mouse wheel and touch drag (when touch is available) are also valid ways to pan the child control around.
|
||||
|
||||
.. image:: img/containers_center_pan.gif
|
||||
|
||||
As in the example above, one of the most common ways to use this container is together with a *VBoxContainer* as child.
|
||||
|
||||
|
||||
ViewportContainer
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
This is a special control that will only accept a single *Viewport* node as child, and it will display
|
||||
it as if it was an image (via :ref:`ViewportContainer <class_ViewportContainer>`).
|
||||
|
||||
Creating custom Containers
|
||||
--------------------------
|
||||
|
||||
It is possible to easily create a custom container using script. Here is an example of a simple container that fits children
|
||||
to its rect size:
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
extends Container
|
||||
|
||||
func _notification(what):
|
||||
if what == NOTIFICATION_SORT_CHILDREN:
|
||||
# Must re-sort the children
|
||||
for c in get_children():
|
||||
# Fit to own size
|
||||
fit_child_in_rect( c, Rect2( Vector2(), rect_size ) )
|
||||
|
||||
func set_some_setting():
|
||||
# Some setting changed, ask for children re-sort
|
||||
queue_sort()
|
||||
79
tutorials/ui/gui_navigation.rst
Normal file
@@ -0,0 +1,79 @@
|
||||
.. _doc_gui_navigation:
|
||||
|
||||
Keyboard/Controller Navigation and Focus
|
||||
========================================
|
||||
|
||||
It is a common requirement for a user interface to have full keyboard
|
||||
and controller support for navigation and interaction. There are two main
|
||||
reasons why this is beneficial for projects: improved accessibility (not everyone
|
||||
can use mouse or touch controls for interactions), and getting your project
|
||||
ready for :ref:`consoles <doc_consoles>` (or just for people who prefer
|
||||
to game with a controller on PC).
|
||||
|
||||
Navigating between UI elements with keyboard or controller is done by
|
||||
changing which node is actively selected. This is also called changing UI focus.
|
||||
Every :ref:`Control <class_Control>` node in Godot is capable of having focus.
|
||||
By default, some control nodes have the ability to automatically grab focus
|
||||
reacting to built-in UI actions such as ``ui_up``, ``ui_down``, ``ui_focus_next``, etc.
|
||||
These actions can be seen in the project settings in the input map and can be modified.
|
||||
|
||||
.. warning::
|
||||
|
||||
Because these actions are used for focus they should not be used for any
|
||||
gameplay code.
|
||||
|
||||
Node settings
|
||||
-------------
|
||||
|
||||
In addition to the built-in logic, you can define what is known as focus neighbors
|
||||
for each individual control node. This allows to finely tune the path the UI focus
|
||||
takes across the user interface of your project. The settings for individual
|
||||
nodes can be found in the Inspector dock, under the "Focus" category of the
|
||||
"Control" section.
|
||||
|
||||
.. image:: img/focus_settings.png
|
||||
|
||||
Neighbor options are used to define nodes for 4-directional navigation, such
|
||||
as using arrow keys or a D-pad on a controller. For example, the bottom neighbor
|
||||
will be used when navigating down with the down arrow or by pushing down on
|
||||
the D-pad. The "Next" and "Previous" options are used with the focus shift button,
|
||||
such as :kbd:`Tab` on desktop operating systems.
|
||||
|
||||
.. note::
|
||||
A node can lose focus if it becomes hidden.
|
||||
|
||||
The mode setting defines how a node can be focused. **All** means a node can
|
||||
be focused by clicking on it with the mouse, or selecting it with a keyboard
|
||||
or controller. **Click** means it can only be focused on by clicking on it.
|
||||
Finally, **None** means it can't be focused at all. Different control nodes have
|
||||
different default settings for this based on how they are typically used, for
|
||||
example, :ref:`Label <class_Label>` nodes are set to "None" by default,
|
||||
while :ref:`buttons <class_Button>` are set to "All".
|
||||
|
||||
Make sure to properly configure your scenes for focus and navigation. If a node has
|
||||
no focus neighbor configured, the engine will try to guess the next control automatically.
|
||||
This may result in unintended behavior, especially in a complex user interface that doesn't
|
||||
have well-defined vertical or horizontal navigation flow.
|
||||
|
||||
Necessary code
|
||||
--------------
|
||||
|
||||
For keyboard and controller navigation to work correctly, any node must be focused on
|
||||
using code when the scene starts. Without doing this, pressing buttons or keys won't
|
||||
do anything. Here is a basic example of setting initial focus with code:
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
func _ready():
|
||||
$StartButton.grab_focus()
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
GetNode<Button>("StartButton").GrabFocus();
|
||||
}
|
||||
|
||||
Now when the scene starts the "Start Button" node will be focused, and the keyboard
|
||||
or a controller can be used to navigate between it and other UI elements.
|
||||
221
tutorials/ui/gui_skinning.rst
Normal file
@@ -0,0 +1,221 @@
|
||||
.. _doc_gui_skinning:
|
||||
|
||||
Introduction to GUI skinning
|
||||
============================
|
||||
|
||||
It is essential for a game to provide clear, informative, and yet visually
|
||||
pleasing user interface to its players. While :ref:`Control <class_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:
|
||||
|
||||
.. figure:: img/tank-kings-by-winterpixel-games.png
|
||||
:align: center
|
||||
|
||||
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.
|
||||
|
||||
Basics of themes
|
||||
----------------
|
||||
|
||||
The skinning system is driven by the :ref:`Theme <class_Theme>` resource. Every
|
||||
Godot project has an inherent default theme that contains the settings used by
|
||||
the built-in control nodes. This is what gives the controls their distinct look
|
||||
out of the box. A theme only describes the configuration, however, and it is still
|
||||
the job of each individual control to use that configuration in the way it requires
|
||||
to display itself. This is important to remember when implementing
|
||||
:ref:`your own custom controls <doc_custom_gui_controls>`.
|
||||
|
||||
.. note::
|
||||
Even the Godot editor itself relies on the default theme. But it doesn't look the
|
||||
same as a Godot project, because it applies its own heavily customized theme on top
|
||||
of the default one. In principle, this works exactly like it would in your game
|
||||
as explained :ref:`below <doc_gui_theme_in_project>`.
|
||||
|
||||
Theme items
|
||||
~~~~~~~~~~~
|
||||
|
||||
The configuration that is stored in a theme consists of theme items. Each item has
|
||||
a unique name and must be one of the following data types:
|
||||
|
||||
- **Color**
|
||||
|
||||
A :ref:`color <class_Color>` value, which is often used for fonts
|
||||
and backgrounds. Colors can also be used for modulation of controls
|
||||
and icons.
|
||||
|
||||
- **Constant**
|
||||
|
||||
An integer value, which can be used either for numeric properties of
|
||||
controls (such as the item separation in a :ref:`BoxContainer <class_BoxContainer>`),
|
||||
or for boolean flags (such as the drawing of relationship lines in a :ref:`Tree <class_Tree>`).
|
||||
|
||||
- **Font**
|
||||
|
||||
A :ref:`font <class_Font>` resource, which is used by controls that
|
||||
display text. Fonts contain most text rendering settings, except for
|
||||
its size and color. On top of that, alignment and text direction are
|
||||
controlled by individual controls.
|
||||
|
||||
- **Icon**
|
||||
|
||||
A :ref:`texture <class_Texture>` resource, which is normally used
|
||||
to display an icon (on a :ref:`Button <class_Button>`, for example).
|
||||
|
||||
- **StyleBox**
|
||||
|
||||
A :ref:`StyleBox <class_StyleBox>` resource, a collection of configuration
|
||||
options which define the way a UI panel should be displayed. This is
|
||||
not limited to the :ref:`Panel <class_Panel>` control, as styleboxes
|
||||
are 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 item
|
||||
is defined by its name, its data type and its theme type. This combination
|
||||
must be unique within the theme. For example, there cannot be two color items named
|
||||
``font_color`` in a type called ``Label``, but there can be another ``font_color``
|
||||
item 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 above
|
||||
contains actual theme items present in the default theme. You can refer to the
|
||||
**Theme Properties** section in the class reference for each control to see
|
||||
which items are available to it and its child classes.
|
||||
|
||||
.. note::
|
||||
Child classes can use theme items defined for their parent class (``Button``
|
||||
and its derivatives being a good example of that). In fact, every control can
|
||||
use every theme item of any theme type, if it needs to (but for the clarity and
|
||||
predictability 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 omit
|
||||
the 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 allows
|
||||
changes to the parent class, such as ``Button``, to affect all derived
|
||||
classes without the need to customize every one of them.
|
||||
|
||||
You can also define your own theme types, and additionally customize both built-in
|
||||
controls and your own controls. Because built-in controls have no knowledge of
|
||||
your custom theme types, you must utilize scripts to access those items. All control
|
||||
nodes have several methods that allow to fetch theme items from the theme that
|
||||
is applied to them. Those methods accept the theme type as one of the arguments.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript
|
||||
|
||||
var accent_color = get_color("accent_color", "MyType")
|
||||
label.add_color_override("font_color", accent_color)
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
Color accentColor = GetColor("accent_color", "MyType");
|
||||
label.AddColorOverride("font_color", accentColor);
|
||||
|
||||
Customizing a control
|
||||
---------------------
|
||||
|
||||
Each control node can be customized directly without the use of themes. This
|
||||
is called local overrides. Every theme property from the control's class
|
||||
reference can be overridden directly on the control itself, using either
|
||||
the Inspector dock, or scripts. This allows to make granular changes to a
|
||||
particular part of the UI, while not affecting anything else in the project,
|
||||
including this control's children.
|
||||
|
||||
.. figure:: img/themecheck.png
|
||||
:align: center
|
||||
|
||||
Local overrides are less useful for the visual flair of your user interface,
|
||||
especially if you aim for consistency. However, for layout nodes these are
|
||||
essential. Nodes such as :ref:`BoxContainer <class_BoxContainer>` and
|
||||
:ref:`GridContainer <class_GridContainer>` use theme constants for defining
|
||||
separation between their children, and :ref:`MarginContainer <class_MarginContainer>`
|
||||
stores its customizable margins in its theme items.
|
||||
|
||||
Whenever a control has a local theme item override, this is the value that
|
||||
it uses. Values provided by the theme are ignored.
|
||||
|
||||
.. _doc_gui_theme_in_project:
|
||||
|
||||
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:
|
||||
:ref:`gui/theme/custom<class_ProjectSettings_property_gui/theme/custom>` allows you to
|
||||
set a custom project-wide theme, and :ref:`gui/theme/custom_font<class_ProjectSettings_property_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 :ref:`theme <class_Control_property_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.
|
||||
|
||||
.. note::
|
||||
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.
|
||||
|
||||
To sum it up, for an arbitrary control its theme item lookup would look something
|
||||
like this:
|
||||
|
||||
#. Check for local overrides of the same data type and name.
|
||||
#. Using control's class name and parent class names:
|
||||
|
||||
a. Check every control starting from itself and see if it has a theme property set;
|
||||
b. If it does, check that theme for the matching item of the same name, data and theme type;
|
||||
c. If there is no custom theme or it doesn't have the item, move to the parent control;
|
||||
d. Repeat steps a-c. until the root of the tree is reached, or a non-control node is reached.
|
||||
|
||||
#. Using control's class name check the project-wide theme, if it's present.
|
||||
#. Using control's class name check the default theme.
|
||||
|
||||
Even if the item doesn't exist in any theme, a corresponding default value for that
|
||||
data type will be returned.
|
||||
|
||||
Beyond controls
|
||||
---------------
|
||||
|
||||
Naturally, themes are an ideal type of resource for storing configuration for
|
||||
something 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 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.
|
||||
158
tutorials/ui/gui_using_theme_editor.rst
Normal file
@@ -0,0 +1,158 @@
|
||||
.. _doc_gui_using_theme_editor:
|
||||
|
||||
Using the theme editor
|
||||
======================
|
||||
|
||||
This articles explains how to create and manage UI themes using the Godot
|
||||
editor and its theme editor tool. We recommend getting familiar with the
|
||||
basics behind GUI skinning/theming by reading :ref:`doc_gui_skinning` before starting.
|
||||
|
||||
The theme editor is a bottom panel tool that activates automatically, when
|
||||
a :ref:`Theme <class_Theme>` resource is selected for editing. It contains
|
||||
the necessary UI for adding, removing, and adjusting theme types and theme
|
||||
items. It features a preview section for testing your changes live, as well
|
||||
as a window dialog for doing bulk operations of the theme items.
|
||||
|
||||
Creating a theme
|
||||
----------------
|
||||
|
||||
Like any other resources, themes can be created directly in the file system dock
|
||||
by right-clicking and selecting **New Resource...**, then selecting **Theme**
|
||||
and clicking **Create**. This is especially useful for creating project-wide
|
||||
themes.
|
||||
|
||||
Themes also can be created from any control node. Select a control node in the scene
|
||||
hierarchy, then in the inspector go to the ``theme`` property. From there you can
|
||||
select **New Theme**.
|
||||
|
||||
.. figure:: img/new_theme.png
|
||||
:align: center
|
||||
|
||||
This will create an empty theme and open up the theme editor. Keep in mind that
|
||||
resources created this way are bundled with the scene by default. Use the context
|
||||
menu to save the new theme to a file instead.
|
||||
|
||||
While the theme editor provides the tools to manage theme types and items, themes also
|
||||
include the default, fallback font that you can edit only using the Inspector dock.
|
||||
Same applies to the contents of complex resource types, such as :ref:`StyleBoxes <class_StyleBox>`
|
||||
and icons — they open for editing in the Inspector.
|
||||
|
||||
.. figure:: img/default_font.png
|
||||
:align: center
|
||||
|
||||
Theme editor overview
|
||||
---------------------
|
||||
|
||||
.. figure:: img/theme_editor.png
|
||||
:align: center
|
||||
|
||||
The theme editor has two main parts. The main theme editor, located at the bottom of
|
||||
the Godot editor, aims to provide users with tools to quickly create, edit, and delete
|
||||
theme items and types. It gives visual tools for picking and changing controls, abstracting
|
||||
the underlying theme concepts. The **Manage Theme Items** dialog, on the other hand,
|
||||
tries to address the needs of those who want to change themes manually. It's also
|
||||
useful for creating a new editor theme.
|
||||
|
||||
Theme previews
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
The left-hand side of the main editor has a set of preview tabs. The **Default Preview**
|
||||
tab is visible out of the box and contains most of the frequently used controls in various
|
||||
states. Previews are interactive, so intermediate states (e.g. hover) can be previewed as well.
|
||||
|
||||
.. figure:: img/default_preview.png
|
||||
:align: center
|
||||
|
||||
Additional tabs can be created from arbitrary scenes in your project. The scene
|
||||
must have a control node as its root to function as a preview. To add a new tab
|
||||
click the **Add Preview** button and select the saved scene from your file system.
|
||||
|
||||
.. figure:: img/scene_preview.png
|
||||
:align: center
|
||||
|
||||
If you make changes to the scene, they will not be reflected in the preview
|
||||
automatically. To update the preview click the reload button on the toolbar.
|
||||
|
||||
Previews can also be used to quickly select the theme type to edit. Select the
|
||||
picker tool from the toolbar and hover over the preview area to highlight control
|
||||
nodes. Highlighted control nodes display their class name. Clicking on the highlighted
|
||||
control opens it for editing on the right-hand side.
|
||||
|
||||
.. figure:: img/theme_preview_picker.png
|
||||
:align: center
|
||||
|
||||
Theme types and items
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The right-hand side of them theme editor provides a list of theme types available
|
||||
in the edited theme resource, and the contents of the selected type. The list of
|
||||
type's items is divided into several tabs, corresponding to each data type available
|
||||
in the theme (colors, constants, styles, etc.). If the **Show Default** option is
|
||||
enabled, then for each built-in type its default theme values are displayed, greyed
|
||||
out. If the option is disabled, only the items available in the edited theme itself
|
||||
are displayed.
|
||||
|
||||
.. figure:: img/theme_type_editor.png
|
||||
:align: center
|
||||
|
||||
Individual items from the default theme can be added to the current theme by
|
||||
clicking on the **Override** button next to the item. You can also override all
|
||||
the default items of the selected theme type by clicking on the **Override All**
|
||||
button. Overridden properties can then be removed with the **Remove Item** button.
|
||||
Properties can also be renamed using the **Rename Item** button, and completely
|
||||
custom properties can be added to the list using the text field below it.
|
||||
|
||||
Overridden theme items can be edited directly in the right-hand panel, unless they
|
||||
are resources. Resources have rudimentary controls available for them, but must be
|
||||
edited in the Inspector dock instead.
|
||||
|
||||
.. figure:: img/theme_item_inspector.png
|
||||
:align: center
|
||||
|
||||
Styleboxes have an unique feature available, where you can pin an individual
|
||||
stylebox from the list. Pinned stylebox acts like the leader of the pack, and
|
||||
all styleboxes of the same type are updated alongside it when you change its
|
||||
properties. This allows you to edit properties of several styleboxes at the
|
||||
same time.
|
||||
|
||||
.. figure:: img/theme_pin_the_stylebox.png
|
||||
:align: center
|
||||
|
||||
While theme types can be picked from a preview, they can also be added manually.
|
||||
Clicking the plus button next to the type list opens the **Add item Type** menu.
|
||||
In that menu you can either select a type from the list, or you can enter an
|
||||
arbitrary name to create a custom type. Text field also filters the list of control
|
||||
nodes.
|
||||
|
||||
.. figure:: img/add_item_type.png
|
||||
:align: center
|
||||
|
||||
Manage and import items
|
||||
-----------------------
|
||||
|
||||
Clicking the **Manage Items** button brings up the **Manage Theme Items** dialog. In
|
||||
the **Edit Items** tab you can view and add theme types, as well as view and edit
|
||||
the theme items of the selected type.
|
||||
|
||||
.. figure:: img/manage_items.png
|
||||
:align: center
|
||||
|
||||
You can create, rename and remove individual theme items here by clicking the
|
||||
corresponding **Add X Item** and specifying their name. You can also mass delete
|
||||
theme items either by their data type (using the brush icon in the list) or by
|
||||
their quality. **Remove Class Items** will remove all built-in theme items you
|
||||
have customized for a control node type. **Remove Custom Items** will remove all
|
||||
the custom theme items for the selected type. Finally, **Remove All Items** will
|
||||
remove everything from the type.
|
||||
|
||||
From the **Import Items** tab you can import theme items from other themes. You can
|
||||
import items from the default Godot theme, the Godot editor theme, or another custom
|
||||
theme. You can import individual or multiple items, and you can decide whether to
|
||||
copy or omit their data as well. There are several way you can select and deselect the
|
||||
items, including by hand, by hierarchy, by data type, and everything. Opting to
|
||||
include the data will copy all theme items as they are to your theme. Omitting the data
|
||||
will create the items of the corresponding data type and name, but will leave them empty,
|
||||
creating a template of a theme in a way.
|
||||
|
||||
.. figure:: img/import_items.png
|
||||
:align: center
|
||||
BIN
tutorials/ui/img/add_item_type.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
tutorials/ui/img/anchors.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
tutorials/ui/img/bbcodeDemo.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
tutorials/ui/img/bbcodeText.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
tutorials/ui/img/container_example.gif
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
tutorials/ui/img/container_size_flags.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
tutorials/ui/img/containers_box.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
tutorials/ui/img/containers_center_pan.gif
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
tutorials/ui/img/containers_grid.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
tutorials/ui/img/containers_margin.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
tutorials/ui/img/containers_margin_constants.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
tutorials/ui/img/containers_panel.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
tutorials/ui/img/containers_scroll.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
tutorials/ui/img/containers_split.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
tutorials/ui/img/containers_split_drag.gif
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
tutorials/ui/img/containers_tab.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
tutorials/ui/img/containers_tab_click.gif
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
tutorials/ui/img/default_font.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
tutorials/ui/img/default_preview.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
tutorials/ui/img/fade.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
tutorials/ui/img/focus_settings.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
tutorials/ui/img/godot_containers.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
tutorials/ui/img/import_items.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
tutorials/ui/img/layout_dropdown_menu.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
tutorials/ui/img/manage_items.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
tutorials/ui/img/margin.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
tutorials/ui/img/marginaround.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
tutorials/ui/img/marginend.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
tutorials/ui/img/new_theme.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
tutorials/ui/img/rainbow.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
tutorials/ui/img/sb1.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
tutorials/ui/img/sb2.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
tutorials/ui/img/scene_preview.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
tutorials/ui/img/shake.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
tutorials/ui/img/skinbuttons1.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
tutorials/ui/img/skinbuttons2.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
tutorials/ui/img/tank-kings-by-winterpixel-games.png
Normal file
|
After Width: | Height: | Size: 392 KiB |
BIN
tutorials/ui/img/theme_editor.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
tutorials/ui/img/theme_item_inspector.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
tutorials/ui/img/theme_pin_the_stylebox.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
tutorials/ui/img/theme_preview_picker.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
tutorials/ui/img/theme_type_editor.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
tutorials/ui/img/themecheck.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
tutorials/ui/img/themeci.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
tutorials/ui/img/themeci2.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
tutorials/ui/img/themeci3.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
tutorials/ui/img/tornado.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
tutorials/ui/img/wave.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
36
tutorials/ui/index.rst
Normal file
@@ -0,0 +1,36 @@
|
||||
User Interface (UI)
|
||||
===================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:name: toc-gui-basics
|
||||
|
||||
size_and_anchors
|
||||
gui_containers
|
||||
custom_gui_controls
|
||||
gui_navigation
|
||||
control_node_gallery
|
||||
|
||||
GUI skinning and themes
|
||||
-----------------------
|
||||
|
||||
Godot features an in-depth skinning/theming system for control nodes. The pages in this section
|
||||
explain the benefits of that system and how to set it up in your projects.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:name: toc-gui-skinning
|
||||
|
||||
gui_skinning
|
||||
gui_using_theme_editor
|
||||
|
||||
Control node tutorials
|
||||
----------------------
|
||||
|
||||
The following articles cover specific details of using particular control nodes.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:name: toc-control-nodes-tutorials
|
||||
|
||||
bbcode_in_richtextlabel
|
||||
74
tutorials/ui/size_and_anchors.rst
Normal file
@@ -0,0 +1,74 @@
|
||||
.. _doc_size_and_anchors:
|
||||
|
||||
Size and anchors
|
||||
================
|
||||
|
||||
If a game was always going to be run on the same device and at the same
|
||||
resolution, positioning controls would be a simple matter of setting the
|
||||
position and size of each one of them. Unfortunately, that is rarely the
|
||||
case.
|
||||
|
||||
Only TVs nowadays have a standard resolution and aspect ratio.
|
||||
Everything else, from computer monitors to tablets, portable consoles
|
||||
and mobile phones have different resolutions and aspect ratios.
|
||||
|
||||
There are several ways to handle this, but for now, let's just imagine
|
||||
that the screen resolution has changed and the controls need to be
|
||||
re-positioned. Some will need to follow the bottom of the screen, others
|
||||
the top of the screen, or maybe the right or left margins.
|
||||
|
||||
.. image:: img/anchors.png
|
||||
|
||||
This is done by editing the *margin* properties of controls. Each
|
||||
control has four margins: left, right, bottom and top. By default, all of
|
||||
them represent a distance in pixels relative to the top-left corner of
|
||||
the parent control or (in case there is no parent control) the viewport.
|
||||
|
||||
.. image:: img/margin.png
|
||||
|
||||
When horizontal (left, right) and/or vertical (top, bottom) anchors are
|
||||
changed to 1, the margin values become relative to the bottom-right
|
||||
corner of the parent control or viewport.
|
||||
|
||||
.. image:: img/marginend.png
|
||||
|
||||
Here, the control is set to expand its bottom-right corner with that of
|
||||
the parent, so when re-sizing the parent, the control will always cover
|
||||
it, leaving a 20 pixel margin:
|
||||
|
||||
.. image:: img/marginaround.png
|
||||
|
||||
Centering a control
|
||||
-------------------
|
||||
|
||||
To center a control in its parent, set its anchors to 0.5 and each margin
|
||||
to half of its relevant dimension. For example, the code below shows how
|
||||
a TextureRect can be centered in its parent:
|
||||
|
||||
::
|
||||
|
||||
var rect = TextureRect.new()
|
||||
rect.texture = load("res://icon.png")
|
||||
rect.anchor_left = 0.5
|
||||
rect.anchor_right = 0.5
|
||||
rect.anchor_top = 0.5
|
||||
rect.anchor_bottom = 0.5
|
||||
var texture_size = rect.texture.get_size()
|
||||
rect.margin_left = -texture_size.x / 2
|
||||
rect.margin_right = -texture_size.x / 2
|
||||
rect.margin_top = -texture_size.y / 2
|
||||
rect.margin_bottom = -texture_size.y / 2
|
||||
add_child(rect)
|
||||
|
||||
Setting each anchor to 0.5 moves the reference point for the margins to
|
||||
the center of its parent. From there, we set negative margins so that
|
||||
the control gets its natural size.
|
||||
|
||||
Layout Presets
|
||||
--------------
|
||||
|
||||
Instead of manually adjusting the margin and anchor values, you can use the
|
||||
toolbar's Layout menu, above the viewport. Besides centering, it gives you many
|
||||
options to align and resize control nodes.
|
||||
|
||||
.. image:: img/layout_dropdown_menu.png
|
||||