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"

[4.10] Full screen widget not forwarding input

I have a fullscreen SWidget added as a child to game's viewport that's transparent everywhere and all of its mouse methods return FReply::Unhandled. Nevertheless, mouse events don't bubble up to the game viewport and because of that ingame objects are not getting notified when the mouse hovers over them. More precisely, they only receive ActorBeginCursorOverlap and ActorEndCursorOverlap when they get clicked and they never receive ActorOnClicked. What baffles me is that the exact same project works perfectly fine in 4.9 and I could not find anything in the patch notes regarding the problem. Looking forward to your suggestions.

Here's the relevant code:

 class MyWidget : public SCompoundWidget
 {
 FReply SMyWidget::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
 {
     return FReply::Unhandled();
 }
 FReply SMyWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
 {
     return FReply::Unhandled();
 }
 FReply SMyWidget::OnMouseButtonDoubleClick(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
 {
     return FReply::Unhandled();
 }
 FReply SMyWidget::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
 {
     return FReply::Unhandled();
 }
 FReply SMyWidget::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
 {
     return FReply::Unhandled();
 }
 };
 
 // Later during initialization
 MyWidget = SNew(SMyWidget).Owner(this);
 if (GEngine->IsValidLowLevel())
 {
     GEngine->GameViewport->AddViewportWidgetContent(SNew(SWeakWidget).PossiblyNullContent(MyWidget.ToSharedRef()));
 }


And the blueprint event handlers attached to a simple actor:

alt text

Product Version: UE 4.10
Tags:
bpcode.png (119.1 kB)
more ▼

asked Nov 30 '15 at 11:28 AM in C++ Programming

avatar image

NikolaDimitroff
36 3 6

avatar image Niktsuki Dec 04 '15 at 12:49 AM

Has any solution been found for this? I am having the same problem.

avatar image NikolaDimitroff Dec 10 '15 at 09:09 AM

Sadly, no. We've also contacted Epic in the UDN but no solution has been found. I'll let you know once we have more information.

avatar image Rudy Q ♦♦ STAFF Jan 27 '16 at 08:37 PM

Hello NikolaDimitroff,

I have a potential workaround that may be viable depending on your needs. There was another user with a similar issue. I have provided a link below. I hope that this information helps.

Link: https://answers.unrealengine.com/questions/341495/umg-eats-all-of-our-double-click-events.html

Make it a great day

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

2 answers: sort voted first

Hello NikolaDimitroff-

As mentioned on the UDN post, this issue has been reported as UE-25033 for investigation.

Cheers

Doug Wilson

more ▼

answered Jan 27 '16 at 07:28 PM

avatar image IvanTheChemist Jun 16 '16 at 11:38 AM

Is there an update on when this issue will be fixed?

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

Hello again and let me apologize for the incorrect tag - the problem has appeared in 4.9, not in 4.10 and here's a detail description of a hacky workaround:

The breaking change was introduced in 4.9 and is the following:

Prior to 4.9 APlayerController::TickPlayerInput looked like this:

 ...
 if (LocalPlayer->ViewportClient->GetMousePosition(MousePosition))
 {
     bHit = GetHitResultAtScreenPosition(MousePosition, CurrentClickTraceChannel, true, /*out*/ HitResult);
 }
 
 UPrimitiveComponent* PreviousComponent = CurrentClickablePrimitive.Get();
 UPrimitiveComponent* CurrentComponent = (bHit ? HitResult.Component.Get() : NULL);
 
 UPrimitiveComponent::DispatchMouseOverEvents(PreviousComponent, CurrentComponent);

Post 4.9 the code is now:

 // Only send mouse hit events if we're directly over the viewport.
 if ( ViewportClient->GetGameViewportWidget().IsValid() && ViewportClient->GetGameViewportWidget()->IsDirectlyHovered() )
 {
     if ( LocalPlayer->ViewportClient->GetMousePosition(MousePosition) )
     {
         bHit = GetHitResultAtScreenPosition(MousePosition, CurrentClickTraceChannel, true, /*out*/ HitResult);
     }
 }
 
 UPrimitiveComponent* PreviousComponent = CurrentClickablePrimitive.Get();
 UPrimitiveComponent* CurrentComponent = (bHit ? HitResult.Component.Get() : NULL);
 
 UPrimitiveComponent::DispatchMouseOverEvents(PreviousComponent, CurrentComponent);

This is a side-effect of a change listed in the release notes of 4.9:

We no longer ignore hit testing in APlayerController::GetHitResultAtScreenPosition if the mouse isn't directly over the viewport. That function can be used regardless of the state of the mouse, so that logic has been moved elsewhere.

The change to APlayerController::TickPlayerInput is to accomodate for the fact that APlayerController::GetHitResultAtScreenPosition no longer ignores hits outside the viewport. Problem is, the new test is not equivalent to the previous one. Whereas the old one used ULocalPlayer::CalcSceneView which checks whether the mouse coordinates are inside the viewport, the new one (`ViewportClient->GetGameViewportWidget()->IsDirectlyHovered()`) instead checks whether the viewport is the topmost widget under the mouse.

I was able to solve the issue by changing:

 bool FSlateApplication::IsWidgetDirectlyHovered(const TSharedPtr<const SWidget> Widget) const
 {
     for( auto LastWidgetIterator = WidgetsUnderCursorLastEvent.CreateConstIterator(); LastWidgetIterator; ++LastWidgetIterator )
     {
         const FWeakWidgetPath& WeakPath = LastWidgetIterator.Value();
         if( WeakPath.IsValid() && Widget == WeakPath.GetLastWidget().Pin() )
         {
             return true;
         }
     }
     return false;
 }

to

 bool FSlateApplication::IsWidgetDirectlyHovered(const TSharedPtr<const SWidget> Widget) const
 {
     for( auto LastWidgetIterator = WidgetsUnderCursorLastEvent.CreateConstIterator(); LastWidgetIterator; ++LastWidgetIterator )
     {
         const FWeakWidgetPath& WeakPath = LastWidgetIterator.Value();
         if( WeakPath.IsValid() && 
             ( Widget == WeakPath.GetLastWidget().Pin() ||
               WeakPath.GetLastWidget().Pin()->GetTypeAsString() == "MyWidget") )
         {
             return true;
         }
     }
     return false;
 }

This way checking if a widget is on top will return true if either it, or the invisible widget is on top. This introduces an inconsistency as the function will return true for multiple widget but generally having my widget on top is the same as having none at all so it shouldn't matter.

Besides, searching for it in the engine's source revealed that this is its only usage (although it's pubic and clients may call it in other places)

Another working solution is to remove the check from PlayerController::TickPlayerInput:

 // Change line 3842 in PlayerController.cpp as of 4.11 from
 if ( ViewportClient && ViewportClient->GetGameViewportWidget().IsValid() && ViewportClient->GetGameViewportWidget()->IsDirectlyHovered() )
 // to
 if ( ViewportClient && ViewportClient->GetGameViewportWidget().IsValid())


more ▼

answered Apr 06 '16 at 03:56 PM

avatar image

NikolaDimitroff
36 3 6

avatar image VBBonchev Dec 11 '18 at 04:49 PM

Unfortunately this seems to not be working anymore in UE 4.21. I've got the same setup: An SWidget in the game's viewport that's transparent and returns FReply::Unhandled, plus the fix from above that makes the IsWidgetDirectlyHovered check pass. What happens currently is that my in-world UMG widget is not receiving any mouse events (neither ActorBeginCursorOverlap nor ActorEndCursorOverlap seem to work). Is there a change that could've introduced this behaviour? Do you have any suggestions as to how to fix this?

(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