Download

Trouble getting custom input device plugin working

I am writing a IInputDeviceModule plugin to take values from an analog slider and pipes it into the UE4 input system as a new float axis FKey.

I based the plugin heavily on existing plugins like the steamcontroller, and xbox controller code I found in UE4.

I report input events with UE4 in what appears to be the standard way, inside my IInputDevice::SendControllerEvents:



// from 0 to 127
SliderVal = GetRawValueOfAnalogSlider();
// If value reported by device changed this tick
if (PreviousSliderVal != SliderVal )
{
	// Normalize from [0,127] to [0,1]
	float Normalized = (float)SliderVal / 127.f;
	FSlateApplication::Get().OnControllerAnalog(FCustomPluginKeys::MyNewKey.GetFName(), 0, Normalized);

	PreviousSliderVal  = SliderVal;
}

This value gets properly funneled down into UPlayerInput::InputAxis.

However, it appears the code in UPlayerInput::InputAxis expects delta values…? And the delta values are accumulated in a buffer until the next time the player’s input stack is processed.

This leads to behavior where if I change the slider quickly, large values build up in the axis value accumulator, and error builds up. But if I move the slider slowly, the axis values are accurate.

So I tried only sending the delta values


float DeltaNormalized = (float)(SliderVal - PreviousSliderVal) / 127.f;

but this gives even worse behavior, I no longer get any kind of accurate representation of the slider in the reported values of my float axis. And plus, all code I’ve seen so far sends in the normalized raw value to FSlateApplication::Get().OnControllerAnalog, not the normalized delta.

Not sure what I am doing wrong here…? Am I supposed to be scaling my values by a deltaTime or something? I don’t see other plugins doing this though. Any help much appreciated.

Cheers

These are the typical helper functions I write for emitting Input Mapping events:


bool EmitKeyUpEventForKey(FKey key, int32 user, bool repeat)
{
	FKeyEvent KeyEvent(key, FSlateApplication::Get().GetModifierKeys(), user, repeat, 0, 0);
	return FSlateApplication::Get().ProcessKeyUpEvent(KeyEvent);
}

bool EmitKeyDownEventForKey(FKey key, int32 user, bool repeat)
{
	FKeyEvent KeyEvent(key, FSlateApplication::Get().GetModifierKeys(), user, repeat, 0, 0);
	return FSlateApplication::Get().ProcessKeyDownEvent(KeyEvent);
}

bool EmitAnalogInputEventForKey(FKey key, float value, int32 user, bool repeat)
{
	FAnalogInputEvent AnalogInputEvent(key, FSlateApplication::Get().GetModifierKeys(), user, repeat, 0, 0, value);
	return FSlateApplication::Get().ProcessAnalogInputEvent(AnalogInputEvent);
}

The analog input one is probably what you want. You can pass any data you get in there and it will emit that as the axis value. IM changed in 4.6 which made things a bit more complicated, haven’t really looked into the specifics since then because the above code has always worked.

Hope that helps.

Thanks getnamo! I will give that a try. Definitely looks promising though, not using the OnControllerAnalog codepath and constructing the analog event myself. Cheers!