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