How do you detect keyboard input in C++?

Please help.

Either by using an input library of your own choice (e.g. OIS), or more convenient by using the PandaFramework class, via PandaFramework::define_key method for example.

pview.exe is a C++ application which uses the PandaFramework to open a window, load a model and listen to some basic keys. Have a look at the source code: panda-1.4.2/src/testbed/pview.cxx for examples on how to use the C++ framework.

enn0x

I didn’t find the file you said… in fact there isn’t a src folder in my version panda-1.4.2 at all… And the exe alone doesn’t help much…

If you want to do anything with Panda3D in C++ you will sooner or later have to look at the engine source code, since there isn’t much documentation for C++. Go to the Panda3D site, then downloads, and there download the Panda3D source code. Inside you will find the source files.

enn0x

I’m still new to Panda3D and I don’t know much, but I roughly know how to do it:

// Set up the framework, basic stuff
framework.open_framework(argc, argv);
framework.set_window_title("My Panda3D Window");
WindowFramework *window = framework.open_window();

// Enable keyboard detection
window->enable_keyboard();

// Let's say I wanna get the key "w"
framework.define_key("w", "weeds", Move, 0);

The define_key() function defines a callback function which is called when a key depress event with a specified event name is triggered.

Confused? You should be, but don’t worry I’ll get into the parameters of the function and things should become clearer (I hope).

Parameters:

  • const std::string & event_name: the name of the key which you want to use.
  • const std::string & description: description of the key I guess. Just put the name of your favorite pasta.
  • EventHandler::EventCallbackFunction * function: the function that is called when the key is pressed. <- THIS IS THE IMPORTANT
  • void * data: The parameter passed into the callback function.

So we need a function that will be called when the key you specified in the first parameter is pressed. In my case, the Move() function will be called when I press “w”. Here’s how to do it:

void Move(const Event * theEvent, void * data)
{
	cout<<"I MOVED!"<<endl;
}

Notice the parameters of my Move function. Your function should have similar parameters. If your memory serves you well, the 2nd parameter (void * data) is passed in by the 4th parameter in the define_keys() functions. Otherwise, visit your local psychologist. By the way, I have no idea that the 1st parameter is and I can’t seem to find out due to the lack of documentation.

You could do loads of stuff by passing the right values to your function like moving a panda with a specified distance of 2:

float distance = 2;
framework.define_key("w", "weeds", Move, (void *) &distance);

----------------------------------------------------------

void Move(const Event * theEvent, void * distance)
{
        float &dist = *((float *) distance); // Type-casting madness!
	myPanda.set_pos(0, myPanda.get_pos().get_y() + dist, 0);
}

but it is kinda retarded in this case as you have the spam the “w” button to get the Panda to move. Remember that this function only calls once when you press the button; it doesn’t keep calling when you hold the button down. Thus, the need for button states.

BUTTON STATES
A button has 2 basic states, UP or DOWN. UP when the key is not being pressed, DOWN when the key is pressed or held down. With these 2 states you can do virtually anything with your button, including: holding down (e.g. firing a machine gun), hold-down then release (e.g. building up strength before throwing a grenade), on press (e.g. firing a pistol), on release, etc.

This means we need a boolean.
False = UP, True = DOWN.

You shouldn’t declare global variables for something like this as it isn’t good programming practice but I’m just going to do it to explain stuff:

bool w_IsDown = false; // Declare global bool; Set it to UP state

void Move(const Event * theEvent, void * data)
{
	w_IsDown = true; // Set bool to DOWN state when pressed.
}

---------------------------------------------------
My main game loop:
while(framework.do_frame(current_thread))
{
	if (w_IsDown) // If "w" key is DOWN, move panda
		myPanda.set_pos(0, myPanda.get_pos().get_y() + 2, 0);
}

By default, the key “w” is at the UP state. However, when you press the key, it changes to the DOWN state, which you set in the Move() function. I’ve also shifted the panda movement code to the main loop so that the panda moves while the key “w” is held down.

Now our key can be set to the DOWN state by a key press event. Now we need our key to be set to the UP state by a key release event. However, the problem is I DON’T KNOW HOW!!! ~>.<~ boohoo

This is one reason why I dislike using the Panda3D framework - the lack of documentation, especially for C++. And why the need for one function callback to every keyboard button? Can’t you have one callback function that gets the key pressed or released? :

void KeyPressed(int theKeyID)
{
	if (theKeyID == KEY_W)
		w_IsDown = true;
}
void KeyReleased(int theKeyID)
{
	if (theKeyID == KEY_W)
		w_IsDown = false;
}

Anyway, if any of you got an idea of how to get key released events in C++, please post your solution!!! I’ve set up a topic just for that by the way.

Help would be very welcomed and appreciated!!! :smiley::D:D:D:D

1 Like

Doesn’t “w-up” work? And, to have the event thrown every frame while the key is pressed, “w-repeat” ?

Correct, of course. These are the same event names familiar to Panda3D programmers from the Python tutorials. It’s probably still useful to go through these tutorials, even if you intend to use Panda strictly from C++.

Also, it’s very useful to know where to look for the C++ documentation. Most functions are documented in the source code, in the comment block preceding each function body definition. For instance, in pandaFramework.cxx, you find:

////////////////////////////////////////////////////////////////////
//     Function: PandaFramework::define_key
//       Access: Public
//  Description: Sets up a handler for the indicated key.  When the
//               key is pressed in a window, the given callback will
//               be called.  The description is a one-line description
//               of the function of the key, for display to the user.
////////////////////////////////////////////////////////////////////
void PandaFramework::
define_key(const string &event_name, const string &description,
           EventHandler::EventCallbackFunction *function,
           void *data) {

which explains (more or less) the purpose of the “favorite pasta” parameter. (In fact, in pview, this is the text that is displayed onscreen when you press the “?” key.)

For class definitions, look to the header files. In event.h, for instance, you can see the method:

  INLINE const string &get_name() const;

which is the name of the event. So you could have multiple keyboard events handled by the same function, and let the function examine the event name to determine which is which.

Of course, this is kind of a pythony way to handle keyboard events. If you really want to get down and dirty with event handling in C++, you would write a subclass of DataNode that you can attach into Panda3D’s data graph. This node would listen for button events at a very low level, and could respond to them appropriately according to your codiing whims. Examples of existing C++ classes that do this are DriveInterface (which drives around a node according to the state of the arrow keys) or ButtonThrower (which listens for the low-level keyboard events, and generates the high-level pythony events we’re adding hooks to in the above discussion).

To undertake that kind of project would require a solid understanding of the Panda3D scene graph mechanism, though, so I wouldn’t recommend attempting it as an introduction to C++ programming in Panda3D, until you were already familiar with the friendlier (and better-documented) Python interface.

Still, I’m not trying to dissuade you from coding in C++. Though I’d recommend using Python at first just to learn Panda3D, if for no other reason; you are certainly free to dive straight into C++ directly. We’ll be happy to answer questions as they come up, to whatever level of detail you wish to ask them. Just be prepared to read a lot of C++ code. :slight_smile:

David

The “w-up” event really works!!! Thanks alot for your help guys. Sorry David, but I’m not quite sure about DataNodes, DriveInterfaces nor ButtonThrowers at the moment. I don’t think I’ll would need them just yet. Thanks for the info anyway!