Search code examples
gdscript

Why doesn't this gdscript dialog box code work?


Why doesn't this code work? I don't know how to describe what happens but here's the code.

extends Node2D


onready var dialog_box = get_node("DialogBox")

func _ready():
    ShowDialog("Example")

func ShowDialog(text, font = "DTM-Mono.ttf", time = 0.25):
    var textbox = dialog_box.get_node("Text")
    var dynamic_font = DynamicFont.new()
    dynamic_font.font_data = load("res://Supply (do not delete)/Fonts/" + str(font))
    textbox.add_font_override("font", dynamic_font)
    for character in text:
        textbox.text = textbox.text + character
        yield(get_tree().create_timer(time), "timeout")

Solution

  • When working Controls what is lower in the scene tree is on top. You can pretend it is the draw order. Except there is 2D batching. But it is as if it were the draw order.

    In this we have a Label and a Panel siblings on the scene tree, in that order. Like this:

    DialogBox
    ├ Text:Label
    └ Container:Panel
    

    And thus, the Panel will appear on top of the Label. Meaning the Label would behind the Panel (assuming they were positioned in the same area. And they were, because this an attempt to make an RPG-style dialog/text box.).


    A simple solution to make the Label visible is to reorganize the scene tree, like this:

    DialogBox
    ├ Container:Panel
    └ Text:Label
    

    However, I'm going to suggest a different solution. Reorganize the scene tree like this:

    DialogBox
    └ Container:Panel
      └ Text:Label
    

    The reason is that children nodes are positioned relative to their parent. Thus, when you move the Panel it also moves the Label. For example, if sometimes the box should appear on the top of the screen and sometimes on the bottom, you only need to move the Panel.

    I also want to mention that if you set rect_clip_content on a Control, it will mask children to its rectangle. That is, any part of the children that goes outside the parent rectangle will not be visible. Which is something you may or may not want.


    And while we are on the topic of moving nodes around. You can export NodePath variables and set them in the inspector panel to reference other nodes (example).

    By the way, when working with Node2D there is a z_index property. Also, you can use a YSort node to deal with fake depth (example).