Common UI Keyboard Focus

Hi

I am investigating Common UI to see if we should move over too using it and I’ve got one last Hurdle to solve.

I am stuggling to get the keyboard movement to trigger the highlights on the UI buttons.
I have it working with Mouse, Touch and Gamepad but its failing to trigger with Keyboard.
I do get the Blue outline showing the underlining focus system is moving between the buttons and pressing the correct button works but just not the actual button focus visuals.

I have tried following the Unreal Youtube talks and deponstrations and each time even your video demonstrators stop trying to work out keyboard and they ignore this issue for the sake of continuing the video.

I’m wondering if i’m missing something or if there is extra setup too get the keyboard highlighting working?

Thanks
Ben

1 Like

Same problem :confused: any advice from the community?

Understanding Slate Widget focus principle can be found here:

Part 3 - Focus and Common Activatable Widgets

1 Like

thank you, very interesting principle, I saw it but it’s something more advanced than my simple test widget with just 3 buttons, and I already used the get desired focus on it. But it still doesn’t works, I see just the blue border and not the hover style, on keyboard and gamepad.

Hi! That issue is not streamlined in Unreal however it is perfectly maintainable. If you are using common ui states and built in logic it wouldn’t work out of the box however with minimal effort input handling can be done for umg’s even just with blueprints, better with mixed C++ and BP.

The trick is to handle inputs properly from the outer most parent and building logic on top of that. Sometimes in input handling we have to detect which input is the main source of truth but think thats another issue. To just to briefly demonstrate an approach (atleast my mindset around it)

I have a button and this has built in atomic logic as its states, styles etc. It has an enum as ist states events.


I have a common molecule called WGT_Horizontal menu. This simply inserted in many places and depending on what designer defines it generates. It sets default selected ids etc. After all its just a menu.

When something is interacted no matter what input event is called and it does something.

for example OnSelectNext unselects alll items and calls menu item to set it as selected

and the important part. When we add a panel with created elements, as example like options menu. I switch inputs to UI or UI Game and assign scheme, and handle all interaction at panel level.

Here is common input actions, like ui nav left right up down etc. and does its specific command granting me strict controlls. Sometimes using unreals navigation system OnSelectFocus widgets interactions are filtered. Like if widget focus is menu bar, Q E makes only step action there.

There is couple of reasons I do like this, since Unreal Focus state is not very relliabllle between hardwares I don’t want to rely on that. Instead I rely on panel and Selected States since UE Focus system isn’t designed for complex nested menu systems. Also I would like to build my ui platform agnostic, I wanted to focus on what user wants to do rather than what button they press. I controll which panell is added to screen and focus, should it be displaying a cursor or not at a lower level UI Manager that controlls everything such as main input detection, hardware changes, focusing on widgets, setting the game state etc.

To Recap

  1. Don’t relly on focus entirely, Mouse can break focus, its not designed for that.
  2. Handle inputs at parent level or centeralize, make them agnostic. NavLeft NavRight etc. can be even in manager panels just listen events.
  3. Have mouse states as hover, pressed however treat them as cosmetic have your selected state. Thats a very common proven interface development method commonly used in web.

What you need to do :
1.Create a custom button widget. Make it generic add its states as enum.
2. Create a container Widget (Panel of yours with 3 buttons). On contruct set one of their state selected and hold the value.
3. OnNext or whatever action input, select next (set all buttons unselected, select currentid+1)
4. You can hide engine blue focus thing cause you don’t need it anymore.

This pattern is common practice and woulld work every development environment.

On below video simply, hovers etc states cosmetic, OnClick, is just a special navigate function to desired id.

PS: MVVM is not a real modelview/viewmodel in unreal, however its a good built in system that you can use to handle things. On the other hand as you said can be overkill for you and everything can be done manually too.

1 Like

This seems like a really really smart approach, but your answer leads me to ask myself another question: should I use CommonUI? Maybe not. I approached this plugin for “automatic input management,” “you don’t have to think about it anymore,” and it seems like it’s opening up worse scenarios than the basic UMG. It certainly scales very well to complex menus like Fortnite, but that’s not my case.

As an alternative, I found this plugin UI Navigation 3.0 | Fab , which seems like a good simpler compromise. It uses a simplified stack system and handles inputs automatically. Have you ever seen it? What do you think?

Well, it is a nice way of approaching it using similar patterns.

Just to inform you about this is an upperclass that controls common ui anyway. In that terms can be easy for you however if you will go deep eventually you have to modify things and that can create learning curve for learning somebody elses system design even create friction (saying this without knowing plugin code base just skimmed through some files)

In short

  • For shortcut things you can use
    • if you are looking into a project that is for experiments.
    • You don’t have big need on interfaces or you don’t plan to release a game multi platform.
    • You are not looking into deep customisation/stylization especially behaviour in ui systems.
    • It offers many things including cursor, custom stepper functions.
  • I don’t recommend if
    • You are trying to learn and how to do things. Start slow make states or even its big you can try learning focus system.
    • If you are launching a game and have a major dependency on a plugiin that you don’t know about fully or you are missing basic programming or you don’t have a technical support.

if you look at this


// Can this component navigate right? Or parent? This comes from a centrall subsystem which is nice.
void UUINavHorizontalComponent::NotifyNavigateRight()
{
	OnNavigateRight();
	if (IsValid(ParentWidget))
	{
		ParentWidget->PropagateOnHorizCompNavigateRight(this);
	}
}

// On navigation BP function shoulld something happen?
void UUINavHorizontalComponent::OnNavigateRight_Implementation()
{
}

// Make a change / update, what index? This is a bit written like CanNavigate checker, check if index changed.

bool UUINavHorizontalComponent::Update(const bool bNotify /*= true*/)
{
	const int MaxOptionIndex = GetMaxOptionIndex();
	if (MaxOptionIndex < 1) return false;
	
	if (OptionIndex > MaxOptionIndex) OptionIndex = MaxOptionIndex;
	else if (OptionIndex < 0) OptionIndex = 0;

	const bool bChangedIndex = LastOptionIndex != OptionIndex;
	LastOptionIndex = OptionIndex;

	if (bChangedIndex && bNotify)
	{
		NotifyUpdated();
	}

	return bChangedIndex;
}

// What happened, broadcast this change!
void UUINavHorizontalComponent::NotifyUpdated()
{
	if (IsDesignTime())
	{
		return;
	}

	OnUpdated();
	OnValueChanged.Broadcast();
	OnNativeValueChanged.Broadcast();
	if (IsValid(ParentWidget))
	{
		ParentWidget->PropagateOnHorizCompUpdated(this);
	}
}

So simply it patternise navigation for many widget types in a meaningfull way. Stil its event driven not a state driven approach like mine but fair.

1 Like

You are playing the role of my conscience perfectly Grimnir…
In your opinion, if one day they fix this problem with CommonUI, will your approach become useless? My fear is learning something that goes ‘against’ the nature of the plugin; it works to solve today’s problems, but what about in the long run?
Anyway can you give me a starting point for approaching your solution? Have you explained your approach in detail somewhere? Otherwise, I’ll make do with the message you wrote, for which I thank you again!

1 Like

:slight_smile: things evolve and change, basics would be there for a long time.

State driven approach is a concrete methodology used in many places and many of the AAA games. There is nothing truly wrong or right imo however state driven approach is a bit more strict and can be a bit harder to get used to, on the other hand results are predictable, understandable, debugable and grants developer maximum control.

Bad news :slight_smile: there would be always something to learn so get used to it :slight_smile: It even can become boring. There is a built in method as demonstrated above post by Epic which works, my approach also works :slight_smile: maybe even sometimes better :slight_smile:

What I think is WRONG is using a wording like “Focus” as UX writing is a (i’ll be a little bit blunt here) absuletely most confusing wording of choice in engine, it really confuses people, it confused me a lot and seems to be its continuing to be more confusing with “Desired Focus” :slight_smile:

I will demo you, will be brief, rest is in your hands. It is pure blueprint also this is not rocket science.

Created 4 input actions specifically for UI

I defined this into a mapping context to keep it simple WSAD for now.

Created a very brief enumaration for my states of interfaces in general

Created a button base widget

In this button created some logic as follows

Over here treated mouse enter leave just cosmetic.
Created 2 events OnButtonStateChanged which passes its state enum
OnButtonInteracted which passes self button widget as object.

Override OnMouseButtonDown and calll OnButtonInteracted
also made a function as SetButtonState which simply sets enum and calls event state change.

Now I have a simple atomic custom element. I shortcut a lot of things so excuse me for that but thing you can do more around it.

I moved to a parent widget, let’s say this is My_Menu_WGT added canvas, verticalbox and some of my buttons.

In simple terms of logic,
I get how many buttons there is and save them as array
I count them
for each button bind to its Interacted.

Create Function SetButtonState :
Which simply iterate all call set state normal
and for index set selected

CreateFunction or Event NavDown/UP
CurrentID (Increment or Decrement) Clamp and Call SetButtonState
You can do wraps etc if you like and make it much nicer.

Additionaly set 1st button as selected on construct

I have another function which is handles the key events, can be like this also if input mode is different can be direct input , think there are some more changes with activatable widget input handling however simply


Get key compare to EnhancedInputSub action If they match Call Up or Down depending on action.

Created widget on my pawn, added to viewport, set input mode to ui and show a cursor.

Results.

Sorry for keeping it simple as possible however this simply demonstrates.

1-Parent is manager
2-Widgets are state driven
3-Atoms don’t care what interacted with them they only know their own status
4-We only focus panel, the rest is history.

Let me know!

Addition

You can also use a hack like this to maintain Input Owner (focus) at your panel if you don’t want to maintain every widgets interaction state however sub widgets in this approach majority of the time shouln’t require a focus.

Wow! Thank you, grimnir! I followed your guide, and indeed, the system isn’t that complicated. Thanks for explaining it to me in detail. I managed to get it working, more or less. I have a small bug where the value goes out of bounds, which I think should be an easy fix. To do that, however, I need to clear up some confusion about the CurrentID variable: I can’t figure out how it works. From what I see in the code, it’s never updated and always stays at 0. Shouldn’t this prevent navigation between 0 and 1?

Aside from that, how do you think this could be integrated with CommonUI’s activatable widget and commonUI style system?

Here is my result


And my blueprints

1 Like

Hey there,

Glad that it worked. It’s true there can be bugs, I just give you the raw fundamentals but you can always improve.

For the bug: You can simply re assign incoming ID to Current ID in SetButtonState() so you can be sure that you allways have the CurrentStateID correct. You can ofcourse do cleanup in a different way its just ok.

  • You can make wraps
  • You can patternise a Common_Vertical_Menu with N buttons
  • You can use MVVM + State machine + Observer patterns to create organisms like a sophisticated map, inventory etc.

For CAW and commonui yes it can be simply used both by meeting the both worlds, depends on the end results you expect in the long term. You can use common ui styling system which is robust and woulld be great. That’s what I do also, when styling not enough I go more low level to solve problems or create my own stuff. Activatable widget I didn’t go into its details but will look.

On high level design, I have my custom widget clases like MGInterfaceWidget and they do their own things, input assignments, hardware event bindings, custom global animations and many more however they are a widget after all. So once you digest they are all widgets :slight_smile: things would be getting more and more clear. In markup driven languages like html, everything is a box.

When you start to build something more complex you can have an approach like this.

InterfaceDirector - > Decides layout, State, Hardware, InputHandling/Routing, GameState etc
InterfaceLayout → What are layers, what are their states, what is on top of what
InterfaceLayer->What I display, What is on Stack, Pop layer, Clean layerr etc.
InterfacePanel-> What widgets I hold, how they work
InterfaceWidget-> Organisms or Atomic any element.

Ex Flow : PushContentToLayer(HUDNew, GameLayer)

Director->GetCurrentLayout->GetLayers->GameLayer(IsNotEmpty)->PopStack(Hud)->PushContent(HudNew)->Callback->OnInterfaceLayerUpdated()

On InterfaceLayerUpdated(Layer, Object)->CheckState()-> Try SetFocus(Object)

1 Like

Great! I’ll work on an implementation of this method with the CommonUI systems, CAW and style. I’ll come back to this thread to document my, hopefully working, progress. It may be helpfull for anyone else in the community newbie who wants to know more about this approach. Thanks again!

1 Like