Official Murl Engine Forum

Full Version: Keyboard Support
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
How does the Murl Engine handle keyboard support?
(26 Mar 2013, 15:46)stranger Wrote: [ -> ]How does the Murl Engine handle keyboard support?

The Murl Engine provides two possible ways to process keyboard events.

RawKeys

The Murl::Input::IRawKeyboardDevice can be used to obtain the status of physical keys on the keyboard – we call them "raw keys". The definition for raw key codes can be found in the file murl_raw_key_codes.h:
enum RawKeyCode
    {
        RAWKEY_NONE             = 0x00,
       
        RAWKEY_ESCAPE           = 0x01,
        RAWKEY_1                = 0x02,
        RAWKEY_2                = 0x03,
        …
 

The file should contain a RAWKEY_… definition for every possible physical key. The list includes e.g. RAWKEY_0, RAWKEY_KEYPAD_0, RAWKEY_LEFT_SHIFT, RAWKEY_KEYPAD_NUMLOCK, RAWKEY_VOLUME_UP, RAWKEY_KANJI etc.

If you press on an English keyboard the key Y you will get events for RAWKEY_Y. The same key is labeled with Z on a German keyboard. Nevertheless if you press the key Z on a German keyboard you will get events for RAWKEY_Y because it is the same physical button with the same key code.

If you press the two keys left SHIFT and Y you will get events for both keys RAWKEY_Y and RAWKEY_LEFT_SHIFT.

To obtain the status for physical keyboard input, you can use the device handler's WasRawKeyPressed() method.
Logic::IDeviceHandler* deviceHandler = state->GetDeviceHandler();
if (deviceHandler->WasRawKeyPressed(RAWKEY_Y))
  //do whatever is to do

In addition to WasRawKeyPressed(), physical keyboard input is also reflected by the IsRawKeyPressed() and WasRawKeyReleased() methods. During a regular keystroke, these methods return true in the following sequence:
  1. At the moment of first pressing the key down, WasRawKeyPressed() returns true for exactly one logic tick
  2. As long as the key is down, IsRawKeyPressed() returns true in every logic tick.
  3. When the key is released, WasRawKeyReleased() returns true for exacly one logic tick.
This behavior is also detailed described in the tutorials section: http://murlengine.com/tutorials/en/_tuto...01_t02.php

Please note that the framework do not report raw keys for non-physical keyboards e.g. touch screen keyboards on mobile devices.

Vanilla Keys

The Murl::Input::IKeyboardDevice can be used to obtain the character value of a keystroke after the operating system processed the key codes – we call them "vanilla keys".

While the IRawKeyboardDevice only reports key states, the IKeyboardDevice reports the UTF8 encoded character representation of a keystroke. The result depends for example on your language settings.

If you press the key Y you will get a lowercase y if the language is set to English. If you press the two keys SHIFT and Y you will get uppercase Y. If the language is set to German you will get z or Z respectively.

You can use the the device handler's GetNumberOfKeys, GetKey and GetKeys methods to obtain the UTF8 character representation.
Logic::IDeviceHandler* deviceHandler = state->GetDeviceHandler();
UInt32 numKeys = deviceHandler->GetNumberOfKeys();
for (UInt32 i = 0; i < numKeys; i++)
	Debug::Trace(deviceHandler->GetKey(i));
if (deviceHandler->WasRawKeyPressed(RAWKEY_Y))
	Debug::Trace("RAW Y PRESSED");
if (deviceHandler->WasRawKeyReleased(RAWKEY_Y))
	Debug::Trace("RAW Y RELEASED");
How can I detect if any keyboard key is currently being pressed? I'm not interested in what the key is.
(13 Apr 2013, 7:23)stranger Wrote: [ -> ]How can I detect if any keyboard key is currently being pressed? I'm not interested in what the key is.

You have to iterate through the Rawkey enum:
    for (UInt32 i=RAWKEY_NONE; i<MAX_RAWKEY_CODES; i++)
    {
        RawKeyCode rawKey = static_cast<RawKeyCode>(i);
        if ((deviceHandler->WasRawKeyPressed(rawKey)))
        {
            Debug::Trace("Key pressed");
            Debug::Trace("RawKeyCode is %d", i);
        }
    }
In addition you can use the function GetEnumName to get a name for the RawKey:
    Logic::IDeviceHandler* deviceHandler = state->GetDeviceHandler();

    for (UInt32 i=RAWKEY_NONE; i<MAX_RAWKEY_CODES; i++)
    {
        RawKeyCode rawKey = static_cast<RawKeyCode>(i);
        if ((deviceHandler->WasRawKeyPressed(rawKey)))
        {
            Debug::Trace("Key pressed");
            Debug::Trace("RawKeyCode is %d", i);
            Bool error = false;
            String name = GetRawKeyCodeEnum().GetEnumName(rawKey, error);
            if (!error) Debug::Trace("RawKeyName is %s", name);
        }
    }

The output for RAWKEY_A, RAWKEY_LEFT_CONTROL and RAWKEY_LEFT_SHIFT would be:
Key pressed
RawKeyCode is 30
RawKeyName is RAWKEY_A
Key pressed
RawKeyCode is 29
RawKeyName is RAWKEY_LEFT_CONTROL
Key pressed
RawKeyCode is 42
RawKeyName is RAWKEY_LEFT_SHIFT
Since Murl Engine Version 1.00.2194 it is possible to get a Map containing the key/value pairs for all Murl enums. The corresponding methods are:
GetItemsByValue() // Get a map with the enum name as value and the enumeration value as key.
GetItemsByName()  // Get a map with the enum name as key and the enumeration value as value.

The map makes it easy to iterate through the enum. The code above to iterate through the RawKey enum would change to:
Logic::IDeviceHandler* deviceHandler = state->GetDeviceHandler();

const Murl::Map<UInt32, String>& mapRawKeyValues = GetRawKeyCodeEnum().GetItemsByValue();
for (UInt32 i=0, size = mapRawKeyValues.GetCount() ; i<size; i++)
{
	UInt32 code = mapRawKeyValues.GetKey(i);
	if ((deviceHandler->WasRawKeyPressed(static_cast<RawKeyCode>(code))))
	{
		Debug::Trace("Key pressed");
		Debug::Trace("RawKeyCode is %d", i);
		Debug::Trace("RawKeyName is %s", mapRawKeyValues.Get(code));
	}
}

Please note that this is the preferred way. Iterating through the map guarantees that only valid enum values are used even if the enum contains “holes”. Consider the following enum:
enum Foo 
{
  a = 1,
  b = 99,
  MAX
};

The previous version would iterate through all values from 1 to 99 while the new version only considers the two valid values.