Disadvantage of FKey Implementaiton

Dear Friends at Epic,

Correct me if I am mistaken, but you cant use Switch statements with FKeys now because they dont convert easily to numbers and EKeys throw this compile error now:

#Compile Error

case expression not constant

#TypeHash

Even if I turn the FKey into a type hash value the above compile error persists for every EKeys:: use.

#Problem

Now I cant make a “Shifted Key” function for my Chat system using FKey


this worked beautifully in the Beta


//returns "" if it was not a letter
FString AVictoryGamePlayerController::ShiftedKeyEntry(FKey key) const
{
	switch (key)
	{
		
	//chat only
	case EKeys::Semicolon	:	return ":";
	case EKeys::Backslash	:	return "|";
	case EKeys::Slash		:	return "?";
	case EKeys::Tilde			:	return "~";
	case EKeys::LeftBracket	:	return "{";
	case EKeys::RightBracket:	return "}";
	case EKeys::Quote		:	return """";
	case EKeys::Comma		:	return "<";
	case EKeys::Equals		:	return "+";
	
	//numbers
	case EKeys::One		:	return "!"; 	case EKeys::Six		:	return "^";
	case EKeys::Two		:	return "@"; 	case EKeys::Seven	:	return "&";
	case EKeys::Three	:	return "#"; 	case EKeys::Eight	:	return "*";
	case EKeys::Four	:	return "$"; 	case EKeys::Nine	:	return "(";
	case EKeys::Five	:	return "%"; 	case EKeys::Zero	:	return ")";
	
	//minus
	case EKeys::Underscore	:	return "_";
	
	//period
	case EKeys::Period		:	return ">";
	
	//no key match found
	default: return "";
	
	}
	
	return "";
}

#Goal = Shifted Key

Is there an easier way to get the Shifted version of any FKey ?

#Thanks!

#:heart:

Rama

You could populate a TMap (probably in the constructor of AVictoryGamePlayerController) with the FKey as the key, and the FString as the value.

Your other option would be if statements. FKey can’t be used with a switch statement.

Is there a reason you’re not using Slate for this? Slate widgets already get a OnKeyChar which is the key press translated to the correct character.

Your implementation above is very naive, and doesn’t take into account the OS key-mapping; for example, Shift+2 for me is ", not @, as I have a UK keyboard.

“Is there a reason you’re not using Slate for this? Slate widgets already get a OnKeyChar which is the key press translated to the correct character.”

Can I call this in a static way? I am not using slate for my user input.

oh wow that’s great to know about UK keyboards!

Currently I am using Player Controller and WasInputKeyJustPressed / IsInputKeyDown

I see I can initialize the Slate App and Get it and then use

/**
	 * Called when a character is entered
	 *
	 * @param  InCharacterEvent  Character event
	 *
	 * @return  Was this event handled by the Slate application?
	 */
	bool ProcessKeyCharMessage( FCharacterEvent& InCharacterEvent );

	/**
	 * Called when a key is pressed
	 *
	 * @param  InKeyboardEvent  Keyboard event
	 *
	 * @return  Was this event handled by the Slate application?
	 */
	bool ProcessKeyDownMessage( FKeyboardEvent& InKeyboardEvent );

:slight_smile:

Would that be sufficient or do I need a window that has focus as well?

Thanks!

Rama

PS: I see this issue of the OS vs my local keyboard, and I do need a proper solution, thanks for your help

:heart:

Not statically as it has to go through the OS-level message system in Slate to let the OS translate the key-press correctly.

How are you currently getting the key events?

FSlateApplication::ProcessKeyCharMessage would be mostly correct (but I’m not sure you can hook into it), however it’s still flawed as it doesn’t handle IMEs correctly.

Really, if you want correct input without having to reimplement all of the Slate OS and IME input processing, then SEditableTextBlock is the way to go.

If you want to manually get what amounts to physical keys and map them to logical keys and then characters, you’re re-implementing some lower level logic than this. Conceptually, you need to get a physical key press (IE: Key 0x1A) and map that to a logical key (a/A) and then a character (‘A’ if shifted, ‘a’ otherwise). There’s no cross-platform way to do that at this time AFAIK.

EKeys values look to be logical keys - note that “PS4_Special” is a member of EKeys. You’re doing something even lower level than FKey. Windows Virtual Keys are also more or less logical keys. They seem to map in FInputKeyManager::InitKeyMappings.

Mind, IMEs don’t merely map logical keys into different ones or even characters - some IMEs, especially those of East Asian languages, actually consume input before they reach the application properly, display their own UI over the application, and submit a batch of processed characters to the application.

If you don’t care about IMEs and keyboard layouts that differ from yours, you just need to use if/else flow control rather than a switch case. Some macro magic might trade tedium for familiar readability.

okay thanks for the clarifications on all of this!

Rama

Thank you for the low-level explanation!

Low-level is definitely the way I like to go :slight_smile:

Thanks Sheevok!

Rama

#Slate Tutorial Posted

Just a follow up on this,

I did end up implementing a SEditableText widget, and I have a tutorial on how to do so here:

#Tutorial Link:

Thanks for the idea Jamie!

#:heart:

Rama