gamepad-map.h

Go to the documentation of this file.
00001 /*
00002  * gamepad-map.h
00003  *
00004  * Copyright (C) 2008-2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Gamepad mapping.  This contains most of the important definitions used in the
00032  * API.
00033  */
00034 
00035 #ifndef GAMEPAD_GAMEPAD_MAP_H__
00036 #define GAMEPAD_GAMEPAD_MAP_H__
00037 
00038 
00039 // includes --------------------------------------------------------------------
00040 #include "gamepad-type.h"
00041 
00042 #include "source-device/source-device.h"
00043 
00044 
00045 namespace gamepad {
00046 
00047 
00048 /// \ingroup gamepadlib
00049 /*@{*/
00050 
00051 
00052 /// the current position of a dpad.  A dpad is a "Directional Pad", see
00053 ///     http://en.wikipedia.org/wiki/D-pad
00054 enum eDpad {
00055         eDpad_Centered          = 0, ///< dpad is not pressed or tilted at all
00056         eDpad_Left              = 1, ///< pushed left
00057         eDpad_Right             = 2, ///< pushed right
00058         eDpad_Up                = 4, ///< pushed up
00059         eDpad_Down              = 8, ///< pushed straight down
00060 
00061         // composite values
00062         eDpad_UpLeft            = eDpad_Up   | eDpad_Left,
00063         eDpad_UpRight           = eDpad_Up   | eDpad_Right,
00064         eDpad_DownLeft          = eDpad_Down | eDpad_Left,
00065         eDpad_DownRight         = eDpad_Down | eDpad_Right,
00066 
00067         // keep this last!
00068         eDpad_Invalid           = 16
00069 };
00070 
00071 
00072 
00073 /// button mapping information
00074 struct button_map_t {
00075         button_map_t(void) throw() { this->clear(); }
00076         void clear(void) throw() {
00077                         index = -1;
00078                 }
00079         void dump(IN const char * title) const throw() {
00080                         DPRINTF("%s (button map): index=%d", title, index);
00081                 }
00082         bool isValid(void) const throw() {
00083                         return (index >= 0);
00084                 }
00085 
00086         // data fields
00087         int             index;  ///< button or pot index
00088 };
00089 
00090 
00091 
00092 /// all button values OR'd together
00093 typedef uint32_t buttons_t;     // TODO: deprecate?
00094 
00095 
00096 /// a joystick is a 2-axis stick
00097 struct joystick_t {
00098         // constructor, manipulators
00099         joystick_t(void) throw() { this->clear(); }
00100         void clear(void) throw() {
00101                         x.clear();
00102                         y.clear();
00103                 }
00104 
00105         // data fields
00106         pot_value_t     x;      ///< current x-axis potentiometer value
00107         pot_value_t     y;      ///< current y-axis potentiometer value
00108 };
00109 
00110 
00111 /// describes joystick mapping
00112 struct joystick_map_t {
00113         joystick_map_t(void) throw() { this->clear(); }
00114         void clear(void) throw() {
00115                         xIndex = yIndex = -1;
00116                 }
00117         void dump(IN const char * title) const throw() {
00118                         DPRINTF("%s (joystick map):  xIndex=%d  yIndex=%d",
00119                             title, xIndex, yIndex);
00120                 }
00121         bool isValid(void) const throw() {
00122                         return (xIndex >= 0 && yIndex >= 0);
00123                 }
00124 
00125         // data fields
00126         int             xIndex;         ///< index of x axis potentiometer
00127         int             yIndex;         ///< index of y axis potentiometer
00128 };
00129 
00130 
00131 /// describes a potentiometer mapping
00132 struct pot_map_t {
00133         pot_map_t(void) throw() { this->clear(); }
00134         void clear(void) throw() {
00135                         index = -1;
00136                 }
00137         void dump(IN const char * title) const throw() {
00138                         DPRINTF("%s (potentiometer map):  index=%d",
00139                             title, index);
00140                 }
00141         bool isValid(void) const throw() {
00142                         return (index >= 0);
00143                 }
00144 
00145         // data fields
00146         int             index;          ///< index of potentiometer
00147 };
00148 
00149 
00150 
00151 /// a dpad_map_t describes how to map from low-level SourceDevice events (buttons
00152 ///     or potentiometers) into dpad events.  
00153 struct dpad_map_t {
00154         // constants
00155         enum eType {
00156                 eType_Button    = 1,    ///< dpad uses buttons for events
00157                 eType_2Pot      = 2,    ///< dpad uses 2 potentiometers
00158                 eType_4Pot      = 3,    ///< dpad uses 4 potentiometers
00159                 eType_Invalid   = 0
00160         };
00161         enum eIndex {
00162                 eLeft   = 0,
00163                 eUp     = 1,
00164                 eRight  = 2,    // left and right will be same for 2 pot
00165                 eDown   = 3,    // up and down will be same for 2 pot
00166 
00167                 // keep this last
00168                 eBad    = 255
00169         };
00170 
00171         // constructor, destructor
00172         dpad_map_t(void) throw() { this->clear(); }
00173 
00174         // manipulators
00175         void clear(void) throw() {
00176                         type = eType_Invalid;
00177                         for (int i = 0;  i < 4; ++i) {
00178                                 index[i] = eBad;
00179                         }
00180                         flipX = flipY = false;
00181                 }
00182         void dump(IN const char * title) const throw() {
00183                         const char * typeName = "INVALID";
00184                         if (eType_Button == type) {
00185                                 typeName = "Button";
00186                         } else if (eType_2Pot == type) {
00187                                 typeName = "Two Potentiometer";
00188                         } else if (eType_4Pot == type) {
00189                                 typeName = "Four Potentiometer";
00190                         }
00191                         DPRINTF("%s (directional pad mapping): %s",
00192                             title, typeName);
00193                         DPRINTF("  indices: up=%d  down=%d  left=%d  right=%d",
00194                             index[eUp], index[eDown],
00195                             index[eLeft], index[eRight]);
00196                         DPRINTF("  flip axis:  X=%s  Y=%s",
00197                             (flipX) ? "yes" : "no", (flipY) ? "yes" : "no");
00198                 }
00199         bool isValid(void) const throw() {
00200                         if (eType_Button != type &&
00201                             eType_2Pot != type &&
00202                             eType_4Pot != type)
00203                                 return false;   // not a valid type!
00204                         for (int i = 0; i < 4; ++i) {
00205                                 if (eBad == index[i])
00206                                         return false;   // not a valid index
00207                         }
00208                         return true;
00209                 }
00210 
00211         // data fields
00212         eType           type;
00213         byte_t          index[4]; ///< button/pot indices for 4 directions
00214         bool            flipX;  ///< flip x-axis value?
00215         bool            flipY;  ///< flip y-axis value?
00216 };
00217 
00218 
00219 
00220 /// A gamepad::Map is the magical binding between physical inputs (button
00221 ///     presses, joystick moves, wheel turns) and logical events (left top
00222 ///     trigger pressed, right joystick pushed up, etc.).  In practice, there is
00223 ///     no agreement between manufacturers how physical and logical events are
00224 ///     related.  So, for instance, different manufacturers will produce
00225 ///     USB adapters that represent the exact same gamepad completely
00226 ///     differently.
00227 /// In short, based on the state of the world today, there is no way for a
00228 ///     programmer to know what type of gamepad a player is holding, or how to
00229 ///     interpret the events coming from that device.  The gamepad::Map
00230 ///     performs that mapping, and most of the purpose of this entire API is to
00231 ///     provide easy-to-create and manage gamepad mappings so that programmers
00232 ///     can work with gamepad objects and not worry about the underlying
00233 ///     details.
00234 /// This particular object gamepad::Map is fairly low-level and is designed
00235 ///     to be easily persisted.  Users of the gamepad library will probably want
00236 ///     to use the Gamepad object instead, which is intended to represent the
00237 ///     physical instance of a connected gamepad.
00238 class Map {
00239 public:
00240         // virtual destructor --------------------------------------------------
00241         virtual ~Map(void) throw();
00242 
00243         // gamepad::Map class interface methods --------------------------------
00244 
00245         /// returns the ID of this mapping.  IDs should be UUIDs
00246         virtual const char * getId(void) const throw() = 0;
00247 
00248         /// returns the ID of the gamepad type this mapping is for (also UUID)
00249         virtual const char * getTypeId(void) const throw() = 0;
00250 
00251         /// returns the name of this mapping.  This is for debugging and is not
00252         ///     meant for end users.
00253         virtual const char * getName(void) const throw() = 0;
00254 
00255         /// returns the list of device names for which this mapping is
00256         ///     recommended.  A device name is the same as what is returned
00257         ///     from gamepad::SourceDevice::getPublicName().  That is, it should
00258         ///     be the device name as returned directly by the hardware itself.
00259         /// This list can be empty, and there could be multiple mappings that
00260         ///     claim to support the same device.  This is especially true for
00261         ///     source devices that support multiple gamepads.
00262         virtual const VecString& getDeviceNames(void) const throw() = 0;
00263 
00264         /// given a button index for the gamepad (see gamepad::Type), how is it
00265         ///     mapped to buttons or potentiometers?  Returns NULL on error
00266         ///     (usually because the logicalName isn't recognized).
00267         virtual const button_map_t * getButtonMapping(
00268                                 IN const char * logicalName) const throw() = 0;
00269 
00270         /// given a joystick index for the gamepad, how is it mapped to
00271         ///     potentiometers?  Returns NULL on error.
00272         virtual const joystick_map_t * getJoystickMapping(
00273                                 IN const char * logicalName) const throw() = 0;
00274 
00275         /// given an potentiometer index for the gamepad (see gamepad::Type),
00276         ///     what is the corresponding potentiometer index on the source
00277         ///     device?  Returns NULL on error.
00278         virtual const pot_map_t * getPotMapping(
00279                                 IN const char * logicalName) const throw() = 0;
00280 
00281         /// given a dpad index for the gamepad (see gamepad::Type), what is the
00282         ///     corresponding dpad index on the source device?  Returns NULL
00283         ///     on error.
00284         virtual const dpad_map_t * getDpadMapping(
00285                                 IN const char * logicalName) const throw() = 0;
00286 };
00287 
00288 
00289 
00290 /// read mapping from a datahash (often a text file)
00291 smart_ptr<Map> readMap(IN const Datahash * hash);
00292 
00293 
00294 /// write mapping to a datahash (you can then use Datahash utility methods to
00295 ///     write to a stream etc)
00296 smart_ptr<Datahash> writeMap(IN const Map * map);
00297 
00298 
00299 };      // gamepad namespace
00300 
00301 
00302 #endif  // GAMEPAD_GAMEPAD_MAP_H__
00303