DEV Community

christine
christine

Posted on • Originally published at christinec-dev.Medium on

The Book of Nodes: UI

Book of Nodes

Below you can find a list of UI nodes that can be used in Godot 4. This is part of my Book of Nodes series. If you want to see similar content on 2D or 3D nodes, please refer to the parent page of this post for those links. šŸ˜Š

Before we begin, if you need a base project to test these code snippets, feel free to download my FREE 2D and 3D templates here. Iā€™ll be using these templates throughout this post.

*Please note that this list is NOT 100% complete yet, but I will be updating this list as time goes on.

  • Control
  • CanvasLayer
  • CanvasModulate
  • Container
  • HBoxContainer
  • VBoxContainer
  • GridContainer
  • ColorRect
  • Panel
  • Button
  • Label
  • RichTextLabel
  • ProgressBar

Common Properties

Anchoring

  • Determines how a UI element is positioned and resized relative to its parent container.
  • anchor_left: Sets the left anchor point (0 to 1).
  • anchor_top: Sets the top anchor point (0 to 1).
  • anchor_right: Sets the right anchor point (0 to 1).
  • anchor_bottom: Sets the bottom anchor point (0 to 1).
  • full_rect: Sets the anchor point to all sides.

Margins

  • Defines the distance between the UI element and its parent containerā€™s edges.
  • margin_left: Distance from the left edge.
  • margin_top: Distance from the top edge.
  • margin_right: Distance from the right edge.
  • margin_bottom: Distance from the bottom edge.

Font

  • Customizes the appearance of text within UI elements.
  • font: The font resource used for the text.
  • font_size: The size of the font.
  • font_color: The color of the font.

Color

  • Customize the color properties of UI elements.
  • color: The main color of the UI element.
  • font_color: The color of the text.
  • modulate: The alpha value applied to the UI element.

Transform

  • Controls the position, rotation, and scale of UI elements.
  • position: The position of the UI element.
  • rotation: The rotation of the UI element in degrees.
  • scale: The scale of the UI element.

Size Flags

  • Determines how a UI element resizes within its parent container.
  • size_flags_horizontal: Horizontal resizing behavior (e.g., fill, expand).
  • size_flags_vertical: Vertical resizing behavior (e.g., fill, expand).

Visibility

  • Controls the visibility of UI elements.
  • visible: Whether the UI element is visible.
  • self_modulate: The color modulation applied to the UI element, affecting its visibility.

Focus

  • Manages keyboard and controller focus for UI elements.
  • focus_mode: Determines if the UI element can receive focus (none, click, all).
  • focus_neighbour_*: Specifies neighboring UI elements for focus navigation (up, down, left, right).

Tooltip

  • Provides additional information when the user hovers over a UI element.
  • hint_tooltip: The text displayed as a tooltip.

Theme Overrides

  • Allows customization of the UI elementā€™s appearance beyond the default theme.
  • theme: The theme resource applied to the UI element.
  • theme_type_variation: A variation of the theme type for more specific customization.

Control

A Control node provides a bounding rectangle on the viewport that can be used for creating user interfaces in Godot, as they handle input events, focus, and other UI-specific functionalities.

Mechanic:

Drag and drop a sprite on the map.

Implementation:

  • Add a Control node to your scene. This represents the item you will drag and drop.

Book of Nodes

  • We need to visualize it, so add a TextureRect node to it. This node allows us to add a sprite to the control so that we can see what we are moving. This works better than the Sprite2D/3D node because it can be anchored to our Control container.

Book of Nodes

  • Add any texture (icon) to this TextureRect.

Book of Nodes

Book of Nodes

  • Attach a script to your Control node. To be able to drag and drop this object, we will need to connect its gui_input signal to our script.

Book of Nodes

  • In your code, add the functionality to select the item using the LEFT mouse button. Use set_drag_preview to show a visual representation of the item being dragged.
  • Then, add the functionality to drop your item on the LEFT mouse button release.
  • And then also add the functionality to snap the item to your mouse cursor whilst dragging it around.
### Control.gd

extends Control

var drag_offset = Vector2.ZERO
var is_dragging = false

func _on_gui_input(event):
 if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
  # Select
  if event.pressed:
   is_dragging = true
   if get_viewport().gui_is_dragging():
    set_drag_preview(self)
  else:
   # Drop
   is_dragging = false
 # Drag
 elif event is InputEventMouseMotion and is_dragging:
  var global_pos = get_global_mouse_position()
  global_position = global_pos - size / 2
Enter fullscreen mode Exit fullscreen mode
  • Test your logic by selecting the item and dragging it around.

Book of Nodes

CanvasLayer

A CanvasLayer is used for independent rendering of objects within a 2D scene, often for UI elements or HUDs. It renders its child nodes independently of the main scene's camera, which means that they remain fixed on the screen.

Example Use Cases:

  • HUD (Heads-Up Display).
  • Fixed-position UI elements.
  • Overlay menus.

Mechanic:

To demonstrate the use of the layer property, we will create a simple scene with two CanvasLayer nodes. One will be used for a background layer, and the other for a UI layer. The background layer will be drawn behind the UI layer.

Implementation:

  • Add two CanvasLayernodes to your scene.

Book of Nodes

  • Add a Label node to the first CanvasLayer node. Add a ColorRect to the second CanvasLayer node.

Book of Nodes

  • Give the Label some text, and change the ColorRects color to a dark grey. Also, change its anchor-preset to be full_rect.

Book of Nodes

Book of Nodes

  • You will see that our label isnā€™t showing, because our first CanvasLayer node has the same Layer value as the second CanvasLayer.
  • Change the first CanvasLayer nodeā€™s Layer value to be ā€œ2ā€.

Book of Nodes

  • Your label should now be on top of the background!

Book of Nodes

Container

A Container is used to organize UI elements, providing a base class for various container types. It inherits from Control and provides functionality for arranging child nodes. We usually donā€™t use this node a lot, as a normal Control node suffices.

You might, however, use a ScrollContainer node. A ScrollContainer is a type of container node in Godot that provides scrollbars to its child control when needed. It is useful for creating scrollable areas in your UI, such as lists, text areas, or any content that exceeds the visible area of the container.

Example Use Cases:

  • Base class for custom container types.
  • Organizing complex UI layouts.
  • Creating custom layout behaviors.

Book of Nodes

HBoxContainer

An HBoxContainer is used to arrange UI elements horizontally. It inherits from Container and arranges its children in a horizontal line.

Example Use Cases:

  • Horizontal menus.
  • Toolbars.
  • Row-based layouts.

Book of Nodes

Mechanic:

Arrange a list of items horizontally on the scene.

Implementation:

  • Add a Control node to your scene. This will hold our HBoxContainer. Change its size to something like 600px by 600px to give it a bounding area.

Book of Nodes

Book of Nodes

  • Add a HboxContainer node to this Control node. Also, make sure its anchor preset is full_rect so that it takes up the entire space provided by the Control node.

Book of Nodes

  • Add three Label nodes to the HBoxContainer.

Book of Nodes

  • You will see that the items stack next to each other, but they donā€™t take up the entire space. To fix this, we will need to set their container sizing properties to fill and expand.

Book of Nodes

  • Now your labels will be arranged horizontally across the entire 600px by 600px boundary box!

Book of Nodes

  • To add some spacing between the items, select the HBoxContainer node, and change its separation constant to a value such as 10.

Book of Nodes

Book of Nodes

VBoxContainer

A VBoxContainer is used to arrange UI elements vertically. It inherits from Container and arranges its children in a vertical line.

Example Use Cases:

  • Vertical settings menus.
  • Stacked buttons.
  • Column-based layouts.

Book of Nodes

Mechanic:

Arrange a list of items vertically on the scene.

Implementation:

  • Add a Control node to your scene. This will hold our VBoxContainer. Change its size to something like 600px by 600px to give it a bounding area.

Book of Nodes

Book of Nodes

  • Add a VboxContainer node to this Control node. Also, make sure its anchor preset is full_rect so that it takes up the entire space provided by the Control node.

Book of Nodes

  • Add three Label nodes to the VBoxContainer.

Book of Nodes

  • You will see that the items stack on top of each other, but they donā€™t take up the entire space. To fix this, we will need to set their container sizing properties to fill and expand.

Book of Nodes

  • Now your labels will be arranged horizontally across the entire 600px by 600px boundary box!

Book of Nodes

  • To add some spacing between the items, select the VBoxContainer node, and change its separation constant to a value such as 10.

Book of Nodes

Book of Nodes

GridContainer

A GridContainer is used to arrange UI elements in a grid. It inherits from Container and arranges its children in a grid layout.

Example Use Cases:

  • Keypads.
  • Control panels.
  • Inventory grids.

Book of Nodes

Mechanic:

Arrange a list of items in a grid on the scene.

Implementation:

  • Add a Control node to your scene. This will hold our GridContainer. Change its size to something like 600px by 600px to give it a bounding area.

Book of Nodes

Book of Nodes

  • Add a GridContainer node to this Control node. Also, make sure its anchor preset is full_rect so that it takes up the entire space provided by the Control node.

Book of Nodes

  • Add fourLabel nodes to the GridContainer.

Book of Nodes

  • You will see that the items stack on top of each other, instead of in a grid. To fix this, we will need to up our columns property in our GridContainer node. Change this value to 2.

Book of Nodes

Book of Nodes

  • Now they are arranged in the grid, but they donā€™t take up the entire space. To fix this, we will need to set their container sizing properties to fill and expand.

Book of Nodes

  • Now your labels will be arranged in a grid format across the entire 600px by 600px boundary box!

Book of Nodes

  • To add some spacing between the items, select the GridContainer node, and change its separation constant to a value such as 10.

Book of Nodes

Book of Nodes

ColorRect

A ColorRect is used to display a solid color rectangle, often for backgrounds or color overlays. It inherits from Control and provides a simple way to display a rectangle filled with a specified color. The color can be set and changed dynamically.

Example Use Case:

  • Background overlays.
  • Progress bars.
  • Color indicators.

Book of Nodes

Mechanic:

Add a background color to your scene.

Implementation:

  • Add a CanvasLayer node to your scene. This will ensure that our ColorRect is drawn on our UI, so it can be displayed in the background.

Book of Nodes

  • Add a ColorRectnode to your CanvasLayer node.

Book of Nodes

  • Change its color, and change its anchor preset to be full_rect so that it takes up the entire screen.

Book of Nodes

  • Change the CanvasLayer nodeā€™s layer property to something like -1 so that it is displayed behind our other nodes. We should now have a background color!

Book of Nodes

Panel

  • A Panel is used to create a panel for grouping UI elements, providing a background and border. It inherits from Control and provides a simple way to group and visually separate UI elements.

Example Use Case:

  • Settings panels.
  • Dialog boxes.
  • Grouping related UI elements.

Book of Nodes

Mechanic:

Add a background color to your scene.

Implementation:

  • Add a CanvasLayer node to your scene. This will ensure that our Panel is drawn on our UI, so it can be displayed in the background.

Book of Nodes

  • Add a Panel node to your CanvasLayer node.

Book of Nodes

  • To change its color, weā€™ll need to give it a new theme style of type StyleBoxFlat.

Book of Nodes

  • Now we can give it a new color, border, and even a shadow!

Book of Nodes

  • Change its anchor preset to full_rect so that it takes up the entire screen.

Book of Nodes

  • Change the CanvasLayer nodeā€™s layer property to something like -1 so that it is displayed behind our other nodes. We should now have a background color!

Book of Nodes

CanvasModulate

A CanvasModulate applies a color tint to all nodes on a canvas. It tints the canvas elements using its assigned color.

Example Use Cases:

  • Night mode effect.
  • Global color adjustments.
  • Visual effects for different game states.

Book of Nodes

Book of Nodes

Mechanic:

Add a day-and-night cycle to your game

Implementation:

  • Add a CanvasModulatenode to your scene.

Book of Nodes

  • If you change its color property, the entire scene's color should change.

Book of Nodes

  • We want to animate this property. So, add an AnimationPlayer node to your scene.

Book of Nodes

  • Create a new animation called day_night_cycle. Set the length of this animation to be 24 seconds long. This will make our day 24 seconds long (for 24 hours).

Book of Nodes

Book of Nodes

  • Also, enable looping.

Book of Nodes

  • Now add a color keyframe for every 6 hours (or whatever preference you have). These colors should represent the colors from 0 AM to 24 PM.
  • On my timeline, my colors are: 0: #0f0a49 6: #7b5436 12: #ffffff 18: #5b6a99 *24: * #0f0a49

Book of Nodes

  • Now when we run our game, we should play this animation.
### Main.gd

extends Node2D

@onready var animation_player = $AnimationPlayer

func _ready():
 animation_player.play("day_night_cycle")
Enter fullscreen mode Exit fullscreen mode

Book of Nodes

  • If you want a better tutorial using shaders, check out the video on my YouTube channel!

Button

A Button is used to create a clickable button for user interactions. It inherits from BaseButton and provides functionality for detecting clicks and triggering actions.

If you want to use a button that has a texture (image) and more customizability, you should use a TextureButton node. The TextureButton node is a button that uses textures for its different states (normal, pressed, hover, etc.) instead of the default theme. This allows for more customized and visually appealing buttons. It inherits from BaseButton and provides properties to set textures for different states.

Example Use Cases:

  • Interactive buttons.
  • Menu options.
  • Form submissions.

Book of Nodes

Mechanic:

Add a clickable button to your scene.

Implementation:

  • Add a CanvasLayer node to your scene. This will ensure that our Buttonis drawn on our UI, so it can be displayed at all times.
  • Add a Button node to your CanvasLayer node.

Book of Nodes

  • If you run your scene, your Button should be visible.

Book of Nodes

  • Now, attach its pressed() signal function to your script.

Book of Nodes

  • If we press the button, we will change its text. We will keep track of the times weā€™ve pressed it and update it each time we press the button.
### Main.gd

extends Node2D

@onready var button = $CanvasLayer/Button

var button_pressed_count = 0

func _on_button_pressed():
 button_pressed_count += 1
 button.text = "You've pressed me: " + str(button_pressed_count) + " times!"
Enter fullscreen mode Exit fullscreen mode
  • Every time you press the button, the count should update!

Book of Nodes

Book of Nodes

Book of Nodes

Label

A Label is used to display text. It inherits from Control and provides functionality for displaying text.

Example Use Cases:

  • Static text display.
  • Descriptive labels.
  • Titles and headings.

Book of Nodes

Mechanic:

Add a label that changes its text when you hover over it.

Implementation:

  • Add a CanvasLayer node to your scene. This will ensure that our Label is drawn on our UI, so it can be displayed at all times.
  • Add a Labelnode to your CanvasLayer node.

Book of Nodes

  • If you run your scene, your Label should be visible.

Book of Nodes

  • Now, letā€™s make it more visible. Change its font color to be red, and its size to something like 25px.

Book of Nodes

  • Since we want it to detect mouse events, we need to change its Mouse Filter mode to Pass.

Book of Nodes

  • Now, to detect that we are hovering over it, we need to attach its mouse_entered() and mouse_exited() signals to our script.

Book of Nodes

  • Then, simply change the text when we enter and exit the label while hovering! If you run your game, the label should change depending on whether or not you are hovering over it.
### Main.gd

extends Node2D

@onready var label = $CanvasLayer/Label

func _on_label_mouse_entered():
 label.text = "You're hovering over a label"

func _on_label_mouse_exited():
 label.text = "You're away from the label"
Enter fullscreen mode Exit fullscreen mode

Book of Nodes

Book of Nodes

Book of Nodes

RichTextLabel

A RichTextLabel is used to display formatted text. It inherits from Control and provides functionality for displaying rich text with formatting, such as bold, italics, and images.

Example Use Cases:

  • Formatted text display.
  • Dialogue boxes.
  • Instructional text.

Book of Nodes

Mechanic:

Write words in a typewriter effect.

Implementation:

  • Add a CanvasLayer node to your scene. This will ensure that our RichTextLabelis drawn on our UI, so it can be displayed at all times.
  • Add a RichTextLabel node to your CanvasLayer node.

Book of Nodes

  • Change its size to something like 200px by 200px.

Book of Nodes

  • If you run your scene, your RichTextLabel should be visible.

Book of Nodes

  • Now, letā€™s make it more visible. Change its font color to red, and its size to something like 25px.

Book of Nodes

  • To create our typewriter animation, we will need to use an AnimationPlayer node. Add this node to your scene.

Book of Nodes

  • Create a new animation called typewriter.

Book of Nodes

  • To create a typewriter effect, we need to animate our RichTextLabel nodeā€™s visible ratio property, which defines how much of our text is visible.

Book of Nodes

Book of Nodes

  • At the 0 keyframe mark, set your visible ratio to be equal to 0.

Book of Nodes

  • At the 1 keyframe mark, set your visible ratio to be equal to 1. This means in 1 second, our text will go from no characters to full characters.

Book of Nodes

  • Now if you play your animation, your text should play as if it's being typed out.

Book of Nodes

ProgressBar

ProgressBar is a UI element that visually represents a value within a range. It inherits from the Range class, which provides properties like min_value, max_value, and value to control the progress.

Example Use Cases:

  • Loading screens.
  • Health bars.
  • Progress indicators.

Mechanic:

Create a health bar that increases every 1 second, and when we press SPACE, it decreases in value.

Implementation:

  • Add a CanvasLayer node to your scene. This will ensure that our ProgressBar node is drawn on our UI, so it can be displayed at all times.
  • Add a ProgressBarnode to your CanvasLayer node.

Book of Nodes

  • Change its size to something like 200px by 27px, and enable its Rounded value so it only shows whole numbers.

Book of Nodes

  • To be able to increase our ProgressBar, we should add a Timer node. Enable this timer nodeā€™s autostart property, and connect its timeout signal to your script.

Book of Nodes

Book of Nodes

Book of Nodes

  • Whenever it times out (every 1 second its active), we will increase our ā€œhealthā€ value.
### Main.gd

extends Node2D

@onready var progress_bar = $CanvasLayer/ProgressBar

func _on_timer_timeout():
 progress_bar.value += 1
Enter fullscreen mode Exit fullscreen mode
  • Whenever we press our SPACE bar, we should decrease our health value.
### Main.gd

extends Node2D

@onready var progress_bar = $CanvasLayer/ProgressBar

func _on_timer_timeout():
 progress_bar.value += 1

func _input(event):
 if event.is_action_pressed("ui_accept"):
  progress_bar.value -= 5
Enter fullscreen mode Exit fullscreen mode
  • Now if we run our scene, our health should increase every second, but decrease when we press our button.

Book of Nodes

Top comments (0)