Hi there, I’m trying to set up a menu to work the same way regardless of your input method, so if you’re using your gamepad or keyboard, the focused button should look the same as when you hover your mouse, since the “focus” button outline is nearly invisible, not a proper visual indicator for gamepad or keyboard navigation.
You’d normally wrap a button with a widget. You can then have script inside the button - methods that modify style depending on its state. You could then have that widget trigger a method when focus is received or lost.
As a bonus you can update all buttons with a single click rather than visit 47 menus to find them all.
but would you make this custom button as a child blueprint of the button class, or just a sub-widget blueprint with a button inside? if the latter, then how do I manage to get on clicked events in my main blueprint?
The custom button would be a child of the UUserWidget, with either a button widget inside or any setup you prefer. You can pass on click events up to the parent through the event dispatcher, or give another widget public access to the button widget within your UserWidget
I drag an event pin from the “Bind Event” node and type “Create Event”. Then I get a simple dropdown where I can select an existing function, so it never clutters the event graph like yours.
Also never make a binding on PreConstruct. PreConstruct runs both in-game and in editor (where the binding is undesired). It also can run multiple times. Make your bindings during
OnInitialized instead.
on my second example that’s what I did, typed “create event”, but I still had to do it one time for each button.
however, as Everynone pointed out, click events are automatically bound when you add a custom button widget to your main widget, no need to bind them again.
I’m still trying to find an easier way to set each button’s text though
Yeah, those are alredy hookep up automatically. This behaves the same as the native widgets. If you place a native button in a native canvas, you’ll also get 5 or so click events from the get-go. Without additional binding. The parent can see its childrens’ dispatchers. Same thing here.
Also works for actors and components.
We need to set the text somehow, though. You could expose the text block as variable and avoid the custom event.
Or you could bind a text variable to a text block and set only that variable’s value from outside. Really minimalistic but polled every frame. Fine if that’s just a handful of text fields or you need this updated every frame anyway.
Finally, for an utterly nodeless experience, you can give the child button a reference to the actor / widget it needs to pull the data from. You can actually do this when binding:
I did think of exposing the text variable, but I don’t think it’s possible?
and binding to a variable isn’t ideal either since it polls every frame as you mentioned, but I can set the button text on construct to that exposed text variable, and I guess it works…? not sure if it’ll stay after refreshing the widget or such.
However, regarding the initial premise of using a user widget button instead of a regular button, I found an issue.
when you’re using arrow keys to navigate, and you need to set up explicit navigation for the bottom button to go back to the top on arrow down (and similar for the top button), it works fine with regular buttons, but not quite with user created button widgets.
After navigating to any explicitly set button, the interaction input key (such as space bar, enter, etc) won’t work, it won’t interact with the button, even though is has keyboard focus.
If you move from the first button to the second button, as in the standard navigation flow that doesn’t need any explicit mapping, it still works fine, but the previous issue is kind of a deal breaker. is there any way to fix this behavior?
I think the issue might be that the explicit mapping might be focusing on the entire user widget (button and text as a whole) instead of specifically the button.
Yup, you might be right. Inside the button, override OnFocused (?) and move the focus to the native button. May work.
That’s one of the reason why I stopped using buttons years ago - they seem nifty but are inflexible. Never looked back. I just use wrapped borders with inheritance.
It works like a charm. I had set up a custom function for each of those buttons (instead of explicit mapping), which worked, but your way is much better. I guess this solves everything, so thanks again! Will mark your previous reply as solution.
I’m now interested in the border method you described though, I thought it would require extra work, since they don’t have native button functions? could you explain a bit the overall process?
Indeed, it’s quite a bit of extra upfront work since the button already has useful functionality, and plenty of bells & whistles - like styles, click methods, sound handling, hover states…
But if you do want a UI control that does not steal focus like it’s its job, you cannot use a button as is. I could not.
I needed a layered, flexibile click-through interface, so I settled for something along the lines of:
base class
specialised children
All standard behaviours and shared functionality are scripted in the Base - hover states, sound handling, visual styles, dynamic material creation and so on:
The specialised UI elements inherit from that base:
The actual UI control used in the project are reparented to this base and equipped with additional unique functionality - standard inheritance, really.
In the child, do note how the reparented hierarchy is empty:
And you can add parent calls as per usual. If half way through the project you need to change something across the entire UI or parts of it, add functionality, touch up the visuals, you can do it in the base classes.
This would allow you to create highly customisable UI controls.