Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Controles de GUI personalizados

Muitos controles...

Ainda assim, nunca são suficientes. Criar seus próprios controles personalizados que agem exatamente da maneira que você deseja é uma obsessão de quase todo programador de GUI. O Godot fornece uma abundância deles, mas eles podem não funcionar exatamente como você deseja. Antes de entrar em contato com os desenvolvedores com um pull-request para dar suporte a barras de rolagem diagonais, pelo menos será bom saber como criar esses controles facilmente a partir de scripts.

Desenhando

Para desenhar, recomenda-se verificar o tutorial Desenho personalizado em 2D. O mesmo se aplica. Algumas funções valem a pena mencionar devido à sua utilidade ao desenhar, por isso serão detalhadas a seguir:

Verificando o tamanho do controle

Ao contrário dos nós 2D, o "tamanho" (size) é importante nos controles, pois ajuda a organizá-los em layouts adequados. Para isso, a propriedade Control.size é fornecida. Verificá-la durante o _draw() é vital para garantir que tudo seja mantido dentro dos limites.

Verificando o foco

Alguns controles (como botões ou editores de texto) podem fornecer foco de entrada para entrada de teclado ou controle (joypad). Exemplos disso são digitar texto ou pressionar um botão. Isso é controlado com la propriedade Control.focus_mode. Ao desenhar, e se o controle suportar foco de entrada, é sempre desejável mostrar algum tipo de indicador (destaque, caixa, etc.) para indicar que este é o controle focado no momento. Para verificar esse status, existe o método Control.has_focus(). Exemplo

func _draw():
    if has_focus():
         draw_selected()
    else:
         draw_normal()

Dimensionando

Como mencionado antes, o tamanho é importante para os controles. Isso permite que eles se organizem adequadamente quando inseridos em grades, containers ou ancorados. Os controles, na maioria das vezes, fornecem um tamanho mínimo para ajudar a organizá-los adequadamente. Por exemplo, se os controles forem colocados verticalmente uns sobre os outros usando um VBoxContainer, o tamanho mínimo garantirá que seu controle personalizado não seja esmagado pelos outros controles no container.

Para fornecer esse callback, basta sobrescrever o método Control._get_minimum_size(), por exemplo:

func _get_minimum_size():
    return Vector2(30, 30)

Como alternativa, defina-o usando uma função:

func _ready():
    set_custom_minimum_size(Vector2(30, 30))

Entrada

Os controles fornecem alguns assistentes para tornar o gerenciamento de eventos de entrada muito mais fácil do que nos nós regulares.

Eventos de entrada

Existem alguns tutoriais sobre entrada antes deste, mas vale a pena mencionar que os controles possuem um método de entrada especial que só funciona quando:

  • O ponteiro do mouse está sobre o controle.

  • O botão foi pressionado sobre este controle (o controle sempre captura a entrada até que o botão seja solto)

  • O controle fornece foco de teclado/controle via Control.focus_mode.

Esta função é o Control._gui_input(). Para usá-la, sobrescreva-a em seu controle. Nenhum processamento precisa ser configurado.

extends Control

func _gui_input(event):
   if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
       print("Left mouse button was pressed!")

For more information about events themselves, see the Usando InputEvent tutorial.

Notificações

Controls also receive many useful notifications for which no dedicated virtual method exists, but which can be checked within the _notification virtual method:

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().