0 votes

I am building an inventory menu using a TabContainer as base with a bunch of different tab scenes and modular sub-scenes that I add to the tabs. The sub-scenes are basically just GridContainers into which I instance Buttons corresponding to my player's items. The buttons are the only things with focus enabled, and the player can scroll through them by pressing the arrow keys (no mouse).

Here's an example of my inventory structure:

> InventoryBase (`TabContainer`)
    >> WeaponsTab (`Container`)
        >>> EquippedWeapons (`GridContainer`)
        >>> AvailableWeapons(`GridContainer`)

    >> MagicTab (`Container`)
        >>> EquippedMagic (`GridContainer`)
        >>> AvailableMagic(`GridContainer`)

My question concerns setting focus.

Currently, I watch the the TabContainer's tab_changed signal, and when a tab is changed, I manually set the focus to the first Button in either the AvailableWeapons or AvailableMagic (depending on which tab I'm changing to). For this, I use grab_focus().

The problem is that it's possible that the player only picked up one weapon and has already equipped it, so there is only one button on the inventory page, in EquippedWeapons rather than AvailableWeapons. So, nothing is focused.

I could write some code which handles this situation, but that doesn't feel like the right solution to me.

In fact, I dislike how often I find myself needing to manually change focus depending on the situation. I feel like I write a lot of ad hoc code for grabbing focus.

I would like to just auto-focus to the first available Button in my tab (regardless of whether it's in EquippedWeapons or AvailableWeapons).

So, my question: Is there a way to auto-focus on the first available control with focus enabled?

in Engine by (1,586 points)

1 Answer

0 votes

You could create a function like this:

func focus_first_button(container: Node) -> bool:
    for child in container:
        if child is Button:
            child.grab_focus()
            return true
    return false

Or this, if you want to focus any control:

func focus_first_control(container: Node) -> bool:
    for child in container:
        if child is Control and child.focus_mode != FOCUS_NONE:
            child.grab_focus()
            return true
    return false

And then just call it whenever you switch to a different tab.

by (118 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.