x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Capturing mouse input in a Slate widget

Hey everyone.

I'm having an issue where I've hooked up Slate to my HUD class and got a widget to render.

This widget consists of a TextBlock and an SImage, side-by-side. I want the SImage to act more or less like a button, so when clicked it will expand a submenu and the SImage will change appearance.

Here's the Construct code for the SImage:

   + SHorizontalBox::Slot()
     .AutoWidth()
     [
         SAssignNew(ToggleButton, SImage)
         .Image(&PlanetStatusStyle->ToggleButtonCollapsed)
         .OnMouseButtonDown(FPointerEventHandler(ToggleClickEvent))
     ]

As you can see, I've hooked up an event delegate that calls a function on trigger. Here's the declaration:

 TBaseDelegate_RetVal_TwoParams<FReply, const FGeometry&, const FPointerEvent&> ToggleClickEvent;

And here's the function:

 FReply SPlanetStatusWidget::OnToggleClick(const FGeometry& Geometry, const FPointerEvent& Event)
 {
     // Toggle dropdown menu visibility.
     MenuVisibility = MenuVisibility == EVisibility::Collapsed ? EVisibility::Visible : EVisibility::Collapsed;
 
     // Notify UE event system that event was handled.
     return FReply::Handled();
 }

I've bound the function to the delegate like so:

 ToggleClickEvent.BindRaw(this, &SPlanetStatusWidget::OnToggleClick);

Now with all this out of the way, I was hoping I'd get a triggered breakpoint inside the function when the image was clicked. Alas, no luck. So I studied on, mainly in StrategyGame sample. I found out that there was a virtual function returning whether or not keyboard focus is supported by the widget. As far as I understand keyboard and mouse focus goes hand-in-hand (and I didn't find anything related to mouse focus), so I made an override of that and returned true.

Still nothing... My face is now starting to adopt a red/blue hue. So I plowed on - found, inside the playercontroller, that there are a few bools there that could be related to it. So I set bEnableClickEvents to true and bEnableTouchEvents to true.

Still nothing... And, frankly, now I'm out of ideas...

So if anyone have any input, I'd love to hear it!

Thanks in advance guys - firstly for taking the time reading this wall of text and secondly for any useful info :D

Product Version: Not Selected
Tags:
more ▼

asked Mar 26 '14 at 06:22 PM in C++ Programming

avatar image

ReqPro
59 9 12 15

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

4 answers: sort voted first

With regard to attribute binding, you can just do: OnMouseButtonDown(this, &SPlanetStatusWidget::OnToggleClick)

more ▼

answered Mar 26 '14 at 06:33 PM

avatar image

Jamie Dale STAFF
7.5k 177 67 305

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

Hey, I haven't code the code in front of me at the moment, but it looks like you want to bind the on mouse button down to a delegate that invokes SPlanetStatusWidget::OnToggleClick.

If so, I think this code should do what you want:

 SAssignNew(ToggleButton, SImage)
 .Image(&PlanetStatusStyle->ToggleButtonCollapsed)
 .OnMouseButtonDown(this, &SPlanetStatusWidget::OnToggleClick)

(Assuming 'this' is an SPlanetStatusWidget*)

more ▼

answered Mar 26 '14 at 06:31 PM

avatar image

BrɑκеPɑd STAFF
1.4k 33 22 78

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

If you want something to act like a button you should use an actual button widget. The button widget's content and style can be completely customized to get the look you desire.

You'll want something like the following.

        SNew( SButton )
         .ContentPadding(0)
         .OnClicked( this, &SPlanetStatusWidget::OnToggleClicked )
         .ButtonStyle( FCoreStyle::Get(), "NoBorder" )
         [
             SNew(SImage)
             .Image( &PlanetStatusStyle->ToggleButtonCollapsed )
         ]


         FReply SPlanetStatusWidget::OnToggleClicked ()
         {
             // Toggle dropdown menu visibility.
             MenuVisibility = MenuVisibility == EVisibility::Collapsed ? EVisibility::Visible : EVisibility::Collapsed;
             return FReply::Handled();
         }

more ▼

answered Mar 26 '14 at 07:35 PM

avatar image

Sarge STAFF
627 14 5 36

avatar image ReqPro Mar 26 '14 at 07:53 PM

Hi Sarge, and thanks for your input!

I'm having somewhat of a problem forcing the no border style through since I'm grabbing styles from a style set.

My code for getting the style looks like this: .ButtonStyle(&PlanetStatusStyle->ToggleButtonStyle)

If I were to "merge" the grabbed style from the editor's WidgetStyle with the no border, how would I go about that?

avatar image Sarge STAFF Mar 26 '14 at 08:00 PM

Well you have a couple options. One super easy one is to consider whether or not being able to style this particular aspect of your UI is important. If it isn't then referencing FCoreStyle in the way i did above is perfectly legit.

Another option would be to create your own version of "NoBorder" in your style.

 const FButtonStyle NoBorder = FButtonStyle()
     .SetNormal(FSlateNoResource())
     .SetHovered(FSlateNoResource())
     .SetPressed(FSlateNoResource())
     .SetNormalPadding(FMargin(0,0,0,1))
     .SetPressedPadding(FMargin(0,1,0,0));

 Style->Set( "NoBorder", NoBorder );

This has the benefit of not being dependent on FCoreStyle, so if in the future FCoreStyle isn't always around all your stuff will continue to work.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

Hi both, and thanks for your answers!

That's more or less exactly what I've done, though I've used an iseparate delegate instead...

Just to make sure that wasn't the issue, I've now tried your method of just passing the function as a binding, without the separate delegate, but it isn't triggered.

I'm wondering what I could've missed?

I noticed that if I hold down the left mouse button over the image, the rest of the scene stops updating/rendering.

more ▼

answered Mar 26 '14 at 07:03 PM

avatar image

ReqPro
59 9 12 15

avatar image Jamie Dale STAFF Mar 26 '14 at 07:25 PM

Given you want something that behaves like a button, is there a reason you don't just use an SButton with an SImage as the content?

You can set the button style to "NoBorder" from FCoreStyle if you don't want the gradient on the button .ButtonStyle(FCoreStyle::Get(), "NoBorder")

avatar image ReqPro Mar 26 '14 at 07:27 PM

Hi Jamie,

no there's no real reason, I'm just still trying to get my bearings with Slate and didn't want to overcomplicate things by having to fight a default button layout as well as trying to get functionality to work - but as you said, I may have overcomplicated things by NOT going that direction.

I will try using a button instead and see how it works out :)

avatar image ReqPro Mar 26 '14 at 07:48 PM

Well I just tried replacing the SImage with a button and there's no difference - the result is exactly identical. The function isn't called, and when holding down the mouse button over the button, it just stops the rendering/update.

One thing I did notice though, is that the hover and clicked brushes aren't being shown either, so it's like the mouse cursor is completely ignored by the widget.

avatar image ReqPro Mar 26 '14 at 08:26 PM

Okay, I feel severely stupid now...

I just remembered that it was stated in the docs that Slate will not work in PIE - it needs to be launched in a standalone for Slate functionality for work.

So I started the thing in a standalone game and lo and behold - it works!

Sorry to have wasted so much of your guys time because I can't think worth a penny :(

Thank you to you all for all your help!

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question