// input.hxx -- handle user input from various sources. // // Written by David Megginson, started May 2001. // // Copyright (C) 2001 David Megginson, david@megginson.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // $Id$ #ifndef _INPUT_HXX #define _INPUT_HXX #ifndef __cplusplus # error This library requires C++ #endif #include #include #include #include #include
#include
#include #include SG_USING_STD(map); SG_USING_STD(vector); /** * An input binding of some sort. * *

This class represents a binding that can be assigned to a * keyboard key, a joystick button or axis, or even a panel * instrument.

*/ class FGBinding : public FGConditional { public: /** * Default constructor. */ FGBinding (); /** * Convenience constructor. * * @param node The binding will be built from this node. */ FGBinding (const SGPropertyNode * node); /** * Destructor. */ virtual ~FGBinding (); /** * Get the command name. * * @return The string name of the command for this binding. */ virtual const string &getCommandName () const { return _command_name; } /** * Get the command itself. * * @return The command associated with this binding, or 0 if none * is present. */ virtual SGCommandMgr::command_t getCommand () const { return _command; } /** * Get the argument that will be passed to the command. * * @return A property node that will be passed to the command as its * argument, or 0 if none was supplied. */ virtual const SGPropertyNode * getArg () { return _arg; } /** * Read a binding from a property node. * * @param node The property node containing the binding. */ virtual void read (const SGPropertyNode * node); /** * Fire a binding. */ virtual void fire () const; /** * Fire a binding with a setting (i.e. joystick axis). * * A double 'setting' property will be added to the arguments. * * @param setting The input setting, usually between -1.0 and 1.0. */ virtual void fire (double setting) const; private: string _command_name; SGCommandMgr::command_t _command; mutable SGPropertyNode * _arg; mutable SGPropertyNode * _setting; mutable SGCommandState * _command_state; }; /** * Generic input module. * *

This module is designed to handle input from multiple sources -- * keyboard, joystick, mouse, or even panel switches -- in a consistent * way, and to allow users to rebind any of the actions at runtime.

*/ class FGInput : public FGSubsystem { public: enum { FG_MOD_NONE = 0, FG_MOD_UP = 1, // key- or button-up FG_MOD_SHIFT = 2, FG_MOD_CTRL = 4, FG_MOD_ALT = 8, FG_MOD_MAX = 16 // enough to handle all combinations }; FGInput(); virtual ~FGInput(); // // Implementation of FGSubsystem. // virtual void init (); virtual void bind (); virtual void unbind (); virtual void update (); /** * Handle a single keystroke. * *

Note: for special keys, the integer key code will be the Glut * code + 256.

* * @param k The integer key code, as returned by glut. * @param modifiers Modifier keys pressed (bitfield). * @param x The mouse x position at the time of keypress. * @param y The mouse y position at the time of keypress. * @see #FG_MOD_SHIFT * @see #FG_MOD_CTRL * @see #FG_MOD_ALT */ virtual void doKey (int k, int modifiers, int x, int y); private: // Constants enum { MAX_KEYS = 1024, #ifdef WIN32 MAX_JOYSTICKS = 2, #else MAX_JOYSTICKS = 10, #endif MAX_AXES = _JS_MAX_AXES, MAX_BUTTONS = 32 }; typedef vector binding_list_t; /** * Settings for a key or button. */ struct button { button () : is_repeatable(false), last_state(-1) {} virtual ~button () { for (int i = 0; i < FG_MOD_MAX; i++) for (int j = 0; i < bindings[i].size(); j++) delete bindings[i][j]; } bool is_repeatable; int last_state; binding_list_t bindings[FG_MOD_MAX]; }; /** * Settings for a single joystick axis. */ struct axis { axis () : last_value(9999999), tolerance(0.002), low_threshold(-0.9), high_threshold(0.9) {} virtual ~axis () { for (int i = 0; i < FG_MOD_MAX; i++) for (int j = 0; i < bindings[i].size(); j++) delete bindings[i][j]; } float last_value; float tolerance; binding_list_t bindings[FG_MOD_MAX]; float low_threshold; float high_threshold; struct button low; struct button high; }; /** * Settings for a joystick. */ struct joystick { virtual ~joystick () { delete js; delete[] axes; delete[] buttons; } int naxes; int nbuttons; jsJoystick * js; axis * axes; button * buttons; }; /** * Initialize key bindings. */ void _init_keyboard (); /** * Initialize joystick bindings. */ void _init_joystick (); /** * Initialize a single button. */ inline void _init_button (const SGPropertyNode * node, button &b, const string name); /** * Update the keyboard. */ void _update_keyboard (); /** * Update the joystick. */ void _update_joystick (); /** * Update a single button. */ inline void _update_button (button &b, int modifiers, bool pressed); /** * Read bindings and modifiers. */ void _read_bindings (const SGPropertyNode * node, binding_list_t * binding_list, int modifiers); /** * Look up the bindings for a key code. */ const vector &_find_key_bindings (unsigned int k, int modifiers); button _key_bindings[MAX_KEYS]; joystick _joystick_bindings[MAX_JOYSTICKS]; }; // Handle keyboard events void GLUTkey(unsigned char k, int x, int y); void GLUTkeyup(unsigned char k, int x, int y); void GLUTspecialkey(int k, int x, int y); void GLUTspecialkeyup(int k, int x, int y); extern FGInput current_input; #endif // _CONTROLS_HXX