home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 June / PCFJune.iso / Xenon / XenonSource.exe / gamesystem / source / gs_joystick.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-12  |  9.6 KB  |  396 lines

  1. //-------------------------------------------------------------
  2. //
  3. // Module:    gsCJoystick
  4. //
  5. // Author:    John M Phillips
  6. //
  7. // Started:    12/03/00
  8. //
  9. // Base:    gsCInput
  10. //
  11. // Derived:    None
  12. //
  13. //-------------------------------------------------------------
  14.  
  15. #include "gamesystem.h"
  16.  
  17. //-------------------------------------------------------------
  18.  
  19. int gsCJoystick::m_num_joysticks = 0;
  20.  
  21. gsLPDIRECTINPUTDEVICE gsCJoystick::m_joystick_device[gsJOYSTICK_MAX_STICKS] = { 0 };
  22.  
  23. DIDEVICEINSTANCE gsCJoystick::m_device_desc[gsJOYSTICK_MAX_STICKS];
  24.  
  25. gsCPoint gsCJoystick::m_previous_position[gsJOYSTICK_MAX_STICKS];
  26. gsCPoint gsCJoystick::m_position[gsJOYSTICK_MAX_STICKS];
  27. bool gsCJoystick::m_previous_buttons[gsJOYSTICK_MAX_STICKS][gsJOYSTICK_CODES];
  28. bool gsCJoystick::m_buttons[gsJOYSTICK_MAX_STICKS][gsJOYSTICK_CODES];
  29.  
  30. gsJoystickCode gsCJoystick::m_code = gsJOY_NONE;
  31.  
  32. const char *gsCJoystick::joystickcode_description[gsJOYSTICK_CODES] = {
  33.     "None",
  34.     "Joystick Left",
  35.     "Joystick Right",
  36.     "Joystick Up",
  37.     "Joystick Down",
  38.     "Button 0",
  39.     "Button 1",
  40.     "Button 2",
  41.     "Button 3",
  42.     "Button 4",
  43.     "Button 5",
  44.     "Button 6",
  45.     "Button 7",
  46. };
  47.  
  48. //-------------------------------------------------------------
  49.  
  50. gsCJoystick::gsCJoystick()
  51. {
  52.     for (int i = 0; i < gsJOYSTICK_MAX_STICKS; i++) {
  53.         m_previous_position[i] = gsCPoint(0,0);
  54.         m_position[i] = gsCPoint(0,0);
  55.         for (int j = 0; j < gsJOYSTICK_CODES; j++) {
  56.             m_previous_buttons[i][j] = false;
  57.             m_buttons[i][j] = false;
  58.             }
  59.         }
  60. }
  61.  
  62. //-------------------------------------------------------------
  63.  
  64. gsCJoystick::~gsCJoystick()
  65. {
  66.     destroy();
  67. }
  68.  
  69. //-------------------------------------------------------------
  70.  
  71. BOOL CALLBACK gsCJoystick::enumDevicesCallback(LPDIDEVICEINSTANCE lpddi,LPVOID pvRef)
  72. {
  73.     if (lpddi != NULL && (lpddi->dwDevType & 0x000F) == DIDEVTYPE_JOYSTICK) {
  74.         if (m_num_joysticks == gsJOYSTICK_MAX_STICKS)
  75.             return DIENUM_STOP;
  76.  
  77.         memcpy(&m_device_desc[m_num_joysticks],lpddi,lpddi->dwSize);
  78.     
  79.         m_num_joysticks++;
  80.         }
  81.  
  82.     return DIENUM_CONTINUE;
  83. }
  84.  
  85. //-------------------------------------------------------------
  86.  
  87. bool gsCJoystick::create()
  88. {
  89. #ifdef gsDIRECTX_NT_COMPATIBLE
  90.     return false;
  91. #else
  92.  
  93.     if (!m_direct_input) {
  94.         gsREPORT("gsCJoystick::create called with no direct input device");
  95.         return false;
  96.         }
  97.  
  98.     if (m_joystick_device)
  99.         return true;
  100.  
  101.     m_direct_input->EnumDevices(DIDEVTYPE_JOYSTICK,
  102.                                 (LPDIENUMDEVICESCALLBACK) enumDevicesCallback,
  103.                                 0,
  104.                                 DIEDFL_ATTACHEDONLY);
  105.  
  106.     if (m_num_joysticks == 0)
  107.         return false;
  108.  
  109.     for (int stick = 0; stick < m_num_joysticks; stick++) {
  110.  
  111.         HRESULT hr;
  112.  
  113.         LPDIRECTINPUTDEVICE dev;
  114.  
  115.         hr = m_direct_input->CreateDevice(m_device_desc[0].guidInstance,
  116.                                           &dev,
  117.                                           NULL);
  118.  
  119.         if (hr != DI_OK) {
  120.             gsREPORT("gsCJoystick::create couldn't create device");
  121.             return false;
  122.             }
  123.  
  124.         hr = dev->QueryInterface(gsID_DIRECTINPUTDEVICE,(LPVOID *) &m_joystick_device[stick]);
  125.  
  126.         if (hr != DI_OK) {
  127.             gsREPORT("gsCJoystick::create couldn't create device");
  128.             return false;
  129.             }
  130.  
  131.         dev->Release();
  132.  
  133.         hr = m_joystick_device[stick]->SetDataFormat(&c_dfDIJoystick);
  134.  
  135.         if (hr != DI_OK) {
  136.             gsREPORT("gsCJoystick::create couldn't set data format");
  137.             return false;
  138.             }
  139.  
  140.         hr = m_joystick_device[stick]->SetCooperativeLevel(gsCApplication::getWindow(),
  141.                                                     DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
  142.  
  143.         if (hr != DI_OK) {
  144.             gsREPORT("gsCJoystick::create couldn't set co-op level");
  145.             return false;
  146.             }
  147.  
  148.         DIPROPRANGE diprg;
  149.  
  150.         diprg.diph.dwSize = sizeof(diprg);
  151.         diprg.diph.dwHeaderSize = sizeof(diprg.diph);
  152.         diprg.diph.dwObj = DIJOFS_X;
  153.         diprg.diph.dwHow = DIPH_BYOFFSET;
  154.         diprg.lMin = -gsJOYSTICK_RANGE;
  155.         diprg.lMax = gsJOYSTICK_RANGE;
  156.  
  157.         hr = m_joystick_device[stick]->SetProperty(DIPROP_RANGE,&diprg.diph);
  158.  
  159.         if (hr != DI_OK) {
  160.             gsREPORT("gsCJoystick::create couldn't set X axis property");
  161.             return false;
  162.             }
  163.  
  164.         diprg.diph.dwSize = sizeof(diprg);
  165.         diprg.diph.dwHeaderSize = sizeof(diprg.diph);
  166.         diprg.diph.dwObj = DIJOFS_Y;
  167.         diprg.diph.dwHow = DIPH_BYOFFSET;
  168.         diprg.lMin = -gsJOYSTICK_RANGE;
  169.         diprg.lMax = gsJOYSTICK_RANGE;
  170.  
  171.         hr = m_joystick_device[stick]->SetProperty(DIPROP_RANGE,&diprg.diph);
  172.  
  173.         if (hr != DI_OK) {
  174.             gsREPORT("gsCJoystick::create couldn't set Y axis property");
  175.             return false;
  176.             }
  177.         }
  178.  
  179.     m_active_inputs.addItem(this);
  180.  
  181.     m_code = gsJOY_NONE;
  182.  
  183.     gsREPORT("gsCJoystick device created");
  184.  
  185.     return true;
  186.  
  187. #endif
  188. }
  189.  
  190. //-------------------------------------------------------------
  191.  
  192. bool gsCJoystick::destroy()
  193. {
  194.     for (int stick = 0; stick < m_num_joysticks; stick++) {
  195.     
  196.         if (m_joystick_device[stick]) {
  197.  
  198.             m_active_inputs.removeItem(this);
  199.         
  200.             m_joystick_device[stick]->Unacquire();
  201.             m_joystick_device[stick]->Release();
  202.             m_joystick_device[stick] = 0;
  203.  
  204.             gsREPORT("gsCJoystick device destroyed");
  205.             }
  206.         }
  207.  
  208.     return true;
  209. }
  210.  
  211. //-------------------------------------------------------------
  212.  
  213. bool gsCJoystick::acquire()
  214. {
  215.     for (int stick = 0; stick < m_num_joysticks; stick++) {
  216.  
  217.         if (!m_joystick_device[stick]) {
  218.             gsREPORT("gsCJoystick::acquire called with no joystick device");
  219.             return false;
  220.             }
  221.     
  222.         HRESULT hr;
  223.     
  224.         if (gsCApplication::isActive()) {
  225.             hr = m_joystick_device[stick]->Acquire();
  226.  
  227.             if (hr != DI_OK) {
  228.                 gsREPORT("gsCJoystick::acquire failed");
  229.                 return false;
  230.                 }
  231.             }
  232.         else {
  233.             hr = m_joystick_device[stick]->Unacquire();
  234.  
  235.             if (hr != DI_OK) {
  236.                 gsREPORT("gsCJoystick::acquire unacquire failed");
  237.                 return false;
  238.                 }
  239.             }
  240.         }
  241.  
  242.     return true;
  243. }
  244.  
  245. //-------------------------------------------------------------
  246.  
  247. bool gsCJoystick::update()
  248. {
  249. #ifdef gsDIRECTX_NT_COMPATIBLE
  250.     return false;
  251. #else
  252.  
  253.     DIJOYSTATE joy_state;
  254.  
  255.     for (int stick = 0; stick < m_num_joysticks; stick++) {
  256.  
  257.         // save previous state
  258.         // clear current state in case we lose the joystick
  259.  
  260.         m_previous_position[stick] = m_position[stick];
  261.         m_position[stick] = gsCPoint(0,0);
  262.  
  263.         int i;
  264.  
  265.         for (i = 0; i < gsJOYSTICK_CODES; i++) {
  266.             m_previous_buttons[stick][i] = m_buttons[stick][i];
  267.             m_buttons[stick][i] = false;
  268.             }
  269.  
  270.         if (m_joystick_device[stick]) {
  271.             HRESULT hr = DIERR_INPUTLOST;
  272.  
  273.             while (hr == DIERR_INPUTLOST) {
  274.                 hr = m_joystick_device[stick]->Poll();
  275.  
  276.                 if (hr != DIERR_INPUTLOST)
  277.                     hr = m_joystick_device[stick]->GetDeviceState(sizeof(joy_state),&joy_state);
  278.             
  279.                 if (hr == DIERR_INPUTLOST) {
  280.                     gsREPORT("gsCJoystick::update input lost");
  281.                     hr = m_joystick_device[stick]->Acquire();
  282.                     if (hr != DI_OK) {
  283.                         gsREPORT("gsCJoystick::update couldn't acquire device");
  284.                         return false;
  285.                         }
  286.                     }
  287.                 }
  288.  
  289.             if (hr != DI_OK) {
  290.                 gsREPORT("gsCJoystick::update couldn't get device state");
  291.                 return false;
  292.                 }
  293.             }
  294.  
  295.         if (joy_state.lX < -gsJOYSTICK_THRESHOLD) {
  296.             m_buttons[stick][gsJOY_LEFT] = true;
  297.             m_position[stick].setX(-1);
  298.             }
  299.         else if (joy_state.lX > gsJOYSTICK_THRESHOLD) {
  300.             m_buttons[stick][gsJOY_RIGHT] = true;
  301.             m_position[stick].setX(1);
  302.             }
  303.  
  304.         if (joy_state.lY < -gsJOYSTICK_THRESHOLD) {
  305.             m_buttons[stick][gsJOY_UP] = true;
  306.             m_position[stick].setY(1);
  307.             }
  308.         else if (joy_state.lY > gsJOYSTICK_THRESHOLD) {
  309.             m_buttons[stick][gsJOY_DOWN] = true;
  310.             m_position[stick].setY(-1);
  311.             }
  312.  
  313.         m_buttons[stick][gsJOY_BUTTON0] = (joy_state.rgbButtons[0] & 0x80) != 0;
  314.         m_buttons[stick][gsJOY_BUTTON1] = (joy_state.rgbButtons[1] & 0x80) != 0;
  315.         m_buttons[stick][gsJOY_BUTTON2] = (joy_state.rgbButtons[2] & 0x80) != 0;
  316.         m_buttons[stick][gsJOY_BUTTON3] = (joy_state.rgbButtons[3] & 0x80) != 0;
  317.         m_buttons[stick][gsJOY_BUTTON4] = (joy_state.rgbButtons[4] & 0x80) != 0;
  318.         m_buttons[stick][gsJOY_BUTTON5] = (joy_state.rgbButtons[5] & 0x80) != 0;
  319.         m_buttons[stick][gsJOY_BUTTON6] = (joy_state.rgbButtons[6] & 0x80) != 0;
  320.         m_buttons[stick][gsJOY_BUTTON7] = (joy_state.rgbButtons[7] & 0x80) != 0;
  321.  
  322.         for (i = 0; i < gsJOYSTICK_MAX_BUTTONS; i++) {
  323.             if (!m_previous_buttons[stick][i] && m_buttons[stick][i])
  324.                 m_code = (gsJoystickCode) ((int) gsJOY_BUTTON0 + i);
  325.             }
  326.         }
  327.  
  328.     return true;
  329. #endif
  330. }
  331.  
  332. //-------------------------------------------------------------
  333.  
  334. bool gsCJoystick::isActive()
  335. {
  336.     return m_joystick_device[0] != 0;
  337. }
  338.  
  339. //-------------------------------------------------------------
  340.  
  341. int gsCJoystick::getNumSticks()
  342. {
  343.     if (m_joystick_device[0])
  344.         return m_num_joysticks;
  345.     else
  346.         return 0;
  347. }
  348.  
  349. //-------------------------------------------------------------
  350.  
  351. gsCPoint gsCJoystick::getPosition(int stick)
  352. {
  353.     if (stick >= 0 && stick < m_num_joysticks)
  354.         return m_position[stick];
  355.     else
  356.         return gsCPoint(0,0);
  357. }
  358.  
  359. //-------------------------------------------------------------
  360.  
  361. bool gsCJoystick::testButton(gsJoystickCode button,int stick)
  362. {
  363.     if (button != gsJOY_NONE && stick >= 0 && stick < m_num_joysticks)
  364.         return m_buttons[stick][button];
  365.     else
  366.         return 0;
  367. }
  368.  
  369. //-------------------------------------------------------------
  370.  
  371. bool gsCJoystick::testButtonPressed(gsJoystickCode button,int stick)
  372. {
  373.     if (button != gsJOY_NONE && stick >= 0 && stick < m_num_joysticks)
  374.         return !m_previous_buttons[stick][button] && m_buttons[stick][button];
  375.     else
  376.         return 0;
  377. }
  378.  
  379. //-------------------------------------------------------------
  380.  
  381. gsJoystickCode gsCJoystick::getEmulatedKey()
  382. {
  383.     gsJoystickCode code = m_code;
  384.     m_code = gsJOY_NONE;
  385.     return code;
  386. }
  387.  
  388. //-------------------------------------------------------------
  389.  
  390. const char * gsCJoystick::joystickCodeToDescription(gsJoystickCode code)
  391. {
  392.     return joystickcode_description[code - gsJOY_NONE];
  393. }
  394.  
  395. //-------------------------------------------------------------
  396.