gxinput.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. #include "std.h"
  2. #include "gxinput.h"
  3. #include "gxruntime.h"
  4. #include <dinput.h>
  5. static const int QUE_SIZE=32;
  6. class Device : public gxDevice{
  7. public:
  8. bool acquired;
  9. gxInput *input;
  10. IDirectInputDevice7 *device;
  11. Device( gxInput *i,IDirectInputDevice7 *d ):input(i),acquired(false),device(d){
  12. }
  13. virtual ~Device(){
  14. device->Release();
  15. }
  16. bool acquire(){
  17. return acquired=device->Acquire()>=0;
  18. }
  19. void unacquire(){
  20. device->Unacquire();
  21. acquired=false;
  22. }
  23. };
  24. class Keyboard : public Device{
  25. public:
  26. Keyboard( gxInput *i,IDirectInputDevice7 *d ):Device(i,d){
  27. }
  28. void update(){
  29. if( !acquired ){
  30. input->runtime->idle();
  31. return;
  32. }
  33. int k,cnt=32;
  34. DIDEVICEOBJECTDATA data[32],*curr;
  35. if( device->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),data,(DWORD*)&cnt,0 )<0 ) return;
  36. curr=data;
  37. for( k=0;k<cnt;++curr,++k ){
  38. int n=curr->dwOfs;if( !n || n>255 ) continue;
  39. if( curr->dwData&0x80 ) downEvent( n );
  40. else upEvent( n );
  41. }
  42. }
  43. };
  44. class Mouse : public Device{
  45. public:
  46. Mouse( gxInput *i,IDirectInputDevice7 *d ):Device(i,d){
  47. }
  48. void update(){
  49. if( !acquired ){
  50. input->runtime->idle();
  51. return;
  52. }
  53. DIMOUSESTATE state;
  54. if( device->GetDeviceState(sizeof(state),&state)<0 ) return;
  55. if( gxGraphics *g=input->runtime->graphics ){
  56. int mx=axis_states[0]+state.lX;
  57. int my=axis_states[1]+state.lY;
  58. if( mx<0 ) mx=0;
  59. else if( mx>=g->getWidth() ) mx=g->getWidth()-1;
  60. if( my<0 ) my=0;
  61. else if( my>=g->getHeight() ) my=g->getHeight()-1;
  62. axis_states[0]=mx;
  63. axis_states[1]=my;
  64. axis_states[2]+=state.lZ;
  65. }
  66. for( int k=0;k<3;++k ){
  67. setDownState( k+1,state.rgbButtons[k]&0x80 ? true : false );
  68. }
  69. }
  70. };
  71. class Joystick : public Device{
  72. public:
  73. int type,poll_time;
  74. int mins[12],maxs[12];
  75. Joystick( gxInput *i,IDirectInputDevice7 *d,int t ):Device(i,d),type(t),poll_time(0){
  76. for( int k=0;k<12;++k ){
  77. //initialize joystick axis ranges (d'oh!)
  78. DIPROPRANGE range;
  79. range.diph.dwSize=sizeof(DIPROPRANGE);
  80. range.diph.dwHeaderSize=sizeof(DIPROPHEADER);
  81. range.diph.dwObj=k*4+12;
  82. range.diph.dwHow=DIPH_BYOFFSET;
  83. if( d->GetProperty( DIPROP_RANGE,&range.diph )<0 ){
  84. mins[k]=0;
  85. maxs[k]=65535;
  86. continue;
  87. }
  88. mins[k]=range.lMin;
  89. maxs[k]=range.lMax-range.lMin;
  90. }
  91. }
  92. void update(){
  93. unsigned tm=timeGetTime();
  94. if( tm-poll_time<3 ) return;
  95. if( device->Poll()<0 ){
  96. acquired=false;
  97. input->runtime->idle();
  98. acquire();if( device->Poll()<0 ) return;
  99. }
  100. poll_time=tm;
  101. DIJOYSTATE state;
  102. if( device->GetDeviceState( sizeof( state ),&state )<0 ) return;
  103. axis_states[0]=(state.lX-mins[0])/(float)maxs[0]*2-1;
  104. axis_states[1]=(state.lY-mins[1])/(float)maxs[1]*2-1;
  105. axis_states[2]=(state.lZ-mins[2])/(float)maxs[2]*2-1;
  106. axis_states[3]=(state.rglSlider[0]-mins[6])/(float)maxs[6]*2-1;
  107. axis_states[4]=(state.rglSlider[1]-mins[7])/(float)maxs[7]*2-1;
  108. axis_states[5]=(state.lRx-mins[3])/(float)maxs[3]*2-1;
  109. axis_states[6]=(state.lRy-mins[4])/(float)maxs[4]*2-1;
  110. axis_states[7]=(state.lRz-mins[5])/(float)maxs[5]*2-1;
  111. if( (state.rgdwPOV[0]&0xffff)==0xffff ) axis_states[8]=-1;
  112. else axis_states[8]=floor(state.rgdwPOV[0]/100.0f+.5f);
  113. for( int k=0;k<31;++k ){
  114. setDownState( k+1,state.rgbButtons[k]&0x80 ? true : false );
  115. }
  116. }
  117. };
  118. static Keyboard *keyboard;
  119. static Mouse *mouse;
  120. static vector<Joystick*> joysticks;
  121. static Keyboard *createKeyboard( gxInput *input ){
  122. IDirectInputDevice7 *dev;
  123. if( input->dirInput->CreateDeviceEx( GUID_SysKeyboard,IID_IDirectInputDevice7,(void**)&dev,0 )>=0 ){
  124. if( dev->SetCooperativeLevel( input->runtime->hwnd,DISCL_FOREGROUND|DISCL_EXCLUSIVE )>=0 ){
  125. if( dev->SetDataFormat( &c_dfDIKeyboard )>=0 ){
  126. DIPROPDWORD dword;
  127. memset( &dword,0,sizeof(dword) );
  128. dword.diph.dwSize=sizeof(DIPROPDWORD);
  129. dword.diph.dwHeaderSize=sizeof(DIPROPHEADER);
  130. dword.diph.dwObj=0;
  131. dword.diph.dwHow=DIPH_DEVICE;
  132. dword.dwData=32;
  133. if( dev->SetProperty( DIPROP_BUFFERSIZE,&dword.diph )>=0 ){
  134. return d_new Keyboard( input,dev );
  135. }else{
  136. // input->runtime->debugInfo( "keyboard: SetProperty failed" );
  137. }
  138. }else{
  139. // input->runtime->debugInfo( "keyboard: SetDataFormat failed" );
  140. }
  141. return d_new Keyboard( input,dev );
  142. }else{
  143. input->runtime->debugInfo( "keyboard: SetCooperativeLevel failed" );
  144. }
  145. dev->Release();
  146. }else{
  147. input->runtime->debugInfo( "keyboard: CreateDeviceEx failed" );
  148. }
  149. return 0;
  150. }
  151. static Mouse *createMouse( gxInput *input ){
  152. IDirectInputDevice7 *dev;
  153. if( input->dirInput->CreateDeviceEx( GUID_SysMouse,IID_IDirectInputDevice7,(void**)&dev,0 )>=0 ){
  154. if( dev->SetCooperativeLevel( input->runtime->hwnd,DISCL_FOREGROUND|DISCL_EXCLUSIVE )>=0 ){
  155. if( dev->SetDataFormat( &c_dfDIMouse )>=0 ){
  156. return d_new Mouse( input,dev );
  157. }else{
  158. // input->runtime->debugInfo( "mouse: SetDataFormat failed" );
  159. }
  160. return d_new Mouse( input,dev );
  161. }else{
  162. input->runtime->debugInfo( "mouse: SetCooperativeLevel failed" );
  163. }
  164. dev->Release();
  165. }else{
  166. input->runtime->debugInfo( "mouse: CreateDeviceEx failed" );
  167. }
  168. return 0;
  169. }
  170. static Joystick *createJoystick( gxInput *input,LPCDIDEVICEINSTANCE devinst ){
  171. IDirectInputDevice7 *dev;
  172. if( input->dirInput->CreateDeviceEx( devinst->guidInstance,IID_IDirectInputDevice7,(void**)&dev,0 )>=0 ){
  173. if( dev->SetCooperativeLevel( input->runtime->hwnd,DISCL_FOREGROUND|DISCL_EXCLUSIVE )>=0 ){
  174. if( dev->SetDataFormat( &c_dfDIJoystick )>=0 ){
  175. int t=((devinst->dwDevType>>8)&0xff)==DIDEVTYPEJOYSTICK_GAMEPAD ? 1 : 2;
  176. return d_new Joystick( input,dev,t );
  177. }
  178. }
  179. dev->Release();
  180. }
  181. return 0;
  182. }
  183. static BOOL CALLBACK enumJoystick( LPCDIDEVICEINSTANCE devinst,LPVOID pvRef ){
  184. if( (devinst->dwDevType&0xff)!=DIDEVTYPE_JOYSTICK ) return DIENUM_CONTINUE;
  185. if( Joystick *joy=createJoystick( (gxInput*)pvRef,devinst ) ){
  186. joysticks.push_back( joy );
  187. }
  188. return DIENUM_CONTINUE;
  189. }
  190. gxInput::gxInput( gxRuntime *rt,IDirectInput7 *di ):
  191. runtime(rt),dirInput(di){
  192. keyboard=createKeyboard( this );
  193. mouse=createMouse( this );
  194. joysticks.clear();
  195. dirInput->EnumDevices( DIDEVTYPE_JOYSTICK,enumJoystick,this,DIEDFL_ATTACHEDONLY );
  196. }
  197. gxInput::~gxInput(){
  198. for( int k=0;k<joysticks.size();++k ) delete joysticks[k];
  199. joysticks.clear();
  200. delete mouse;
  201. delete keyboard;
  202. dirInput->Release();
  203. }
  204. void gxInput::wm_keydown( int key ){
  205. if( keyboard ) keyboard->downEvent( key );
  206. }
  207. void gxInput::wm_keyup( int key ){
  208. if( keyboard ) keyboard->upEvent( key );
  209. }
  210. void gxInput::wm_mousedown( int key ){
  211. if( mouse ) mouse->downEvent( key );
  212. }
  213. void gxInput::wm_mouseup( int key ){
  214. if( mouse ) mouse->upEvent( key );
  215. }
  216. void gxInput::wm_mousemove( int x,int y ){
  217. if( mouse ){
  218. mouse->axis_states[0]=x;
  219. mouse->axis_states[1]=y;
  220. }
  221. }
  222. void gxInput::wm_mousewheel( int dz ){
  223. if( mouse ) mouse->axis_states[2]+=dz;
  224. }
  225. void gxInput::reset(){
  226. if( mouse ) mouse->reset();
  227. if( keyboard ) keyboard->reset();
  228. for( int k=0;k<joysticks.size();++k ) joysticks[k]->reset();
  229. }
  230. bool gxInput::acquire(){
  231. bool m_ok=true,k_ok=true;
  232. if( mouse ) m_ok=mouse->acquire();
  233. if( keyboard ) k_ok=keyboard->acquire();
  234. if( m_ok && k_ok ) return true;
  235. if( k_ok ) keyboard->unacquire();
  236. if( m_ok ) mouse->unacquire();
  237. return false;
  238. }
  239. void gxInput::unacquire(){
  240. if( keyboard ) keyboard->unacquire();
  241. if( mouse ) mouse->unacquire();
  242. }
  243. void gxInput::moveMouse( int x,int y ){
  244. if( !mouse ) return;
  245. mouse->axis_states[0]=x;
  246. mouse->axis_states[1]=y;
  247. runtime->moveMouse( x,y );
  248. }
  249. gxDevice *gxInput::getMouse()const{
  250. return mouse;
  251. }
  252. gxDevice *gxInput::getKeyboard()const{
  253. return keyboard;
  254. }
  255. gxDevice *gxInput::getJoystick( int n )const{
  256. return n>=0 && n<joysticks.size() ? joysticks[n] : 0;
  257. }
  258. int gxInput::getJoystickType( int n )const{
  259. return n>=0 && n<joysticks.size() ? joysticks[n]->type : 0;
  260. }
  261. int gxInput::numJoysticks()const{
  262. return joysticks.size();
  263. }
  264. int gxInput::toAscii( int scan )const{
  265. switch( scan ){
  266. case DIK_INSERT:return ASC_INSERT;
  267. case DIK_DELETE:return ASC_DELETE;
  268. case DIK_HOME:return ASC_HOME;
  269. case DIK_END:return ASC_END;
  270. case DIK_PGUP:return ASC_PAGEUP;
  271. case DIK_PGDN:return ASC_PAGEDOWN;
  272. case DIK_UP:return ASC_UP;
  273. case DIK_DOWN:return ASC_DOWN;
  274. case DIK_LEFT:return ASC_LEFT;
  275. case DIK_RIGHT:return ASC_RIGHT;
  276. }
  277. scan&=0x7f;
  278. int virt=MapVirtualKey( scan,1 );
  279. if( !virt ) return 0;
  280. static unsigned char mat[256];
  281. mat[VK_LSHIFT]=keyboard->keyDown( DIK_LSHIFT ) ? 0x80 : 0;
  282. mat[VK_RSHIFT]=keyboard->keyDown( DIK_RSHIFT ) ? 0x80 : 0;
  283. mat[VK_SHIFT]=mat[VK_LSHIFT]|mat[VK_RSHIFT];
  284. mat[VK_LCONTROL]=keyboard->keyDown( DIK_LCONTROL ) ? 0x80 : 0;
  285. mat[VK_RCONTROL]=keyboard->keyDown( DIK_RCONTROL ) ? 0x80 : 0;
  286. mat[VK_CONTROL]=mat[VK_LCONTROL]|mat[VK_RCONTROL];
  287. mat[VK_LMENU]=keyboard->keyDown( DIK_LMENU ) ? 0x80 : 0;
  288. mat[VK_RMENU]=keyboard->keyDown( DIK_RMENU ) ? 0x80 : 0;
  289. mat[VK_MENU]=mat[VK_LMENU]|mat[VK_RMENU];
  290. WORD ch;
  291. if( ToAscii( virt,scan,mat,&ch,0 )!=1 ) return 0;
  292. return ch & 255;
  293. }