Download

Improved Keyboard/Gamepad Input & Widget Focus Handling for UMG Menus

One area I’ve found to be particularly cumbersome is handling gamepad input & widget focus in UMG menus. I’ll do my best to annotate specific issues & how I think they could be fixed. First, here’s a quick video demoing my front end menu system:

https://drive.google.com/open?id=0B9Wy3lqTOMHKWG1uSHhsRm1INkk

If the issues below can be resolved, it’d remove SO much complex blueprint bookkeeping that’s currently required.


1. Communicating Widget Focus to the User

Problem:
There is no simple way to clearly communicate which widget currently has gamepad (or keyboard) focus.

Suggestion for Fix:
Add a new “Focused” style for all relevant widgets (button, checkbox, combo box, slider, etc.) and focus sound events. I view keyboard focus & mouse hover as kinda the same thing. IMHO, there should be an analog “focus” implementation for every “hover” implementation.

0401a360cf1dc329b9765c5fa25e92fba92f7be7.png

2. Handling Widget Focus Events & Tracking Widget Focus

Problem:
There is no simple way to track which widget currently has focus or when a widget changes focus.

Suggestion for Fix:
There are blueprint callbacks for user defined widgets like OnFocusReceived & OnFocusLost, but there are no events for core widgets like Buttons. Again, in the spirit of matching “hover” implementations, adding new “On Focused” & “On Unfocused” bindings here could help. In addition, it would be really useful to be able to query which widget currently has focus at any given time. In all my time searching, I haven’t been able to find a blueprint function (or function in code, for that matter) that can do that.

44a051cc29bf05f96072b2fe8d788132dfadb45d.png

3. Losing Widget Focus w/ Unhandled Mouse Clicks

Problem:
When you mouse click an area of the screen that has no effect for a menu, you lose current keyboard focus. I’ve included some examples of other users running into this problem. Moderators say it’s “working as intended”, but it’s SUPER confusing/annoying in practice.

The answer on this post is actually what I’m doing to handle this issue and it’s a giant pain for complex menus:

Suggestion for Fix:
Add an option to keep current widget focus if user has unhandled mouse click event…or something. This one I’m less sure about how to handle, but the current workarounds are not great.

4. Focus Brush Is Difficult to Work With

Problem:
It took me FOREVER just to figure out how to turn it off and there’s no way to change its look.

Suggestion for Fix:
I don’t really see how this would be needed if all of the above are taken care of.

  1. It’s much more complex than that. Describing focus is more complicated than a brush swap. Think Final Fantasy’s Hand icon that bounces next to focused items in the menu. Additionally, the focused sound is an interesting problem, see you can’t just signal for focusing, you’ve also got to allow people to be notified when focus was attempted, but failed, that way you can have menus that go, dink dink dink wwwng when you try to focus in a direction that doesn’t take you anywhere. Anyway - valid complaint, it’s something I’m considering.

  2. Yeah, planning to do something like that.

  3. Yup that problem is tough. I don’t want to choose anything that prevents games from seamlessly moving from a mouse or controller UI when the user’s input style changes.

  4. The focus brush isn’t intended to be something people use in production, but it is useful when you’re trying to figure out where focus is in development. Not sure what I’ll do with it.

I appreciate the feedback. I’m working on this stuff now that I’m done with the clipping changes, not sure when the changes will be ready.

Thanks for responding, Nick! Just a few quick follow up comments:

  1. Describing focus could be more complicated than a brush swap, but I would then propose that describing hover could be more complicated than a brush swap, as well. As long as we have a simple option for describing it (brush swap) and events for doing more (see point 2), then I think we’re set! For sound, I would propose a sound triggered upon focus, just like sound on a hover, is most important. Having an option to signal a failed focus might be nice, too, but less important, IMHO.

  2. Sweet!

  3. I agree you wouldn’t want to lose any of the current functionality that allows switching between UI and viewport. However, I would definitely propose that we need a simple, clean solution for preventing it when we know we’re in a state where it should never happen (e.g. typical pause menu in most games).

  4. Gotcha. I didn’t realize it’s not intended for use outside development, but that totally makes sense. If it’s a debug tool, maybe have it off by default? It took me forever to find out how to turn it off cause I didn’t even know what to call it when searching in the editor or on the internet :slight_smile:

Sure. Need ‘focus-events’ for binding on init stage (constructor) in widget, for example.
It would be help for develop navigation menu systems specially for gamepad/keyboard input.

But 1st step with visual/audial stuff for ‘focus’ is not really need. Possible just use ‘hover’ for dat in WidgetBP logic like so.

Any way if using keyboard/gamepad and mouse at same time need always to check what is your primary input device (to hide mouse cursor or not until mouse doesn’t move/use).

If 2nd feature request will be, it would be nice.

2nd feature.That’s why I got here.I can’t do that at all.

Hey how about this?Снимо1к.PNG

Looks interesting. It’d be great to see that in action @Silêncio… Any chance of a Video etc?
I often give up on focus. Just accept inputs to everything / filter using Gates + Game-States.

Looks interesting… It’d be great to see that in action @Silêncio… Any chance of a Video etc?
I often give up on focus. Just accept inputs to everything & filter using Gates + Game-States.

99% of the time the issues with focus that people have are because widgets that you don’t want to be focusable often are. Make sure you uncheck the bIsFocusable flag in Blueprint, and set the widget visibility to something non-hit testable. Both are things you should do anyway really while building the widget.

Good evening, first of all with the focused and unFocused events the problems of making widgets with gampad or keyboard would be solved very much.

I’ve been a programmer for some time (Delphi, java, c ++ … = but it’s the first time I’ve programmed a videogame and use unreal engine 4.18.

After a lot of reading through forums and not getting much … I have come up with a solution that I think is elegant that I am using (until we have the onFocus and onUnFocus events) and I wanted to share it with you …

The code consists of the following_

Step 1: I enter manually All widget buttons in an array in the begin play event

In my case they are always inside a vertical box

Note: I do not think there is an array with all the elements of the widget, it’s a pity because it would be very useful

Step 2: In a tick event I use a loop I check if the button is focused with a branch.

If this focus changed the normal style “imitating” hovered and if it is not, change to normal style

Step3: To not have the sound in loop I use a doOnce event that is reset each time the style is changed to focused with the variable focused

The integer variable “focused” saves the last element “focused”, if the variable changes, it resets the doOnce function

Note1: The UnFocusButton function is simple because my buttons are transparent

Note2: I’m sorry for my english … it’s very bad


Buenas noches, antes de nada con los eventos focused y unFocused se solucionaría mucho los problemas de hacer widgets con gampad o teclado.

Soy programador desde hace tiempo (Delphi, java, c++…= pero es la primera vez que programo un videojuego y uso unreal engine 4.18.

Después de mucho leer por foros y no conseguir gran cosa… he llegado a una solución que me parece elegante que estoy utilizando (hasta que tengamos los eventos onFocus y onUnFocus) y quería compartirla con vosotros…

El código consiste en lo siguiente_

Paso 1: Introduzco manualmente Todos los botones del widget en un array en el evento begin play

En mi caso están siempre dentro de un vertical box

PD: Creo que no existe un array con todos los elementos del widget, es una lastima porque seria de gran utilidad

Paso 2: En un evento tick utilizo un loop compruebo si el boton esta focused con una rama.

Si esta focused cambio el estilo normal “imitando” hovered y si no lo esta, cambio a stilo normal

Paso3: Para no tener el sonido en loop utilizo un evento doOnce que es reseteado cada vez que cambia el estilo a focused con la variable focused

La variable integer “focused” guarda el ultimo elemento “focused”, si la variable cambia, resetea la funcion doOnce

PD1: La funncion UnFocusButton es simple porque mis botones son transparentes
PD2: I’ m sorry por mi ingles… es muy malo

I never understood the focus in UMG, in the end I decided to create a custom UserWidget with a focus and lost focus custom delegates, all my widget inherited from this, and then when I receive inputs I look for all widgets of this class and only those marked as focusable, then by comparing their screen absolute position with the one in focus I was able to determine if something is focusable for the axis, let say if it was nothing at right then is not possible lost my focus, but if it was, then you can focus something new and broadcast the delegate for every widget,

Probably not the smart idea ever, but it does the job!

And why? because for that project I expended 2 days dealing with my widgets just in a effort to use properly the focus feature inside UE, but in change I expended just 1 day to implement my own,

I agree with the guy who began this thread, UMG is powerful but some stuff like this is confusing, not hard but confusing enough for me to create my own

I added this function to track widget focus in Ticks which is super gross/not optimized, but it makes for some WAY cleaner HUD blueprints.


UWidget* APFPlayerController::GetCurrentWidgetFocus()
{
    for (TObjectIterator<UWidget> Itr; Itr; ++Itr)
    {
        if (Itr->HasUserFocus(this))
            return *Itr;
    }

    return nullptr;
}

Here is a brief description of my implementation.
For me, Focus means Hovered. same thing. So I edited SWidget.h to do that.
was a very simple change.



    /** @return True if this widget hovered */
    virtual bool IsHovered() const
    {
        return bIsHovered || HasKeyboardFocus();
    }


Keyboard focus is the same for gamepad as well so this works. My buttons then get the Hovered Style through navigation provided I set the User Focus to a button. I made my own subclass of UUserWidget to manage focus, at well as addition and removal from the screen. This class keeps the last focused element. It’s important in large UMGs to call focus when you show and hide panels, but otherwise nagivation works well.

in the Player controller I created an array of Widgets in a sort of stack (it’s not really lifo because you could remove something that’s not at index 0). and this is called by MyUserWidget. This allows me to automatically set the user focus back to the last focussed objects if I close a popup, or if I click outside the area with the mouse. We assume the player doesn’t want to see focus at this point and focus is lost so everything works for them.

in MyGameViewportClient (subclass of GameViewportClient) I override InputAxis and InputKey which allows me to check if I pushed a gamepad or keyboard. This sends a message to my player controller which will refocus on the last element based on the Widget on top of my stack.

Hope that helps and I’m always ready to talk about it if you have questions or share some code.

If you don’t want to mess with engine code, you can re-implement your own button widget entirely using a UserWidget and add your own focus handling logic. It’s a pain, unfortunately. There should be more exposed controls over focus handling logic. For an engine that focus consoles, it’s a shame every dev has to hack together their own gamepad navigation code.

Oh good. I thought I was being dumb for hacking together my own gamepad navigation because I just couldn’t figure out how to use the built in stuff.

I see from the previous comments that there may not be an easy solution to this, but I’m hoping there’s a Blueprint solution that I’m overlooking.

As shown in the first image, I have a Main Menu that starts with the focus on the “Play” button from which the player can navigate with arrow keys down to select the other buttons.

As shown in the second image, pressing the “Option” button opens a different Options Menu widget with focus set on the “Video” button. However, when exiting this menu to reveal the Main Menu underneath, I cannot restore focus back to the “Play” button. *Note: When navigating with arrow keys the focus/navigation occurs on both in the Options menu in front as well as the Main Menu beneath. That is to say all focus has not truly shifted solely to the Options Menu when opened to conceal the Main Menu.

I’m not sure if this is possible. If not, I was hoping as a workaround to destroy the Main Menu widget beneath and recreate it upon exiting the Option Menu with the focus set to “Play” upon event construct. Unfortunately I have not been able to accomplish this either.

Any help with the proper way to fix this or even an ugly workaround would be greatly appreciated.

It’s annoying, yes. If you need keyboard/gamepad navigation, do not use the Button widget directly on your screens/windows/popups, period. The same goes if you are making any game with more than a couple screens: manually setting up each button scales very poorly and going back and re-styling them is a major time sink.

Create your own custom button by creating a Widget Blueprint that implements and forwards the events you need using dispatchers (you can use a button as the root widget to re-use most of the functionality) and use the PreConstruct event to make it behave as WYSIWYG in the editor. You can then make all your buttons follow the same style rules, already contain the text field (with the text being set using an editable property) and most importantly: you can add the focus received and focus lost events to it and display focus as you see fit. You can even use animations instead of brush swapping for button state changes.

Thanks for the reply. Having difficulty using this with a menu system I got from the Market Place… I will try this later from scratch, but it will be a while.

100% agree.

Brilliant! This is an excellent quick fix/hack for solving the “focused” styling problem. You inspired me to make this change in SWidget.cpp, as well, to make focus events trigger hover events.

!!!WARNING!!! I know, hacky af…but works for my use case and is what I’ll be doing until Epic finds a cleaner solution.



FReply SWidget::OnFocusReceived(const FGeometry& MyGeometry, const FFocusEvent& InFocusEvent)
{
    //-----------------------------
    // CUSTOM CODE
    FPointerEvent MouseEvent;
    OnMouseEnter(MyGeometry, MouseEvent);
    //-----------------------------

    return FReply::Unhandled();
}

void SWidget::OnFocusLost(const FFocusEvent& InFocusEvent)
{
    //-----------------------------
    // CUSTOM CODE
    FPointerEvent MouseEvent;
    OnMouseLeave(MouseEvent);
    //-----------------------------
}


I’m doing something very similar to handle navigating between menus and losing focus due to clicking outside the window.

The vast majority of problems with UMGs focus could be resolved with a simple “lock focus” option that makes a widget remain focused no matter what you do until that bool is manually cleared.