glutIgnoreKeyRepeat
to ignore auto-repeated keystrokes. (that resolves Questions 1 & 2.)
There, unfortunately, isn't an option to make the mouse button's get called repeatedly. You can, however, create variables recording the mouse button states. And then read those when you need to know if a button is down. Just as good, or better. (Question 3)
Further Description: Recording key-states in variables for repeated use over many frames
Typically in games when you walk forward using a key, they don't rely on the OS's key-repeat. That can be adjusted so the repeat will likely be much slower then your game-loop cycle. That will create jerky movement that could be smoothed out if it was calculated on a per-frame basis.
One of the simplest ways to cut out that jerky movement, is to check that keys state on a per-frame basis. You can do that with function call's, that however will add a bit of unneeded overhead. So instead, you can record the key-state locally in the program. Since GLUT defines a key with char
, there are only 255 different key's that you might get. So you only need an array 255 bytes long to store each key's state.
But then there are the 3 mouse buttons. 3 bytes, 1 for each mouse button. The ending result of all this is:
#define BUTTON_UP 0
#define BUTTON_DOWN 1
#define MOUSE_LEFT 0
#define MOUSE_MIDDLE 1
#define MOUSE_RIGHT 2
unsigned char keyState[255];
unsigned char mouseState[3];
void keyboard(unsigned char key, int x, int y)
{
keyState[key] = BUTTON_DOWN;
}
void keyboard_up(unsigned char key, int x, int y)
{
keyState[key] = BUTTON_UP;
}
void mouse(int button, int button_state, int x, int y)
{
#define state ( (button_state == GLUT_DOWN) ? BUTTON_DOWN : BUTTON_UP ) // shortens later code
switch (button)
{
case GLUT_MOUSE_LEFT:
mouseState[MOUSE_LEFT] = state;
break;
case GLUT_MOUSE_MIDDLE:
mouseState[MOUSE_MIDDLE] = state;
break;
case GLUT_MOUSE_RIGHT:
mouseState[MOUSE_RIGHT] = state;
break;
}
#undef state // make sure the defined "state" code above is only used in this function
}
void main()
{
// some fancy code
if (keyState[(unsigned char)'W'] == BUTTON_DOWN) // Walk forward
{
// W is being pressed! Time to walk.
}
if (keyState[(unsigned char)'1'] == BUTTON_DOWN) // render in Wire-Frame
{
// toggle wire-frame rendering
// this key toggles wire-frame mode. We dont want it changing every frame,
// Or it would keep changing to fast for the user to keep track of.
// so we'll just say the key is up. Then it wont switch back before the user
// is ready.
keyState['1'] = BUTTON_UP;
}
// some more fancy code
}