/*** Crealysm 3D engine, Cristiaan Kop - updated 17-03-2015 ***/ /*** ============================================================================== ***/ /*** NAMESPACE: CREALYSM_DXINPUT ***/ /*** cpp file with CInputHandler implementation for user input, keyboard, mouse etc ***/ #include "Crealysm_input.h" namespace Crealysm_input { /**************************************************************************************/ /*** CONSTRUCTOR ***/ /*** ==> usage: when creating a CInputHandler object ***/ /*** ==> sets all variables in the CInputHandler object to initial values ***/ /**************************************************************************************/ CInputHandler::CInputHandler() { mRawInput = NULL; mMouseBuffer = NULL; mMouseMoved = false; mMouseScrolled = false; mMouseMoveX = 0; mMouseMoveY = 0; mMouseScrollPos = 0; mMouseLastScrollPos = 0; for(int c=0;c<256;++c) { mKeyCounterA[c] = 0; mKeyCounterB[c] = 0; } mInitialized = false; } /**************************************************************************************/ /*** DESTRUCTOR ***/ /*** ==> usage: when CInputHandler object is not needed anymore ***/ /*** ==> releases all input handler objects ***/ /**************************************************************************************/ CInputHandler::~CInputHandler() { mRawInput = NULL; delete[] mMouseBuffer; // nothing } /**************************************************************************************/ /*** UPDATE KEYS ***/ /*** ==> usage: to copy the current keys state to last keys ***/ /*** ==> memcpy's the whole keys array of bools ***/ /**************************************************************************************/ void CInputHandler::UpdateKeys() { memcpy(mKeyCounterB, mKeyCounterA, sizeof(char)*256); } /**************************************************************************************/ /*** SET KEY STATE ***/ /*** ==> usage: to update the state of an individual key ***/ /*** ==> updates the state ***/ /**************************************************************************************/ void CInputHandler::SetKeyState(const int pKey, const bool pState) { mKeys[pKey] = pState; // NOT USED CURRENTLY: 25-1-2015 mKeyCounterA[pKey] += ((pState && (mKeyCounterA[pKey] & 1)==0) || (!pState && (mKeyCounterA[pKey] & 1)!= 0)) ? 1:0; } /**************************************************************************************/ /*** SETUP MOUSE RAW ***/ /*** ==> usage: at initalization, if user input is needed ***/ /*** ==> sets up RAW input for mouse (no DX/Dinput) ***/ /**************************************************************************************/ bool CInputHandler::SetupMouseRaw(const HWND pHwnd) { Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC; Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE; Rid[0].dwFlags = RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE;// | RIDEV_INPUTSINK; // CAPTUREMOUSE = CLICK REACTION OUTSIDE WINDOW OK Rid[0].hwndTarget = pHwnd; if(!RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]))) return false; mMouseBuffer = new BYTE[40]; mInitialized = true; return true; } /**************************************************************************************/ /*** UPDATE MOUSE RAW ***/ /*** ==> usage: during runtime, after WM_INPUT message is received ***/ /*** ==> updates mouse properties based on RAW mouse input ***/ /**************************************************************************************/ void CInputHandler::UpdateMouseRaw() { mRawInput = NULL; mRawInput = (RAWINPUT*)mMouseBuffer; if(mRawInput != NULL) { if(mRawInput->header.dwType == RIM_TYPEMOUSE) { mMouseScrolled = false; // POSITION mMouseMoveX += mRawInput->data.mouse.lLastX; mMouseMoveY += mRawInput->data.mouse.lLastY; mMouseMoved = true; // BUTTONS if(mRawInput->data.mouse.ulButtons & RI_MOUSE_LEFT_BUTTON_DOWN) { mLastMouseButtonDown[0] = mMouseButtonDown[0]; mMouseButtonDown[0] = true; } if(mRawInput->data.mouse.ulButtons & RI_MOUSE_LEFT_BUTTON_UP) { mLastMouseButtonDown[0] = mMouseButtonDown[0]; mMouseButtonDown[0] = false; } if(mRawInput->data.mouse.ulButtons & RI_MOUSE_MIDDLE_BUTTON_DOWN) { mLastMouseButtonDown[1] = mMouseButtonDown[1]; mMouseButtonDown[1] = true; } if(mRawInput->data.mouse.ulButtons & RI_MOUSE_MIDDLE_BUTTON_UP) { mLastMouseButtonDown[1] = mMouseButtonDown[1]; mMouseButtonDown[1] = false; } if(mRawInput->data.mouse.ulButtons & RI_MOUSE_RIGHT_BUTTON_DOWN) { mLastMouseButtonDown[2] = mMouseButtonDown[2]; mMouseButtonDown[2] = true; } if(mRawInput->data.mouse.ulButtons & RI_MOUSE_RIGHT_BUTTON_UP) { mLastMouseButtonDown[2] = mMouseButtonDown[2]; mMouseButtonDown[2] = false; } // SCROLL if(mRawInput->data.mouse.ulButtons & RI_MOUSE_WHEEL) { mMouseScrolled = true; mMouseLastScrollPos = mMouseScrollPos; if(mRawInput->data.mouse.usButtonData > 0) mMouseScrollPos = 1; else mMouseScrollPos = -1; } } } } /**************************************************************************************/ /*** GET MOUSE BUFFER PTR ***/ /*** ==> usage: when RAW input needs updating in the wndproc ***/ /*** ==> returns a pointer to the BYTE buffer ***/ /**************************************************************************************/ BYTE* CInputHandler::GetMouseBufferPtr() { return mMouseBuffer; } /**************************************************************************************/ /*** RESET ***/ /*** ==> usage: during runtime, after input logics are handled ***/ /*** ==> resets all (mouse) properties for new WM_INPUT input (frame timing) ***/ /**************************************************************************************/ void CInputHandler::Reset() { mMouseMoved = false; mMouseScrolled = false; mMouseButtonDown[0] = false; mMouseButtonDown[1] = false; mMouseButtonDown[2] = false; mMouseMoveX = 0; mMouseMoveY = 0; } /**************************************************************************************/ /*** KEY UP CONST ***/ /*** ==> usage: to check if a key was and is still up - NO STATE CHANGE ***/ /*** ==> returns true if the key is still up ***/ /**************************************************************************************/ bool CInputHandler::KeyUp(const int pKey) const { return(mKeyCounterA[pKey] - mKeyCounterB[pKey]) > 1 || (mKeyCounterA[pKey] & 1) == 0; } /**************************************************************************************/ /*** KEY DOWN CONST ***/ /*** ==> usage: to check if a key was and is still pressed - NO STATE CHANGE ***/ /*** ==> returns true if the key is still down ***/ /**************************************************************************************/ bool CInputHandler::KeyDown(const int pKey) const { return (mKeyCounterA[pKey] - mKeyCounterB[pKey]) > 1 || (mKeyCounterA[pKey] & 1) != 0; } /**************************************************************************************/ /*** KEY PRESSED CONST ***/ /*** ==> usage: to check if a key was up and now is down - STATE CHANGE ***/ /*** ==> returns true if the key was pressed ***/ /**************************************************************************************/ bool CInputHandler::KeyPressed(const int pKey) const { return (mKeyCounterA[pKey] - mKeyCounterB[pKey]) > 0 && (mKeyCounterB[pKey] & 1) == 0; // return mKeys[pKey]; } /**************************************************************************************/ /*** KEY RELEASED CONST ***/ /*** ==> usage: to check if a key was down and now is up - STATE CHANGE ***/ /*** ==> returns true if the key was released ***/ /**************************************************************************************/ bool CInputHandler::KeyReleased(const int pKey) const { return (mKeyCounterA[pKey] - mKeyCounterB[pKey]) > 0 && (mKeyCounterB[pKey] & 1) != 0; } /**************************************************************************************/ /*** CHAR PRESSED CONST ***/ /*** ==> usage: to check if an alphabet character was pressed ***/ /*** ==> returns false or true with the corresonding character (to pointer) ***/ /**************************************************************************************/ bool CInputHandler::CharPressed(char *pCharacter) const { if(KeyPressed(VkKeyScan('a')&0xFF)) { *pCharacter = 'a'; return true; } if(KeyPressed(VkKeyScan('b')&0xFF)) { *pCharacter = 'b'; return true; } if(KeyPressed(VkKeyScan('c')&0xFF)) { *pCharacter = 'c'; return true; } if(KeyPressed(VkKeyScan('d')&0xFF)) { *pCharacter = 'd'; return true; } if(KeyPressed(VkKeyScan('e')&0xFF)) { *pCharacter = 'e'; return true; } if(KeyPressed(VkKeyScan('f')&0xFF)) { *pCharacter = 'f'; return true; } if(KeyPressed(VkKeyScan('g')&0xFF)) { *pCharacter = 'g'; return true; } if(KeyPressed(VkKeyScan('h')&0xFF)) { *pCharacter = 'h'; return true; } if(KeyPressed(VkKeyScan('i')&0xFF)) { *pCharacter = 'i'; return true; } if(KeyPressed(VkKeyScan('j')&0xFF)) { *pCharacter = 'j'; return true; } if(KeyPressed(VkKeyScan('k')&0xFF)) { *pCharacter = 'k'; return true; } if(KeyPressed(VkKeyScan('l')&0xFF)) { *pCharacter = 'l'; return true; } if(KeyPressed(VkKeyScan('m')&0xFF)) { *pCharacter = 'm'; return true; } if(KeyPressed(VkKeyScan('n')&0xFF)) { *pCharacter = 'n'; return true; } if(KeyPressed(VkKeyScan('o')&0xFF)) { *pCharacter = 'o'; return true; } if(KeyPressed(VkKeyScan('p')&0xFF)) { *pCharacter = 'p'; return true; } if(KeyPressed(VkKeyScan('q')&0xFF)) { *pCharacter = 'q'; return true; } if(KeyPressed(VkKeyScan('r')&0xFF)) { *pCharacter = 'r'; return true; } if(KeyPressed(VkKeyScan('s')&0xFF)) { *pCharacter = 's'; return true; } if(KeyPressed(VkKeyScan('t')&0xFF)) { *pCharacter = 't'; return true; } if(KeyPressed(VkKeyScan('u')&0xFF)) { *pCharacter = 'u'; return true; } if(KeyPressed(VkKeyScan('v')&0xFF)) { *pCharacter = 'v'; return true; } if(KeyPressed(VkKeyScan('w')&0xFF)) { *pCharacter = 'w'; return true; } if(KeyPressed(VkKeyScan('x')&0xFF)) { *pCharacter = 'x'; return true; } if(KeyPressed(VkKeyScan('y')&0xFF)) { *pCharacter = 'y'; return true; } if(KeyPressed(VkKeyScan('z')&0xFF)) { *pCharacter = 'z'; return true; } return false; } /**************************************************************************************/ /*** GET MOUSE MOVE X CONST ***/ /*** ==> usage: to retrieve mouse X movement , from outside class ***/ /*** ==> returns the last mouse movement on the X-axis ***/ /**************************************************************************************/ int CInputHandler::GetMouseMoveX() const { return mMouseMoveX; } /**************************************************************************************/ /*** GET MOUSE MOVE Y CONST ***/ /*** ==> usage: to retrieve mouse Y movement , from outside class ***/ /*** ==> returns the last mouse movement on the Y-axis ***/ /**************************************************************************************/ int CInputHandler::GetMouseMoveY() const { return mMouseMoveY; } /**************************************************************************************/ /*** MOUSE MOVED CONST ***/ /*** ==> usage: when checking if mouse has moved, outside class ***/ /*** ==> returns true if the mouse has moved ***/ /**************************************************************************************/ bool CInputHandler::MouseMoved() const { return mMouseMoved; } /**************************************************************************************/ /*** MOUSE BUTTON DOWN CONST ***/ /*** ==> usage: to check if a specific mouse button is down, from outside class ***/ /*** ==> returns the current status of the mouse button ***/ /**************************************************************************************/ bool CInputHandler::MouseButtonDown(const int pButton) const { return mMouseButtonDown[pButton]; } /**************************************************************************************/ /*** MOUSE BUTTON PRESSED CONST ***/ /*** ==> usage: to check if a specific mouse button was pressed ***/ /*** ==> returns if the button was pressed ***/ /**************************************************************************************/ bool CInputHandler::MouseButtonPressed(const int pButton) const { if(!mLastMouseButtonDown[pButton] && mMouseButtonDown[pButton]) return true; return false; } /**************************************************************************************/ /*** MOUSE SCROLLED CONST ***/ /*** ==> usage: when checking if the was scrolled, outside class ***/ /*** ==> returns true if the mouse has scrolled ***/ /**************************************************************************************/ bool CInputHandler::MouseScrolled() const { return mMouseScrolled; } /**************************************************************************************/ /*** GET MOUSE SCROLLPOS CONST ***/ /*** ==> usage: to retrieve the current scroll position of the mouse ***/ /*** ==> returns the current position ***/ /**************************************************************************************/ int CInputHandler::GetMouseScrollPos() const { return mMouseScrollPos; } /**************************************************************************************/ /*** IS INITIALIZED CONST ***/ /*** ==> usage: when wanting to know if directinput is initialized ***/ /*** ==> returns true if the dinput devices are ready to go ***/ /**************************************************************************************/ bool CInputHandler::IsInitialized() const { return mInitialized; } } /* POINT test; GetCursorPos(&test); _d3dcam.FreeLook(test.x - 640, test.y - 360, _player.GetLookSpeed() * _timer.GetDelta()); SetCursorPos(640, 360); */ // MOUSE INPUT: RAW /* case WM_INPUT: { UINT dwSize = 40; static BYTE lpb[40]; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); RAWINPUT* raw = (RAWINPUT*)lpb; if(raw->header.dwType == RIM_TYPEMOUSE) { _input.UpdateMouse(raw->data.mouse.lLastX, raw->data.mouse.lLastY); // TEMPORARY!!! if(_input.MouseMoved()) { _d3dcam.FreeLook(_input.GetMousePosX(), _input.GetMousePosY(), _player.GetLookSpeed()); _input.SetMouseMoved(false); } // CONTINUE!!! } } break;*/ /* RAW MOUSE SETUP Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC; Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE; Rid[0].dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_INPUTSINK | RIDEV_NOLEGACY; Rid[0].hwndTarget = pHwnd; RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])); */ // HANDLE MOUSE INPUT /* case WM_MOUSEMOVE: { int newX = LOWORD(lParam); int newY = HIWORD(lParam); _input.UpdateMouse(newX, newY); } break;*/