Binding Mouse Left Click to Gamepad Button

I have been having an issue that I have not found a fix for within 5.4. I am trying to set up the ability to use the gamepad to control the mouse cursor. I can move it around the screen, and when the cursor hovers over the buttons, it shows that it is hovered, but I cannot click using the gamepad face button bottom. In the past I know there was a way to add more buttons to the Click Event Keys array, but I can not find a way to add additional items into the array. Is there a solution that anyone can give?

1 Like

hey @Sw1ftW1ngs how are you?

I think you can do something like this in your Character Blueprint:

As you can see, you can use Press Pointer Key and Release Pointer Key to convert any gamepad button into a “left click”.

“Widget Interaction” is a component you should add in your character blueprint and assign the corresponding widget to it.

Let me know if this helps you!

Hey. Unfortunately, I had tried this before making the post. I think my issue is that I am using UI widgets, and the widget interaction is looking for clickable items in the 3D world. At least that’s what it seems like with my lack of experience.

1 Like

Haha I’m just like you :grinning_face_with_smiling_eyes:

1 Like

Doesn’t this work with the built in analog cursor system?

FAnalogCursor | Unreal Engine 5.6 Documentation | Epic Developer Community

There’s a lack of documentation online but the analog cursor exists to control mouse movement / click behavior with gamepads.

If you’re working with C++ I can give you an example implementation from my UI system:

Ferrefy-Plugin-UI-Additions/UIAdditionsPlugin/Source/UIAdditionsPlugin/Private/Input/PreProcessor/ExtendedAnalogCursor.cpp at master · Seda145/Ferrefy-Plugin-UI-Additions · GitHub

Also, partly borrowed from the widget interaction component, I put the functionality to simulate an input key into a utility method, so you can do that literally anywhere. Here you can see how that is done:

bool USlateUtils::ProcessKeyEvent(int32 InSlateUserIndex, const FKey& InKey, bool bInIsKeyDown, bool bInIsRepeat) {
	// Wanted to use FModifierKeysState as parameter on the method, but didn't compile on USlateUtils.h. FInputChord is not a 1:1 match.
	// Then found out on SEditableTextBox that it was ignored entirely anyway (no shift, no caps, character R remains R not r), so I skip it. 
	// Possible TODO if EPIC cleans up their stuff.

	if (!FSlateApplication::IsInitialized()) {
		UE_LOG(LogUIAdditionsPlugin, Error, TEXT("SimulateInputKey failed, FSlateApplication is not initialized."));
		return false;
	}

	// The following is similar behavior to WidgetInteractionComponent.

	bool bHasKeyCode, bHasCharCode;
	uint32 KeyCode, CharCode;
	GetKeyAndCharCodes(InKey, bHasKeyCode, KeyCode, bHasCharCode, CharCode);
	const FKeyEvent KeyEvent = FKeyEvent(InKey, FModifierKeysState(), InSlateUserIndex, bInIsRepeat, KeyCode, CharCode);
	const bool bIsProcessKeyEventHandled = bInIsKeyDown ? FSlateApplication::Get().ProcessKeyDownEvent(KeyEvent) : FSlateApplication::Get().ProcessKeyUpEvent(KeyEvent);
	
	bool bIsCharEventHandled = true;
	if (bHasCharCode) {
		const FCharacterEvent CharacterEvent(CharCode, FModifierKeysState(), InSlateUserIndex, bInIsRepeat);
		bIsCharEventHandled = FSlateApplication::Get().ProcessKeyCharEvent(CharacterEvent);
		// UE5.2:
		// On the OS level a physical key press would result in getting the correct character.
		// When simulating a character event, the engine lacks some functionality:
		// Modifier keys (shift, caps etc.) can't be simulated through this method properly. 
		// Sending "R, no shift, no caps" to an editable text box widget results in "R" (see FSlateEditableTextLayout::HandleTypeChar),
		// ignoring FCharacterEvent. It's a Slate bug because it seems this key processing has to be finished up at the OS level, and Slate allows wrong results.
		// 
		// While this method is still useful to simulate an input action, it lacks in functionality when used for actual text input (such as virtual keyboard (only capital text, missing symbols etc.)). For such purposes, an alternative must be implemented.
	}

	return (bIsProcessKeyEventHandled || bIsCharEventHandled);
}
1 Like