Page 1 of 1

injecting character input

Posted: Tue Jul 05, 2005 19:54
by granx
Hi,
I have a full featured application using CEGUI and Producer. I have the mouse input handled properly, finally, and now I am focusing on correctly implementing the character input. Here is a snapshot of my code, which does work:

Code: Select all

void Injector::keyPress(Producer::KeyCharacter key)
{
   //CEGUI::System::getSingleton().injectKeyDown( static_cast<CEGUI::uint>(key) );
   CEGUI::System::getSingleton().injectChar( static_cast<CEGUI::utf32>( key ) );
}

void Injector::keyRelease(Producer::KeyCharacter key)
{
   //CEGUI::System::getSingleton().injectKeyUp( static_cast<CEGUI::uint>(key) );
   CEGUI::System::getSingleton().injectChar( static_cast<CEGUI::utf32>( key ) );
}


I would prefer to use the commented code. It will compile, but it produces no results. The uncommented code is currently being used and it allows me to edit text fields. Why doesn't the commented one work? BTW, a Producer::KeyCharacter is just a typedef for some ascii code, defined like this excerpt shows:

Code: Select all

enum KeyCharacter
{
    ...
    KeyChar_X                   = 0x058,
    KeyChar_Y                   = 0x059,
    KeyChar_Z                   = 0x05a,
    KeyChar_bracketleft         = 0x05b,
    KeyChar_backslash           = 0x05c,
    KeyChar_bracketright        = 0x05d,
    KeyChar_asciicircum         = 0x05e,
    KeyChar_underscore          = 0x05f,
    KeyChar_grave               = 0x060,
    KeyChar_quoteleft           = 0x060,
    KeyChar_a                   = 0x061,
    KeyChar_b                   = 0x062,
    KeyChar_c                   = 0x063,
    ....
};


Thanks, -granx

Re: injecting character input

Posted: Tue Jul 05, 2005 20:31
by lindquist
key press events should call both injectKeyDown and injectChar.
key release events on the other hand should only call injectKeyUp.

with injectKeyDown/Up you should pass the scancode of the key.
with injectChar you should pass the actual character code.

HTH

Re: injecting character input

Posted: Thu Jul 07, 2005 23:04
by granx
lindquist,
Yeah, that helped, thanks. I understand the intent behind those injections now. However, I am still having some problems. A big problem is that I don't even know what you mean by 'scan code'. Also, I can't get some keys recognized by CEGUI when I press them. For instance, I can highlight some text in a text field, and then I will hit the 'backspace' key, expecting them to erase. This does not work :( . Any ideas? Here is my slightly improved code:

Code: Select all

void Injector::keyPress(Producer::KeyCharacter key)
{
   // try to support some KeyCharacters that are not translating well
   if( key == Producer::Key_BackSpace )
   {
      ///\todo FIX THIS - nothing is making 'backspace' be recognized.
      //CEGUI::System::getSingleton().injectChar( CEGUI::Key::Backspace );   // not a fix :-(
      CEGUI::System::getSingleton().injectKeyDown( 0xFF08 );                 // also, not a fix :-(
   }

   ///\todo use the "scan code" here instead of the KeyCharacter, which unfortunately is the actual character code
   //CEGUI::System::getSingleton().injectKeyDown( static_cast<CEGUI::uint>(key) );
   CEGUI::System::getSingleton().injectChar( static_cast<CEGUI::utf32>( key ) );
}

void Injector::keyRelease(Producer::KeyCharacter key)
{
   ///\todo use the "scan code" here instead of the KeyCharacter, which is the actual character code
   //CEGUI::System::getSingleton().injectKeyUp( static_cast<CEGUI::uint>(key) );
}

Re: injecting character input

Posted: Fri Jul 08, 2005 00:28
by lindquist
Try taking a look at CEGUIInputEvent.h
It lists the key scancodes.

AFAIK the scancode is a hardware identifier for the keys.
Thus fx regular number buttons have different codes than the ones on the numpad.

Unfortunately I don't know Producer, so I really can't say whether it even has the feature.

If all fails, I guess you could set up a map or a switch statement to do the work...

so fx something like this:

Code: Select all

CEGUI::Key::Scan k;
switch(incoming_key)
{
    case Producer::Backspace:
        k = CEGUI::Key::Backspace;
    ...
}
CEGUI::System::getSingleton().injectKeyDown(k);
CEGUI::System::getSingleton().injectChar(incoming_key);


as you can see the CEGUI::Key::Scan enum is scancodes to be passed to injectKeyDown - not injectChar

Re: injecting character input

Posted: Sat Jul 09, 2005 19:30
by POLSKASH
I'm working on the key input for the GUI, and I don't think sample code compiles lindquist. Here's what I'm doing, I'm using DirectInput to get my input:

Code: Select all

...
//KEYBOARD INPUT//
char KeyStateBuffer[256];

ReadData(keyboard, (void*)KeyStateBuffer, 256);
   
if(KeyState(DIK_ESCAPE) == TRUE)
{
   CEGUI::Key k;
   k = CEGUI::Key::Escape;
   man->injectKeyPress(k);
}

void cGUIManager::injectKeyPress(const CEGUI::Key key)
{
        CEGUI::System::getSingleton().injectKeyDown(key);
   //CEGUI::System::getSingleton().injectChar(???); Dunno how to get the char code
}


I'm trying to figure out how to set this up. I need a scan code, and if it's a character key, and char code. I'm not sure how get these. The above code produces this error:

c:\Documents and Settings\Owner\Desktop\GUI Manager\main.cpp(224) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'CEGUI::Key::Scan' (or there is no acceptable conversion)
cGUIManager.cpp
c:\Documents and Settings\Owner\Desktop\GUI Manager\cGUIManager.cpp(129) : error C2664: 'CEGUI::System::injectKeyDown' : cannot convert parameter 1 from 'const CEGUI::Key' to 'CEGUI::uint'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

Re: injecting character input

Posted: Sun Jul 10, 2005 00:11
by lindquist
I updated my post.

Code: Select all

CEGUI::Key
should have been

Code: Select all

CEGUI::Key::Scan


also remember to inject key-release events...

Re: injecting character input

Posted: Sun Jul 10, 2005 04:03
by POLSKASH
Here's what I've put together for character input, but I'm not getting results. The problem is somewhere in my use of CEGUI; I already checked the DirectInput and it's working fine.

I'm doing something like this in my input function:

Code: Select all

if(KeyState(DIK_A) == TRUE)//Check directinput buffer
{

   CEGUI::Key::Scan k;
   k = CEGUI::Key::A;
   man->injectKeyPress(k);
}


I have these inject functions:

Code: Select all

void cGUIManager::injectKeyPress(const CEGUI::Key::Scan key)
{
   CEGUI::System::getSingleton().injectKeyDown(key);
   injectChar(static_cast<CEGUI::utf32>(key));
   injectKeyUp(key);
}

void cGUIManager::injectChar(const CEGUI::utf32 charCode)
{
   CEGUI::System::getSingleton().injectChar(charCode);
}

void cGUIManager::injectKeyUp(const CEGUI::Key::Scan key)
{
   CEGUI::System::getSingleton().injectKeyUp(key);
}


Is what I'm doing in the injectKeyPress() function valid? The static_cast<>()? Also, I'm thinking a subsequent call to inject key up would be ok, even if the key is pressed down. Because really, the program will loop back around and detect the key to be pressed down again if the user is holding it down anyway, so it will inject a key press and inject a key up again. If this is flawed thinking, let me know.

Re: injecting character input

Posted: Sun Jul 10, 2005 12:02
by lindquist
injectKeyDown is to be called when the user presses the key down.
injectKeyUp is to be called when the user releases it again.

Re: injecting character input

Posted: Sun Jul 10, 2005 16:52
by POLSKASH
Alright, so here's what I'm doing now:

I do this for every key in my input function:

Code: Select all

//Checks a boolean array to see if we have to worry about
//injecting a key up
if(man->alreadyDown(DIK_A)){//the key was pressed on that last iteration
   if(KeyState(DIK_A) == TRUE)//if it's pressed again
   {
      CEGUI::Key::Scan k;
      k = CEGUI::Key::A;
      man->injectKeyPress(k);
   }
   else//not pressed, need to send key up
   {
      CEGUI::Key::Scan k;
      k = CEGUI::Key::A;
      man->injectKeyUp(k);
   }
}
else  //not pressed during last iteration
{
        if(KeyState(DIK_A) == TRUE)//Pressed during this one
   {
      CEGUI::Key::Scan k;
      k = CEGUI::Key::A;
      man->injectKeyPress(k);
      man->setDown(DIK_A);
   }
}


My inject function

Code: Select all

void cGUIManager::injectKeyPress(const CEGUI::Key::Scan key)
{
   CEGUI::System::getSingleton().injectKeyDown(key);
        //I don't think this next line works
   injectChar(static_cast<CEGUI::utf32>(key));
}


I don't think that static_cast is working for me. I'm not even sure if I can do that. I don't know how else to get the character code.

Re: injecting character input

Posted: Sun Jul 10, 2005 17:38
by lindquist
You cannot just cast the scancode to make it a charactercode.

I suggest that you take a look at the sample sources once more. In the directory Samples/common/src check out Win32AppHelper.cpp and CEGuiD3D9BaseApplication.cpp

the character injection is done like this in Win32AppHelper.cpp:

Code: Select all

LRESULT CALLBACK Win32AppHelper::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_CHAR:
        CEGUI::System::getSingleton().injectChar((CEGUI::utf32)wParam);
        break;
    ...
    ...
    ...


as to your keydown injections, there must be an easier way than the one you're useing. As the the value you need to inject exactly matches the keycodes you're getting from DirectInput having hundreds of those if else... statements is not something I would like to do...

Re: injecting character input

Posted: Sun Jul 10, 2005 20:25
by POLSKASH
What do you mean the value I need to inject matches the key codes I get from DirectInput? All I get from DirectInput is a 256 char array. I just check the high bit on those to see if the key is pressed. DIK_A is just an enumerated value.

As for the character input, I'm not using Windows Messages to get input, so I don't have a WPARAM to typecast as in that example. There's no samples using DirectInput, so I have no idea of how to get a character code.

Re: injecting character input

Posted: Sun Jul 10, 2005 22:50
by lindquist
The samples uses DirectInput for keyDown injections. Take a look at that. As to the character - this is a forum of CEGUI discussion - not how to use DirectInput. I _don't_ use DirectInput and as such I'm only providing pointers that I hope might give you ideas.

My suggestion is that you get the hang of your tools before you start using them together with other tools.

If the samples and all this talk is'nt enough, well, it's all there is at the moment...

I feel that I'm not able to help you!

Re: injecting character input

Posted: Mon Jul 11, 2005 08:18
by CrazyEddie
The Win32 sample helper class is a good thing to look at if you want to see at least one successful way of injecting inputs to CEGUI.

Generally speaking, for GUI use, you want to be using buffered input from DirectInput for your key up / kwy down injections, otherwise you may end up testing a whole load of buttons in your state array (like 100, or something). Having said that, you only really need to inject scan codes for keys you care about; usually this is the arrow keys, shift, alt, control, backspace, delete, and return.

For character input, you can either use the WM_CHAR message (using DirectInput does not mean you can't use windows messages also). If for some unknown reason this is unacceptable, then you'll need to create your own key translation table and also correctly deal with shift/caps-lock states etc (so you'll be doing your own key-mapping).

Re: injecting character input

Posted: Thu Jul 14, 2005 19:18
by granx
[url=cyrf.com/content/apps/producer_cegui.zip]Producer & CEGUI example[/url]
I fixed my problem - Producer offered a 'specialKeyPress' function that I was not using. Apparently, some keys are "special" :) Anyway, I would be flattered if these files were hosted on the Wiki. I would be happy to document the code there at some point soon. It is pretty straight forward, so it really serves as a good example for CEGUI users that want to learn the basics for rendering in a pretty generic windowing API, Producer. I know there is an example using SDL, but somehow it wasn't enough. Maybe this will help others. OpenGL users will probably like it a lot. :pint:

Re: injecting character input

Posted: Fri Jul 15, 2005 13:29
by CrazyEddie
Yeah, glut thinks certain keys are special too :)

I don't know about hosting files, usually people host these themselves and link to that within the wiki articles. I think if we started hosting files the costs would start to rack up.

Though please do put up any documentation or tutorials you write - we need as much of this kind of thing as we can get :hammer: