void CSDLPad::HandleAxisEvent(const SDL_JoyAxisEvent& axisEvt) { if (!m_connected) return; SInputSymbol *pSymbol = NULL; SInputEvent inputEvt; //CryLogAlways("CSDLPad - AXIS requested(%d) %d on Gamepad [%d]", axisEvt.axis, axisEvt.value, m_deviceNo); const int id = SDL_GAMEPAD_AXIS(axisEvt.axis); pSymbol = DevSpecIdToSymbol(id); if (pSymbol) { switch(id) { case SDL_GAMEPAD_LEFT_THUMB_X: case SDL_GAMEPAD_RIGHT_THUMB_X: pSymbol->value = DeadZoneFilter(axisEvt.value); break; case SDL_GAMEPAD_LEFT_THUMB_Y: case SDL_GAMEPAD_RIGHT_THUMB_Y: // Input system seems to expect Y input to be inverted relative to SDL values pSymbol->value = -1.0f * DeadZoneFilter(axisEvt.value); break; case SDL_GAMEPAD_RIGHT_TRIGGER_DUPE: // ignore break; case SDL_GAMEPAD_LEFT_TRIGGER_DUPE: // ignore break; case SDL_GAMEPAD_RIGHT_TRIGGER: case SDL_GAMEPAD_LEFT_TRIGGER: if (axisEvt.value < 0) pSymbol->value = -1.0f * ((float)(SDL_GAMEPAD_AXIS_MIN - axisEvt.value) / ((float) SDL_GAMEPAD_AXIS_MAX * 2.0f)); else pSymbol->value = 0.5f + ((float)axisEvt.value / ((float) SDL_GAMEPAD_AXIS_MAX * 2.0f)); if (pSymbol->value > -1.0f) { SInputSymbol *btnSymbol = DevSpecIdToSymbol(id == SDL_GAMEPAD_LEFT_TRIGGER ? SDL_GAMEPAD_LEFT_TRIGGER_BTN : SDL_GAMEPAD_RIGHT_TRIGGER_BTN); if (btnSymbol) { if (pSymbol->value > SDL_GAMEPAD_TRIGGER_MIN_VAL_FOR_BUTTON) btnSymbol->state = eIS_Pressed; else btnSymbol->state = eIS_Released; btnSymbol->AssignTo(inputEvt); GetLinuxInput().PostInputEvent(inputEvt); } } break; default: gEnv->pLog->LogError("CSDLPad - Unknown AXIS requested(%d) on Gamepad [%d]", axisEvt.axis, m_deviceNo); return; } pSymbol->state = eIS_Changed; pSymbol->AssignTo(inputEvt); GetLinuxInput().PostInputEvent(inputEvt); } }
void CXInputDevice::ClearAnalogKeyState(TInputSymbols& clearedSymbols) { if (m_state.Gamepad.sThumbLX!=0 || m_state.Gamepad.sThumbLY!=0 || m_state.Gamepad.sThumbRX!=0 || m_state.Gamepad.sThumbRY!=0) { // Only resend if the sticks are actually active. If they aren't then active then sending a resendsticks causes pad inputs to be sent through even if you aren't using the pad - which messes with the UI on PC. m_forceResendSticks = true; } // Reset internal state and decrement packet number so updated again immediately // This will force-send the current state of all analog keys on next update m_state.Gamepad.sThumbLX = 0; m_state.Gamepad.sThumbLY = 0; m_state.Gamepad.sThumbRX = 0; m_state.Gamepad.sThumbRY = 0; m_state.Gamepad.bLeftTrigger = 0; m_state.Gamepad.bRightTrigger = 0; m_state.dwPacketNumber--; //remove the symbols cleared above from the hold list static SInputSymbol* pSymbolUpL = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_UP); static SInputSymbol* pSymbolDownL = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_DOWN); static SInputSymbol* pSymbolLeftL = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_LEFT); static SInputSymbol* pSymbolRightL = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_RIGHT); static SInputSymbol* pSymbolUpR = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_UP); static SInputSymbol* pSymbolDownR = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_DOWN); static SInputSymbol* pSymbolLeftR = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_LEFT); static SInputSymbol* pSymbolRightR = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_RIGHT); static SInputSymbol* pSymbolTrgBtnL = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_TRIGGER_BTN); static SInputSymbol* pSymbolTrgBtnR = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_TRIGGER_BTN); clearedSymbols.reserve(10); clearedSymbols.push_back(pSymbolUpL); clearedSymbols.push_back(pSymbolDownL); clearedSymbols.push_back(pSymbolLeftL); clearedSymbols.push_back(pSymbolRightL); clearedSymbols.push_back(pSymbolUpR); clearedSymbols.push_back(pSymbolDownR); clearedSymbols.push_back(pSymbolLeftR); clearedSymbols.push_back(pSymbolRightR); clearedSymbols.push_back(pSymbolTrgBtnL); clearedSymbols.push_back(pSymbolTrgBtnR); }
void CSDLPad::HandleButtonEvent(const SDL_JoyButtonEvent& btEvt) { if (!m_connected) return; //CryLogAlways("BTEVENT EVT: bt:%d %s",btEvt.button, (btEvt.state & SDL_PRESSED) ? "PRESSED" : "RELEASED" ); SInputSymbol *pSymbol = DevSpecIdToSymbol(btEvt.button); if (pSymbol) { SInputEvent inputEvt; const EInputState currState = (btEvt.state & SDL_PRESSED) ? eIS_Pressed : eIS_Released; //CryLogAlways("BTEVENT SYM: name: %s state:%d=>%d", pSymbol->name.c_str(), int(pSymbol->state), int(currState)); bool isPost = false; switch (btEvt.button) { // Special handling so they act more like the hat events; events only triggered on // initial press and release case SDL_GAMEPAD_LEFT_THUMB_UP: case SDL_GAMEPAD_LEFT_THUMB_DOWN: case SDL_GAMEPAD_LEFT_THUMB_LEFT: case SDL_GAMEPAD_LEFT_THUMB_RIGHT: isPost = (pSymbol->state == eIS_Unknown) || (currState == eIS_Pressed && (pSymbol->state == eIS_Released)) || (currState == eIS_Released && (pSymbol->state == eIS_Pressed || pSymbol->state == eIS_Down)); break; default: isPost = true; break; } if (isPost) { pSymbol->state = currState; pSymbol->AssignTo(inputEvt); GetLinuxInput().PostInputEvent(inputEvt); } } else { switch (btEvt.button) { // Ignore buttons that are known to be unmapped and we intentionally don't handle case SDL_GAMEPAD_BUTTON_LEFT_TRIGGER_DUPE: case SDL_GAMEPAD_BUTTON_RIGHT_TRIGGER_DUPE: break; default: gEnv->pLog->LogError("CSDLPad - Gamepad [%d] received unmapped button event %d", m_deviceNo, btEvt.button); break; } } }
void CMouse::Update(bool bFocus) { FUNCTION_PROFILER( GetISystem(),PROFILE_INPUT ); HRESULT hr; if (!GetDirectInputDevice()) return; m_deltas.zero(); m_mouseWheel = 0; SInputSymbol* pSymbol = 0; EInputState newState; if (g_pInputCVars->i_mouse_buffered) { //memcpy(m_oldEvents, m_Events, sizeof(m_Events)); //memset(m_Events,0,sizeof(m_Events)); DIDEVICEOBJECTDATA Events[200]; // // Buffer mouse input. DWORD nElements = 200; while (nElements > 0) { hr = GetDirectInputDevice()->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), Events, &nElements, 0); if (FAILED(hr) && Acquire()) { // try again hr = GetDirectInputDevice()->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), Events, &nElements, 0); } if (FAILED(hr)) return; if (nElements > 0) { for (int i = 0; i < (int)nElements; i++) { pSymbol = DevSpecIdToSymbol(Events[i].dwOfs); if (pSymbol) { // marcok: should actually process axis events here as` well, // but I'm not sure if the game can handle multiple move events if (pSymbol->type == SInputSymbol::Button) { if (Events[i].dwData&0x80) { pSymbol->state = eIS_Pressed; pSymbol->value = 1.0; } else { pSymbol->state = eIS_Released; pSymbol->value = 0.0; } PostEvent(pSymbol); } } switch (Events[i].dwOfs) { case DIMOFS_X: m_deltas.x += float((int)Events[i].dwData); break; case DIMOFS_Y: m_deltas.y += float((int)Events[i].dwData); break; case DIMOFS_Z: m_mouseWheel += float((int)Events[i].dwData); break; } } } } } else { // Not buffered. DIMOUSESTATE2 dims; memset (&dims, 0, sizeof(dims)); hr = GetDirectInputDevice()->GetDeviceState(sizeof(DIMOUSESTATE2), &dims); if (FAILED(hr) && Acquire()) { // try again hr = GetDirectInputDevice()->GetDeviceState(sizeof(DIMOUSESTATE2), &dims); } if (SUCCEEDED(hr)) { m_deltas.set((float)dims.lX, (float)dims.lY); m_mouseWheel = (float)dims.lZ; for (int i=0; i<8; ++i) { newState = (dims.rgbButtons[i]&0x80) ? eIS_Pressed : eIS_Released; PostOnlyIfChanged(Symbol[i], newState); } } } m_deltas *= g_pInputCVars->i_mouse_sensitivity; //marcok: here the raw input already gets cooked a bit ... should be moved float mouseaccel = g_pInputCVars->i_mouse_accel; if (mouseaccel>0.0f) { m_deltas.x = m_deltas.x * (float)fabs(m_deltas.x * mouseaccel); m_deltas.y = m_deltas.y * (float)fabs(m_deltas.y * mouseaccel); CapDeltas(g_pInputCVars->i_mouse_accel_max); } SmoothDeltas(g_pInputCVars->i_mouse_smooth); const bool hasDeltaChanged = !(fcmp(m_deltas.x,m_oldDeltas.x) && fcmp(m_deltas.y,m_oldDeltas.y)); m_oldDeltas = m_deltas; //this needs to happen always. We want to keep the attribute always valid //mouse wheel - use custom code instead of PostOnlyWhenChanged because we want the mouseWheel value if(m_mouseWheel > 0.0f) { SInputSymbol* pSymbol = Symbol[eKI_MouseWheelUp-KI_MOUSE_BASE]; pSymbol->value = m_mouseWheel; pSymbol->state = eIS_Pressed; PostEvent(pSymbol); } else if (m_mouseWheel < 0.0f) { SInputSymbol* pSymbol = Symbol[eKI_MouseWheelDown-KI_MOUSE_BASE]; pSymbol->value = m_mouseWheel; pSymbol->state = eIS_Pressed; PostEvent(pSymbol); } else { SInputSymbol* pSymbol = Symbol[eKI_MouseWheelUp-KI_MOUSE_BASE]; if(pSymbol->state != eIS_Released) { pSymbol->value = 0.0f; pSymbol->state = eIS_Released; PostEvent(pSymbol); } SInputSymbol* pSymbol2 = Symbol[eKI_MouseWheelDown-KI_MOUSE_BASE]; if(pSymbol2->state != eIS_Released) { pSymbol2->value = 0.0f; pSymbol2->state = eIS_Released; PostEvent(pSymbol2); } } // mouse movements if (m_deltas.GetLength2()>0.0f || hasDeltaChanged || m_mouseWheel) { pSymbol = Symbol[eKI_MouseX-KI_MOUSE_BASE]; pSymbol->state = eIS_Changed; pSymbol->value = m_deltas.x; PostEvent(pSymbol); pSymbol = Symbol[eKI_MouseY-KI_MOUSE_BASE]; pSymbol->state = eIS_Changed; pSymbol->value = m_deltas.y; PostEvent(pSymbol); pSymbol = Symbol[eKI_MouseZ-KI_MOUSE_BASE]; pSymbol->state = eIS_Changed; pSymbol->value = m_mouseWheel; PostEvent(pSymbol); } ////////////////////////////////////////////////////////////////////////// float inertia = g_pInputCVars->i_mouse_inertia; // mouse inertia if (inertia>0) { float dt = gEnv->pTimer->GetFrameTime(); if (dt>0.1f) dt=0.1f; m_deltas = (m_deltasInertia += (m_deltas-m_deltasInertia)*inertia*dt); } }
void CXInputDevice::Update(bool bFocus) { FUNCTION_PROFILER( GetISystem(),PROFILE_INPUT ); DEBUG_CONTROLLER_RENDER_BUTTON_ACTION; const bool wasConnected = m_connected; const bool connected = g_bConnected[m_deviceNo]; const bool disconnecting = (wasConnected && !connected); UpdateConnectedState(connected); float frameTime = gEnv->pTimer->GetFrameTime(); float now = gEnv->pTimer->GetFrameStartTime().GetSeconds(); if((m_fVibrationTimer && m_fVibrationTimer < now) || g_pInputCVars->i_forcefeedback == 0 || gEnv->pSystem->IsPaused() || frameTime<0.001f) { m_fVibrationTimer = 0; SetVibration(0, 0, 0.0f); } // Force inputs to get sent out when we're disconnecting or // we can get stuck with thumbsticks in a non-neutral state if (disconnecting) { m_forceResendSticks = true; } // interpret input if ((m_connected && bFocus) || disconnecting) { XINPUT_STATE state; memset( &state, 0, sizeof(XINPUT_STATE) ); if ( ERROR_SUCCESS != XInputGetState(m_deviceNo, &state) && !disconnecting) return; if (state.dwPacketNumber != m_state.dwPacketNumber) { SInputEvent event; SInputSymbol* pSymbol = 0; event.deviceIndex = (uint8)m_deviceNo; if (g_pInputCVars->i_xinput_deadzone_handling > 0) { { Vec2 d( state.Gamepad.sThumbLX, state.Gamepad.sThumbLY ); FixDeadzone( d ); state.Gamepad.sThumbLX = d[0]; state.Gamepad.sThumbLY = d[1]; } { Vec2 d( state.Gamepad.sThumbRX, state.Gamepad.sThumbRY ); FixDeadzone( d ); state.Gamepad.sThumbRX = d[0]; state.Gamepad.sThumbRY = d[1]; } } else { const float INV_VALIDRANGE = (1.0f / (INPUT_MAX - m_fDeadZone)); // make the inputs move smoothly out of the deadzone instead of snapping straight to m_fDeadZone float fraction=max((float)abs(state.Gamepad.sThumbLX) - m_fDeadZone, 0.f) * INV_VALIDRANGE; float oldVal=state.Gamepad.sThumbLX; state.Gamepad.sThumbLX = fraction * INPUT_MAX * sgn(state.Gamepad.sThumbLX); fraction = max((float)abs(state.Gamepad.sThumbLY) - m_fDeadZone, 0.f) * INV_VALIDRANGE; oldVal = state.Gamepad.sThumbLY; state.Gamepad.sThumbLY = fraction * INPUT_MAX * sgn(state.Gamepad.sThumbLY); // make the inputs move smoothly out of the deadzone instead of snapping straight to m_fDeadZone fraction=max((float)abs(state.Gamepad.sThumbRX) - m_fDeadZone, 0.f) * INV_VALIDRANGE; oldVal=state.Gamepad.sThumbRX; state.Gamepad.sThumbRX = fraction * INPUT_MAX * sgn(state.Gamepad.sThumbRX); fraction = max((float)abs(state.Gamepad.sThumbRY) - m_fDeadZone, 0.f) * INV_VALIDRANGE; oldVal = state.Gamepad.sThumbRY; state.Gamepad.sThumbRY = fraction * INPUT_MAX * sgn(state.Gamepad.sThumbRY); } // compare new values against cached value and only send out changes as new input WORD buttonsChange = m_state.Gamepad.wButtons ^ state.Gamepad.wButtons; if (buttonsChange) { for (int i = 0; i < 16; ++i) { uint32 id = (1 << i); if (buttonsChange & id && (pSymbol = DevSpecIdToSymbol(id))) { pSymbol->PressEvent((state.Gamepad.wButtons & id) != 0); pSymbol->AssignTo(event); event.deviceType = eIDT_Gamepad; GetIInput().PostInputEvent(event); DEBUG_CONTROLLER_LOG_BUTTON_ACTION(pSymbol); } } } // now we have done the digital buttons ... let's do the analog stuff if (m_state.Gamepad.bLeftTrigger != state.Gamepad.bLeftTrigger) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_TRIGGER); pSymbol->ChangeEvent(state.Gamepad.bLeftTrigger / 255.0f); pSymbol->AssignTo(event); event.deviceType = eIDT_Gamepad; GetIInput().PostInputEvent(event); DEBUG_CONTROLLER_LOG_BUTTON_ACTION(pSymbol); //--- Check previous and current trigger against threshold for digital press/release event bool bIsPressed=state.Gamepad.bLeftTrigger>XINPUT_GAMEPAD_TRIGGER_THRESHOLD ? true : false; bool bWasPressed=m_state.Gamepad.bLeftTrigger>XINPUT_GAMEPAD_TRIGGER_THRESHOLD ? true : false; if(bIsPressed!=bWasPressed) { pSymbol=DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_TRIGGER_BTN); pSymbol->PressEvent(bIsPressed); pSymbol->AssignTo(event); event.deviceType = eIDT_Gamepad; GetIInput().PostInputEvent(event); DEBUG_CONTROLLER_LOG_BUTTON_ACTION(pSymbol); } } if (m_state.Gamepad.bRightTrigger != state.Gamepad.bRightTrigger) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_TRIGGER); pSymbol->ChangeEvent(state.Gamepad.bRightTrigger / 255.0f); pSymbol->AssignTo(event); event.deviceType = eIDT_Gamepad; GetIInput().PostInputEvent(event); DEBUG_CONTROLLER_LOG_BUTTON_ACTION(pSymbol); //--- Check previous and current trigger against threshold for digital press/release event bool bIsPressed=state.Gamepad.bRightTrigger>XINPUT_GAMEPAD_TRIGGER_THRESHOLD; bool bWasPressed=m_state.Gamepad.bRightTrigger>XINPUT_GAMEPAD_TRIGGER_THRESHOLD; if(bIsPressed!=bWasPressed) { pSymbol=DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_TRIGGER_BTN); pSymbol->PressEvent(bIsPressed); pSymbol->AssignTo(event); event.deviceType = eIDT_Gamepad; GetIInput().PostInputEvent(event); DEBUG_CONTROLLER_LOG_BUTTON_ACTION(pSymbol); } } if ((m_state.Gamepad.sThumbLX != state.Gamepad.sThumbLX) || m_forceResendSticks) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_X); if(state.Gamepad.sThumbLX==0.f) pSymbol->ChangeEvent(0.f); else pSymbol->ChangeEvent((state.Gamepad.sThumbLX + 32768) / 32767.5f - 1.0f); pSymbol->AssignTo(event); event.deviceType = eIDT_Gamepad; GetIInput().PostInputEvent(event); //--- Check previous and current state to generate digital press/release event static SInputSymbol* pSymbolLeft = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_LEFT); ProcessAnalogStick(pSymbolLeft, m_state.Gamepad.sThumbLX, state.Gamepad.sThumbLX, -25000); static SInputSymbol* pSymbolRight = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_RIGHT); ProcessAnalogStick(pSymbolRight, m_state.Gamepad.sThumbLX, state.Gamepad.sThumbLX, 25000); } if ((m_state.Gamepad.sThumbLY != state.Gamepad.sThumbLY) || m_forceResendSticks) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_Y); if(state.Gamepad.sThumbLY==0.f) pSymbol->ChangeEvent(0.f); else pSymbol->ChangeEvent((state.Gamepad.sThumbLY + 32768) / 32767.5f - 1.0f); pSymbol->AssignTo(event); event.deviceType = eIDT_Gamepad; GetIInput().PostInputEvent(event); //--- Check previous and current state to generate digital press/release event static SInputSymbol* pSymbolUp = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_UP); ProcessAnalogStick(pSymbolUp, m_state.Gamepad.sThumbLY, state.Gamepad.sThumbLY, 25000); static SInputSymbol* pSymbolDown = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_DOWN); ProcessAnalogStick(pSymbolDown, m_state.Gamepad.sThumbLY, state.Gamepad.sThumbLY, -25000); } if ((m_state.Gamepad.sThumbRX != state.Gamepad.sThumbRX) || m_forceResendSticks) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_X); if(state.Gamepad.sThumbRX==0.f) pSymbol->ChangeEvent(0.f); else pSymbol->ChangeEvent((state.Gamepad.sThumbRX + 32768) / 32767.5f - 1.0f); pSymbol->AssignTo(event); event.deviceType = eIDT_Gamepad; GetIInput().PostInputEvent(event); //--- Check previous and current state to generate digital press/release event static SInputSymbol* pSymbolLeft = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_LEFT); ProcessAnalogStick(pSymbolLeft, m_state.Gamepad.sThumbRX, state.Gamepad.sThumbRX, -25000); static SInputSymbol* pSymbolRight = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_RIGHT); ProcessAnalogStick(pSymbolRight, m_state.Gamepad.sThumbRX, state.Gamepad.sThumbRX, 25000); } if ((m_state.Gamepad.sThumbRY != state.Gamepad.sThumbRY) || m_forceResendSticks) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_Y); if(state.Gamepad.sThumbRY==0.f) pSymbol->ChangeEvent(0.f); else pSymbol->ChangeEvent((state.Gamepad.sThumbRY + 32768) / 32767.5f - 1.0f); pSymbol->AssignTo(event); event.deviceType = eIDT_Gamepad; GetIInput().PostInputEvent(event); //--- Check previous and current state to generate digital press/release event static SInputSymbol* pSymbolUp = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_UP); ProcessAnalogStick(pSymbolUp, m_state.Gamepad.sThumbRY, state.Gamepad.sThumbRY, 25000); static SInputSymbol* pSymbolDown = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_DOWN); ProcessAnalogStick(pSymbolDown, m_state.Gamepad.sThumbRY, state.Gamepad.sThumbRY, -25000); } // update cache m_state = state; m_forceResendSticks = false; } } }
void gkXboxInputDevice::Update(bool bFocus) { float now = gEnv->pTimer->GetCurrTime(); // if((m_fVibrationTimer && m_fVibrationTimer < now) || g_pInputCVars->i_forcefeedback == 0 || gEnv->pSystem->IsPaused()) // { // m_fVibrationTimer = 0; // //SetVibration(0, 0, 0.0f); // } // interpret input if (true || bFocus) { XINPUT_STATE state; memset( &state, 0, sizeof(XINPUT_STATE) ); if ( ERROR_SUCCESS != XInputGetState(m_deviceNo, &state) ) { // disconnected. UpdateConnectedState(false); return; } else { // connected. UpdateConnectedState(true); } if (true || state.dwPacketNumber != m_state.dwPacketNumber) { SInputEvent event; SInputSymbol* pSymbol = 0; event.deviceIndex = (uint8)m_deviceNo; const float INV_VALIDRANGE = (1.0f / (INPUT_MAX - m_fDeadZone)); // make the inputs move smoothly out of the deadzone instead of snapping straight to m_fDeadZone float fraction=max(abs(state.Gamepad.sThumbLX) - m_fDeadZone, 0) * INV_VALIDRANGE; float oldVal=state.Gamepad.sThumbLX; state.Gamepad.sThumbLX = fraction * INPUT_MAX * sgn(state.Gamepad.sThumbLX); fraction = max(abs(state.Gamepad.sThumbLY) - m_fDeadZone, 0) * INV_VALIDRANGE; oldVal = state.Gamepad.sThumbLY; state.Gamepad.sThumbLY = fraction * INPUT_MAX * sgn(state.Gamepad.sThumbLY); // make the inputs move smoothly out of the deadzone instead of snapping straight to m_fDeadZone fraction=max(abs(state.Gamepad.sThumbRX) - m_fDeadZone, 0) * INV_VALIDRANGE; oldVal=state.Gamepad.sThumbRX; state.Gamepad.sThumbRX = fraction * INPUT_MAX * sgn(state.Gamepad.sThumbRX); fraction = max(abs(state.Gamepad.sThumbRY) - m_fDeadZone, 0) * INV_VALIDRANGE; oldVal = state.Gamepad.sThumbRY; state.Gamepad.sThumbRY = fraction * INPUT_MAX * sgn(state.Gamepad.sThumbRY); // compare new values against cached value and only send out changes as new input WORD buttonsChange = m_state.Gamepad.wButtons ^ state.Gamepad.wButtons; if (buttonsChange) { for (int i = 0; i < 16; ++i) { uint32 id = (1 << i); if (buttonsChange & id && (pSymbol = DevSpecIdToSymbol(id))) { pSymbol->PressEvent((state.Gamepad.wButtons & id) != 0); pSymbol->AssignTo(event); event.deviceId = eDI_XBox; GetInputManager().PostInputEvent(event); } } } // now we have done the digital buttons ... let's do the analog stuff if (m_state.Gamepad.bLeftTrigger != state.Gamepad.bLeftTrigger) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_TRIGGER); pSymbol->ChangeEvent(state.Gamepad.bLeftTrigger / 255.0f); pSymbol->AssignTo(event); event.deviceId = eDI_XBox; GetInputManager().PostInputEvent(event); //--- Check previous and current trigger against threshold for digital press/release event bool bIsPressed=state.Gamepad.bLeftTrigger>XINPUT_GAMEPAD_TRIGGER_THRESHOLD ? true : false; bool bWasPressed=m_state.Gamepad.bLeftTrigger>XINPUT_GAMEPAD_TRIGGER_THRESHOLD ? true : false; if(bIsPressed!=bWasPressed) { pSymbol=DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_TRIGGER_BTN); pSymbol->PressEvent(bIsPressed); pSymbol->AssignTo(event); event.deviceId = eDI_XBox; GetInputManager().PostInputEvent(event); } } if (m_state.Gamepad.bRightTrigger != state.Gamepad.bRightTrigger) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_TRIGGER); pSymbol->ChangeEvent(state.Gamepad.bRightTrigger / 255.0f); pSymbol->AssignTo(event); event.deviceId = eDI_XBox; GetInputManager().PostInputEvent(event); //--- Check previous and current trigger against threshold for digital press/release event bool bIsPressed=state.Gamepad.bRightTrigger>XINPUT_GAMEPAD_TRIGGER_THRESHOLD; bool bWasPressed=m_state.Gamepad.bRightTrigger>XINPUT_GAMEPAD_TRIGGER_THRESHOLD; if(bIsPressed!=bWasPressed) { pSymbol=DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_TRIGGER_BTN); pSymbol->PressEvent(bIsPressed); pSymbol->AssignTo(event); event.deviceId = eDI_XBox; GetInputManager().PostInputEvent(event); } } if (1) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_X); if(state.Gamepad.sThumbLX==0.f) pSymbol->ChangeEvent(0.f); else pSymbol->ChangeEvent((state.Gamepad.sThumbLX + 32768) / 32767.5f - 1.0f); pSymbol->AssignTo(event); event.deviceId = eDI_XBox; GetInputManager().PostInputEvent(event); //--- Check previous and current state to generate digital press/release event static SInputSymbol* pSymbolLeft = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_LEFT); ProcessAnalogStick(pSymbolLeft, m_state.Gamepad.sThumbLX, state.Gamepad.sThumbLX, -25000); static SInputSymbol* pSymbolRight = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_RIGHT); ProcessAnalogStick(pSymbolRight, m_state.Gamepad.sThumbLX, state.Gamepad.sThumbLX, 25000); } if (1) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_Y); if(state.Gamepad.sThumbLY==0.f) pSymbol->ChangeEvent(0.f); else pSymbol->ChangeEvent((state.Gamepad.sThumbLY + 32768.0f) / 32767.5f - 1.0f); pSymbol->AssignTo(event); event.deviceId = eDI_XBox; GetInputManager().PostInputEvent(event); //--- Check previous and current state to generate digital press/release event static SInputSymbol* pSymbolUp = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_UP); ProcessAnalogStick(pSymbolUp, m_state.Gamepad.sThumbLY, state.Gamepad.sThumbLY, 25000); static SInputSymbol* pSymbolDown = DevSpecIdToSymbol(_XINPUT_GAMEPAD_LEFT_THUMB_DOWN); ProcessAnalogStick(pSymbolDown, m_state.Gamepad.sThumbLY, state.Gamepad.sThumbLY, -25000); } if (1) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_X); if(state.Gamepad.sThumbRX==0.f) pSymbol->ChangeEvent(0.f); else pSymbol->ChangeEvent((state.Gamepad.sThumbRX + 32768) / 32767.5f - 1.0f); pSymbol->AssignTo(event); event.deviceId = eDI_XBox; GetInputManager().PostInputEvent(event); //--- Check previous and current state to generate digital press/release event static SInputSymbol* pSymbolLeft = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_LEFT); ProcessAnalogStick(pSymbolLeft, m_state.Gamepad.sThumbRX, state.Gamepad.sThumbRX, -25000); static SInputSymbol* pSymbolRight = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_RIGHT); ProcessAnalogStick(pSymbolRight, m_state.Gamepad.sThumbRX, state.Gamepad.sThumbRX, 25000); } if (1) { pSymbol = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_Y); if(state.Gamepad.sThumbRY==0.f) pSymbol->ChangeEvent(0.f); else pSymbol->ChangeEvent((state.Gamepad.sThumbRY + 32768) / 32767.5f - 1.0f); pSymbol->AssignTo(event); event.deviceId = eDI_XBox; GetInputManager().PostInputEvent(event); //--- Check previous and current state to generate digital press/release event static SInputSymbol* pSymbolUp = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_UP); ProcessAnalogStick(pSymbolUp, m_state.Gamepad.sThumbRY, state.Gamepad.sThumbRY, 25000); static SInputSymbol* pSymbolDown = DevSpecIdToSymbol(_XINPUT_GAMEPAD_RIGHT_THUMB_DOWN); ProcessAnalogStick(pSymbolDown, m_state.Gamepad.sThumbRY, state.Gamepad.sThumbRY, -25000); } // update cache m_state = state; } } }
void CSDLKeyboard::Update(bool focus) { SDL_Event eventList[KEYBOARD_MAX_PEEP]; int nEvents; unsigned type = 0; #if !defined(_RELEASE) // Stop SDL2 from generating text input event when pressing the console // key to hide/show the in-game console bool didPressTild = false; #endif SInputSymbol *pSymbol = NULL; nEvents = SDL_PeepEvents(eventList, KEYBOARD_MAX_PEEP, SDL_GETEVENT, SDL_KEYDOWN,SDL_TEXTINPUT); if (nEvents == -1) { gEnv->pLog->LogError("SDL_GETEVENT error: %s", SDL_GetError()); return; } for (int i = 0; i < nEvents; ++i) { type = eventList[i].type; if (type == SDL_KEYDOWN || type == SDL_KEYUP) { SDL_KeyboardEvent *const keyEvent = &eventList[i].key; m_lastKeySym = keyEvent->keysym.sym; m_lastMod = ConvertModifiers(keyEvent->keysym.mod); } // ignore this event. We can't skip it since the events are sampeled // in intervals and the value of SDL_TEXTEDITING is lower than // SDL_TEXTINPUT and higher than SDL_KEYUP if (type == SDL_TEXTEDITING) continue; if (type == SDL_KEYDOWN) { SDL_KeyboardEvent *const keyEvent = &eventList[i].key; SDL_Scancode keySym = keyEvent->keysym.scancode; #if !defined(_RELEASE) didPressTild = (keySym == SDL_SCANCODE_GRAVE); #endif pSymbol = DevSpecIdToSymbol((uint32)keySym); if (pSymbol == NULL) continue; pSymbol->state = eIS_Pressed; pSymbol->value = 1.f; // Check for CRTL+ALT combintaions if ((keyEvent->keysym.mod & KMOD_ALT) && (keyEvent->keysym.mod & KMOD_CTRL)) { // CRLT + ALT + SHIFT + g = ungrab if (keySym == SDL_SCANCODE_G && keyEvent->keysym.mod & KMOD_SHIFT) GetLinuxInput().GrabInput(false); // CRLT + ALT + g = grab else if (keySym == SDL_SCANCODE_G) GetLinuxInput().GrabInput(true); } PostEvent(pSymbol, keyEvent->keysym.mod); // TODO: Make consistent with other keyboard devices and fire OnInputEventUI with unicode char /* wchar_t unicode = keyEvent->keysym.unicode if (unicode) { SInputEvent event; event.keyName = pSymbol->name; event.deviceId = eDI_Mouse; event.timestamp = GetTickCount(); if (keyMod != ~0) event.modifiers = ConvertModifiers(keyMod); else event.modifiers = 0; // FIXMCSDLMouse* pMouseE add mouse modifier support event.state = eIS_UI; event.inputChar = (wchar_t)unicode; event.value = 1.0f; event.pSymbol = pSymbol; GetIInput().PostInputEvent(event); } */ } else if (type == SDL_KEYUP) { SDL_KeyboardEvent *const keyEvent = &eventList[i].key; SDL_Scancode keySym = keyEvent->keysym.scancode; pSymbol = DevSpecIdToSymbol((uint32)keySym); if (pSymbol == NULL) continue; pSymbol->state = eIS_Released; pSymbol->value = 0.f; PostEvent(pSymbol, keyEvent->keysym.mod); } else if (type == SDL_TEXTINPUT) { #if !defined(_RELEASE) if (!didPressTild) { #endif SDL_TextInputEvent *const txtEvent = &eventList[i].text; // try to convert the utf8 string to a single wchar_t character wstring strWide; CryStringUtils::UTF8ToWStr(&txtEvent->text[0], strWide); for(size_t i = 0; i < strWide.length(); ++i) { SInputEvent event; event.deviceType = m_deviceType; event.state = eIS_UI; event.value = 1.0f; event.inputChar = strWide[i]; event.keyName = txtEvent->text; GetLinuxInput().PostInputEvent(event); } #if !defined(_RELEASE) } #endif } else { // Unexpect0;//ed event type. abort(); } } }
void gkMouse::Update(bool bFocus) { HRESULT hr; if (!GetDirectInputDevice()) return; m_deltas.zero(); m_mouseWheel = 0; SInputSymbol* pSymbol = 0; EInputState newState; if (g_pInputCVars->i_mouse_buffered) { //memcpy(m_oldEvents, m_Events, sizeof(m_Events)); //memset(m_Events,0,sizeof(m_Events)); DIDEVICEOBJECTDATA Events[200]; // // Buffer mouse input. DWORD nElements = 200; while (nElements > 0) { hr = GetDirectInputDevice()->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), Events, &nElements, 0); if (FAILED(hr) && Acquire()) { // try again hr = GetDirectInputDevice()->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), Events, &nElements, 0); } if (FAILED(hr)) return; if (nElements > 0) { for (int i = 0; i < (int)nElements; i++) { pSymbol = DevSpecIdToSymbol(Events[i].dwOfs); if (pSymbol) { // marcok: should actually process axis events here as` well, // but I'm not sure if the game can handle multiple move events if (pSymbol->type == SInputSymbol::Button) { if (Events[i].dwData&0x80) { pSymbol->state = eIS_Pressed; pSymbol->value = 1.0; } else { pSymbol->state = eIS_Released; pSymbol->value = 0.0; } PostEvent(pSymbol); } } switch (Events[i].dwOfs) { case DIMOFS_X: m_deltas.x += float((int)Events[i].dwData); break; case DIMOFS_Y: m_deltas.y += float((int)Events[i].dwData); break; case DIMOFS_Z: m_mouseWheel += float((int)Events[i].dwData); break; } } } } } else { // Not buffered. DIMOUSESTATE2 dims; memset (&dims, 0, sizeof(dims)); hr = GetDirectInputDevice()->GetDeviceState(sizeof(DIMOUSESTATE2), &dims); if (FAILED(hr) && Acquire()) { // try again hr = GetDirectInputDevice()->GetDeviceState(sizeof(DIMOUSESTATE2), &dims); } if (SUCCEEDED(hr)) { m_deltas.set((float)dims.lX, (float)dims.lY); m_mouseWheel = (float)dims.lZ; // mouse1 - mouse8 for (int i=0; i<8; ++i) { newState = (dims.rgbButtons[i]&0x80) ? eIS_Pressed : eIS_Released; PostOnlyIfChanged(Symbol[i], newState); } } } //marcok: here the raw input already gets cooked a bit ... should be moved float mouseaccel = g_pInputCVars->i_mouse_accel; if (mouseaccel>0.0f) { m_deltas.x = m_deltas.x * (float)fabs(m_deltas.x * mouseaccel); m_deltas.y = m_deltas.y * (float)fabs(m_deltas.y * mouseaccel); CapDeltas(g_pInputCVars->i_mouse_accel_max); } SmoothDeltas(g_pInputCVars->i_mouse_smooth); //mouse wheel newState = (m_mouseWheel > 0.0f) ? eIS_Pressed : eIS_Released; PostOnlyIfChanged(Symbol[eKI_MouseWheelUp-KI_MOUSE_BASE], newState); newState = (m_mouseWheel < 0.0f) ? eIS_Pressed : eIS_Released; PostOnlyIfChanged(Symbol[eKI_MouseWheelDown-KI_MOUSE_BASE], newState); // mouse movements if (m_deltas.GetLength2()>0.0f || m_mouseWheel) { POINT point; GetCursorPos( &point ); ScreenToClient( gEnv->pRenderer->GetWindowHwnd(), &point ); Vec2i offset = gEnv->pRenderer->GetWindowOffset(); pSymbol = Symbol[eKI_MouseX-KI_MOUSE_BASE]; pSymbol->state = eIS_Changed; pSymbol->value = m_deltas.x; pSymbol->value2 = point.x - offset.x; PostEvent(pSymbol); pSymbol = Symbol[eKI_MouseY-KI_MOUSE_BASE]; pSymbol->state = eIS_Changed; pSymbol->value = m_deltas.y; pSymbol->value2 = point.y - offset.y; PostEvent(pSymbol); pSymbol = Symbol[eKI_MouseZ-KI_MOUSE_BASE]; pSymbol->state = eIS_Changed; pSymbol->value = m_mouseWheel; PostEvent(pSymbol); } ////////////////////////////////////////////////////////////////////////// float inertia = g_pInputCVars->i_mouse_inertia; // mouse inertia if (inertia>0) { float dt = gEnv->pTimer->GetFrameTime(); if (dt>0.1f) dt=0.1f; m_deltas = (m_deltasInertia += (m_deltas-m_deltasInertia)*inertia*dt); } }