Controls GUI personnalisés

Tant de controls...

Pourtant, il n'y en a jamais assez. Créer vos propres controls personnalisés qui agissent exactement comme vous le souhaitez est une obsession de presque tous les programmeurs d'interface graphique. Godot en fournit beaucoup, mais ils peuvent ne pas fonctionner exactement comme vous le souhaitez. Avant de contacter les développeurs avec une demande de prise en charge des barres de défilement diagonales, il sera au moins bon de savoir comment créer ces controls facilement à partir du script.

Dessin

Pour le dessin, il est recommandé de consulter le tutoriel Dessin personnalisé en 2D. Il en va de même. Certaines fonctions méritent d'être mentionnées en raison de leur utilité lors du dessin, elles seront donc détaillées par la suite :

Vérification de la taille du control

Contrairement aux nœuds 2D, la "taille" est importante pour les controls, car elle permet de les organiser dans des mises en page appropriées. Pour cela, la propriété Control.rect_size est fournie. La vérifier pendant _draw() est vital pour s'assurer que tout est maintenu dans les limites.

Vérification du focus

Certains controls (tels que les boutons ou les éditeurs de texte) peuvent permettre de capturer les entrées clavier ou joypad. Il s'agit par exemple de saisir du texte ou d'appuyer sur un bouton. Ceci est contrôlé avec la propriété Control.focus_mode. Lors du dessin, et si le control supporte la capture d'entrée, il est toujours souhaitable d'afficher une sorte d'indicateur (surbrillance, boîte, etc.) pour indiquer que c'est le contrôle actuellement capturé. Pour vérifier ce statut, la méthode Control.has_focus() existe. Exemple

func _draw():
    if has_focus():
         draw_selected()
    else:
         draw_normal()
public override void _Draw()
{
    if (HasFocus())
    {
        DrawSelected()
    }
    else
    {
        DrawNormal();
    }
}

Dimensionnement

Comme nous l'avons déjà mentionné, la taille est importante pour les controls. Cela leur permet de s'étaler correctement, lorsqu'ils sont placés dans des grilles, des conteneurs ou ancrés. Les controls, la plupart du temps, fournissent une taille minimale pour aider à les disposer correctement. Par exemple, si les contrôles sont placés verticalement les uns sur les autres en utilisant un VBoxContainer, la taille minimum fera en sorte que votre contrôle personnalisé ne soit pas écrasé par les autres contrôles dans le conteneur.

Pour fournir ce rappel, il suffit de surcharger Control.get_minimum_size(), par exemple :

func get_minimum_size():
    return Vector2(30, 30)
public override Vector2 _GetMinimumSize()
{
    return new Vector2(20, 20);
}

Vous pouvez également le régler à l'aide d'une fonction :

func _ready():
    set_custom_minimum_size(Vector2(30, 30))
public override void _Ready()
{
    SetCustomMinimumSize(new Vector2(20, 20));
}

Entrée

Les controls fournissent quelques aides pour rendre la gestion des événements d'entrée beaucoup plus facile qu'avec les nœuds ordinaires.

Événement d’entrée

Il y a quelques tutoriels sur les entrées avant celui-ci, mais il est utile de mentionner que les controls ont une méthode d'entrée spéciale qui ne fonctionne que lorsque :

  • Le pointeur de la souris est sur le control.
  • Le bouton a été appuyé sur ce control (la control capture toujours l'entrée jusqu'à ce que le bouton soit relâché)
  • Le controls fournit le focus du clavier/joypad via Control.focus_mode.

Cette fonction est Control._gui_input(). Il vous suffit de l'ignorer dans votre control. Il n'est pas nécessaire de définir un traitement.

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!")
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!");
    }
}

Pour plus d'informations sur les événements eux-mêmes, consultez le tutoriel InputEvent.

Notifications

Les contrôles ont également de nombreuses notifications utiles pour lesquelles aucun rappel dédié n'existe, mais qui peuvent être utilisées avec le rappel _notification :

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.
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;
    }
}