00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright © 2000-2002 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 #include "OgreWin32Input8.h" 00026 #include "OgreRenderWindow.h" 00027 #include "OgreLogManager.h" 00028 #include "OgreException.h" 00029 #include "OgreRoot.h" 00030 #include "OgreRenderSystem.h" 00031 #include "OgreMouseEvent.h" 00032 #include "OgreInputEvent.h" 00033 #include "OgreEventQueue.h" 00034 #include "OgreCursor.h" 00035 #include <dxerr8.h> 00036 00037 #define DINPUT_BUFFERSIZE 16 00038 //#define DIPROP_BUFFERSIZE 256 00039 00040 namespace Ogre { 00041 //----------------------------------------------------------------------- 00042 Win32Input8::Win32Input8() : 00043 InputReader() 00044 { 00045 mlpDI = 0; 00046 mlpDIKeyboard = 0; 00047 mlpDIMouse = 0; 00048 mEventQueue = 0; 00049 mScale = 0.001; 00050 00051 memset(mKeyboardBuffer,0,256); 00052 } 00053 //----------------------------------------------------------------------- 00054 Win32Input8::~Win32Input8() 00055 { 00056 // Shutdown 00057 if (mlpDIKeyboard) 00058 { 00059 mlpDIKeyboard->Unacquire(); 00060 mlpDIKeyboard->Release(); 00061 mlpDIKeyboard = 0; 00062 } 00063 if (mlpDIMouse) 00064 { 00065 mlpDIMouse->Unacquire(); 00066 mlpDIMouse->Release(); 00067 mlpDIMouse = 0; 00068 } 00069 if (mlpDI) 00070 { 00071 mlpDI->Release(); 00072 mlpDI = 0; 00073 } 00074 00075 } 00076 00077 //----------------------------------------------------------------------- 00078 void Win32Input8::initialiseBufferedKeyboard() 00079 { 00080 00081 HRESULT hr; 00082 LogManager::getSingleton().logMessage("Win32Input8: Establishing keyboard input."); 00083 00084 // Create keyboard device 00085 hr = mlpDI->CreateDevice(GUID_SysKeyboard, &mlpDIKeyboard, NULL); 00086 00087 00088 if (FAILED(hr)) 00089 throw Exception(hr, "Unable to create DirectInput keyboard device.", 00090 "Win32Input8 - initialise"); 00091 00092 // Set data format 00093 hr = mlpDIKeyboard->SetDataFormat(&c_dfDIKeyboard); 00094 if (FAILED(hr)) 00095 throw Exception(hr, "Unable to set DirectInput keyboard device data format.", 00096 "Win32Input8 - initialise"); 00097 00098 // Make the window grab keyboard behaviour when foreground 00099 hr = mlpDIKeyboard->SetCooperativeLevel(mHWnd, 00100 DISCL_FOREGROUND | DISCL_EXCLUSIVE); 00101 if (FAILED(hr)) 00102 throw Exception(hr, "Unable to set DirectInput keyboard device co-operative level.", 00103 "Win32Input8 - initialise"); 00104 00105 00106 // IMPORTANT STEP TO USE BUFFERED DEVICE DATA! 00107 // 00108 // DirectInput uses unbuffered I/O (buffer size = 0) by default. 00109 // If you want to read buffered data, you need to set a nonzero 00110 // buffer size. 00111 // 00112 // Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements. 00113 // 00114 // The buffer size is a DWORD property associated with the device. 00115 DIPROPDWORD dipdw; 00116 dipdw.diph.dwSize = sizeof(DIPROPDWORD); 00117 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 00118 dipdw.diph.dwObj = 0; 00119 dipdw.diph.dwHow = DIPH_DEVICE; 00120 dipdw.dwData = DINPUT_BUFFERSIZE; // Arbitary buffer size 00121 00122 hr = mlpDIKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ); 00123 00124 if (FAILED(hr)) 00125 throw Exception(hr, "Unable to create DirectInput keyboard buffer.", 00126 "Win32Input8 - initialise"); 00127 00128 // Acquire input 00129 hr = mlpDIKeyboard->Acquire(); 00130 if (FAILED(hr)) 00131 throw Exception(hr, "Unable to set aquire DirectInput keyboard device.", 00132 "Win32Input8 - initialise"); 00133 00134 LogManager::getSingleton().logMessage("Win32Input8: Keyboard input established."); 00135 } 00136 00137 //----------------------------------------------------------------------- 00138 void Win32Input8::initialiseImmediateKeyboard() 00139 { 00140 HRESULT hr; 00141 LogManager::getSingleton().logMessage("Win32Input8: Establishing keyboard input."); 00142 00143 // Create keyboard device 00144 hr = mlpDI->CreateDevice(GUID_SysKeyboard, &mlpDIKeyboard, NULL); 00145 00146 00147 if (FAILED(hr)) 00148 throw Exception(hr, "Unable to create DirectInput keyboard device.", 00149 "Win32Input8 - initialise"); 00150 00151 // Set data format 00152 hr = mlpDIKeyboard->SetDataFormat(&c_dfDIKeyboard); 00153 if (FAILED(hr)) 00154 throw Exception(hr, "Unable to set DirectInput keyboard device data format.", 00155 "Win32Input8 - initialise"); 00156 00157 // Make the window grab keyboard behaviour when foreground 00158 // NB Keyboard is never exclusive 00159 hr = mlpDIKeyboard->SetCooperativeLevel(mHWnd, 00160 DISCL_BACKGROUND | DISCL_NONEXCLUSIVE); 00161 if (FAILED(hr)) 00162 throw Exception(hr, "Unable to set DirectInput keyboard device co-operative level.", 00163 "Win32Input8 - initialise"); 00164 00165 // IMPORTANT STEP TO USE BUFFERED DEVICE DATA! 00166 // 00167 // DirectInput uses unbuffered I/O (buffer size = 0) by default. 00168 // If you want to read buffered data, you need to set a nonzero 00169 // buffer size. 00170 // 00171 // Set the buffer size to DINPUT_BUFFERSIZE (defined above) elements. 00172 // 00173 // The buffer size is a DWORD property associated with the device. 00174 DIPROPDWORD dipdw; 00175 00176 dipdw.diph.dwSize = sizeof(DIPROPDWORD); 00177 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 00178 dipdw.diph.dwObj = 0; 00179 dipdw.diph.dwHow = DIPH_DEVICE; 00180 dipdw.dwData = DINPUT_BUFFERSIZE ; // Arbitary buffer size 00181 00182 hr = mlpDIKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ; 00183 00184 if (FAILED(hr)) 00185 throw Exception(hr, "Unable to create DirectInput keyboard buffer.", 00186 "Win32Input8 - initialise"); 00187 00188 00189 // Acquire input 00190 hr = mlpDIKeyboard->Acquire(); 00191 if (FAILED(hr)) 00192 throw Exception(hr, "Unable to set aquire DirectInput keyboard device.", 00193 "Win32Input8 - initialise"); 00194 00195 LogManager::getSingleton().logMessage("Win32Input8: Keyboard input established."); 00196 } 00197 //----------------------------------------------------------------------- 00198 void Win32Input8::initialiseImmediateMouse() 00199 { 00200 OgreGuard( "Win32Input8::initialiseImmediateMouse" ); 00201 00202 HRESULT hr; 00203 DIPROPDWORD dipdw; 00204 LogManager::getSingleton().logMessage( "Win32Input8: Initializing mouse input in immediate mode." ); 00205 00206 dipdw.diph.dwSize = sizeof(DIPROPDWORD); 00207 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 00208 dipdw.diph.dwObj = 0; 00209 dipdw.diph.dwHow = DIPH_DEVICE; 00210 dipdw.dwData = DIPROPAXISMODE_ABS; 00211 00212 if( /* Create the DI Device. */ 00213 FAILED( hr = mlpDI->CreateDevice( GUID_SysMouse, &mlpDIMouse, NULL ) ) || 00214 /* Set the data format so that it knows it's a mouse. */ 00215 FAILED( hr = mlpDIMouse->SetDataFormat( &c_dfDIMouse2 ) ) || 00216 /* Absolute mouse input. We can derive the relative input from this. */ 00217 FAILED( hr = mlpDIMouse->SetProperty( DIPROP_AXISMODE, &dipdw.diph ) ) || 00218 /* Exclusive when in foreground, steps back when in background. */ 00219 FAILED( hr = mlpDIMouse->SetCooperativeLevel( mHWnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE ) ) ) 00220 { 00221 Except( hr, "Unable to initialise mouse", "Win32Input8::initialiseImmediateMouse" ); 00222 } 00223 /* Note that we did not acquire the mouse in the code above, since the call may fail (ie you're in the 00224 debugger) and an exception would be thrown. Acquisition happens in the captureMouse() function. */ 00225 00226 /* Get initial mouse data. We might as well fail this initial attempt, so no biggie. */ 00227 captureMouse(); 00228 00229 /* Clear any relative mouse data. */ 00230 mMouseState.Xrel = mMouseState.Yrel = mMouseState.Zrel = 0; 00231 00232 LogManager::getSingleton().logMessage( "Win32Input8: Mouse input in immediate mode initialized." ); 00233 00234 OgreUnguard(); 00235 } 00236 00237 //----------------------------------------------------------------------- 00238 void Win32Input8::initialiseBufferedMouse() 00239 { 00240 HRESULT hr; 00241 LogManager::getSingleton().logMessage("Win32Input8: Establishing mouse input."); 00242 00243 // Create mouse device 00244 hr = mlpDI->CreateDevice(GUID_SysMouse, &mlpDIMouse, NULL); 00245 00246 00247 if (FAILED(hr)) 00248 throw Exception(hr, "Unable to create DirectInput mouse device.", 00249 "Win32Input8 - initialise"); 00250 00251 // Set data format 00252 hr = mlpDIMouse->SetDataFormat(&c_dfDIMouse2); 00253 if (FAILED(hr)) 00254 throw Exception(hr, "Unable to set DirectInput mouse device data format.", 00255 "Win32Input8 - initialise"); 00256 00257 // Make the window grab mouse behaviour when foreground 00258 hr = mlpDIMouse->SetCooperativeLevel(mHWnd, 00259 DISCL_FOREGROUND | DISCL_EXCLUSIVE); 00260 if (FAILED(hr)) 00261 throw Exception(hr, "Unable to set DirectInput mouse device co-operative level.", 00262 "Win32Input8 - initialise"); 00263 00264 00265 // IMPORTANT STEP TO USE BUFFERED DEVICE DATA! 00266 // 00267 // DirectInput uses unbuffered I/O (buffer size = 0) by default. 00268 // If you want to read buffered data, you need to set a nonzero 00269 // buffer size. 00270 // 00271 // Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements. 00272 // 00273 // The buffer size is a DWORD property associated with the device. 00274 DIPROPDWORD dipdw; 00275 dipdw.diph.dwSize = sizeof(DIPROPDWORD); 00276 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 00277 dipdw.diph.dwObj = 0; 00278 dipdw.diph.dwHow = DIPH_DEVICE; 00279 dipdw.dwData = DINPUT_BUFFERSIZE; // Arbitary buffer size 00280 00281 hr = mlpDIMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ); 00282 00283 if (FAILED(hr)) 00284 throw Exception(hr, "Unable to create DirectInput mouse buffer.", 00285 "Win32Input8 - initialise"); 00286 00287 // Acquire input 00288 hr = mlpDIMouse->Acquire(); 00289 if (FAILED(hr)) 00290 throw Exception(hr, "Unable to set aquire DirectInput mouse device.", 00291 "Win32Input8 - initialise"); 00292 00293 LogManager::getSingleton().logMessage("Win32Input8: Mouse input established."); 00294 00295 } 00296 00297 //----------------------------------------------------------------------- 00298 void Win32Input8::initialise(RenderWindow* pWindow, bool useKeyboard, bool useMouse, bool useGameController) 00299 { 00300 HRESULT hr; 00301 00302 mUseKeyboard = useKeyboard; 00303 mUseMouse = useMouse; 00304 LogManager::getSingleton().logMessage("Win32Input8: DirectInput Activation Starts"); 00305 00306 // Get HINST 00307 HINSTANCE hInst = GetModuleHandle("OgrePlatform.dll"); 00308 00309 // Get HWND 00310 HWND hWnd = GetActiveWindow(); 00311 00312 mHWnd = hWnd; 00313 00314 ShowCursor(FALSE); 00315 00316 00317 // Register with the DirectInput subsystem and get a pointer 00318 // to a IDirectInput interface we can use. 00319 // Create a DInput object 00320 hr = DirectInput8Create( hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&mlpDI, NULL ); 00321 if (FAILED(hr)) 00322 throw Exception(hr, "Unable to initialise DirectInput.", 00323 "Win32Input8 - initialise"); 00324 00325 if (useKeyboard) 00326 { 00327 if (mUseBufferedKeys) 00328 { 00329 initialiseBufferedKeyboard(); 00330 } 00331 else 00332 { 00333 initialiseImmediateKeyboard(); 00334 } 00335 } 00336 00337 if (useMouse) 00338 { 00339 if (mUseBufferedMouse) 00340 { 00341 initialiseBufferedMouse(); 00342 } 00343 else 00344 { 00345 initialiseImmediateMouse(); 00346 } 00347 } 00348 00349 00350 LogManager::getSingleton().logMessage("Win32Input8: DirectInput OK."); 00351 00352 } 00353 00354 /* void Win32Input8::setBufferedInput(bool keys, bool mouse) 00355 { 00356 flushAllBuffers(); 00357 InputReader::setBufferedInput(keys, mouse); 00358 } 00359 */ 00360 void Win32Input8::flushAllBuffers() 00361 { 00362 00363 DWORD dwItems = INFINITE; 00364 HRESULT hr = mlpDIKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), 00365 NULL, &dwItems, 0 ); 00366 hr = mlpDIMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), 00367 NULL, &dwItems, 0 ); 00368 } 00369 00370 //----------------------------------------------------------------------- 00371 00372 // this function is not needed at the moment because we are making everything buffered 00373 void Win32Input8::setBufferedInput(bool keys, bool mouse) 00374 { 00375 if (mUseKeyboard && mUseBufferedKeys != keys) 00376 { 00377 if (mlpDIKeyboard) 00378 { 00379 mlpDIKeyboard->Unacquire(); 00380 mlpDIKeyboard->Release(); 00381 mlpDIKeyboard = 0; 00382 } 00383 if (keys) 00384 { 00385 initialiseBufferedKeyboard(); 00386 } 00387 else 00388 { 00389 initialiseImmediateKeyboard(); 00390 } 00391 00392 } 00393 if (mUseMouse && mUseBufferedMouse != mouse) 00394 { 00395 if (mlpDIMouse) 00396 { 00397 mlpDIMouse->Unacquire(); 00398 mlpDIMouse->Release(); 00399 mlpDIMouse= 0; 00400 } 00401 if (mouse) 00402 { 00403 initialiseBufferedMouse(); 00404 } 00405 else 00406 { 00407 initialiseImmediateMouse(); 00408 } 00409 00410 } 00411 InputReader::setBufferedInput(keys,mouse); 00412 } 00413 00414 //----------------------------------------------------------------------- 00415 void Win32Input8::capture(void) 00416 { 00417 if (mUseKeyboard) 00418 { 00419 if (mUseBufferedKeys ) 00420 { 00421 readBufferedKeyboardData(); 00422 } 00423 else 00424 { 00425 mModifiers = getKeyModifiers(); 00426 captureKeyboard(); 00427 } 00428 } 00429 if (mUseMouse) 00430 { 00431 if (mUseBufferedMouse ) 00432 { 00433 readBufferedMouseData(); 00434 } 00435 else 00436 { 00437 captureMouse(); 00438 } 00439 } 00440 00441 } 00442 //----------------------------------------------------------------------- 00443 void Win32Input8::captureKeyboard(void) 00444 { 00445 HRESULT hr; 00446 00447 // Get keyboard state 00448 hr = mlpDIKeyboard->GetDeviceState(sizeof(mKeyboardBuffer),(LPVOID)&mKeyboardBuffer); 00449 if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) 00450 { 00451 hr = mlpDIKeyboard->Acquire(); 00452 if (hr == DIERR_OTHERAPPHASPRIO) 00453 { 00454 hr = 0; 00455 } 00456 else 00457 { 00458 hr = mlpDIKeyboard->GetDeviceState(sizeof(mKeyboardBuffer),(LPVOID)&mKeyboardBuffer); 00459 } 00460 } 00461 else if (hr == DIERR_OTHERAPPHASPRIO) 00462 { 00463 // We've gone into the background - ignore 00464 hr = 0; 00465 } 00466 else if (hr == DIERR_NOTINITIALIZED) 00467 { 00468 hr = 0; 00469 } 00470 else if (hr == E_PENDING) 00471 { 00472 hr = 0; 00473 } 00474 else if (FAILED(hr)) 00475 { 00476 // Ignore for now 00477 // TODO - sort this out 00478 hr = 0; 00479 } 00480 00481 } 00482 00483 //----------------------------------------------------------------------- 00484 void Win32Input8::captureMouse(void) 00485 { 00486 DIMOUSESTATE2 mouseState; 00487 HRESULT hr; 00488 00489 // Get mouse state 00490 hr = mlpDIMouse->GetDeviceState( sizeof( DIMOUSESTATE2 ), (LPVOID)&mouseState ); 00491 00492 if( SUCCEEDED( hr ) || 00493 ( ( hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED ) && 00494 SUCCEEDED( mlpDIMouse->Acquire() ) && 00495 SUCCEEDED( mlpDIMouse->GetDeviceState( sizeof( DIMOUSESTATE2 ), (LPVOID)&mouseState ) ) ) ) 00496 { 00497 /* Register the new 'origin'. */ 00498 mMouseCenterX = mMouseState.Xabs; 00499 mMouseCenterY = mMouseState.Yabs; 00500 mMouseCenterZ = mMouseState.Zabs; 00501 00502 /* Get the new absolute position. */ 00503 mMouseState.Xabs = mouseState.lX; 00504 mMouseState.Yabs = mouseState.lY; 00505 mMouseState.Zabs = mouseState.lZ; 00506 00507 /* Compute the new relative position. */ 00508 mMouseState.Xrel = mMouseState.Xabs - mMouseCenterX; 00509 mMouseState.Yrel = mMouseState.Yabs - mMouseCenterY; 00510 mMouseState.Zrel = mMouseState.Zabs - mMouseCenterZ; 00511 00512 /* Get the mouse buttons. This for loop can be unwrapped for speed. */ 00513 mMouseState.Buttons = 0; 00514 for( size_t i = 0; i < 8; i++ ) 00515 if( mouseState.rgbButtons[ i ] & 0x80 ) 00516 mMouseState.Buttons |= ( 1 << i ); 00517 } 00518 else if (hr == DIERR_OTHERAPPHASPRIO) 00519 { 00520 // We've gone into the background - ignore 00521 hr = 0; 00522 } 00523 else if (hr == DIERR_NOTINITIALIZED) 00524 { 00525 hr = 0; 00526 } 00527 else if (hr == E_PENDING) 00528 { 00529 hr = 0; 00530 } 00531 else if (FAILED(hr)) 00532 { 00533 // Ignore for now 00534 // TODO - sort this out 00535 hr = 0; 00536 } 00537 00538 } 00539 00540 00541 00542 //----------------------------------------------------------------------------- 00543 // Name: readBufferedData() 00544 // Desc: Read the input device's state when in buffered mode and display it. 00545 //----------------------------------------------------------------------------- 00546 bool Win32Input8::readBufferedKeyboardData() 00547 { 00548 DIDEVICEOBJECTDATA didod[ DINPUT_BUFFERSIZE ]; // Receives buffered data 00549 DWORD dwElements; 00550 HRESULT hr; 00551 00552 if( NULL == mlpDIKeyboard ) 00553 return true; 00554 00555 dwElements = DINPUT_BUFFERSIZE; 00556 00557 hr = mlpDIKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), 00558 didod, &dwElements, 0 ); 00559 if( hr != DI_OK ) 00560 { 00561 // We got an error or we got DI_BUFFEROVERFLOW. 00562 // 00563 // Either way, it means that continuous contact with the 00564 // device has been lost, either due to an external 00565 // interruption, or because the buffer overflowed 00566 // and some events were lost. 00567 // 00568 // Consequently, if a button was pressed at the time 00569 // the buffer overflowed or the connection was broken, 00570 // the corresponding "up" message might have been lost. 00571 // 00572 // But since our simple sample doesn't actually have 00573 // any state associated with button up or down events, 00574 // there is no state to reset. (In a real game, ignoring 00575 // the buffer overflow would result in the game thinking 00576 // a key was held down when in fact it isn't; it's just 00577 // that the "up" event got lost because the buffer 00578 // overflowed.) 00579 // 00580 // If we want to be cleverer, we could do a 00581 // GetDeviceState() and compare the current state 00582 // against the state we think the device is in, 00583 // and process all the states that are currently 00584 // different from our private state. 00585 hr = mlpDIKeyboard->Acquire(); 00586 while( hr == DIERR_INPUTLOST ) 00587 hr = mlpDIKeyboard->Acquire(); 00588 00589 // Update the dialog text 00590 /* if( hr == DIERR_OTHERAPPHASPRIO || 00591 hr == DIERR_NOTACQUIRED ) 00592 SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") ); 00593 */ 00594 // hr may be DIERR_OTHERAPPHASPRIO or other errors. This 00595 // may occur when the app is minimized or in the process of 00596 // switching, so just try again later 00597 return S_OK; 00598 } 00599 00600 if( FAILED(hr) ) 00601 return false; 00602 00603 for(unsigned int i = 0; i < dwElements; i++ ) 00604 { 00605 keyChanged( didod[ i ].dwOfs, (didod[ i ].dwData & 0x80) != 0); 00606 } 00607 return true; 00608 } 00609 00610 //----------------------------------------------------------------------------- 00611 // Name: readBufferedData() 00612 // Desc: Read the input device's state when in buffered mode and display it. 00613 //----------------------------------------------------------------------------- 00614 bool Win32Input8::readBufferedMouseData() 00615 { 00616 DIDEVICEOBJECTDATA didod[ DINPUT_BUFFERSIZE ]; // Receives buffered data 00617 DWORD dwElements; 00618 HRESULT hr; 00619 00620 if( NULL == mlpDIMouse ) 00621 return true; 00622 00623 dwElements = DINPUT_BUFFERSIZE; 00624 00625 hr = mlpDIMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), 00626 didod, &dwElements, 0 ); 00627 if( hr != DI_OK ) 00628 { 00629 // We got an error or we got DI_BUFFEROVERFLOW. 00630 // 00631 // Either way, it means that continuous contact with the 00632 // device has been lost, either due to an external 00633 // interruption, or because the buffer overflowed 00634 // and some events were lost. 00635 // 00636 // Consequently, if a button was pressed at the time 00637 // the buffer overflowed or the connection was broken, 00638 // the corresponding "up" message might have been lost. 00639 // 00640 // But since our simple sample doesn't actually have 00641 // any state associated with button up or down events, 00642 // there is no state to reset. (In a real game, ignoring 00643 // the buffer overflow would result in the game thinking 00644 // a key was held down when in fact it isn't; it's just 00645 // that the "up" event got lost because the buffer 00646 // overflowed.) 00647 // 00648 // If we want to be cleverer, we could do a 00649 // GetDeviceState() and compare the current state 00650 // against the state we think the device is in, 00651 // and process all the states that are currently 00652 // different from our private state. 00653 hr = mlpDIMouse->Acquire(); 00654 while( hr == DIERR_INPUTLOST ) 00655 hr = mlpDIMouse->Acquire(); 00656 00657 // Update the dialog text 00658 /* if( hr == DIERR_OTHERAPPHASPRIO || 00659 hr == DIERR_NOTACQUIRED ) 00660 SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") ); 00661 */ 00662 // hr may be DIERR_OTHERAPPHASPRIO or other errors. This 00663 // may occur when the app is minimized or in the process of 00664 // switching, so just try again later 00665 return S_OK; 00666 } 00667 00668 if( FAILED(hr) ) 00669 return false; 00670 00671 bool xSet = false; 00672 bool ySet = false; 00673 bool zSet = false; 00674 00675 for(unsigned int i = 0; i < dwElements; i++ ) 00676 { 00677 int nMouseCode = -1; // not set 00678 00679 // this will display then scan code of the key 00680 // plus a 'D' - meaning the key was pressed 00681 // or a 'U' - meaning the key was released 00682 switch( didod [ i ].dwOfs ) 00683 { 00684 case DIMOFS_BUTTON0: 00685 nMouseCode = InputEvent::BUTTON0_MASK; 00686 break; 00687 00688 case DIMOFS_BUTTON1: 00689 nMouseCode = InputEvent::BUTTON1_MASK; 00690 break; 00691 00692 case DIMOFS_BUTTON2: 00693 nMouseCode = InputEvent::BUTTON2_MASK; 00694 break; 00695 00696 case DIMOFS_BUTTON3: 00697 nMouseCode = InputEvent::BUTTON3_MASK; 00698 break; 00699 00700 case DIMOFS_X: 00701 if (xSet) 00702 { // process the last X move since we have a new one 00703 mouseMoved(); 00704 xSet = false; 00705 } 00706 mCursor->addToX(getScaled(didod[i].dwData)); 00707 xSet = true; 00708 break; 00709 00710 case DIMOFS_Y: 00711 if (ySet) 00712 { 00713 mouseMoved(); 00714 ySet = false; 00715 } 00716 mCursor->addToY(getScaled(didod[i].dwData)); 00717 ySet = true; 00718 break; 00719 00720 case DIMOFS_Z: 00721 if (zSet) 00722 { 00723 mouseMoved(); 00724 zSet = false; 00725 } 00726 mCursor->addToZ(getScaled(didod[i].dwData)); 00727 zSet = true; 00728 break; 00729 00730 default: 00731 break; 00732 } 00733 if (nMouseCode != -1) 00734 { 00735 triggerMouseButton(nMouseCode, (didod [ i ].dwData & 0x80) != 0); 00736 } 00737 if (xSet && ySet) // don't create 2 mousemove events for an single X and Y move, just create 1. 00738 { 00739 mouseMoved(); 00740 ySet = false; 00741 xSet = false; 00742 } 00743 00744 00745 } 00746 if (zSet || xSet || ySet) // check for last moved at end 00747 { 00748 mouseMoved(); 00749 } 00750 00751 return true; 00752 } 00753 //----------------------------------------------------------------------- 00754 00755 Real Win32Input8::getScaled(DWORD dwVal) const 00756 { 00757 return (Real)((int)dwVal) * mScale; 00758 } 00759 00760 //----------------------------------------------------------------------- 00761 bool Win32Input8::isKeyDown(KeyCode kc) const 00762 { 00763 return ( mKeyboardBuffer[ kc ] & 0x80 ) != 0; 00764 } 00765 00766 //--------------------------------------------------------------------------------------------- 00767 long Win32Input8::getMouseRelX() const 00768 { 00769 return mMouseState.Xrel; 00770 } 00771 00772 //--------------------------------------------------------------------------------------------- 00773 long Win32Input8::getMouseRelY() const 00774 { 00775 return mMouseState.Yrel; 00776 } 00777 00778 //--------------------------------------------------------------------------------------------- 00779 long Win32Input8::getMouseRelZ() const 00780 { 00781 return mMouseState.Zrel; 00782 } 00783 00784 long Win32Input8::getMouseAbsX() const 00785 { 00786 return mMouseState.Xabs; 00787 } 00788 00789 long Win32Input8::getMouseAbsY() const 00790 { 00791 return mMouseState.Yabs; 00792 } 00793 00794 long Win32Input8::getMouseAbsZ() const 00795 { 00796 return mMouseState.Zabs; 00797 } 00798 00799 //--------------------------------------------------------------------------------------------- 00800 bool Win32Input8::getMouseButton( uchar button ) const 00801 { 00802 return mMouseState.isButtonDown( button ) != 0; 00803 } 00804 00805 //--------------------------------------------------------------------------------------------- 00806 void Win32Input8::getMouseState( MouseState& state ) const 00807 { 00808 memcpy( &state, &mMouseState, sizeof( MouseState ) ); 00809 } 00810 00811 //--------------------------------------------------------------------------------------------- 00812 long Win32Input8::getKeyModifiers() const 00813 { 00814 long ret = mModifiers; 00815 00816 if (mModifiers == 16) 00817 { 00818 int x=5; 00819 00820 } 00821 00822 if (isKeyDown(KC_LMENU) || isKeyDown(KC_RMENU)) 00823 { 00824 ret |= InputEvent::ALT_MASK; 00825 } 00826 else 00827 { 00828 ret &= ~InputEvent::ALT_MASK; 00829 } 00830 00831 if (isKeyDown(KC_LSHIFT) || isKeyDown(KC_RSHIFT)) 00832 { 00833 ret |= InputEvent::SHIFT_MASK; 00834 } 00835 else 00836 { 00837 ret &= ~InputEvent::SHIFT_MASK; 00838 } 00839 00840 if (isKeyDown(KC_LCONTROL) || isKeyDown(KC_LCONTROL)) 00841 { 00842 ret |= InputEvent::CTRL_MASK; 00843 } 00844 else 00845 { 00846 ret &= ~InputEvent::CTRL_MASK; 00847 } 00848 00849 return ret; 00850 } 00851 00852 } // namespace
Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:55 2004