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