From: <mk...@us...> - 2003-01-04 23:49:54
|
Update of /cvsroot/csp/APPLICATIONS/CSPFlightSim/Include In directory sc8-pr-cvs1:/tmp/cvs-serv16793/Include Added Files: Tag: simdata HID.h Log Message: initial version of a new virtual human interface device --- NEW FILE: HID.h --- // Combat Simulator Project - FlightSim Demo // Copyright (C) 2002 The Combat Simulator Project // http://csp.sourceforge.net // // 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. /** * @file HID.h * **/ #ifndef __HID_H__ #define __HID_H__ #include "SDL_events.h" #include "SDL_keysym.h" #include "SDL_keyboard.h" #include <vector> #include <hash_map> #include "SimObject.h" /** * class HID - Base class for Human Interface Device mapping and scripting. * */ class HID { public: virtual bool OnKeyDown(SDL_keysym &key) = 0; virtual bool OnKeyUp(SDL_keysym &key) = 0; virtual bool OnJoystickButtonDown(int joynum, int butnum) = 0; virtual bool OnJoystickButtonUp(int joynum, int butnum) = 0; virtual void OnJoystickAxisMotion(int joynum, int axis, int val) = 0; virtual bool OnMouseMove(SDL_MouseMotionEvent const &) = 0; virtual bool OnMouseButtonDown(SDL_MouseButtonEvent const &) = 0; virtual bool OnMouseButtonUp(SDL_MouseButtonEvent const &) = 0; /* virtual void OnJoystickHatMotion(int joynum, int hat, int val) = 0; */ virtual void OnUpdate(double) = 0; virtual void bindObject(SimObject *) = 0; }; class EventMapping { public: typedef enum { RELEASE, PRESS } EDir; struct LinearCorrection { int low, high; int offset; double scale; }; struct Axis { Axis(int id_ = -1): id(id_) {} int id; }; struct Action { double time; int id; }; typedef std::vector<Action> Script; typedef std::hash_map<int, Script> script_map; typedef script_map::const_iterator EventScript; typedef std::hash_map<int, int> motion_map; int getKeyID(SDL_keysym &key, EDir dir, int mode) const; int getJoystickButtonID(int device, int button, EDir dir, int mode) const; int getMouseButtonID(int device, int button, EDir dir, int kmode, int mode) const; int getMouseMotionID(int device, int state, int kmode, int mode) const; Script const *getKeyScript(SDL_keysym &key, EDir dir, int mode) const; Script const *getJoystickButtonScript(int device, int button, EDir dir, int mode) const; Script const *getMouseButtonScript(int device, int button, EDir dir, int kmode, int mode) const; Axis const *getJoystickAxis(int device, int axis) const; int getMouseMotion(int device, int state, int kmode, int mode) const; void addKeyMap(SDL_keysym &key, EDir dir, int mode, Script const &s); void addJoystickButtonMap(int device, int button, EDir dir, int mode, Script const &s); void addJoystickAxisMap(int device, int axis, Axis const &a); void addMouseMotionMap(int device, int state, int kmod, int mode, int map_to); // convenience method for testing purposes only void addKeyMap(SDLKey vkey, SDLMod kmode, EDir dir, int mode, int action, double time); // convenience method for testing purposes only void addJoystickButtonMap(int device, int button, EDir dir, int mode, int action, double time); private: script_map m_KeyMap; script_map m_JoystickButtonMap; script_map m_MouseButtonMap; motion_map m_MouseMotionMap; Axis m_JoystickAxisMap[4][8]; }; class VirtualHID: public HID { public: typedef void (*ActionAdapter)(SimObject *, int, int); typedef void (*MotionAdapter)(SimObject *, int, int, int, int); typedef void (*AxisAdapter)(SimObject *, int); VirtualHID(); virtual ~VirtualHID(); virtual void setMapping(EventMapping const & map); virtual void bindObject(SimObject *object); virtual bool OnKeyDown(SDL_keysym &key); virtual bool OnKeyUp(SDL_keysym &key); virtual bool OnJoystickButtonDown(int joynum, int butnum); virtual bool OnJoystickButtonUp(int joynum, int butnum); virtual void OnJoystickAxisMotion(int joynum, int axis, int val); virtual bool OnMouseMove(SDL_MouseMotionEvent const &event); virtual bool OnMouseButtonDown(SDL_MouseButtonEvent const &event); virtual bool OnMouseButtonUp(SDL_MouseButtonEvent const &event); virtual void OnUpdate(double dt); protected: virtual void setScript(EventMapping::Script const *s, int x = -1, int y = -1); virtual void bindEvents() = 0; virtual void setVirtualMode(int mode); typedef std::hash_map<int, ActionAdapter> ActionMap; typedef std::hash_map<int, MotionAdapter> MotionMap; typedef std::vector<AxisAdapter> AxisMap; ActionMap m_Actions; MotionMap m_Motions; AxisMap m_Axes; int m_VirtualMode; const EventMapping *m_Map; SimObject *m_Object; EventMapping::Script const *m_ActiveScript; EventMapping::Script::const_iterator m_ScriptAction; double m_ScriptTime; int m_LastMouseMoveID; MotionAdapter m_LastMouseMoveAdapter; int m_MouseEventX; int m_MouseEventY; }; #define ACTION_INTERFACE(obj_class, method) static void on##method(SimObject* obj, int, int) {\ obj_class* target = dynamic_cast<obj_class*>(obj);\ assert(target); \ target->method();\ } #define CLICK_INTERFACE(obj_class, method) static void on##method(SimObject* obj, int x, int y) {\ obj_class* target = dynamic_cast<obj_class*>(obj);\ assert(target); \ target->method(x, y);\ } #define MOTION_INTERFACE(obj_class, method) static void on##method(SimObject* obj, int x, int y, int dx, int dy) {\ obj_class* target = dynamic_cast<obj_class*>(obj);\ assert(target); \ target->method(x, y, dx, dy);\ } #define AXIS_INTERFACE(obj_class, method) static void on##method(SimObject* obj, int value) {\ obj_class* target = dynamic_cast<obj_class*>(obj);\ assert(target); \ target->set##method(value);\ } class AircraftObject: public SimObject { public: virtual void RetractGear() { cout << "retracting gear\n"; } virtual void ExtendGear() { cout << "extending gear\n"; } virtual void ToggleGear() { cout << "toggling gear\n"; } virtual void setThrottle(double x) { cout << "throttle = " << x << endl; } virtual void PanView(int x, int y, int dx, int dy) { cout << "mouse " << x << ", " << y << " (" << dx << ", " << dy << ")\n"; } virtual void dump() {} virtual void OnUpdate(double) {} virtual void initialize() {} virtual unsigned int OnRender() {} ACTION_INTERFACE(AircraftObject, RetractGear); ACTION_INTERFACE(AircraftObject, ExtendGear); ACTION_INTERFACE(AircraftObject, ToggleGear); MOTION_INTERFACE(AircraftObject, PanView); AXIS_INTERFACE(AircraftObject, Throttle); }; #define BIND_ACTION(obj_class, id, method) \ m_Actions[id] = &obj_class::on##method; #define BIND_AXIS(obj_class, id, method) \ m_Axes[id] = &obj_class::on##method; #define BIND_MOTION(obj_class, id, method) \ m_Motions[id] = &obj_class::on##method; class AircraftInterface: public VirtualHID { public: enum { RETRACT_GEAR, EXTEND_GEAR, TOGGLE_GEAR }; enum { THROTTLE, AILERONS, ELEVATORS, RUDDER }; enum { PAN_VIEW }; AircraftInterface(); protected: virtual void bindEvents(); }; /* Right now identifiers like THROTTLE and EXTEND_GEAR are class static enums. In principle they are only needed for the bindEvents method. External tools need to access these values as STRING:INT pairs, and I don't see a safe/easy way to do this right now. Moreover, when a class is extended the resulting enums must be set higher than the parent enum range (which may change!). This is rather inelegant. It would be better if we could do something like string concatination to grow the list of ID's in derived classes. Spacing the ranges in derived classes probably a good thing, so that the base class id list can grow without breaking other ids. Once defined an id would ideally never change, since such changes require rebuilding of all binary map images. */ /* map scripts want: define RETRACT_GEAR 0 define EXTEND_GEAR 1 define TOGGLE_GEAR 2 which has to be generated somehow. the id numbers only have to be unique within a given class inheritance chain. internally we have enums, #defines, const int, etc. to work with. it would be ideal to keep these values within the classes they refer to rather than a namespace so that changes can be made locally. this makes generation of the map defines much harder though. for namespaces we'd have something like: namespace map_AircraftObject { const int RETRACT_GEAR = 0; const int EXTEND_GEAR = 1; } which doesn't really solve the problem, introduces unnecessary variables, and separates the constants from their associated class. considering that the script namespace is flat, we are "guaranteed" that the ids are unique. so we can put them in a separate file and #include them directly into the class? given a suitable file extension it would be easy to scan them all and extract the necessary define commands. this works pretty well: class A { public: enum { #include "A.map" }; ... }; with A.map in the form: X = 2000, Y, Z, which can easily be converted to define X 2000 define Y 2001 define Z 2002 the converter should check for duplicate id names with different id values and spew copious warnings if any are found. probably commenting should be enforced by the converter, so you would have to write: X = 2000, // Do X blah blah Y, // Do Y blah blah Z, // Do something else which would then translate to define X 2000 # Do X blah blah define Y 2001 # Do Y blah blah define Z 2002 # Do something else the filename will match the classname so it should be fairly clear what each id is used for. the enum lists should always end with a comma so they can be concatinated with multiple #include directives. */ /* map x36.axis0 to THROTTLE map x36.axis4 to HUDSCALE in NAV band HUDSCALE map band.HUDSCALE 0.0 script map band.HUDSCALE 0.1 script map band.HUDSCALE 0.5 script */ #endif // __HID_H__ |