1
0
mirror of synced 2024-07-03 01:20:35 +00:00
G940LEDControl/LogitechSDK/ControllerInput/Src/LogiGameController.cpp

333 lines
10 KiB
C++

/*
The Logitech Controller Input SDK, including all accompanying
documentation, is protected by intellectual property laws. All rights
not expressly granted by Logitech are reserved.
*/
#include "LogiGameController.h"
#include "LogiControllerInputUtils.h"
using namespace LogitechControllerInput;
LogiGameController::LogiGameController()
{
m_timeCreated = GetTickCount();
Init();
}
VOID LogiGameController::Init()
{
m_device = NULL;
m_numFFAxes = 0;
m_deviceType = LG_DEVICE_TYPE_NONE;
m_actuatorsAreOn = FALSE;
m_vid = 0;
m_pid = 0;
m_friendlyProductName[0] = '\0';
m_isXInputDevice = FALSE;
m_deviceXID = LG_XINPUT_ID_NONE;
m_ctrlNbr = LG_CONTROLLER_NUMBER_NONE;
m_gameHWnd = NULL;
m_deviceUniqueID[0] = '\0';
m_nonLinearCoefficient = 0;
for (INT jj = 0; jj < LG_LOOKUP_TABLE_SIZE; jj++)
{
m_nonLinearWheel[jj] = 0;
}
GenerateNonLinearValues(m_nonLinearCoefficient);
}
LPDIRECTINPUTDEVICE8 LogiGameController::GetDeviceHandle()
{
return m_device;
}
VOID LogiGameController::SetDeviceHandle(CONST LPDIRECTINPUTDEVICE8 device)
{
m_device = device;
}
BOOL LogiGameController::IsConnected(CONST DeviceType deviceType)
{
if (NULL == m_device)
return FALSE;
return (m_deviceType == deviceType) ? TRUE : FALSE;
}
BOOL LogiGameController::IsConnected(CONST ManufacturerName manufacturerName)
{
if (NULL == m_device)
return FALSE;
DWORD vid_ = GetVid();
if (manufacturerName == LG_MANUFACTURER_OTHER)
{
if (vid_ != VID_LOGITECH && vid_ != VID_MICROSOFT)
{
return TRUE;
}
}
else
{
DWORD manufacturer_ = 0xffffffff;
switch (manufacturerName)
{
case LG_MANUFACTURER_LOGITECH:
manufacturer_ = VID_LOGITECH;
break;
case LG_MANUFACTURER_MICROSOFT:
manufacturer_ = VID_MICROSOFT;
break;
default:
return FALSE;
}
if (vid_ == manufacturer_)
{
return TRUE;
}
}
return FALSE;
}
BOOL LogiGameController::IsConnected(CONST ModelName modelName)
{
if (NULL == m_device)
return FALSE;
// We only support this function for Logitech devices
if (!IsConnected(LG_MANUFACTURER_LOGITECH))
{
return FALSE;
}
DWORD model_ = 0xffffffff;
switch (modelName)
{
case LG_MODEL_G27: model_ = PID_G27; break;
case LG_MODEL_DRIVING_FORCE_GT: model_ = PID_DRIVING_FORCE_GT; break;
case LG_MODEL_G25: model_ = PID_G25; break;
case LG_MODEL_MOMO_RACING: model_ = PID_MOMO_RACING; break;
case LG_MODEL_MOMO_FORCE: model_ = PID_MOMO_FORCE; break;
case LG_MODEL_DRIVING_FORCE_PRO: model_ = PID_DRIVING_FORCE_PRO; break;
case LG_MODEL_DRIVING_FORCE: model_ = PID_DRIVING_FORCE; break;
case LG_MODEL_NASCAR_RACING_WHEEL: model_ = PID_NASCAR_RACING_WHEEL; break;
case LG_MODEL_FORMULA_FORCE: model_ = PID_FORMULA_FORCE; break;
case LG_MODEL_FORMULA_FORCE_GP: model_ = PID_FORMULA_FORCE_GP; break;
case LG_MODEL_FORCE_3D_PRO: model_ = PID_FORCE_3D_PRO; break;
case LG_MODEL_EXTREME_3D_PRO: model_ = PID_EXTREME_3D_PRO; break;
case LG_MODEL_FREEDOM_24: model_ = PID_FREEDOM_24; break;
case LG_MODEL_ATTACK_3: model_ = PID_ATTACK_3; break;
case LG_MODEL_FORCE_3D: model_ = PID_FORCE_3D; break;
case LG_MODEL_STRIKE_FORCE_3D: model_ = PID_STRIKE_FORCE_3D; break;
case LG_MODEL_G940_JOYSTICK: model_ = PID_G940_JOYSTICK; break;
case LG_MODEL_G940_THROTTLE: model_ = PID_G940_THROTTLE; break;
case LG_MODEL_G940_PEDALS: model_ = PID_G940_PEDALS; break;
case LG_MODEL_RUMBLEPAD: model_ = PID_RUMBLEPAD; break;
case LG_MODEL_RUMBLEPAD_2: model_ = PID_RUMBLEPAD_2; break;
case LG_MODEL_CORDLESS_RUMBLEPAD_2: model_ = PID_CORDLESS_RUMBLEPAD_2; break;
case LG_MODEL_CORDLESS_GAMEPAD: model_ = PID_CORDLESS_GAMEPAD; break;
case LG_MODEL_DUAL_ACTION_GAMEPAD: model_ = PID_DUAL_ACTION_GAMEPAD; break;
case LG_MODEL_PRECISION_GAMEPAD_2: model_ = PID_PRECISION_GAMEPAD_2; break;
case LG_MODEL_CHILLSTREAM: model_ = PID_CHILLSTREAM; break;
default:
_ASSERT(FALSE);
break;
}
DWORD pid_ = GetPid();
if (model_ == pid_)
{
return TRUE;
}
return FALSE;
}
VOID LogiGameController::SetVidPid(CONST DWORD vidPid)
{
m_vid = LOWORD(vidPid);
m_pid = HIWORD(vidPid);
}
VOID LogiGameController::SetVid(CONST DWORD vid)
{
m_vid = vid;
}
VOID LogiGameController::SetPid(CONST DWORD pid)
{
m_pid = pid;
}
DWORD32 LogiGameController::GetVid()
{
return m_vid;
}
DWORD32 LogiGameController::GetPid()
{
return m_pid;
}
VOID LogiGameController::SetFriendlyProductName(LPCTSTR name)
{
_tcscpy_s(m_friendlyProductName, name);
}
LPCTSTR LogiGameController::GetFriendlyProductName()
{
return m_friendlyProductName;
}
// nonLinCoeff between 0 and 100. 0 = linear, 100 = maximum mon-linear.
VOID LogiGameController::GenerateNonLinearValues(CONST INT nonLinCoeff)
{
if (nonLinCoeff == m_nonLinearCoefficient)
{
return;
}
m_nonLinearCoefficient = nonLinCoeff;
// Populate lookup table
for (INT ii = 0; ii < LG_LOOKUP_TABLE_SIZE - 1; ii++)
{
m_nonLinearWheel[ii] = (INT)CalculateNonLinValue(ii, m_nonLinearCoefficient, LG_DINPUT_RANGE_MIN, LG_DINPUT_RANGE_MAX);
}
// Let's use 10 bits for reading wheel axis, which means 1024 counts. 0 - 1023 gives 511.5 as center position. We need a TRUE center
// so let's use the range of 0 to 1022 and just define 1023 as equal to 1022.
m_nonLinearWheel[LG_LOOKUP_TABLE_SIZE - 1] = m_nonLinearWheel[LG_LOOKUP_TABLE_SIZE - 2];
}
///////////////////////////////////////////////////////////////////////
// Method: calculateNonLinearValue(INT inputValue, INT nonLinearCoeff,
// FLOAT physicsMinInput, FLOAT physicsMaxInput)
// Method calculates a non-linear output value from a linear
// input value that corresponds to the Logitech wheel output.
//
// Arguments: inputValue: must be between 0 and 255. This corresponds
// directly to the wheel's position values.
//
// nonLinearCoeff: non-linearity coefficient which must be a
// value between 0 and 100.
// 0 corresponds to a completely linear response curve and 100
// to a heavily non-linear response curve.
//
// physicsMinInput and physicsMaxInput: minimum and maximum
// numbers that you want as output in your lookup table. For
// example if your physics engine takes -1000 to 1000 as input
// you may specify those values here.
//
// Returns: floating number which has a value between physicsMinInput
// and physicsMaxInput and which reflects the chosen
// non-linearity curve.
///////////////////////////////////////////////////////////////////////
FLOAT LogiGameController::CalculateNonLinValue(CONST INT inputValue, CONST INT nonLinearCoeff, CONST LONG physicsMinInput, CONST LONG physicsMaxInput)
{
// Let's use 10 bits for reading wheel axis, which means 1024 counts. 0 - 1023 gives 511.5 as center position. We need a TRUE center
// so let's use the range of 0 to 1022 and just define 1023 as equal to 1022.
INT MaxLookupTableInput_ = 1022; // These values correspond to the
// wheel's position values.
INT MinLookupTableInput_ = 0;
FLOAT outputValue_;
// In order to center our curve on the X axis let's calculate the
// center offset value
FLOAT centerOffset_ = (FLOAT)(MaxLookupTableInput_ -
MinLookupTableInput_) / 2;
// Calculate maximum on x axis for the centered curve
FLOAT centeredCurveMax_ = MaxLookupTableInput_ - centerOffset_;
// Normalize non-linear coefficient
FLOAT nonLinearCoeffNormalized_ = (FLOAT)nonLinearCoeff/100;
// Normalize input value
outputValue_=((FLOAT)(inputValue - centerOffset_))/centeredCurveMax_;
// Apply a cubical curve
outputValue_=(((physicsMaxInput - physicsMinInput)/2)*((1.0f-nonLinearCoeffNormalized_)*outputValue_+(nonLinearCoeffNormalized_)
*(outputValue_*outputValue_*outputValue_))) + ((physicsMaxInput + physicsMinInput)/2);
// if LG_DINPUT_RANGE_MIN is an even number and LG_DINPUT_RANGE_MAX is
// odd, then because of the way the calculation is made we probably
// get a min that is 1 above, so let's re-adjust it to make sure we do
// indeed get the min.
if (Utils::Instance()->IsEven(LG_DINPUT_RANGE_MIN) && !Utils::Instance()->IsEven(LG_DINPUT_RANGE_MAX))
{
if (outputValue_ == LG_DINPUT_RANGE_MIN + 1)
outputValue_ = outputValue_ - 1.0f;
}
// Clip output value
if (outputValue_ < LG_DINPUT_RANGE_MIN)
{
outputValue_ = LG_DINPUT_RANGE_MIN;
}
if (outputValue_ > LG_DINPUT_RANGE_MAX)
{
outputValue_ = LG_DINPUT_RANGE_MAX;
}
return outputValue_;
}
INT LogiGameController::GetNonLinearValue(CONST INT inputValue)
{
if (inputValue < LG_DINPUT_RANGE_MIN)
{
return LG_DINPUT_RANGE_MIN;
}
if (inputValue > LG_DINPUT_RANGE_MAX)
{
return LG_DINPUT_RANGE_MAX;
}
INT index_ = (INT)(((511.5f * (FLOAT)inputValue) / LG_DINPUT_RANGE_MAX) + 511.5f);
if (index_ < 0 && index_ > 1024)
return inputValue;
return m_nonLinearWheel[index_];
}
VOID LogiGameController::SetDeviceType(CONST DeviceType deviceType)
{
m_deviceType = deviceType;
}
BOOL LogiGameController::IsXInputDevice()
{
return m_isXInputDevice;
}
HRESULT LogiGameController::SetDeviceUniqueID(LPCTSTR uniqueID)
{
errno_t ret_ = _tcscpy_s(m_deviceUniqueID, _countof(m_deviceUniqueID), uniqueID);
if (0 != ret_)
return E_FAIL;
return S_OK;
}
TCHAR* LogiGameController::GetDeviceUniqueID()
{
return m_deviceUniqueID;
}