#include "ASW.h" #ifdef WIN32 /* MS_Input implements Input using the standard Microsoft Windows mechanism of a WndProc() method to recieve messages from the operating system. Refer to comments in the individual class methods for more details. */ class MS_Input : public ASW::Input { private: bool m_blnMouse; bool m_blnRecievedQuit; char m_chrFocusState; UTIL::DN::Point m_stuMousePos; UTIL::DN::Point m_stuMouseDelta; UTIL::ArrayEx m_clsKeys; WNDPROC m_ftnWndProc; LONG_PTR m_lngOldValue; ASW::Window * m_ptrWindow; static const KeyType m_enmMsInputKeys[('z' - 'a') + 1]; static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); protected: virtual bool Sync(ASW::Input::KeyChange * Changes, unsigned int & Amount, ASW::Point3i & MouseMovement); public: MS_Input(); ~MS_Input(); virtual bool Acquire(void); virtual bool Init(ASW::Window * WindowRef); virtual void Finish(void); }; const ASW::Input::KeyType MS_Input::m_enmMsInputKeys[('z' - 'a') + 1] = { KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, }; MS_Input:: MS_Input() : m_blnRecievedQuit(false), m_blnMouse(false), m_stuMouseDelta(0), m_ftnWndProc(NULL), m_lngOldValue(0), m_ptrWindow(NULL) { } MS_Input:: ~MS_Input() { Finish(); } /* Aquiring is simply grabbing the focus, after which we should start recieving messages via WndProc() */ bool MS_Input:: Acquire(void) { return m_ptrWindow->Focus(); } /* During initialization, both the WndProc() routine and the 'user data' of the window are saved, and overwritten with our own values. Our own 'user data' is simply a pointer to 'this', which we retrieve again in our WndProc() and use to access member variables (see the WndProc() method below). Our mechanism of saving the current 'user data' and WndProc() and calling it for messages we don't handle is overkill and can probably be commented out or conditionally ignored. Oh well, I'll think about it later */ bool MS_Input:: Init(ASW::Window * p_ptrWindow) { m_ptrWindow = p_ptrWindow; HWND hndWindow = (HWND)(p_ptrWindow->GetWindow()); m_ftnWndProc = (WNDPROC)(GetWindowLongPtr(hndWindow, GWLP_WNDPROC)); m_lngOldValue = GetWindowLongPtr(hndWindow, GWLP_USERDATA); SetWindowLongPtr(hndWindow, GWLP_USERDATA, (long)(this)); SetWindowLongPtr(hndWindow, GWLP_WNDPROC, (long)(WndProc)); return true; } /* Old WndProc() and 'user data' are restored */ void MS_Input:: Finish(void) { m_clsKeys.Finish(); if ( m_ptrWindow != NULL ) { SetWindowLongPtr((HWND)(m_ptrWindow->GetWindow()), GWLP_USERDATA, m_lngOldValue); SetWindowLongPtr((HWND)(m_ptrWindow->GetWindow()), GWLP_WNDPROC, (long)(m_ftnWndProc)); m_ptrWindow = NULL; } } /* Standard WndProc() routine as required by Windows programs. State changes (i.e. mouse and keyboard changes) are inserted into the m_clsKeys variable and the Sync() method removes them. It follows that it is important for Sync() to be called (via the Get() method of Input), or else state changes will continue to pile up here */ LRESULT CALLBACK MS_Input:: WndProc(HWND p_hndWindow, UINT p_uintMsg, WPARAM p_wParam, LPARAM p_lParam) { // // A pointer to 'this' is stored in the 'user data' of the window (see // the Init() method) // MS_Input * ptrInput = (MS_Input *)(GetWindowLongPtr(p_hndWindow, GWLP_USERDATA)); if ( ptrInput == NULL ) return DefWindowProc(p_hndWindow, p_uintMsg, p_wParam, p_lParam); // // Check the message type // ASW::Input::KeyChange stuKey; stuKey.m_enmKey = ASW::Input::KEY_UNKNOWN; switch ( p_uintMsg ) { case WM_LBUTTONDOWN: stuKey.m_enmKey = ASW::Input::KEY_MB0; stuKey.m_blnDown = true; break; case WM_LBUTTONUP: stuKey.m_enmKey = ASW::Input::KEY_MB0; stuKey.m_blnDown = false; break; case WM_RBUTTONDOWN: stuKey.m_enmKey = ASW::Input::KEY_MB1; stuKey.m_blnDown = true; break; case WM_RBUTTONUP: stuKey.m_enmKey = ASW::Input::KEY_MB1; stuKey.m_blnDown = false; break; case WM_MOUSEMOVE: if ( ptrInput->m_blnMouse ) { ptrInput->m_stuMouseDelta[0] += ptrInput->m_stuMousePos[0] - (int)(p_lParam & 0xffff); ptrInput->m_stuMouseDelta[1] += ptrInput->m_stuMousePos[1] - (int)((p_lParam >> 16) & 0xffff); ptrInput->m_stuMousePos[0] = (int)(p_lParam & 0xffff); ptrInput->m_stuMousePos[1] = (int)((p_lParam >> 16) & 0xffff); } else { ptrInput->m_stuMousePos[0] = (int)(p_lParam & 0xffff); ptrInput->m_stuMousePos[1] = (int)((p_lParam >> 16) & 0xffff); ptrInput->m_blnMouse = true; } break; case WM_KEYDOWN: case WM_KEYUP: stuKey.m_blnDown = ( p_uintMsg == WM_KEYDOWN ); if ( p_wParam < 'A' || p_wParam > 'Z' ) { switch ( p_wParam ) { case VK_TAB: stuKey.m_enmKey = ASW::Input::KEY_TAB; break; case VK_UP: stuKey.m_enmKey = ASW::Input::KEY_UP; break; case VK_DOWN: stuKey.m_enmKey = ASW::Input::KEY_DOWN; break; case VK_LEFT: stuKey.m_enmKey = ASW::Input::KEY_LEFT; break; case VK_RIGHT: stuKey.m_enmKey = ASW::Input::KEY_RIGHT; break; } } else stuKey.m_enmKey = MS_Input::m_enmMsInputKeys[p_wParam - 'A']; break; default: break; } // // Only add the key to the state change array if it is one we care // about (it is not UNKNOWN) and at least one action uses it // if ( stuKey.m_enmKey != ASW::Input::KEY_UNKNOWN && ptrInput->m_ptrActionIndices[stuKey.m_enmKey] ) { // // Since Windows will keep sending messages for keys that are // held down, only add the key if there is actually a state change // if ( stuKey.m_blnDown == false || ptrInput->m_blnKeys[stuKey.m_enmKey] == false ) ptrInput->m_clsKeys.Insert(stuKey); return 0; } else { // // Call the old WndProc routine for this window (this is probably // not necessary and can be commented out if you don't care to // support the old WndProc (see the Init() method)) // SetWindowLongPtr(p_hndWindow, GWLP_WNDPROC, (long)(ptrInput->m_ftnWndProc)); SetWindowLongPtr(p_hndWindow, GWLP_USERDATA, ptrInput->m_lngOldValue); LRESULT stuTemp = CallWindowProc(ptrInput->m_ftnWndProc, p_hndWindow, p_uintMsg, p_wParam, p_lParam); ptrInput->m_ftnWndProc = (WNDPROC)(GetWindowLongPtr(p_hndWindow, GWLP_WNDPROC)); ptrInput->m_lngOldValue = GetWindowLongPtr(p_hndWindow, GWLP_USERDATA); SetWindowLongPtr(p_hndWindow, GWLP_WNDPROC, (long)(MS_Input::WndProc)); SetWindowLongPtr(p_hndWindow, GWLP_USERDATA, (long)(ptrInput)); return stuTemp; } } /* Here the action array is copied into the parameter array, after which the action array is emptied. Refer to WndProc() to see how the action array is filled. 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 MS_Input:: Sync(ASW::Input::KeyChange * p_ptrChanges, unsigned int & p_uintAmount, ASW::Point3i & p_stuMouseMovement) { // // Copy the member action array to the parameter action array, then // empty the member action array. // // WE SHOULD HAVE SOME SORT OF MUTEX AROUND THIS, AS WndProc() CAN BE // ADDING TO THIS ARRAY AT THE SAME TIME WE ARE EMPTYING IT. ALSO, WE // CAN'T HAVE MORE THAN 255 THIS WAY // memcpy(p_ptrChanges, m_clsKeys.GetIndex(0), m_clsKeys.Length() * sizeof(ASW::Input::KeyChange)); p_uintAmount = m_clsKeys.Length(); m_clsKeys.RemoveAll(); p_stuMouseMovement[0] = m_stuMouseDelta[0]; p_stuMouseMovement[1] = m_stuMouseDelta[1]; m_stuMouseDelta = 0; return m_ptrWindow->Focus(); } #endif #ifdef ASW_DIRECTX /* DX_Input implements Input using DirectInput to communicate directly with the hardware devices. Buffered input is used (see Init()). */ class DX_Input : public ASW::Input { private: LPDIRECTINPUT8 m_ptrManager; LPDIRECTINPUTDEVICE8 m_ptrMouse; LPDIRECTINPUTDEVICE8 m_ptrKeyboard; DIDEVICEOBJECTDATA m_stuDataMouse[BUFFER_SIZE]; DIDEVICEOBJECTDATA m_stuDataKeyboard[BUFFER_SIZE]; static const ASW::Input::KeyType m_enmDirectXKeys[256]; protected: bool Sync(KeyChange * Changes, unsigned int & Amount, ASW::Point3i & MouseMovement); public: DX_Input(); ~DX_Input(); virtual bool Acquire(void); virtual bool Init(ASW::Window * WindowRef); virtual void Finish(void); 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; } } }; const ASW::Input::KeyType DX_Input::m_enmDirectXKeys[256] = { ASW::Input::KEY_0, ASW::Input::KEY_1, ASW::Input::KEY_2, ASW::Input::KEY_3, ASW::Input::KEY_4, ASW::Input::KEY_5, ASW::Input::KEY_6, ASW::Input::KEY_7, ASW::Input::KEY_8, ASW::Input::KEY_9, ASW::Input::KEY_A, ASW::Input::KEY_KEYPAD_ADD, ASW::Input::KEY_QUOTE, ASW::Input::KEY_BACKSPACE, ASW::Input::KEY_BACKSLASH, ASW::Input::KEY_C, ASW::Input::KEY_CAPSLOCK, ASW::Input::KEY_COMMA, ASW::Input::KEY_D, ASW::Input::KEY_KEYPAD_PERIOD, ASW::Input::KEY_DELETE, ASW::Input::KEY_KEYPAD_DIVIDE, ASW::Input::KEY_DOWN, ASW::Input::KEY_E, ASW::Input::KEY_END, ASW::Input::KEY_EQUALS, ASW::Input::KEY_ESCAPE, ASW::Input::KEY_F, ASW::Input::KEY_F1, ASW::Input::KEY_F2, ASW::Input::KEY_F3, ASW::Input::KEY_F4, ASW::Input::KEY_F5, ASW::Input::KEY_F6, ASW::Input::KEY_F7, ASW::Input::KEY_F8, ASW::Input::KEY_F9, ASW::Input::KEY_F10, ASW::Input::KEY_F11, ASW::Input::KEY_F12, ASW::Input::KEY_G, ASW::Input::KEY_ACCENT, ASW::Input::KEY_H, ASW::Input::KEY_HOME, ASW::Input::KEY_I, ASW::Input::KEY_INSERT, ASW::Input::KEY_J, ASW::Input::KEY_K, ASW::Input::KEY_L, ASW::Input::KEY_BRACKETL, ASW::Input::KEY_CONTROLL, ASW::Input::KEY_LEFT, ASW::Input::KEY_ALTL, ASW::Input::KEY_SHIFTL, ASW::Input::KEY_WINDOWSL, ASW::Input::KEY_M, ASW::Input::KEY_MINUS, ASW::Input::KEY_KEYPAD_MULTIPLY, ASW::Input::KEY_KEYPAD_NUMLOCK, ASW::Input::KEY_KEYPAD_0, ASW::Input::KEY_KEYPAD_1, ASW::Input::KEY_KEYPAD_2, ASW::Input::KEY_KEYPAD_3, ASW::Input::KEY_KEYPAD_4, ASW::Input::KEY_KEYPAD_5, ASW::Input::KEY_KEYPAD_6, ASW::Input::KEY_KEYPAD_7, ASW::Input::KEY_KEYPAD_8, ASW::Input::KEY_KEYPAD_9, ASW::Input::KEY_KEYPAD_ENTER, ASW::Input::KEY_O, ASW::Input::KEY_P, ASW::Input::KEY_PAUSE, ASW::Input::KEY_PERIOD, ASW::Input::KEY_PAGEUP, ASW::Input::KEY_Q, ASW::Input::KEY_R, ASW::Input::KEY_BRACKETR, ASW::Input::KEY_CONTROLR, ASW::Input::KEY_ENTER, ASW::Input::KEY_RIGHT, ASW::Input::KEY_ALTR, ASW::Input::KEY_SHIFTR, ASW::Input::KEY_WINDOWSR, ASW::Input::KEY_S, ASW::Input::KEY_SCRLCK, ASW::Input::KEY_SEMICOLON, ASW::Input::KEY_FORWARDSLASH, ASW::Input::KEY_SPACE, ASW::Input::KEY_KEYPAD_SUBTRACT, ASW::Input::KEY_T, ASW::Input::KEY_TAB, ASW::Input::KEY_U, ASW::Input::KEY_UP, ASW::Input::KEY_V, ASW::Input::KEY_W, ASW::Input::KEY_X, ASW::Input::KEY_Y, ASW::Input::KEY_Z, }; DX_Input:: DX_Input() : m_ptrManager(NULL), m_ptrMouse(NULL), m_ptrKeyboard(NULL) { //SetKeys(); } DX_Input:: ~DX_Input() { Finish(); } /* Attempts to get focus of the mouse and keyboard, i.e. when a user alt+tabs */ bool DX_Input:: Acquire(void) { HRESULT hndResultMouse = m_ptrMouse->Acquire(); HRESULT hndResultKeyboard = m_ptrKeyboard->Acquire(); return ( (hndResultMouse == DI_OK || hndResultMouse == S_FALSE) && (hndResultKeyboard == DI_OK || hndResultKeyboard == S_FALSE) ); } /* Keyboard, mouse, and the main DirectInput objects are destroyed here */ void DX_Input:: Finish(void) { if ( m_ptrMouse ) { m_ptrMouse->Release(); m_ptrMouse = NULL; } if ( m_ptrKeyboard ) { m_ptrKeyboard->Release(); m_ptrKeyboard = NULL; } if ( m_ptrManager ) { m_ptrManager->Release(); m_ptrManager = NULL; } } /* Keyboard and mouse objects are created and properties are set for both. Buffered input is used. */ bool DX_Input:: Init(ASW::Window * p_ptrWindow) { // // Create the base input object // if ( FAILED(DirectInput8Create((HINSTANCE)(p_ptrWindow->GetInstance()), DIRECTINPUT_VERSION, IID_IDirectInput8, (void **)(&m_ptrManager), NULL)) ) return false; // // Create and initialize the keyboard object // if ( FAILED(m_ptrManager->CreateDevice(GUID_SysKeyboard, &m_ptrKeyboard, NULL)) ) { m_ptrManager->Release(); m_ptrManager = NULL; return false; } // // Set properties on the keyboard object // DIPROPDWORD stuWordStruct; stuWordStruct.diph.dwSize = sizeof(DIPROPDWORD); stuWordStruct.diph.dwHeaderSize = sizeof(DIPROPHEADER); stuWordStruct.diph.dwObj = 0; stuWordStruct.diph.dwHow = DIPH_DEVICE; stuWordStruct.dwData = BUFFER_SIZE; if ( FAILED(m_ptrKeyboard->SetProperty(DIPROP_BUFFERSIZE, &stuWordStruct.diph)) || FAILED(m_ptrKeyboard->SetDataFormat(&c_dfDIKeyboard)) || FAILED(m_ptrKeyboard->SetCooperativeLevel((HWND)(p_ptrWindow->GetWindow()), DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)) ) { m_ptrKeyboard->Release(); m_ptrManager->Release(); m_ptrKeyboard = NULL; m_ptrManager = NULL; return false; } // // Create and initialize the mouse object // if ( FAILED(m_ptrManager->CreateDevice(GUID_SysMouse, &m_ptrMouse, NULL)) ) { m_ptrKeyboard->Release(); m_ptrManager->Release(); m_ptrKeyboard = NULL; m_ptrManager = NULL; return false; } // // Set properties on the mouse object // stuWordStruct.diph.dwSize = sizeof(DIPROPDWORD); stuWordStruct.diph.dwHeaderSize = sizeof(DIPROPHEADER); stuWordStruct.diph.dwObj = 0; stuWordStruct.diph.dwHow = DIPH_DEVICE; stuWordStruct.dwData = BUFFER_SIZE; if ( FAILED(m_ptrMouse->SetProperty(DIPROP_BUFFERSIZE, &stuWordStruct.diph)) || FAILED(m_ptrMouse->SetDataFormat(&c_dfDIMouse)) || FAILED(m_ptrMouse->SetCooperativeLevel((HWND)(p_ptrWindow->GetWindow()), DISCL_FOREGROUND | DISCL_EXCLUSIVE)) ) { m_ptrKeyboard->Release(); m_ptrManager->Release(); m_ptrMouse->Release(); m_ptrKeyboard = NULL; m_ptrManager = NULL; m_ptrMouse = NULL; return false; } return true; } /* Here the device data is queried for 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 DX_Input:: 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; } #endif /* Static method that creates an Input object. Will fail (i.e. return NULL) if the object type cannot be initialized or support for it was not compiled in. */ ASW::Input * ASW::Input:: Create(const ASW::Input::InputType p_enmType, ASW::Window * p_ptrWindow) { ASW::Input * ptrInput; switch ( p_enmType ) { case ASW::Input::INPUT_MS: #ifdef WIN32 ptrInput = new MS_Input(); break; #else return NULL; #endif case ASW::Input::INPUT_DX: #ifdef ASW_DIRECTX ptrInput = new DX_Input(); break; #else return NULL; #endif default: return NULL; } // // Initialize the input object // if ( ptrInput->Init(p_ptrWindow) == false ) { delete ptrInput; ptrInput = NULL; } return ptrInput; } /* Actions that have become active or inactive are queried here. Active actions are those that have their associated key sequences depressed since this method was last called; inactive actions are those that were active since this method was last called, but have become inactive by at least one of the keys in their associated key sequences unpressed. */ bool ASW::Input:: Get(ASW::Input::Action * p_ptrActions, unsigned int & p_uintAmount, ASW::Point3i & p_stuMouseMovement) { // // Get key state changes (pressed or unpressed since last Sync()) // unsigned int uintAmount = 0; ASW::Input::KeyChange stuKeys[256]; bool blnResult = Sync(&(stuKeys[0]), uintAmount, p_stuMouseMovement); // // Check key state changes // ASW::Input::KeyType * ptrKeys; unsigned char j; unsigned char uchrKeys; unsigned int uintActions = 0; for (unsigned int i=0; i= uchrKeys ) { // // All of the keys for the action are pressed, add it to the array as activated // p_ptrActions[uintActions].m_blnOn = true; p_ptrActions[uintActions].m_enmType = m_clsActions[*ptrIndices].m_enmType; uintActions++; } } while ( *(++ptrIndices) != (unsigned int)(-1) ); } else { // // Check all actions that use this key // unsigned int * ptrIndices = m_ptrActionIndices[stuKeys[i].m_enmKey]; do { ptrKeys = m_clsActions[*ptrIndices].m_ptrKeys; uchrKeys = m_clsActions[*ptrIndices].m_uchrKeys; for (j=0; j= uchrKeys ) { // // This key is not pressed, add it to the array as inactive // p_ptrActions[uintActions].m_blnOn = false; p_ptrActions[uintActions].m_enmType = m_clsActions[*ptrIndices].m_enmType; uintActions++; } } while ( *(++ptrIndices) != (unsigned int)(-1) ); m_blnKeys[stuKeys[i].m_enmKey] = false; } } p_uintAmount = uintActions; return blnResult; } /* An action and its associated key sequence are specified here. While this method can be called any time, it is usually called during initialization to set up default actions. It might also be called if the user changes key bindings. - If the key sequence is NULL, the action is removed (if it exists). - If the key sequence is already present, the current action is replaced with the new one, unless the action is UNKNOWN, in which case the key sequence and associated action are removed. - If the action is already present, the current key sequence for that action is replaced by the new one. Finally, if neither the action or key sequence are present, they are added to the action/sequence array. */ bool ASW::Input:: Set(const ASW::Input::ActionType p_enmType, const ASW::Input::KeyType * p_ptrKeys, const unsigned char p_uchrAmount) { if ( p_ptrKeys == NULL ) { // // The KeyType array is NULL, which means we remove the action with the corresponding identifier // for (unsigned int i=0; i= ptrTemp[j] ) { KeyType enmTemp = ptrTemp[i]; ptrTemp[i] = ptrTemp[j]; ptrTemp[j] = enmTemp; } } } // // Try to find the key sequence in the action array // for (i=0; i