x157 / x157.github.io

46 stars 7 forks source link

Tutorial Request: How to Take Control of the Mouse with CommonUI #14

Closed x157 closed 1 year ago

x157 commented 1 year ago

EDIT: Created Tutorial: https://youtu.be/A9dp3cmCFtQ

As of UE 5.1, this code implicitly changes the input mode to Menu:

PlayerController->SetShowMouseCursor(true);

And this code does not change the input mode at all:

PlayerController->SetShowMouseCursor(false);

This means any time I want to show/hide the mouse as a part of normal game play I need to explicitly manage the input mode and mouse capture settings every time the mouse visibility changes.

Note it's possible the forced switch only occurs if you start off in Game only input mode. For certain it happened to me from Game mode, it kept forcing me into Menu just from making the mouse visible.

In my case, I'm trying to use a widget that is on UI.Layer.Game that is sometimes active and sometimes not active. I do not want all the input to stop working for the game, I just want the user to be able to click a widget if they want to, or not click it, with a sometimes visible mouse cursor during normal gameplay.

Ultimately I solved the problem by overriding ULyraHUDLayout::GetDesiredInputConfig such that it returns a different config for when I want the mouse to be visible during gameplay compared to what it returns when I want the mouse to be invisible. (Also explicitly disable bIsFocusable for the HUD Layout, or it sometimes starts stealing input(?)).

This also required overriding the base ULyraActivatableWidget::GetDesiredInputConfig to manage look input ignore settings in the various scenarios since Lyra provides no visibility into or access to set look input ignore preferences.

Finally, a complete and total overhaul of UCommonUIActionRouterBase::ApplyUIInputConfig was required, I literally had to throw out that entire method and rewrite it all to get it to work. Part of that included not completely ignoring look/move input ignore preferences like it does by default. (In 5.1 this requires a custom engine, in 5.2 the Launcher Engine will support this by default).

With all of this in place, I had to write a virtual PlayerController->SetShowMouseCursor (which itself is not virtual) and any time I want to show or hide the mouse in my extended SetShowMouseCursor I also explicitly call my (hacked to be public) overridden Action Router ApplyUIInputConfig with the appropriate config for a visible mouse (or invisible as the case may now be).

For all of this to work, the HUD and the C++ need to agree that the appropriate Input Mode is All (Game+Menu). And the mouse capture in my case was CapturePermanently_IncludingInitialMouseDown with an invisible mouse, and CaptureDuringMouseDown with a visible mouse.

Furthermore, since I use the mouse for Look input, I disable Look when the mouse cursor is visible, though Move is still active.


Additional reading related to Game capture and mouse weirdness:

https://forums.unrealengine.com/t/why-axis-value-of-moveforward-event-is-0-when-left-mouse-button-event/577686/5?u=xi57

x157 commented 1 year ago

This seems to be related to this "Wont Fix" bug:

https://issues.unrealengine.com/issue/UE-100627

x157 commented 1 year ago

Created YT vid: https://youtu.be/A9dp3cmCFtQ

And Dev Notes: https://x157.github.io/UE5/LyraStarterGame/Tutorials/How-to-Take-Control-of-the-Mouse