My Documents/dxframework/dxf/dxf-engine/dxf_controller.cpp

Go to the documentation of this file.
00001 /*      DXFramework Copyright (c) 2006, Jonathan Voigt, University of Michigan.
00002         See http://dxframework.sourceforge.net/ for a list of contributors.
00003         All rights reserved.
00004 
00005         Redistribution and use in source and binary forms, with or without modification, 
00006         are permitted provided that the following conditions are met:
00007 
00008                 * Redistributions of source code must retain the above copyright notice, 
00009                 this list of conditions and the following disclaimer.
00010 
00011                 * Redistributions in binary form must reproduce the above copyright notice, 
00012                 this list of conditions and the following disclaimer in the documentation 
00013                 and/or other materials provided with the distribution.
00014 
00015                 * Neither the name of the DXFramework project nor the names of its 
00016                 contributors may be used to endorse or promote products derived from this 
00017                 software without specific prior written permission.
00018 
00019         THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
00020         ANY 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 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
00023         ANY 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 ON 
00026         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 #include "dxframework.h"
00032 
00033 LPDIRECTINPUT8       g_pDI = 0;         
00034 LPDIRECTINPUTDEVICE8 g_pJoystick = 0;     
00035 dxf::JoystickCaps g_JoystickCaps;
00036 
00037 BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ){
00038     HRESULT hr;
00039 
00040     // Obtain an interface to the enumerated Joystick.
00041     hr = g_pDI->CreateDevice( pdidInstance->guidInstance, &g_pJoystick, NULL );
00042 
00043     // If it failed, then we can't use this Joystick. (Maybe the user unplugged
00044     // it while we were in the middle of enumerating it.)
00045     if( FAILED(hr) ) return DIENUM_CONTINUE;
00046 
00047     // Stop enumeration. Note: we're just taking the first Joystick we get. You
00048     // could store all the enumerated Joysticks and let the user pick.
00049     return DIENUM_STOP;
00050 }
00051 
00052 BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
00053                                    VOID* pContext )
00054 {
00055         HRESULT hr;
00056 
00057     static int nSliderCount = 0;  // Number of returned slider controls
00058     static int nPOVCount = 0;     // Number of returned POV controls
00059 
00060     // For axes that are returned, set the DIPROP_RANGE property for the
00061     // enumerated axis in order to scale min/max values.
00062     if( pdidoi->dwType & DIDFT_AXIS )
00063     {
00064         DIPROPRANGE diprg; 
00065         diprg.diph.dwSize       = sizeof(DIPROPRANGE); 
00066         diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
00067         diprg.diph.dwHow        = DIPH_BYID; 
00068         diprg.diph.dwObj        = pdidoi->dwType; // Specify the enumerated axis
00069         diprg.lMin              = -1000; 
00070         diprg.lMax              = +1000; 
00071     
00072         // Set the range for the axis
00073                 V(g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph));
00074                 if (FAILED(hr)) return DIENUM_STOP;         
00075     }
00076 
00077     // Set the UI to reflect what objects the Joystick supports
00078     if (pdidoi->guidType == GUID_XAxis) {
00079                 g_JoystickCaps.x = true;
00080     }
00081     if (pdidoi->guidType == GUID_YAxis) {
00082                 g_JoystickCaps.y = true;
00083     }
00084     if (pdidoi->guidType == GUID_ZAxis) {
00085                 g_JoystickCaps.z = true;
00086     }
00087     if (pdidoi->guidType == GUID_RxAxis) {
00088                 g_JoystickCaps.xr = true;
00089     }
00090     if (pdidoi->guidType == GUID_RyAxis) {
00091                 g_JoystickCaps.yr = true;
00092     }
00093     if (pdidoi->guidType == GUID_RzAxis) {
00094                 g_JoystickCaps.zr = true;
00095     }
00096     if (pdidoi->guidType == GUID_Slider) {
00097                 ++g_JoystickCaps.sliderCount;
00098     }
00099     if (pdidoi->guidType == GUID_POV) {
00100                 ++g_JoystickCaps.povCount;
00101     }
00102 
00103     return DIENUM_CONTINUE;
00104 }
00105 
00106 void CALLBACK MouseProc( bool bLeftButtonDown, bool bRightButtonDown, bool bMiddleButtonDown, bool bSideButton1Down, bool bSideButton2Down, INT nMouseWheelDelta, INT xPos, INT yPos, void* pUserContext ) {
00107         dxf::Controller::Instance()->MouseProc(bLeftButtonDown, bRightButtonDown, bMiddleButtonDown, bSideButton1Down, bSideButton2Down, nMouseWheelDelta, xPos, yPos, pUserContext);
00108 }
00109 
00110 namespace dxf {
00111         extern bool gMouse;
00112 
00113         Controller::Controller() {
00114                 ZeroMemory(&g_JoystickCaps, sizeof(JoystickCaps));
00115         }
00116 
00117         Controller* const Controller::Instance() {
00118                 static Controller instance;
00119                 return &instance;
00120         }
00121 
00122         HRESULT Controller::Load() {
00123                 current = 0;
00124 
00125                 keyboardRaw.reset();
00126                 keyboard[0].reset();
00127                 keyboard[1].reset();
00128 
00129                 mouseRaw.reset();
00130                 mouse[0].reset();
00131                 mouse[1].reset();
00132 
00133                 ZeroMemory(&jsRaw, sizeof(DIJOYSTATE2));
00134                 ZeroMemory(&js, sizeof(DIJOYSTATE2) * 2);
00135 
00136                 DXUTSetCallbackMouse( ::MouseProc );
00137 
00138                 HRESULT hr;
00139                 V_RETURN(DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_pDI, 0));
00140 
00141                 V_RETURN(g_pDI->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, 0, DIEDFL_ATTACHEDONLY));
00142 
00143                 if(!g_pJoystick) {
00144                         g_JoystickCaps.enabled = false;
00145                         Console::output << L"Joystick not found." << std::endl;
00146                         return S_OK;
00147                 }
00148 
00149                 g_JoystickCaps.enabled = true;
00150                 Console::output << L"Joystick found." << std::endl;
00151 
00152                 V_RETURN(g_pJoystick->SetDataFormat(&c_dfDIJoystick2));
00153 
00154                 HWND h = DXUTGetHWND();
00155                 V_RETURN(g_pJoystick->SetCooperativeLevel(h, DISCL_EXCLUSIVE | DISCL_FOREGROUND));
00156 
00157                 V_RETURN(g_pJoystick->EnumObjects(EnumObjectsCallback, (VOID*)DXUTGetHWND(), DIDFT_ALL));
00158 
00159                 return S_OK;
00160         }
00161 
00162         void Controller::Unload() {
00163         }
00164 
00165         void Controller::MouseProc( bool bLeftButtonDown, bool bRightButtonDown, bool bMiddleButtonDown, bool bSideButton1Down, 
00166                                                                         bool bSideButton2Down, INT nMouseWheelDelta, INT xPos, INT yPos, void* pUserContext ) {
00167                 mouseRaw.set(MBUTTON_LEFT, bLeftButtonDown);
00168                 mouseRaw.set(MBUTTON_RIGHT, bRightButtonDown);
00169                 mouseRaw.set(MBUTTON_MIDDLE, bMiddleButtonDown);
00170                 mouseRaw.set(MBUTTON_SIDE1, bSideButton1Down);
00171                 mouseRaw.set(MBUTTON_SIDE2, bSideButton2Down);
00172                 mouseWheelDelta = nMouseWheelDelta;
00173         }
00174 
00175         void Controller::Poll() {
00176                 if (current) {
00177                         current = 0;
00178                 } else {
00179                         current = 1;
00180                 }
00181 
00182                 keyboard[current] = keyboardRaw;
00183                 mouse[current] = mouseRaw;
00184 
00185                 if (!g_pJoystick) return;
00186 
00187                 HRESULT hr;
00188                 // Poll the device to read the current state
00189                 hr = g_pJoystick->Poll(); 
00190                 if(FAILED(hr)) {
00191                         // DInput is telling us that the input stream has been
00192                         // interrupted. We aren't tracking any state between polls, so
00193                         // we don't have any special reset that needs to be done. We
00194                         // just re-acquire and try again.
00195                         hr = g_pJoystick->Acquire();
00196                         while( hr == DIERR_INPUTLOST ) {
00197                                 hr = g_pJoystick->Acquire();
00198                         }
00199 
00200                         // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
00201                         // may occur when the app is minimized or in the process of 
00202                         // switching, so just try again later 
00203                         int last;
00204                         if (current) {
00205                                 last = 0;
00206                         } else {
00207                                 last = 1;
00208                         }
00209                         CopyMemory(&js[current], &js[last], sizeof(DIJOYSTATE2));
00210                         return; 
00211                 }
00212 
00213                 // Get the input's device state
00214                 V(g_pJoystick->GetDeviceState(sizeof(DIJOYSTATE2), &jsRaw));
00215 
00216                 // Update recorded state
00217                 CopyMemory(&js[current], &jsRaw, sizeof(DIJOYSTATE2));
00218         }
00219 
00220         eButtonState Controller::CheckKeyboard(BYTE key) {
00221                 keyboard[current].set(key, DXUTIsKeyDown(key));
00222 
00223                 int last;
00224                 if (current) {
00225                         last = 0;
00226                 } else {
00227                         last = 1;
00228                 }
00229 
00230                 if (!keyboard[current].test(key) && keyboard[last].test(key)) {
00231                         return BUTTON_RELEASED;     
00232 
00233                 } else if (keyboard[current].test(key) && !keyboard[last].test(key)) {
00234                         return BUTTON_PRESSED;
00235 
00236                 } else if (keyboard[current].test(key)) {
00237                         return BUTTON_DOWN;
00238                 }         
00239                 return BUTTON_UP;        
00240         }
00241 
00242         void Controller::BufferedInput(wchar_t key) {
00243                 bufferedInput += key;
00244         }
00245 
00246         void Controller::GetBufferedInput(std::wstring& input) {
00247                 input = bufferedInput;
00248                 bufferedInput = L"";
00249         }
00250 
00251         eButtonState Controller::CheckMouse(eMouseButton button) {
00252                 int last;
00253                 if (current) {
00254                         last = 0;
00255                 } else {
00256                         last = 1;
00257                 }
00258 
00259                 if (!mouse[current].test(button) && mouse[last].test(button)) {
00260                         return BUTTON_RELEASED;     
00261 
00262                 } else if (mouse[current].test(button) && !mouse[last].test(button)) {
00263                         return BUTTON_PRESSED;
00264 
00265                 } else if (mouse[current].test(button)) {
00266                         return BUTTON_DOWN;
00267                 }         
00268                 return BUTTON_UP;        
00269         }
00270 
00271         int Controller::GetMouseWheelDelta() { return mouseWheelDelta; }
00272 
00273         void Controller::SetMousePosition(int x, int y) {
00274                 mousePos.x = x;
00275                 mousePos.y = y;
00276                 if (gMouse) Console::output << "(" << mousePos.x << "," << mousePos.y << ")" << std::endl;
00277         }
00278 
00279         POINT Controller::GetMousePosition() {
00280                 return mousePos;
00281         }
00282 
00283         eButtonState Controller::CheckJoystick(int button) {
00284                 if ((button < 0) || (button >= 128)) return BUTTON_UP;
00285 
00286                 int last;
00287                 if (current) {
00288                         last = 0;
00289                 } else {
00290                         last = 1;
00291                 }
00292 
00293                 if (!js[current].rgbButtons[button] && js[last].rgbButtons[button]) {
00294                         return BUTTON_RELEASED;     
00295 
00296                 } else if (js[current].rgbButtons[button] && !js[last].rgbButtons[button]) {
00297                         return BUTTON_PRESSED;
00298 
00299                 } else if (js[current].rgbButtons[button]) {
00300                         return BUTTON_DOWN;
00301                 }         
00302                 return BUTTON_UP;        
00303         }
00304 
00305         const DIJOYSTATE2* Controller::GetJoystickState() {
00306                 return &jsRaw;
00307         }
00308 
00309         void DXFPollInput() { Controller::Instance()->Poll(); }
00310         eButtonState DXFCheckKeyboard(BYTE key) { return Controller::Instance()->CheckKeyboard(key); }
00311         void DXFGetBufferedInput(std::wstring& input) { Controller::Instance()->GetBufferedInput(input); }
00312         eButtonState DXFCheckMouse(eMouseButton button) { return Controller::Instance()->CheckMouse(button); }
00313         int DXFGetMouseWheelDelta() { return Controller::Instance()->GetMouseWheelDelta(); }
00314         POINT DXFGetMousePosition() { return Controller::Instance()->GetMousePosition(); }
00315         const JoystickCaps* DXFGetJoystickCapabilities() { return &g_JoystickCaps; }
00316         eButtonState DXFCheckJoystick(int button) { return Controller::Instance()->CheckJoystick(button); }
00317         const DIJOYSTATE2* DXFGetJoystickState() { return Controller::Instance()->GetJoystickState(); }
00318 } // namespace dxf

Generated on Fri Aug 18 12:01:27 2006 for DXFramework by  doxygen 1.4.7