#include "ASW_Input_DX.H" #define DX_CHECK(result) if (FAILED(result)) throw InputDX::Exception(__FILE__, __LINE__, __FUNCTION__, NULL, result) InputDX::Exception:: Exception(const char * p_ptrFile, const unsigned int p_uintLine, const char * p_ptrFunction, const char * p_ptrDetail, const HRESULT p_hndError) : ASW::Exception(p_ptrFile, p_uintLine, p_ptrFunction, p_ptrDetail), m_hndError(p_hndError) {} void InputDX::Exception:: Print(UTIL::Output & p_clsOutput) { char * ptrBuffer; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, m_hndError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)(&ptrBuffer), 0, NULL); p_clsOutput.Printf("An error has occurred with DirectInput.\n\nFile: [%s]\nLine: [%i]\nFunction: [%s]\nDetail: [%s]\nError: [%s]", ( m_ptrFile != NULL ) ? m_ptrFile : "unknown", m_uintLine, ( m_ptrFunction != NULL ) ? m_ptrFunction : "unknown", ( m_ptrDetail != NULL ) ? m_ptrDetail : "none", ptrBuffer); LocalFree(ptrBuffer); } const char * InputDX::Exception:: Type() { return "DirectInput"; } inline ASW::Input::KeyType ConvertMouseKey(const DWORD p_enmMouseKey) { switch ( p_enmMouseKey ) { case DIMOFS_BUTTON0: return ASW::Input::KEY_MB0; case DIMOFS_BUTTON1: return ASW::Input::KEY_MB1; case DIMOFS_BUTTON2: return ASW::Input::KEY_MB2; case DIMOFS_BUTTON3: return ASW::Input::KEY_MB3; case DIMOFS_BUTTON4: return ASW::Input::KEY_MB4; case DIMOFS_BUTTON5: return ASW::Input::KEY_MB5; case DIMOFS_BUTTON6: return ASW::Input::KEY_MB6; case DIMOFS_BUTTON7: return ASW::Input::KEY_MB7; default: return ASW::Input::KEY_UNKNOWN; } } ASW::Input::KeyType InputDX::m_enmDirectXKeys[256]; InputDX:: InputDX(WindowW32 & p_clsWindow) : m_ptrManager(NULL), m_ptrMouse(NULL), m_ptrKeyboard(NULL) { try { // // Create the base input object // HRESULT hndResult = DirectInput8Create(p_clsWindow.GetInstance(), DIRECTINPUT_VERSION, IID_IDirectInput8, (void **)(&m_ptrManager), NULL); DX_CHECK(hndResult); // // Create and initialize the keyboard object // hndResult = m_ptrManager->CreateDevice(GUID_SysKeyboard, &m_ptrKeyboard, NULL); DX_CHECK(hndResult); // // Set properties on the keyboard object // DIPROPDWORD stuBufferSize; stuBufferSize.diph.dwHeaderSize = sizeof(DIPROPHEADER); stuBufferSize.diph.dwSize = sizeof(DIPROPDWORD); stuBufferSize.diph.dwObj = 0; stuBufferSize.diph.dwHow = DIPH_DEVICE; stuBufferSize.dwData = BUFFER_SIZE; hndResult = m_ptrKeyboard->SetProperty(DIPROP_BUFFERSIZE, &stuBufferSize.diph); DX_CHECK(hndResult); hndResult = m_ptrKeyboard->SetDataFormat(&c_dfDIKeyboard); DX_CHECK(hndResult); hndResult = m_ptrKeyboard->SetCooperativeLevel(p_clsWindow.GetWindow(), DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); DX_CHECK(hndResult); // // Create and initialize the mouse object // hndResult = m_ptrManager->CreateDevice(GUID_SysMouse, &m_ptrMouse, NULL); DX_CHECK(hndResult); // // Set properties on the mouse object // hndResult = m_ptrMouse->SetProperty(DIPROP_BUFFERSIZE, &stuBufferSize.diph); DX_CHECK(hndResult); hndResult = m_ptrMouse->SetDataFormat(&c_dfDIMouse); DX_CHECK(hndResult); hndResult = m_ptrMouse->SetCooperativeLevel(p_clsWindow.GetWindow(), DISCL_FOREGROUND | DISCL_EXCLUSIVE); DX_CHECK(hndResult); } catch ( ... ) { if ( m_ptrMouse ) m_ptrMouse->Release(); if ( m_ptrKeyboard ) m_ptrKeyboard->Release(); if ( m_ptrManager ) m_ptrManager->Release(); throw; } InputDX::InitKeys(); } /* Keyboard, mouse, and the main DirectInput objects are destroyed here */ InputDX:: ~InputDX() { if ( m_ptrMouse ) m_ptrMouse->Release(); if ( m_ptrKeyboard ) m_ptrKeyboard->Release(); if ( m_ptrManager ) m_ptrManager->Release(); } /* Attempts to get focus of the mouse and keyboard, i.e. when a user alt+tabs */ bool InputDX:: Acquire() { HRESULT hndResultMouse = m_ptrMouse->Acquire(); HRESULT hndResultKeyboard = m_ptrKeyboard->Acquire(); return ( (hndResultMouse == DI_OK || hndResultMouse == S_FALSE) && (hndResultKeyboard == DI_OK || hndResultKeyboard == S_FALSE) ); } void InputDX:: InitKeys() { m_enmDirectXKeys[DIK_0] = ASW::Input::KEY_0; m_enmDirectXKeys[DIK_1] = ASW::Input::KEY_1; m_enmDirectXKeys[DIK_2] = ASW::Input::KEY_2; m_enmDirectXKeys[DIK_3] = ASW::Input::KEY_3; m_enmDirectXKeys[DIK_4] = ASW::Input::KEY_4; m_enmDirectXKeys[DIK_5] = ASW::Input::KEY_5; m_enmDirectXKeys[DIK_6] = ASW::Input::KEY_6; m_enmDirectXKeys[DIK_7] = ASW::Input::KEY_7; m_enmDirectXKeys[DIK_8] = ASW::Input::KEY_8; m_enmDirectXKeys[DIK_9] = ASW::Input::KEY_9; m_enmDirectXKeys[DIK_A] = ASW::Input::KEY_A; m_enmDirectXKeys[DIK_ADD] = ASW::Input::KEY_KEYPAD_ADD; m_enmDirectXKeys[DIK_APOSTROPHE] = ASW::Input::KEY_QUOTE; m_enmDirectXKeys[DIK_B] = ASW::Input::KEY_B; m_enmDirectXKeys[DIK_BACK] = ASW::Input::KEY_BACKSPACE; m_enmDirectXKeys[DIK_BACKSLASH] = ASW::Input::KEY_BACKSLASH; m_enmDirectXKeys[DIK_C] = ASW::Input::KEY_C; m_enmDirectXKeys[DIK_CAPITAL] = ASW::Input::KEY_CAPSLOCK; m_enmDirectXKeys[DIK_COMMA] = ASW::Input::KEY_COMMA; m_enmDirectXKeys[DIK_D] = ASW::Input::KEY_D; m_enmDirectXKeys[DIK_DECIMAL] = ASW::Input::KEY_KEYPAD_PERIOD; m_enmDirectXKeys[DIK_DELETE] = ASW::Input::KEY_DELETE; m_enmDirectXKeys[DIK_DIVIDE] = ASW::Input::KEY_KEYPAD_DIVIDE; m_enmDirectXKeys[DIK_DOWN] = ASW::Input::KEY_DOWN; m_enmDirectXKeys[DIK_E] = ASW::Input::KEY_E; m_enmDirectXKeys[DIK_END] = ASW::Input::KEY_END; m_enmDirectXKeys[DIK_EQUALS] = ASW::Input::KEY_EQUALS; m_enmDirectXKeys[DIK_ESCAPE] = ASW::Input::KEY_ESCAPE; m_enmDirectXKeys[DIK_F] = ASW::Input::KEY_F; m_enmDirectXKeys[DIK_F1] = ASW::Input::KEY_F1; m_enmDirectXKeys[DIK_F2] = ASW::Input::KEY_F2; m_enmDirectXKeys[DIK_F3] = ASW::Input::KEY_F3; m_enmDirectXKeys[DIK_F4] = ASW::Input::KEY_F4; m_enmDirectXKeys[DIK_F5] = ASW::Input::KEY_F5; m_enmDirectXKeys[DIK_F6] = ASW::Input::KEY_F6; m_enmDirectXKeys[DIK_F7] = ASW::Input::KEY_F7; m_enmDirectXKeys[DIK_F8] = ASW::Input::KEY_F8; m_enmDirectXKeys[DIK_F9] = ASW::Input::KEY_F9; m_enmDirectXKeys[DIK_F10] = ASW::Input::KEY_F10; m_enmDirectXKeys[DIK_F11] = ASW::Input::KEY_F11; m_enmDirectXKeys[DIK_F12] = ASW::Input::KEY_F12; m_enmDirectXKeys[DIK_G] = ASW::Input::KEY_G; m_enmDirectXKeys[DIK_GRAVE] = ASW::Input::KEY_ACCENT; m_enmDirectXKeys[DIK_H] = ASW::Input::KEY_H; m_enmDirectXKeys[DIK_HOME] = ASW::Input::KEY_HOME; m_enmDirectXKeys[DIK_I] = ASW::Input::KEY_I; m_enmDirectXKeys[DIK_INSERT] = ASW::Input::KEY_INSERT; m_enmDirectXKeys[DIK_J] = ASW::Input::KEY_J; m_enmDirectXKeys[DIK_K] = ASW::Input::KEY_K; m_enmDirectXKeys[DIK_L] = ASW::Input::KEY_L; m_enmDirectXKeys[DIK_LBRACKET] = ASW::Input::KEY_BRACKETL; m_enmDirectXKeys[DIK_LCONTROL] = ASW::Input::KEY_CONTROLL; m_enmDirectXKeys[DIK_LEFT] = ASW::Input::KEY_LEFT; m_enmDirectXKeys[DIK_LMENU] = ASW::Input::KEY_ALTL; m_enmDirectXKeys[DIK_LSHIFT] = ASW::Input::KEY_SHIFTL; m_enmDirectXKeys[DIK_LWIN] = ASW::Input::KEY_WINDOWSL; m_enmDirectXKeys[DIK_M] = ASW::Input::KEY_M; m_enmDirectXKeys[DIK_MINUS] = ASW::Input::KEY_MINUS; m_enmDirectXKeys[DIK_MULTIPLY] = ASW::Input::KEY_KEYPAD_MULTIPLY; m_enmDirectXKeys[DIK_NUMLOCK] = ASW::Input::KEY_KEYPAD_NUMLOCK; m_enmDirectXKeys[DIK_NUMPAD0] = ASW::Input::KEY_KEYPAD_0; m_enmDirectXKeys[DIK_NUMPAD1] = ASW::Input::KEY_KEYPAD_1; m_enmDirectXKeys[DIK_NUMPAD2] = ASW::Input::KEY_KEYPAD_2; m_enmDirectXKeys[DIK_NUMPAD3] = ASW::Input::KEY_KEYPAD_3; m_enmDirectXKeys[DIK_NUMPAD4] = ASW::Input::KEY_KEYPAD_4; m_enmDirectXKeys[DIK_NUMPAD5] = ASW::Input::KEY_KEYPAD_5; m_enmDirectXKeys[DIK_NUMPAD6] = ASW::Input::KEY_KEYPAD_6; m_enmDirectXKeys[DIK_NUMPAD7] = ASW::Input::KEY_KEYPAD_7; m_enmDirectXKeys[DIK_NUMPAD8] = ASW::Input::KEY_KEYPAD_8; m_enmDirectXKeys[DIK_NUMPAD9] = ASW::Input::KEY_KEYPAD_9; m_enmDirectXKeys[DIK_NUMPADENTER] = ASW::Input::KEY_KEYPAD_ENTER; m_enmDirectXKeys[DIK_O] = ASW::Input::KEY_O; m_enmDirectXKeys[DIK_P] = ASW::Input::KEY_P; m_enmDirectXKeys[DIK_PAUSE] = ASW::Input::KEY_PAUSE; m_enmDirectXKeys[DIK_PERIOD] = ASW::Input::KEY_PERIOD; m_enmDirectXKeys[DIK_PRIOR] = ASW::Input::KEY_PAGEUP; m_enmDirectXKeys[DIK_Q] = ASW::Input::KEY_Q; m_enmDirectXKeys[DIK_R] = ASW::Input::KEY_R; m_enmDirectXKeys[DIK_RBRACKET] = ASW::Input::KEY_BRACKETR; m_enmDirectXKeys[DIK_RCONTROL] = ASW::Input::KEY_CONTROLR; m_enmDirectXKeys[DIK_RETURN] = ASW::Input::KEY_ENTER; m_enmDirectXKeys[DIK_RIGHT] = ASW::Input::KEY_RIGHT; m_enmDirectXKeys[DIK_RMENU] = ASW::Input::KEY_ALTR; m_enmDirectXKeys[DIK_RSHIFT] = ASW::Input::KEY_SHIFTR; m_enmDirectXKeys[DIK_RWIN] = ASW::Input::KEY_WINDOWSR; m_enmDirectXKeys[DIK_S] = ASW::Input::KEY_S; m_enmDirectXKeys[DIK_SCROLL] = ASW::Input::KEY_SCRLCK; m_enmDirectXKeys[DIK_SEMICOLON] = ASW::Input::KEY_SEMICOLON; m_enmDirectXKeys[DIK_SLASH] = ASW::Input::KEY_FORWARDSLASH; m_enmDirectXKeys[DIK_SPACE] = ASW::Input::KEY_SPACE; m_enmDirectXKeys[DIK_SUBTRACT] = ASW::Input::KEY_KEYPAD_SUBTRACT; m_enmDirectXKeys[DIK_T] = ASW::Input::KEY_T; m_enmDirectXKeys[DIK_TAB] = ASW::Input::KEY_TAB; m_enmDirectXKeys[DIK_U] = ASW::Input::KEY_U; m_enmDirectXKeys[DIK_UP] = ASW::Input::KEY_UP; m_enmDirectXKeys[DIK_V] = ASW::Input::KEY_V; m_enmDirectXKeys[DIK_W] = ASW::Input::KEY_W; m_enmDirectXKeys[DIK_X] = ASW::Input::KEY_X; m_enmDirectXKeys[DIK_Y] = ASW::Input::KEY_Y; m_enmDirectXKeys[DIK_Z] = ASW::Input::KEY_Z; } /* Here the device data is queried It is important to call this method every so often (via the Get() method of Input), or else action array will keep filling up with state changes. */ bool InputDX:: Sync(ASW::Input::KeyChange * p_ptrChanges, unsigned int & p_uintAmount, ASW::Point3i & p_stuMouseMovement) { // // Get mouse device data // unsigned long ulngMouseSize = BUFFER_SIZE; HRESULT hndResultMouse = m_ptrMouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &(m_stuDataMouse[0]), &ulngMouseSize, 0); // // Get keyboard device data // unsigned long ulngKeyboardSize = BUFFER_SIZE; HRESULT hndResultKeyboard = m_ptrKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &(m_stuDataKeyboard[0]), &ulngKeyboardSize, 0); if ( FAILED(hndResultMouse) || FAILED(hndResultKeyboard) ) return false; /*{ return ( (hndResultMouse == DIERR_INPUTLOST && hndResultKeyboard == DIERR_INPUTLOST) || (hndResultMouse == DIERR_INPUTLOST && SUCCEEDED(hndResultKeyboard)) || (hndResultKeyboard == DIERR_INPUTLOST && SUCCEEDED(hndResultMouse)) ) ? ASW::Input::SYNC_RESULT_LOST : ASW::Input::SYNC_RESULT_ERROR; }*/ // // Insert the input events into the array, being mindful of the time they occured // unsigned int uintAmount = 0; unsigned long ulngMouseIndex = 0; unsigned long ulngKeyboardIndex = 0; ASW::Input::KeyType enmMouseKey = ASW::Input::KEY_UNKNOWN; while ( ulngMouseIndex < ulngMouseSize && ulngKeyboardIndex < ulngKeyboardSize ) { if ( m_stuDataMouse[ulngMouseIndex].dwOfs == DIMOFS_X ) p_stuMouseMovement[0] += m_stuDataMouse[ulngMouseIndex++].dwData; else if ( m_stuDataMouse[ulngMouseIndex].dwOfs == DIMOFS_Y ) p_stuMouseMovement[1] += m_stuDataMouse[ulngMouseIndex++].dwData; else if ( m_stuDataMouse[ulngMouseIndex].dwOfs == DIMOFS_Z ) p_stuMouseMovement[2] += m_stuDataMouse[ulngMouseIndex++].dwData; else { if ( enmMouseKey == ASW::Input::KEY_UNKNOWN ) { enmMouseKey = ConvertMouseKey(m_stuDataMouse[ulngMouseIndex].dwOfs); if ( enmMouseKey == ASW::Input::KEY_UNKNOWN ) { ulngMouseIndex++; continue; } } if ( m_ptrActionIndices[m_enmDirectXKeys[m_stuDataKeyboard[ulngKeyboardIndex].dwOfs]] == NULL ) ulngKeyboardIndex++; else if ( m_ptrActionIndices[enmMouseKey] == NULL ) { enmMouseKey = ASW::Input::KEY_UNKNOWN; ulngMouseIndex++; } else if ( DISEQUENCE_COMPARE(m_stuDataMouse[ulngMouseIndex].dwSequence, <, m_stuDataKeyboard[ulngKeyboardIndex].dwSequence)) { p_ptrChanges[uintAmount].m_blnDown = ( (m_stuDataMouse[ulngMouseIndex].dwData & 0x80) != 0 ); p_ptrChanges[uintAmount].m_enmKey = enmMouseKey; enmMouseKey = ASW::Input::KEY_UNKNOWN; ulngMouseIndex++; } else { p_ptrChanges[uintAmount].m_enmKey = m_enmDirectXKeys[m_stuDataKeyboard[ulngKeyboardIndex].dwOfs]; p_ptrChanges[uintAmount].m_blnDown = ( (m_stuDataKeyboard[ulngKeyboardIndex].dwData & 0x80) != 0 ); ulngKeyboardIndex++; uintAmount++; } } } while ( ulngMouseIndex < ulngMouseSize ) { if ( m_stuDataMouse[ulngMouseIndex].dwOfs == DIMOFS_X ) p_stuMouseMovement[0] += m_stuDataMouse[ulngMouseIndex].dwData; else if ( m_stuDataMouse[ulngMouseIndex].dwOfs == DIMOFS_Y ) p_stuMouseMovement[1] += m_stuDataMouse[ulngMouseIndex].dwData; else if ( m_stuDataMouse[ulngMouseIndex].dwOfs == DIMOFS_Z ) p_stuMouseMovement[2] += m_stuDataMouse[ulngMouseIndex].dwData; else { if ( enmMouseKey == ASW::Input::KEY_UNKNOWN ) { enmMouseKey = ConvertMouseKey(m_stuDataMouse[ulngMouseIndex].dwOfs); if ( enmMouseKey == ASW::Input::KEY_UNKNOWN ) { ulngMouseIndex++; continue; } } if ( m_ptrActionIndices[enmMouseKey] ) { p_ptrChanges[uintAmount].m_blnDown = ( (m_stuDataMouse[ulngMouseIndex].dwData & 0x80) != 0 ); p_ptrChanges[uintAmount].m_enmKey = enmMouseKey; enmMouseKey = ASW::Input::KEY_UNKNOWN; uintAmount++; } } ulngMouseIndex++; } while ( ulngKeyboardIndex < ulngKeyboardSize ) { if ( m_ptrActionIndices[m_enmDirectXKeys[m_stuDataKeyboard[ulngKeyboardIndex].dwOfs]] ) { p_ptrChanges[uintAmount].m_enmKey = m_enmDirectXKeys[m_stuDataKeyboard[ulngKeyboardIndex].dwOfs]; p_ptrChanges[uintAmount].m_blnDown = ( (((char *)(&(m_stuDataKeyboard[ulngKeyboardIndex].dwData)))[0] & 0x80) != 0 ); uintAmount++; } ulngKeyboardIndex++; } p_uintAmount = uintAmount; return true; }