Invalid FKey Warning on Input Device Plugin

First off, the plugin works. The Input devices are available in blueprints, they compile and the functionality is there. The issue is that all of my inputs have the warning “InputKey Event specifies invalid FKey.”

This is the InputDevice class:

#include "HRF_Controller.h"

#include "HRF.h"
#include "HAL/PlatformTime.h"
#include "HAL/PlatformProcess.h"
#include "Misc/Paths.h"
#include "GenericPlatform/GenericApplicationMessageHandler.h"
#include "Modules/ModuleManager.h"
#include "GenericPlatform/IInputInterface.h"
#include "IInputDevice.h"
#include "IInputDeviceModule.h"
#include "GameFramework/InputSettings.h"

#define LOCTEXT_NAMESPACE "HRFController"

namespace HRFControllerKeyNames {

	// HHL Button Key Names
	const FGamepadKeyNames::Type HRF_Button1("HRF_Button1");
	const FGamepadKeyNames::Type HRF_Button2("HRF_Button2");
	const FGamepadKeyNames::Type HRF_Button3("HRF_Button3");
	const FGamepadKeyNames::Type HRF_Button4("HRF_Button4");
	const FGamepadKeyNames::Type HRF_Button5("HRF_Button5");
}

namespace HRFControllerKeys {

	// HRF Button Keys 
	const FKey HRF_Button1("HRF_Button1");
	const FKey HRF_Button2("HRF_Button2");
	const FKey HRF_Button3("HRF_Button3");
	const FKey HRF_Button4("HRF_Button4");
	const FKey HRF_Button5("HRF_Button5");
}

class FHRFController : public IInputDevice {

public:

	FHRFController(const TSharedRef< FGenericApplicationMessageHandler >& InMessageHandler) :
		MessageHandler(InMessageHandler) {

		// HRF Buttons
		EKeys::AddKey(FKeyDetails(HRFControllerKeys::HRF_Button1, LOCTEXT("HRF_Button1", "HRF_Button1"), FKeyDetails::GamepadKey));
		EKeys::AddKey(FKeyDetails(HRFControllerKeys::HRF_Button2, LOCTEXT("HRF_Button2", "HRF_Button2"), FKeyDetails::GamepadKey));
		EKeys::AddKey(FKeyDetails(HRFControllerKeys::HRF_Button3, LOCTEXT("HRF_Button3", "HRF_Button3"), FKeyDetails::GamepadKey));
		EKeys::AddKey(FKeyDetails(HRFControllerKeys::HRF_Button4, LOCTEXT("HRF_Button4", "HRF_Button4"), FKeyDetails::GamepadKey));
		EKeys::AddKey(FKeyDetails(HRFControllerKeys::HRF_Button5, LOCTEXT("HRF_Button5", "HRF_Button5"), FKeyDetails::GamepadKey));


		// Wait for HRF_ToolServer.exe to load
		FPlatformProcess::Sleep(2);

		hrf = MakeShareable<HRF>(new HRF());

	}

	virtual ~FHRFController() {
	}

	virtual void Tick(float DeltaTime) override {
	}

	virtual void SendControllerEvents() override {
		// Get States
		hrf->GetState(HRF_A);

		// Check Button1
		if (HRF_A.Button1 != HRF_B.Button1) {
			if (HRF_A.Button1 == 1) {
				MessageHandler->OnControllerButtonPressed(HRFControllerKeys::HRF_Button1.GetFName(), 0, false);
			}
			else {
				MessageHandler->OnControllerButtonReleased(HRFControllerKeys::HRF_Button1.GetFName(), 0, false);
			}
		}

		// Check Button2
		if (HRF_A.Button2 != HRF_B.Button2) {
			if (HRF_A.Button2 == 1) {
				MessageHandler->OnControllerButtonPressed(HRFControllerKeys::HRF_Button2.GetFName(), 0, false);
			}
			else {
				MessageHandler->OnControllerButtonReleased(HRFControllerKeys::HRF_Button2.GetFName(), 0, false);
			}
		}

		// Check Button3
		if (HRF_A.Button3 != HRF_B.Button3) {
			if (HRF_A.Button3 == 1) {
				MessageHandler->OnControllerButtonPressed(HRFControllerKeys::HRF_Button3.GetFName(), 0, false);
			}
			else {
				MessageHandler->OnControllerButtonReleased(HRFControllerKeys::HRF_Button3.GetFName(), 0, false);
			}
		}

		// Check Button4
		if (HRF_A.Button4 != HRF_B.Button4) {
			if (HRF_A.Button4 == 1) {
				MessageHandler->OnControllerButtonPressed(HRFControllerKeys::HRF_Button4.GetFName(), 0, false);
			}
			else {
				MessageHandler->OnControllerButtonReleased(HRFControllerKeys::HRF_Button4.GetFName(), 0, false);
			}
		}

		// Check Button5
		if (HRF_A.Button5 != HRF_B.Button5) {
			if (HRF_A.Button5 == 1) {
				MessageHandler->OnControllerButtonPressed(HRFControllerKeys::HRF_Button5.GetFName(), 0, false);
			}
			else {
				MessageHandler->OnControllerButtonReleased(HRFControllerKeys::HRF_Button5.GetFName(), 0, false);
			}
		}


		// Set HRF_B = HRF_A -> Repeat
		HRF_B = HRF_A;
		// End HRF stuff

	}

	void SetChannelValue(int32 ControllerId, FForceFeedbackChannelType ChannelType, float Value) override {

	}

	void SetChannelValues(int32 ControllerId, const FForceFeedbackValues &Values) override {

	}

	void UpdateVibration(int32 ControllerId, const FForceFeedbackValues& ForceFeedbackValues) {

	}

	virtual void SetMessageHandler(const TSharedRef< FGenericApplicationMessageHandler >& InMessageHandler) override {
		MessageHandler = InMessageHandler;
	}

	virtual bool Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar) override {
		return false;
	}

	virtual bool IsGamepadAttached() const override {
		return true;
	}

private:

	TSharedRef<FGenericApplicationMessageHandler> MessageHandler;

	TSharedPtr<HRF> hrf;
	HRF_State HRF_A, HRF_B;

};


class FHRFControllerPlugin : public IInputDeviceModule {
	virtual TSharedPtr< class IInputDevice > CreateInputDevice(const TSharedRef< FGenericApplicationMessageHandler >& InMessageHandler) override {
		return TSharedPtr< class IInputDevice >(new FHRFController(InMessageHandler));
	}
};

#undef LOCTEXT_NAMESPACE  // HRFController

IMPLEMENT_MODULE(FHRFControllerPlugin, HRFController)

When I load the editor, I get the following warning:

Inside my Blueprint before hitting compile:

After Compile:

Output Log while running, using the input device:

243450-outputlogrunning.png

So everything is working. I have tried placing the plugin folder in my project’s plugins folder as well as both the Runtime and Developer folders in the Engine Plugins (not at the same time). I keep getting the warning messages. What am I missing? It works, but I can’t release this with those messages. I am unable to show the HRF class due to IP issues but it mainly contains details about communicating with the device and updating its state → the HRF_State struct. The HRF_ToolServer.exe which is mentioned in the code is a UDP server that allows programs to communicate with devices that we use as controllers → the HRF controller is one of those devices.

Did you figure this out? I have the same problem.

Thanks! I’ll look into this.

Yes. I built my own custom engine version. The warning, here, is because the EKeys I want to use do not exist by default. The warning will disappear on compilation because the EKeys exist after compilation. To avoid warnings altogether, I edited the InputCoreTypes.h/.cpp file to add the EKeys. In inputcoretypes.h, starting around line 205 in v 4.19, is the EKeys struct declaration. Here, I added all of my FKeys , without the namespace.

    struct INPUTCORE_API EKeys
    {
    	 ...     
    	//  HRF Keys
    	static const FKey HRF_Button1;
    	static const FKey HRF_Button2;
    	static const FKey HRF_Button3;
    	static const FKey HRF_Button4;
    	static const FKey HRF_Button5;

    ...
}

Inside InputCoreTypes.cpp, the definition.

...
// HRF
// HRF Button Keys 
const FKey EKeys::HRF_Button1("HRF_Button1");
const FKey EKeys::HRF_Button2("HRF_Button2");
const FKey EKeys::HRF_Button3("HRF_Button3");
const FKey EKeys::HRF_Button4("HRF_Button4");
const FKey EKeys::HRF_Button5("HRF_Button5");
...

At around line 525 in InputcoreTypes.cpp, in the Initialize() method, is where you add they keys

    void EKeys::Initialize()
    {
       ...
    	// HRF Controller specific
    	AddMenuCategoryDisplayInfo("HRF", LOCTEXT("HRFSubCateogry", "HRF"), TEXT("GraphEditor.PadEvent_16x"));
    
    	// HRF
    	AddKey(FKeyDetails(EKeys::HRF_Button1, LOCTEXT("HRF_Button1", "HRF_Button1"), FKeyDetails::GamepadKey, "HRF"));
    
    ...
    
    	// Initialize the input key manager.  This will cause any additional OEM keys to get added
    	FInputKeyManager::Get();
    }

In my previous class from my question, I removed all of the key declarations and definitions, as well as all of the EKey:AddKey lines. Everything else is the same.
There may be an easier solution to this, but I haven’t found it.

Keep in mind the line numbers I have will be very different as I added about 130 keys, didn’t realize that until after I answered and I don’t remeber the line numbers before editing… Just search for the structs/ methods I mentioned.