Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Win32Joystick.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 /***************************************************************************
00009  * RCS INFORMATION:
00010  *
00011  *      $RCSfile: Win32Joystick.C,v $
00012  *      $Author: johns $        $Locker:  $             $State: Exp $
00013  *      $Revision: 1.28 $       $Date: 2020/02/26 14:40:13 $
00014  *
00015  ***************************************************************************/
00021 #include "Win32Joystick.h"
00022 #include "DisplayDevice.h"
00023 #include "TextEvent.h"
00024 #include "CommandQueue.h"
00025 #include "Inform.h"
00026 #include "PickList.h"
00027 #include "VMDApp.h"
00028 #include "stdlib.h" // for getenv()
00029 
00030 // constructor
00031 Win32Joystick::Win32Joystick(VMDApp *vmdapp)
00032         : UIObject(vmdapp) {
00033   MMRESULT mres;
00034   int i, numsticks;
00035   sticks = NULL;
00036 
00037   // max joysticks the driver supports, returns 0 if no driver, or failure
00038   maxjoys = joyGetNumDevs(); 
00039 
00040   if (maxjoys > 0) {
00041     sticks = (vmdwinjoystick *) malloc(maxjoys * sizeof(vmdwinjoystick));
00042 
00043     if (sticks != NULL) {
00044       numsticks = 0; 
00045       for (i=0; i<maxjoys; i++) {
00046         memset(&(sticks[i]), 0, sizeof(vmdwinjoystick));
00047         mres = joyGetDevCaps(i, &sticks[i].caps, sizeof(JOYCAPS));
00048     
00049         if (mres == JOYERR_NOERROR) {
00050           msgInfo << "Joystick " << i << ", " << ((int) sticks[i].caps.wNumAxes) << " axes, " << ((int) sticks[i].caps.wNumButtons) << " buttons, ";
00051 
00052           if (sticks[i].caps.szPname == NULL) 
00053              msgInfo << "type unknown." << sendmsg;
00054           else 
00055              msgInfo << sticks[i].caps.szPname << sendmsg;
00056 
00057           sticks[i].xrange = sticks[i].caps.wXmax - sticks[i].caps.wXmin; 
00058           sticks[i].yrange = sticks[i].caps.wYmax - sticks[i].caps.wYmin; 
00059           sticks[i].zrange = sticks[i].caps.wZmax - sticks[i].caps.wZmin; 
00060 
00061           sticks[i].moveMode = OFF; // set joystick off by default, in case
00062                                     // its wacko, this prevents a bad joystick
00063                                     // from interfering with VMD unless the
00064                                     // user intentionally enables it.
00065           sticks[i].exists = TRUE;
00066           numsticks++;
00067         } else {
00068           sticks[i].exists = FALSE;
00069         }
00070       }
00071     }
00072   }
00073 
00074   if (numsticks < 1 || maxjoys < 1) {
00075     msgInfo << "No joysticks found.  Joystick interface disabled." << sendmsg; 
00076   }
00077 
00078   // set the default translation and rotation increments
00079   transInc = 1.0f / 4000.0f;
00080     rotInc = 1.0f / 500.0f;
00081   scaleInc = 1.0f / 4000.0f;
00082   reset();
00083 }
00084 
00085 
00086 // destructor
00087 Win32Joystick::~Win32Joystick(void) {
00088   if (sticks != NULL)
00089     free(sticks);
00090 }
00091 
00093    
00094 // reset the joystick to original settings
00095 void Win32Joystick::reset(void) {
00096   scaling = 1.0;
00097 }
00098 
00099 // update the display due to a command being executed.  Return whether
00100 // any action was taken on this command.
00101 // Arguments are the command type, command object, and the 
00102 // success of the command (T or F).
00103 int Win32Joystick::act_on_command(int type, Command *cmd) {
00104   return FALSE; // we don't take any commands presently
00105 }
00106 
00107 
00108 // do null region processing on raw joystick values
00109 static int nullregion(int null, int val) {
00110   if (abs(val) > null) {
00111     return ((val > 0) ? (val - null) : (val + null));
00112   }
00113   return 0;
00114 }
00115 
00116 
00117 // check for an event, and queue it if found.  Return TRUE if an event
00118 // was generated.
00119 int Win32Joystick::check_event(void) {
00120   int retval = FALSE;
00121   int rx, ry, rz, tx, ty, tz;
00122   int i;
00123   MMRESULT mres;
00124   float scf;
00125   // for use in UserKeyEvent() calls
00126   DisplayDevice::EventCodes keydev=DisplayDevice::WIN_KBD;
00127   
00128   if (maxjoys < 1 || sticks == NULL)
00129     return FALSE; // joysticks disabled 
00130 
00131   rx = ry = rz = tx = ty = tz = 0;
00132 
00133   for (i=0; i<maxjoys; i++) {
00134     if (sticks[i].exists == FALSE) 
00135       continue; // skip processing joysticks that aren't there
00136 
00137     memset(&(sticks[i].info), 0, sizeof(JOYINFOEX));
00138     sticks[i].info.dwSize = sizeof(JOYINFOEX);
00139     sticks[i].info.dwFlags = JOY_RETURNALL;
00140 
00141     // query current joystick status
00142     mres = joyGetPosEx(i, &sticks[i].info);
00143 
00144     if (mres == JOYERR_NOERROR) {
00145       sticks[i].vx = (int) (10000.0f * ((((float) sticks[i].info.dwXpos - sticks[i].caps.wXmin) / ((float) sticks[i].xrange)) - 0.5f));
00146       sticks[i].vy = (int) (10000.0f * ((((float) sticks[i].info.dwYpos - sticks[i].caps.wYmin) / ((float) sticks[i].yrange)) - 0.5f));
00147       sticks[i].vz = (int) (10000.0f * ((((float) sticks[i].info.dwZpos - sticks[i].caps.wZmin) / ((float) sticks[i].zrange)) - 0.5f));
00148  
00149       sticks[i].vx = nullregion(800, sticks[i].vx);
00150       sticks[i].vy = nullregion(800, sticks[i].vy);
00151       sticks[i].vz = nullregion(800, sticks[i].vz);
00152       sticks[i].avail = TRUE; // joystick moved
00153       retval = TRUE; // at least one stick had data
00154     } else {
00155       sticks[i].avail = FALSE; // error of some kind, or not there
00156     }
00157   }
00158 
00159   // process what stick is actually doing
00160   for (i=0; i<maxjoys; i++) {
00161     if (sticks[i].avail != TRUE) 
00162       continue;  // skip processing that stick 
00163   
00164     sticks[i].buttonchanged = sticks[i].info.dwButtons ^ sticks[i].buttons;
00165    
00166     // if the user presses button 1, reset the view
00167     if ((sticks[i].buttonchanged & JOY_BUTTON1) && (sticks[i].info.dwButtons & JOY_BUTTON1)) {
00168       scaling = 1.0;
00169       app->scene_resetview();
00170       msgInfo << "Joystick " << i << " reset view orientation" << sendmsg;
00171     }
00172 
00173     // Toggle between the different modes
00174     if ((sticks[i].buttonchanged & JOY_BUTTON2) && (sticks[i].info.dwButtons & JOY_BUTTON2)) {
00175       switch (sticks[i].moveMode) {
00176         case ROTATION:
00177           sticks[i].moveMode = TRANSLATION;
00178           msgInfo << "Joystick " << i << " set to translation mode" << sendmsg;
00179           break;
00180 
00181         case TRANSLATION:
00182           sticks[i].moveMode = SCALING;
00183           msgInfo << "Joystick " << i << " set to scaling mode" << sendmsg;
00184           break;
00185 
00186         case SCALING:
00187           sticks[i].moveMode = OFF;
00188           msgInfo << "Joystick " << i << " axes disabled" << sendmsg;
00189           break;
00190 
00191         case OFF:
00192         default:
00193           sticks[i].moveMode = ROTATION;
00194           msgInfo << "Joystick " << i << " set to rotation mode" << sendmsg;
00195           break;
00196       }
00197     }
00198 
00199     if ((sticks[i].buttonchanged & JOY_BUTTON3) && (sticks[i].info.dwButtons & JOY_BUTTON3)) {
00200       runcommand(new UserKeyEvent(keydev, '3', (int) DisplayDevice::AUX));
00201     }
00202     if ((sticks[i].buttonchanged & JOY_BUTTON4) && (sticks[i].info.dwButtons & JOY_BUTTON4)) {
00203       runcommand(new UserKeyEvent(keydev, '4', (int) DisplayDevice::AUX));
00204     }
00205     if ((sticks[i].buttonchanged & JOY_BUTTON5) && (sticks[i].info.dwButtons & JOY_BUTTON5)) {
00206       runcommand(new UserKeyEvent(keydev, '5', (int) DisplayDevice::AUX));
00207     }
00208     if ((sticks[i].buttonchanged & JOY_BUTTON6) && (sticks[i].info.dwButtons & JOY_BUTTON6)) {
00209       runcommand(new UserKeyEvent(keydev, '6', (int) DisplayDevice::AUX));
00210     }
00211     if ((sticks[i].buttonchanged & JOY_BUTTON7) && (sticks[i].info.dwButtons & JOY_BUTTON7)) {
00212       runcommand(new UserKeyEvent(keydev, '7', (int) DisplayDevice::AUX));
00213     }
00214     if ((sticks[i].buttonchanged & JOY_BUTTON8) && (sticks[i].info.dwButtons & JOY_BUTTON8)) {
00215       runcommand(new UserKeyEvent(keydev, '8', (int) DisplayDevice::AUX));
00216     }
00217     if ((sticks[i].buttonchanged & JOY_BUTTON9) && (sticks[i].info.dwButtons & JOY_BUTTON9)) {
00218       runcommand(new UserKeyEvent(keydev, '9', (int) DisplayDevice::AUX));
00219     }
00220  
00221     switch(sticks[i].moveMode) {
00222       case ROTATION:
00223         rx = sticks[i].vy;
00224         ry = sticks[i].vx;
00225 
00226         if (sticks[i].caps.wCaps & JOYCAPS_HASZ)
00227           rz = sticks[i].vz;
00228         else 
00229           rz = 0;
00230 
00231         app->scene_rotate_by(((float) rx) * rotInc, 'x');
00232         app->scene_rotate_by(((float) ry) * rotInc, 'y');
00233         app->scene_rotate_by(((float) rz) * rotInc, 'z');
00234         break;
00235   
00236       case TRANSLATION:
00237         tx = sticks[i].vx;
00238         ty = sticks[i].vy;
00239 
00240         if (sticks[i].caps.wCaps & JOYCAPS_HASZ)
00241           tz = sticks[i].vz;
00242         else 
00243           tz = 0;
00244 
00245         app->scene_translate_by(tx * transInc, ty * transInc, -tz * transInc);
00246         break;
00247 
00248       case SCALING: 
00249         tx = sticks[i].vx;
00250         scf = scaling + scaleInc * (float) tx;
00251         if (scf < 0.0)
00252           scf = 0.0;
00253         app->scene_scale_by(scf);
00254         break;
00255 
00256       case OFF:
00257       default:
00258         // do nothing
00259         // The OFF mode is a safety feature so that VMD's stability 
00260         // isn't compromised by bad joysticks.  This provides the user
00261         // with a way to selectively enable joysticks, even though VMD
00262         // will find and attach them all, only the ones that the user has
00263         // enabled will actually affect the VMD view.
00264         break;
00265     }
00266 
00267     sticks[i].buttons = sticks[i].info.dwButtons;
00268   }
00269 
00270   return retval;
00271 }
00272 
00273 
00274 

Generated on Wed Dec 4 02:44:56 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002