mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 22:05:38 +00:00
Changes relating to input system:
- Added ability to configure axis min, centre and max values in INI file. This allows some types of steering wheel pedals that use an inverted value range to work properly with the emulator. - Modified CINIFile to read and write signed numbers (needed for above change). - Added check at configuration start for "bad" input sources such as axes that are wrongly calibrated or buttons that are always triggering a value. Otherwise they cause the configuration loop to wait indefinitely for the axis or button to be released. - Removed superfluous check for XInput devices when XInput is not enabled in CDirectInputSystem. - Improved force beedback code in CDirectInputSystem and also added the extra feedback effects needed so far for drive board emulation.
This commit is contained in:
parent
5e247021be
commit
e8782b98fa
|
@ -172,7 +172,7 @@ BOOL CINIFile::LookUpSetting(unsigned *idx, unsigned sectionIdx, string SettingN
|
||||||
|
|
||||||
|
|
||||||
// Assigns a value to the given setting, creating the setting if it does not exist. Nulls out the string (sets it to "").
|
// Assigns a value to the given setting, creating the setting if it does not exist. Nulls out the string (sets it to "").
|
||||||
void CINIFile::Set(string SectionName, string SettingName, unsigned value)
|
void CINIFile::Set(string SectionName, string SettingName, int value)
|
||||||
{
|
{
|
||||||
unsigned sectionIdx, settingIdx;
|
unsigned sectionIdx, settingIdx;
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ void CINIFile::Set(string SectionName, string SettingName, string String)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtains a numerical setting, if it exists, otherwise does nothing.
|
// Obtains a numerical setting, if it exists, otherwise does nothing.
|
||||||
BOOL CINIFile::Get(string SectionName, string SettingName, unsigned& value)
|
BOOL CINIFile::Get(string SectionName, string SettingName, int& value)
|
||||||
{
|
{
|
||||||
unsigned sectionIdx, settingIdx;
|
unsigned sectionIdx, settingIdx;
|
||||||
|
|
||||||
|
@ -248,6 +248,17 @@ BOOL CINIFile::Get(string SectionName, string SettingName, unsigned& value)
|
||||||
return OKAY;
|
return OKAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL CINIFile::Get(string SectionName, string SettingName, unsigned& value)
|
||||||
|
{
|
||||||
|
int intVal;
|
||||||
|
if (Get(SectionName, SettingName, intVal) == FAIL || intVal < 0)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
value = (unsigned)intVal;
|
||||||
|
|
||||||
|
return OKAY;
|
||||||
|
}
|
||||||
|
|
||||||
// Obtains a string setting, if it exists, otherwise does nothing.
|
// Obtains a string setting, if it exists, otherwise does nothing.
|
||||||
BOOL CINIFile::Get(string SectionName, string SettingName, string& String)
|
BOOL CINIFile::Get(string SectionName, string SettingName, string& String)
|
||||||
{
|
{
|
||||||
|
@ -323,15 +334,24 @@ CINIFile::CToken CINIFile::GetString(void)
|
||||||
return T;
|
return T;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch number (decimal or hexadecimal integer). linePtr must point to a character and therefore linePtr[1] is guaranteed to be within bounds.
|
// Fetch number (decimal or hexadecimal positive/negative integer).
|
||||||
|
// linePtr must point to a character and therefore linePtr[1] is guaranteed to be within bounds.
|
||||||
CINIFile::CToken CINIFile::GetNumber(void)
|
CINIFile::CToken CINIFile::GetNumber(void)
|
||||||
{
|
{
|
||||||
CToken T;
|
CToken T;
|
||||||
unsigned long long number = 0;
|
unsigned long long number = 0;
|
||||||
|
BOOL isNeg = FALSE;
|
||||||
int overflow = 0;
|
int overflow = 0;
|
||||||
|
|
||||||
T.type = TOKEN_NUMBER;
|
T.type = TOKEN_NUMBER;
|
||||||
|
|
||||||
|
// See if begins with minus sign
|
||||||
|
if (linePtr[0]=='-')
|
||||||
|
{
|
||||||
|
isNeg = TRUE;
|
||||||
|
linePtr++;
|
||||||
|
}
|
||||||
|
|
||||||
// Hexadecimal?
|
// Hexadecimal?
|
||||||
if ((linePtr[0]=='0') && ((linePtr[1]=='X') || (linePtr[1]=='x')))
|
if ((linePtr[0]=='0') && ((linePtr[1]=='X') || (linePtr[1]=='x')))
|
||||||
{
|
{
|
||||||
|
@ -360,7 +380,7 @@ CINIFile::CToken CINIFile::GetNumber(void)
|
||||||
++linePtr;
|
++linePtr;
|
||||||
|
|
||||||
// Check for overflows
|
// Check for overflows
|
||||||
if (number > 0x00000000FFFFFFFFULL)
|
if (!isNeg && number > 0x000000007FFFFFFFULL || isNeg && number > 0x0000000080000000ULL)
|
||||||
overflow = 1;
|
overflow = 1;
|
||||||
}
|
}
|
||||||
else if (IsBlank(linePtr[0]))
|
else if (IsBlank(linePtr[0]))
|
||||||
|
@ -387,7 +407,7 @@ CINIFile::CToken CINIFile::GetNumber(void)
|
||||||
++linePtr;
|
++linePtr;
|
||||||
|
|
||||||
// Check for overflows
|
// Check for overflows
|
||||||
if (number > 0x00000000FFFFFFFFULL)
|
if (!isNeg && number > 0x000000007FFFFFFFULL || isNeg && number > 0x0000000080000000ULL)
|
||||||
overflow = 1;
|
overflow = 1;
|
||||||
}
|
}
|
||||||
else if (IsBlank(linePtr[0]))
|
else if (IsBlank(linePtr[0]))
|
||||||
|
@ -404,7 +424,7 @@ CINIFile::CToken CINIFile::GetNumber(void)
|
||||||
//if (overflow)
|
//if (overflow)
|
||||||
// printf("tokenizer: number exceeds 32 bits and has been truncated\n");
|
// printf("tokenizer: number exceeds 32 bits and has been truncated\n");
|
||||||
|
|
||||||
T.number = (unsigned) number;
|
T.number = (isNeg ? -(int)number : (int)number);
|
||||||
return T;
|
return T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ public:
|
||||||
* OKAY if the setting was found, FAIL otherwise. The type is not
|
* OKAY if the setting was found, FAIL otherwise. The type is not
|
||||||
* checked.
|
* checked.
|
||||||
*/
|
*/
|
||||||
|
BOOL Get(string SectionName, string SettingName, int& value);
|
||||||
BOOL Get(string SectionName, string SettingName, unsigned& value);
|
BOOL Get(string SectionName, string SettingName, unsigned& value);
|
||||||
BOOL Get(string SectionName, string SettingName, string& String);
|
BOOL Get(string SectionName, string SettingName, string& String);
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ public:
|
||||||
* value Value to write. String will be set to "".
|
* value Value to write. String will be set to "".
|
||||||
* String String to write. Value will be set to 0.
|
* String String to write. Value will be set to 0.
|
||||||
*/
|
*/
|
||||||
void Set(string SectionName, string SettingName, unsigned value);
|
void Set(string SectionName, string SettingName, int value);
|
||||||
void Set(string SectionName, string SettingName, string String);
|
void Set(string SectionName, string SettingName, string String);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -146,7 +147,7 @@ private:
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int type; // token type (defined privately in INIFile.cpp)
|
int type; // token type (defined privately in INIFile.cpp)
|
||||||
unsigned number; // numbers and bools
|
int number; // numbers and bools
|
||||||
string String; // strings and identifiers
|
string String; // strings and identifiers
|
||||||
|
|
||||||
// Constructor (initialize to null token)
|
// Constructor (initialize to null token)
|
||||||
|
@ -177,7 +178,7 @@ private:
|
||||||
{
|
{
|
||||||
string Name; // setting name
|
string Name; // setting name
|
||||||
BOOL isNumber; // internal flag: true if the setting is a number, false if it is a string
|
BOOL isNumber; // internal flag: true if the setting is a number, false if it is a string
|
||||||
unsigned value; // value of number
|
int value; // value of number
|
||||||
string String; // string
|
string String; // string
|
||||||
|
|
||||||
Setting(void)
|
Setting(void)
|
||||||
|
|
|
@ -7,11 +7,18 @@ CInput::CInput(const char *inputId, const char *inputLabel, unsigned inputFlags,
|
||||||
ResetToDefaultMapping();
|
ResetToDefaultMapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CInput::~CInput()
|
||||||
|
{
|
||||||
|
// Release source, if any
|
||||||
|
if (m_source != NULL)
|
||||||
|
m_source->Release();
|
||||||
|
}
|
||||||
|
|
||||||
void CInput::CreateSource()
|
void CInput::CreateSource()
|
||||||
{
|
{
|
||||||
// If already have a source, then release it now
|
// If already have a source, then release it now
|
||||||
if (m_system != NULL && m_source != NULL)
|
if (m_source != NULL)
|
||||||
m_system->ReleaseSource(m_source);
|
m_source->Release();
|
||||||
|
|
||||||
// If no system set yet or mapping is empty or NONE, then set source to NULL
|
// If no system set yet or mapping is empty or NONE, then set source to NULL
|
||||||
if (m_system == NULL || m_mapping[0] == '\0' || stricmp(m_mapping, "NONE") == 0)
|
if (m_system == NULL || m_mapping[0] == '\0' || stricmp(m_mapping, "NONE") == 0)
|
||||||
|
@ -21,14 +28,20 @@ void CInput::CreateSource()
|
||||||
// Otherwise, ask system to parse mapping into appropriate input source
|
// Otherwise, ask system to parse mapping into appropriate input source
|
||||||
m_source = m_system->ParseSource(m_mapping, !!(flags & INPUT_FLAGS_AXIS));
|
m_source = m_system->ParseSource(m_mapping, !!(flags & INPUT_FLAGS_AXIS));
|
||||||
|
|
||||||
// Check that mapping was parsed okay and if not then fall back to default mapping
|
// Check that mapping was parsed okay and if so acquire it
|
||||||
if (m_source == NULL && stricmp(m_mapping, m_defaultMapping) != 0)
|
if (m_source != NULL)
|
||||||
|
m_source->Acquire();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise, fall back to default mapping
|
||||||
|
if (stricmp(m_mapping, m_defaultMapping) != 0)
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to map input %s to [%s] - switching to default [%s].\n", id, m_mapping, m_defaultMapping);
|
ErrorLog("Unable to map input %s to [%s] - switching to default [%s].\n", id, m_mapping, m_defaultMapping);
|
||||||
|
|
||||||
ResetToDefaultMapping();
|
ResetToDefaultMapping();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInput::Initialize(CInputSystem *system)
|
void CInput::Initialize(CInputSystem *system)
|
||||||
|
@ -72,8 +85,8 @@ void CInput::ClearMapping()
|
||||||
|
|
||||||
void CInput::SetMapping(const char *mapping)
|
void CInput::SetMapping(const char *mapping)
|
||||||
{
|
{
|
||||||
strncpy(m_mapping, mapping, MAX_MAPPING_LENGTH - 1);
|
strncpy(m_mapping, mapping, MAX_MAPPING_LENGTH);
|
||||||
m_mapping[MAX_MAPPING_LENGTH - 1] = '\0';
|
m_mapping[MAX_MAPPING_LENGTH] = '\0';
|
||||||
CreateSource();
|
CreateSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,13 +112,23 @@ void CInput::ResetToDefaultMapping()
|
||||||
|
|
||||||
void CInput::ReadFromINIFile(CINIFile *ini, const char *section)
|
void CInput::ReadFromINIFile(CINIFile *ini, const char *section)
|
||||||
{
|
{
|
||||||
if (!IsConfigurable())
|
// See if input is configurable
|
||||||
return;
|
if (IsConfigurable())
|
||||||
|
{
|
||||||
|
// If so, check INI file for mapping string
|
||||||
string key("Input");
|
string key("Input");
|
||||||
key.append(id);
|
key.append(id);
|
||||||
string mapping;
|
string mapping;
|
||||||
if (ini->Get(section, key, mapping) == OKAY)
|
if (ini->Get(section, key, mapping) == OKAY)
|
||||||
|
{
|
||||||
|
// If found, then set mapping string
|
||||||
SetMapping(mapping.c_str());
|
SetMapping(mapping.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If input has not been configured, then force recreation of source anyway since input system settings may have changed
|
||||||
|
CreateSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInput::WriteToINIFile(CINIFile *ini, const char *section)
|
void CInput::WriteToINIFile(CINIFile *ini, const char *section)
|
||||||
|
@ -134,7 +157,7 @@ bool CInput::Changed()
|
||||||
return value != prevValue;
|
return value != prevValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CInput::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
|
bool CInput::SendForceFeedbackCmd(ForceFeedbackCmd ffCmd)
|
||||||
{
|
{
|
||||||
if (m_source == NULL)
|
if (m_source == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -18,10 +18,14 @@ class CINIFile;
|
||||||
|
|
||||||
#define MAX_MAPPING_LENGTH 255
|
#define MAX_MAPPING_LENGTH 255
|
||||||
|
|
||||||
|
#define NUM_FF_EFFECTS 3
|
||||||
|
|
||||||
enum EForceFeedback
|
enum EForceFeedback
|
||||||
{
|
{
|
||||||
FFStop,
|
FFStop = -1,
|
||||||
FFConstantForce
|
FFSelfCenter = 0,
|
||||||
|
FFConstantForce = 1,
|
||||||
|
FFVibrate = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ForceFeedbackCmd
|
struct ForceFeedbackCmd
|
||||||
|
@ -37,7 +41,7 @@ class CInput
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Current mapping(s) for input, eg JOY1_XAXIS_POS
|
// Current mapping(s) for input, eg JOY1_XAXIS_POS
|
||||||
char m_mapping[MAX_MAPPING_LENGTH];
|
char m_mapping[MAX_MAPPING_LENGTH + 1];
|
||||||
|
|
||||||
// Default mapping for input
|
// Default mapping for input
|
||||||
const char *m_defaultMapping;
|
const char *m_defaultMapping;
|
||||||
|
@ -54,7 +58,15 @@ protected:
|
||||||
// Current input source
|
// Current input source
|
||||||
CInputSource *m_source;
|
CInputSource *m_source;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constructs an input with the given identifier, label, flags, game flags, default mapping and initial value.
|
||||||
|
*/
|
||||||
|
CInput(const char *inputId, const char *inputLabel, unsigned inputFlags, unsigned inputGameFlags,
|
||||||
|
const char *defaultMapping = "NONE", UINT16 initValue = 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~CInput();
|
||||||
|
|
||||||
// Input identifier
|
// Input identifier
|
||||||
const char *id;
|
const char *id;
|
||||||
|
|
||||||
|
@ -73,12 +85,6 @@ public:
|
||||||
// Previous input value
|
// Previous input value
|
||||||
UINT16 prevValue;
|
UINT16 prevValue;
|
||||||
|
|
||||||
/*
|
|
||||||
* Constructs an input with the given identifier, label, flags, game flags, default mapping and initial value.
|
|
||||||
*/
|
|
||||||
CInput(const char *inputId, const char *inputLabel, unsigned inputFlags, unsigned inputGameFlags,
|
|
||||||
const char *defaultMapping = "NONE", UINT16 initValue = 0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes this input with the given input system. Must be called before any other methods are used.
|
* Initializes this input with the given input system. Must be called before any other methods are used.
|
||||||
*/
|
*/
|
||||||
|
@ -161,7 +167,7 @@ public:
|
||||||
/*
|
/*
|
||||||
* Sends a force feedback command to the input source of this input.
|
* Sends a force feedback command to the input source of this input.
|
||||||
*/
|
*/
|
||||||
bool SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd);
|
bool SendForceFeedbackCmd(ForceFeedbackCmd ffCmd);
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,13 +1,32 @@
|
||||||
#include "InputSource.h"
|
#include "Supermodel.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
CInputSource::CInputSource(ESourceType sourceType) : type(sourceType)
|
CInputSource::CInputSource(ESourceType sourceType) : type(sourceType), m_acquired(0)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CInputSource::Acquire()
|
||||||
|
{
|
||||||
|
m_acquired++;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
CInputSystem::totalSrcsAcquired++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInputSource::Release()
|
||||||
|
{
|
||||||
|
if (--m_acquired == 0)
|
||||||
|
delete this;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
CInputSystem::totalSrcsReleased++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int CInputSource::Clamp(int val, int minVal, int maxVal)
|
int CInputSource::Clamp(int val, int minVal, int maxVal)
|
||||||
{
|
{
|
||||||
if (val > maxVal) return maxVal;
|
if (val > maxVal) return maxVal;
|
||||||
|
@ -22,19 +41,19 @@ int CInputSource::Scale(int val, int fromMinVal, int fromMaxVal, int toMinVal, i
|
||||||
|
|
||||||
int CInputSource::Scale(int val, int fromMinVal, int fromOffVal, int fromMaxVal, int toMinVal, int toOffVal, int toMaxVal)
|
int CInputSource::Scale(int val, int fromMinVal, int fromOffVal, int fromMaxVal, int toMinVal, int toOffVal, int toMaxVal)
|
||||||
{
|
{
|
||||||
int fromRange;
|
double fromRange;
|
||||||
double frac;
|
double frac;
|
||||||
if (fromMaxVal > fromMinVal)
|
if (fromMaxVal > fromMinVal)
|
||||||
{
|
{
|
||||||
val = Clamp(val, fromMinVal, fromMaxVal);
|
val = Clamp(val, fromMinVal, fromMaxVal);
|
||||||
if (val > fromOffVal)
|
if (val > fromOffVal)
|
||||||
{
|
{
|
||||||
fromRange = fromMaxVal - fromOffVal;
|
fromRange = (double)(fromMaxVal - fromOffVal);
|
||||||
frac = (double)(val - fromOffVal) / fromRange;
|
frac = (double)(val - fromOffVal) / fromRange;
|
||||||
}
|
}
|
||||||
else if (val < fromOffVal)
|
else if (val < fromOffVal)
|
||||||
{
|
{
|
||||||
fromRange = fromOffVal - fromMinVal;
|
fromRange = (double)(fromOffVal - fromMinVal);
|
||||||
frac = (double)(val - fromOffVal) / fromRange;
|
frac = (double)(val - fromOffVal) / fromRange;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -45,12 +64,12 @@ int CInputSource::Scale(int val, int fromMinVal, int fromOffVal, int fromMaxVal,
|
||||||
val = Clamp(val, fromMaxVal, fromMinVal);
|
val = Clamp(val, fromMaxVal, fromMinVal);
|
||||||
if (val > fromOffVal)
|
if (val > fromOffVal)
|
||||||
{
|
{
|
||||||
fromRange = fromMinVal - fromOffVal;
|
fromRange = (double)(fromMinVal - fromOffVal);
|
||||||
frac = (double)(fromOffVal - val) / fromRange;
|
frac = (double)(fromOffVal - val) / fromRange;
|
||||||
}
|
}
|
||||||
else if (val < fromOffVal)
|
else if (val < fromOffVal)
|
||||||
{
|
{
|
||||||
fromRange = fromOffVal - fromMaxVal;
|
fromRange = (double)(fromOffVal - fromMaxVal);
|
||||||
frac = (double)(fromOffVal - val) / fromRange;
|
frac = (double)(fromOffVal - val) / fromRange;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -83,7 +102,7 @@ bool CInputSource::IsActive()
|
||||||
return GetValueAsSwitch(boolVal);
|
return GetValueAsSwitch(boolVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CInputSource::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
|
bool CInputSource::SendForceFeedbackCmd(ForceFeedbackCmd ffCmd)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
|
@ -25,6 +25,8 @@ enum ESourceType
|
||||||
class CInputSource
|
class CInputSource
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
unsigned m_acquired;
|
||||||
|
|
||||||
CInputSource(ESourceType sourceType);
|
CInputSource(ESourceType sourceType);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -33,6 +35,10 @@ public:
|
||||||
*/
|
*/
|
||||||
const ESourceType type;
|
const ESourceType type;
|
||||||
|
|
||||||
|
virtual void Acquire();
|
||||||
|
|
||||||
|
virtual void Release();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Static helper methods
|
// Static helper methods
|
||||||
//
|
//
|
||||||
|
@ -73,7 +79,7 @@ public:
|
||||||
/*
|
/*
|
||||||
* Sends a force feedback command to the input source.
|
* Sends a force feedback command to the input source.
|
||||||
*/
|
*/
|
||||||
virtual bool SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd);
|
virtual bool SendForceFeedbackCmd(ForceFeedbackCmd ffCmd);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDED_INPUTSOURCE_H
|
#endif // INCLUDED_INPUTSOURCE_H
|
|
@ -6,6 +6,11 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
unsigned CInputSystem::totalSrcsAcquired = 0;
|
||||||
|
unsigned CInputSystem::totalSrcsReleased = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
const char *CInputSystem::s_validKeyNames[] =
|
const char *CInputSystem::s_validKeyNames[] =
|
||||||
{
|
{
|
||||||
// General keys
|
// General keys
|
||||||
|
@ -343,17 +348,26 @@ JoyPartsStruct CInputSystem::s_joyParts[] =
|
||||||
{ NULL, JoyUnknown }
|
{ NULL, JoyUnknown }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *CInputSystem::s_axisNames[] = { "X", "Y", "Z", "RX", "RY", "RZ" };
|
||||||
|
|
||||||
CInputSystem::CInputSystem(const char *systemName) :
|
CInputSystem::CInputSystem(const char *systemName) :
|
||||||
name(systemName), m_dispX(0), m_dispY(0), m_dispW(0), m_dispH(0), m_grabMouse(false)
|
name(systemName), m_dispX(0), m_dispY(0), m_dispW(0), m_dispH(0), m_grabMouse(false)
|
||||||
{
|
{
|
||||||
m_emptySource = new CMultiInputSource(this);
|
m_emptySource = new CMultiInputSource();
|
||||||
|
m_emptySource->Acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
CInputSystem::~CInputSystem()
|
CInputSystem::~CInputSystem()
|
||||||
{
|
{
|
||||||
DeleteSourceCache();
|
m_emptySource->Release();
|
||||||
|
|
||||||
ClearSettings();
|
ClearSettings();
|
||||||
delete m_emptySource;
|
ClearSourceCache(true);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (totalSrcsAcquired != totalSrcsReleased)
|
||||||
|
printf("WARNING - number of input source acquisitions (%u) does not equal number of releases (%u)\n", totalSrcsAcquired, totalSrcsReleased);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputSystem::CreateSourceCache()
|
void CInputSystem::CreateSourceCache()
|
||||||
|
@ -398,141 +412,95 @@ void CInputSystem::CreateSourceCache()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CInputSystem::IsInSourceCache(CInputSource *source)
|
void CInputSystem::ClearSourceCache(bool deleteCache)
|
||||||
{
|
{
|
||||||
// Check keyboard source cache
|
// Clear cache of keyboard sources
|
||||||
if (m_anyKeySources != NULL)
|
if (m_anyKeySources != NULL)
|
||||||
{
|
{
|
||||||
for (int keyIndex = 0; keyIndex < NUM_VALID_KEYS; keyIndex++)
|
for (int keyIndex = 0; keyIndex < NUM_VALID_KEYS; keyIndex++)
|
||||||
|
ReleaseSource(m_anyKeySources[keyIndex]);
|
||||||
|
if (deleteCache)
|
||||||
{
|
{
|
||||||
if (source == m_anyKeySources[keyIndex])
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (m_numKbds != ANY_KEYBOARD)
|
|
||||||
{
|
|
||||||
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
|
|
||||||
{
|
|
||||||
for (int keyIndex = 0; keyIndex < NUM_VALID_KEYS; keyIndex++)
|
|
||||||
{
|
|
||||||
if (source == m_keySources[kbdNum][keyIndex])
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check mouse source cache
|
|
||||||
if (m_anyMseSources != NULL)
|
|
||||||
{
|
|
||||||
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
|
||||||
{
|
|
||||||
if (source == m_anyMseSources[mseIndex])
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (m_numMice != ANY_MOUSE)
|
|
||||||
{
|
|
||||||
for (int mseNum = 0; mseNum < m_numMice; mseNum++)
|
|
||||||
{
|
|
||||||
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
|
||||||
{
|
|
||||||
if (source == m_mseSources[mseNum][mseIndex])
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check joystick source cache
|
|
||||||
if (m_anyJoySources != NULL)
|
|
||||||
{
|
|
||||||
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
|
||||||
{
|
|
||||||
if (source == m_anyJoySources[joyIndex])
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (m_numJoys != ANY_JOYSTICK)
|
|
||||||
{
|
|
||||||
for (int joyNum = 0; joyNum < m_numJoys; joyNum++)
|
|
||||||
{
|
|
||||||
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
|
||||||
{
|
|
||||||
if (source == m_joySources[joyNum][joyIndex])
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CInputSystem::DeleteSourceCache()
|
|
||||||
{
|
|
||||||
// Delete cache for keyboard sources
|
|
||||||
if (m_anyKeySources != NULL)
|
|
||||||
{
|
|
||||||
for (int keyIndex = 0; keyIndex < NUM_VALID_KEYS; keyIndex++)
|
|
||||||
DeleteSource(m_anyKeySources[keyIndex]);
|
|
||||||
delete[] m_anyKeySources;
|
delete[] m_anyKeySources;
|
||||||
m_anyKeySources = NULL;
|
m_anyKeySources = NULL;
|
||||||
|
}
|
||||||
if (m_numKbds != ANY_KEYBOARD)
|
if (m_numKbds != ANY_KEYBOARD)
|
||||||
{
|
{
|
||||||
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
|
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
|
||||||
{
|
{
|
||||||
for (int keyIndex = 0; keyIndex < NUM_VALID_KEYS; keyIndex++)
|
for (int keyIndex = 0; keyIndex < NUM_VALID_KEYS; keyIndex++)
|
||||||
DeleteSource(m_keySources[kbdNum][keyIndex]);
|
ReleaseSource(m_keySources[kbdNum][keyIndex]);
|
||||||
|
if (deleteCache)
|
||||||
delete[] m_keySources[kbdNum];
|
delete[] m_keySources[kbdNum];
|
||||||
}
|
}
|
||||||
|
if (deleteCache)
|
||||||
|
{
|
||||||
delete[] m_keySources;
|
delete[] m_keySources;
|
||||||
m_keySources = NULL;
|
m_keySources = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete cache for mouse sources
|
// Clear cache of mouse sources
|
||||||
if (m_anyMseSources != NULL)
|
if (m_anyMseSources != NULL)
|
||||||
{
|
{
|
||||||
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
||||||
DeleteSource(m_anyMseSources[mseIndex]);
|
ReleaseSource(m_anyMseSources[mseIndex]);
|
||||||
|
if (deleteCache)
|
||||||
|
{
|
||||||
delete[] m_anyMseSources;
|
delete[] m_anyMseSources;
|
||||||
m_anyMseSources = NULL;
|
m_anyMseSources = NULL;
|
||||||
|
}
|
||||||
if (m_numMice != ANY_MOUSE)
|
if (m_numMice != ANY_MOUSE)
|
||||||
{
|
{
|
||||||
for (int mseNum = 0; mseNum < m_numMice; mseNum++)
|
for (int mseNum = 0; mseNum < m_numMice; mseNum++)
|
||||||
{
|
{
|
||||||
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
||||||
DeleteSource(m_mseSources[mseNum][mseIndex]);
|
ReleaseSource(m_mseSources[mseNum][mseIndex]);
|
||||||
|
if (deleteCache)
|
||||||
delete[] m_mseSources[mseNum];
|
delete[] m_mseSources[mseNum];
|
||||||
}
|
}
|
||||||
|
if (deleteCache)
|
||||||
|
{
|
||||||
delete[] m_mseSources;
|
delete[] m_mseSources;
|
||||||
m_mseSources = NULL;
|
m_mseSources = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete cache for joystick sources
|
// Clear cache of joystick sources
|
||||||
if (m_anyJoySources != NULL)
|
if (m_anyJoySources != NULL)
|
||||||
{
|
{
|
||||||
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
||||||
DeleteSource(m_anyJoySources[joyIndex]);
|
ReleaseSource(m_anyJoySources[joyIndex]);
|
||||||
|
if (deleteCache)
|
||||||
|
{
|
||||||
delete[] m_anyJoySources;
|
delete[] m_anyJoySources;
|
||||||
m_anyJoySources = NULL;
|
m_anyJoySources = NULL;
|
||||||
|
}
|
||||||
if (m_numJoys != ANY_JOYSTICK)
|
if (m_numJoys != ANY_JOYSTICK)
|
||||||
{
|
{
|
||||||
for (int joyNum = 0; joyNum < m_numJoys; joyNum++)
|
for (int joyNum = 0; joyNum < m_numJoys; joyNum++)
|
||||||
{
|
{
|
||||||
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
||||||
DeleteSource(m_joySources[joyNum][joyIndex]);
|
ReleaseSource(m_joySources[joyNum][joyIndex]);
|
||||||
|
if (deleteCache)
|
||||||
delete[] m_joySources[joyNum];
|
delete[] m_joySources[joyNum];
|
||||||
}
|
}
|
||||||
|
if (deleteCache)
|
||||||
|
{
|
||||||
delete[] m_joySources;
|
delete[] m_joySources;
|
||||||
m_joySources = NULL;
|
m_joySources = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputSystem::DeleteSource(CInputSource *source)
|
void CInputSystem::ReleaseSource(CInputSource *&source)
|
||||||
{
|
{
|
||||||
if (source != NULL && source != m_emptySource)
|
if (source != NULL)
|
||||||
delete source;
|
source->Release();
|
||||||
|
source = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CInputSource *CInputSystem::GetKeySource(int kbdNum, int keyIndex)
|
CInputSource *CInputSystem::GetKeySource(int kbdNum, int keyIndex)
|
||||||
|
@ -546,6 +514,7 @@ CInputSource *CInputSystem::GetKeySource(int kbdNum, int keyIndex)
|
||||||
m_anyKeySources[keyIndex] = CreateKeySource(ANY_KEYBOARD, keyIndex);
|
m_anyKeySources[keyIndex] = CreateKeySource(ANY_KEYBOARD, keyIndex);
|
||||||
else
|
else
|
||||||
m_anyKeySources[keyIndex] = CreateAnyKeySource(keyIndex);
|
m_anyKeySources[keyIndex] = CreateAnyKeySource(keyIndex);
|
||||||
|
m_anyKeySources[keyIndex]->Acquire();
|
||||||
}
|
}
|
||||||
return m_anyKeySources[keyIndex];
|
return m_anyKeySources[keyIndex];
|
||||||
}
|
}
|
||||||
|
@ -553,7 +522,10 @@ CInputSource *CInputSystem::GetKeySource(int kbdNum, int keyIndex)
|
||||||
{
|
{
|
||||||
// Check keyboard source cache first
|
// Check keyboard source cache first
|
||||||
if (m_keySources[kbdNum][keyIndex] == NULL)
|
if (m_keySources[kbdNum][keyIndex] == NULL)
|
||||||
|
{
|
||||||
m_keySources[kbdNum][keyIndex] = CreateKeySource(kbdNum, keyIndex);
|
m_keySources[kbdNum][keyIndex] = CreateKeySource(kbdNum, keyIndex);
|
||||||
|
m_keySources[kbdNum][keyIndex]->Acquire();
|
||||||
|
}
|
||||||
return m_keySources[kbdNum][keyIndex];
|
return m_keySources[kbdNum][keyIndex];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -572,6 +544,7 @@ CInputSource *CInputSystem::GetMouseSource(int mseNum, EMousePart msePart)
|
||||||
m_anyMseSources[mseIndex] = CreateMouseSource(ANY_MOUSE, msePart);
|
m_anyMseSources[mseIndex] = CreateMouseSource(ANY_MOUSE, msePart);
|
||||||
else
|
else
|
||||||
m_anyMseSources[mseIndex] = CreateAnyMouseSource(msePart);
|
m_anyMseSources[mseIndex] = CreateAnyMouseSource(msePart);
|
||||||
|
m_anyMseSources[mseIndex]->Acquire();
|
||||||
}
|
}
|
||||||
return m_anyMseSources[mseIndex];
|
return m_anyMseSources[mseIndex];
|
||||||
}
|
}
|
||||||
|
@ -579,7 +552,10 @@ CInputSource *CInputSystem::GetMouseSource(int mseNum, EMousePart msePart)
|
||||||
{
|
{
|
||||||
// Check mouse source cache first
|
// Check mouse source cache first
|
||||||
if (m_mseSources[mseNum][mseIndex] == NULL)
|
if (m_mseSources[mseNum][mseIndex] == NULL)
|
||||||
|
{
|
||||||
m_mseSources[mseNum][mseIndex] = CreateMouseSource(mseNum, msePart);
|
m_mseSources[mseNum][mseIndex] = CreateMouseSource(mseNum, msePart);
|
||||||
|
m_mseSources[mseNum][mseIndex]->Acquire();
|
||||||
|
}
|
||||||
return m_mseSources[mseNum][mseIndex];
|
return m_mseSources[mseNum][mseIndex];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -598,6 +574,7 @@ CInputSource *CInputSystem::GetJoySource(int joyNum, EJoyPart joyPart)
|
||||||
m_anyJoySources[joyIndex] = CreateJoySource(ANY_JOYSTICK, joyPart);
|
m_anyJoySources[joyIndex] = CreateJoySource(ANY_JOYSTICK, joyPart);
|
||||||
else
|
else
|
||||||
m_anyJoySources[joyIndex] = CreateAnyJoySource(joyPart);
|
m_anyJoySources[joyIndex] = CreateAnyJoySource(joyPart);
|
||||||
|
m_anyJoySources[joyIndex]->Acquire();
|
||||||
}
|
}
|
||||||
return m_anyJoySources[joyIndex];
|
return m_anyJoySources[joyIndex];
|
||||||
}
|
}
|
||||||
|
@ -605,14 +582,63 @@ CInputSource *CInputSystem::GetJoySource(int joyNum, EJoyPart joyPart)
|
||||||
{
|
{
|
||||||
// Check joystick source cache first
|
// Check joystick source cache first
|
||||||
if (m_joySources[joyNum][joyIndex] == NULL)
|
if (m_joySources[joyNum][joyIndex] == NULL)
|
||||||
|
{
|
||||||
m_joySources[joyNum][joyIndex] = CreateJoySource(joyNum, joyPart);
|
m_joySources[joyNum][joyIndex] = CreateJoySource(joyNum, joyPart);
|
||||||
|
m_joySources[joyNum][joyIndex]->Acquire();
|
||||||
|
}
|
||||||
return m_joySources[joyNum][joyIndex];
|
return m_joySources[joyNum][joyIndex];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return m_emptySource;
|
return m_emptySource;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputSystem::CheckKeySources(int kbdNum, bool fullAxisOnly, vector<CInputSource*> &sources, string &mapping)
|
void CInputSystem::CheckAllSources(unsigned readFlags, bool fullAxisOnly, bool &mseCentered, vector<CInputSource*> &sources, string &mapping, vector<CInputSource*> &badSources)
|
||||||
|
{
|
||||||
|
// See if should read keyboards
|
||||||
|
if (readFlags & READ_KEYBOARD)
|
||||||
|
{
|
||||||
|
// Check all keyboard sources for inputs, merging devices if required
|
||||||
|
if ((readFlags & READ_MERGE_KEYBOARD) || m_numKbds == ANY_KEYBOARD)
|
||||||
|
CheckKeySources(ANY_KEYBOARD, fullAxisOnly, sources, mapping, badSources);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
|
||||||
|
CheckKeySources(kbdNum, fullAxisOnly, sources, mapping, badSources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if should read mice
|
||||||
|
if (readFlags & READ_MOUSE)
|
||||||
|
{
|
||||||
|
// For mouse input, wait until mouse is in centre of display before parsing X- and Y-axis movements
|
||||||
|
if (!mseCentered)
|
||||||
|
mseCentered = ConfigMouseCentered();
|
||||||
|
|
||||||
|
// Check all mouse sources for input, merging devices if required
|
||||||
|
if ((readFlags & READ_MERGE_MOUSE) || m_numMice == ANY_MOUSE)
|
||||||
|
CheckMouseSources(ANY_MOUSE, fullAxisOnly, mseCentered, sources, mapping, badSources);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int mseNum = 0; mseNum < m_numMice; mseNum++)
|
||||||
|
CheckMouseSources(mseNum, fullAxisOnly, mseCentered, sources, mapping, badSources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if should read joysticks
|
||||||
|
if (readFlags & READ_JOYSTICK)
|
||||||
|
{
|
||||||
|
// Check all joystick sources, merging devices if required
|
||||||
|
if ((readFlags & READ_MERGE_JOYSTICK) || m_numJoys == ANY_JOYSTICK)
|
||||||
|
CheckJoySources(ANY_JOYSTICK, fullAxisOnly, sources, mapping, badSources);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int joyNum = 0; joyNum < m_numJoys; joyNum++)
|
||||||
|
CheckJoySources(joyNum, fullAxisOnly, sources, mapping, badSources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInputSystem::CheckKeySources(int kbdNum, bool fullAxisOnly, vector<CInputSource*> &sources, string &mapping, vector<CInputSource*> &badSources)
|
||||||
{
|
{
|
||||||
// Loop through all valid keys
|
// Loop through all valid keys
|
||||||
for (int i = 0; i < NUM_VALID_KEYS; i++)
|
for (int i = 0; i < NUM_VALID_KEYS; i++)
|
||||||
|
@ -621,9 +647,10 @@ void CInputSystem::CheckKeySources(int kbdNum, bool fullAxisOnly, vector<CInputS
|
||||||
int keyIndex = GetKeyIndex(keyName);
|
int keyIndex = GetKeyIndex(keyName);
|
||||||
if (keyIndex < 0)
|
if (keyIndex < 0)
|
||||||
continue;
|
continue;
|
||||||
// Get key source for keyboard number and key and test it to see if it is active (but was not previously)
|
// Get key source for keyboard number and key and test to see if it is active (but was not previously) and that it is not a "bad" source
|
||||||
CInputSource *source = GetKeySource(kbdNum, keyIndex);
|
CInputSource *source = GetKeySource(kbdNum, keyIndex);
|
||||||
if (source != NULL && source->IsActive() && find(sources.begin(), sources.end(), source) == sources.end())
|
if (source != NULL && source->IsActive() && find(sources.begin(), sources.end(), source) == sources.end() &&
|
||||||
|
find(badSources.begin(), badSources.end(), source) == badSources.end())
|
||||||
{
|
{
|
||||||
// Update mapping string and add source to list
|
// Update mapping string and add source to list
|
||||||
if (sources.size() == 0)
|
if (sources.size() == 0)
|
||||||
|
@ -639,7 +666,7 @@ void CInputSystem::CheckKeySources(int kbdNum, bool fullAxisOnly, vector<CInputS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputSystem::CheckMouseSources(int mseNum, bool fullAxisOnly, bool mseCentered, vector<CInputSource*> &sources, string &mapping)
|
void CInputSystem::CheckMouseSources(int mseNum, bool fullAxisOnly, bool mseCentered, vector<CInputSource*> &sources, string &mapping, vector<CInputSource*> &badSources)
|
||||||
{
|
{
|
||||||
// Loop through all mouse parts
|
// Loop through all mouse parts
|
||||||
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
||||||
|
@ -653,9 +680,10 @@ void CInputSystem::CheckMouseSources(int mseNum, bool fullAxisOnly, bool mseCent
|
||||||
// Ignore X- & Y-axes if mouse hasn't been centered yet and filter axes according to fullAxisOnly
|
// Ignore X- & Y-axes if mouse hasn't been centered yet and filter axes according to fullAxisOnly
|
||||||
if (isXYAxis && !mseCentered || isAxis && (IsFullAxis(msePart) && !fullAxisOnly || !IsFullAxis(msePart) && fullAxisOnly))
|
if (isXYAxis && !mseCentered || isAxis && (IsFullAxis(msePart) && !fullAxisOnly || !IsFullAxis(msePart) && fullAxisOnly))
|
||||||
continue;
|
continue;
|
||||||
// Get mouse source for mouse number and part and test it to see if it is active (but was not previously)
|
// Get mouse source for mouse number and part and test to see if it is active (but was not previously) and that it is not a "bad" source
|
||||||
CInputSource *source = GetMouseSource(mseNum, msePart);
|
CInputSource *source = GetMouseSource(mseNum, msePart);
|
||||||
if (source != NULL && source->IsActive() && find(sources.begin(), sources.end(), source) == sources.end())
|
if (source != NULL && source->IsActive() && find(sources.begin(), sources.end(), source) == sources.end() &&
|
||||||
|
find(badSources.begin(), badSources.end(), source) == badSources.end())
|
||||||
{
|
{
|
||||||
// Otherwise, update mapping string and add source to list
|
// Otherwise, update mapping string and add source to list
|
||||||
const char *partName = LookupName(msePart);
|
const char *partName = LookupName(msePart);
|
||||||
|
@ -672,7 +700,7 @@ void CInputSystem::CheckMouseSources(int mseNum, bool fullAxisOnly, bool mseCent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputSystem::CheckJoySources(int joyNum, bool fullAxisOnly, vector<CInputSource*> &sources, string &mapping)
|
void CInputSystem::CheckJoySources(int joyNum, bool fullAxisOnly, vector<CInputSource*> &sources, string &mapping, vector<CInputSource*> &badSources)
|
||||||
{
|
{
|
||||||
// Loop through all joystick parts
|
// Loop through all joystick parts
|
||||||
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
||||||
|
@ -681,9 +709,10 @@ void CInputSystem::CheckJoySources(int joyNum, bool fullAxisOnly, vector<CInputS
|
||||||
// Filter axes according to fullAxisOnly
|
// Filter axes according to fullAxisOnly
|
||||||
if (IsAxis(joyPart) && (IsFullAxis(joyPart) && !fullAxisOnly || !IsFullAxis(joyPart) && fullAxisOnly))
|
if (IsAxis(joyPart) && (IsFullAxis(joyPart) && !fullAxisOnly || !IsFullAxis(joyPart) && fullAxisOnly))
|
||||||
continue;
|
continue;
|
||||||
// Get joystick source for joystick number and part and test it to see if it is active (but was not previously)
|
// Get joystick source for joystick number and part and test to see if it is active (but was not previously) and that it is not a "bad" source
|
||||||
CInputSource *source = GetJoySource(joyNum, joyPart);
|
CInputSource *source = GetJoySource(joyNum, joyPart);
|
||||||
if (source != NULL && source->IsActive() && find(sources.begin(), sources.end(), source) == sources.end())
|
if (source != NULL && source->IsActive() && find(sources.begin(), sources.end(), source) == sources.end() &&
|
||||||
|
find(badSources.begin(), badSources.end(), source) == badSources.end())
|
||||||
{
|
{
|
||||||
// Otherwise, update mapping string and add source to list
|
// Otherwise, update mapping string and add source to list
|
||||||
const char *partName = LookupName(joyPart);
|
const char *partName = LookupName(joyPart);
|
||||||
|
@ -870,7 +899,7 @@ CInputSource* CInputSystem::ParseMultiSource(string str, bool fullAxisOnly, bool
|
||||||
while (start < size);
|
while (start < size);
|
||||||
|
|
||||||
// If only parsed a single source, return that, otherwise return a CMultiInputSource combining all the sources
|
// If only parsed a single source, return that, otherwise return a CMultiInputSource combining all the sources
|
||||||
return (isMulti ? new CMultiInputSource(this, isOr, sources) : source);
|
return (isMulti ? new CMultiInputSource(isOr, sources) : source);
|
||||||
}
|
}
|
||||||
|
|
||||||
CInputSource *CInputSystem::ParseSingleSource(string str)
|
CInputSource *CInputSystem::ParseSingleSource(string str)
|
||||||
|
@ -886,7 +915,7 @@ CInputSource *CInputSystem::ParseSingleSource(string str)
|
||||||
|
|
||||||
CInputSource *source = ParseSingleSource(str);
|
CInputSource *source = ParseSingleSource(str);
|
||||||
if (source != NULL && source != m_emptySource)
|
if (source != NULL && source != m_emptySource)
|
||||||
return new CNegInputSource(this, source);
|
return new CNegInputSource(source);
|
||||||
else
|
else
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
@ -924,7 +953,7 @@ CInputSource *CInputSystem::ParseSingleSource(string str)
|
||||||
sources.push_back(rightSource);
|
sources.push_back(rightSource);
|
||||||
}
|
}
|
||||||
if (sources.size() > 0)
|
if (sources.size() > 0)
|
||||||
return new CMultiInputSource(this, true, sources);
|
return new CMultiInputSource(true, sources);
|
||||||
}
|
}
|
||||||
return m_emptySource;
|
return m_emptySource;
|
||||||
}
|
}
|
||||||
|
@ -1037,9 +1066,12 @@ void CInputSystem::PrintMouseSettings(MouseSettings *settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print all common settings and any settings that are different to common/default settings
|
// Print all common settings and any settings that are different to common/default settings
|
||||||
if (common == NULL || settings->xDeadZone != common->xDeadZone) printf(" X Dead Zone = %d %%\n", settings->xDeadZone);
|
for (int axisNum = 0; axisNum < NUM_MOUSE_AXES; axisNum++)
|
||||||
if (common == NULL || settings->yDeadZone != common->yDeadZone) printf(" Y Dead Zone = %d %%\n", settings->yDeadZone);
|
{
|
||||||
if (common == NULL || settings->zDeadZone != common->zDeadZone) printf(" Z Dead Zone = %d %%\n", settings->zDeadZone);
|
const char *axisName = s_axisNames[axisNum];
|
||||||
|
if (common == NULL || settings->deadZones[axisNum] != common->deadZones[axisNum])
|
||||||
|
printf(" %s-Axis Dead Zone = %d %%\n", axisName, settings->deadZones[axisNum]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseSettings *CInputSystem::ReadMouseSettings(CINIFile *ini, const char *section, int mseNum)
|
MouseSettings *CInputSystem::ReadMouseSettings(CINIFile *ini, const char *section, int mseNum)
|
||||||
|
@ -1054,9 +1086,11 @@ MouseSettings *CInputSystem::ReadMouseSettings(CINIFile *ini, const char *sectio
|
||||||
if (mseNum != ANY_MOUSE)
|
if (mseNum != ANY_MOUSE)
|
||||||
baseKey.append(IntToString(mseNum + 1));
|
baseKey.append(IntToString(mseNum + 1));
|
||||||
bool read = false;
|
bool read = false;
|
||||||
read |= ini->Get(section, baseKey + "XDeadZone", settings->xDeadZone) == OKAY;
|
for (int axisNum = 0; axisNum < NUM_MOUSE_AXES; axisNum++)
|
||||||
read |= ini->Get(section, baseKey + "YDeadZone", settings->yDeadZone) == OKAY;
|
{
|
||||||
read |= ini->Get(section, baseKey + "ZDeadZone", settings->zDeadZone) == OKAY;
|
const char *axisName = s_axisNames[axisNum];
|
||||||
|
read |= ini->Get(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]) == OKAY;
|
||||||
|
}
|
||||||
if (read)
|
if (read)
|
||||||
return settings;
|
return settings;
|
||||||
delete settings;
|
delete settings;
|
||||||
|
@ -1072,9 +1106,12 @@ void CInputSystem::WriteMouseSettings(CINIFile *ini, const char *section, MouseS
|
||||||
string baseKey("InputMouse");
|
string baseKey("InputMouse");
|
||||||
if (settings->mseNum != ANY_MOUSE)
|
if (settings->mseNum != ANY_MOUSE)
|
||||||
baseKey.append(IntToString(settings->mseNum + 1));
|
baseKey.append(IntToString(settings->mseNum + 1));
|
||||||
if (settings->xDeadZone != common->xDeadZone) ini->Set(section, baseKey + "XDeadZone", settings->xDeadZone);
|
for (int axisNum = 0; axisNum < NUM_MOUSE_AXES; axisNum++)
|
||||||
if (settings->yDeadZone != common->yDeadZone) ini->Set(section, baseKey + "YDeadZone", settings->yDeadZone);
|
{
|
||||||
if (settings->zDeadZone != common->zDeadZone) ini->Set(section, baseKey + "ZDeadZone", settings->zDeadZone);
|
const char *axisName = s_axisNames[axisNum];
|
||||||
|
if (settings->deadZones[axisNum] != common->deadZones[axisNum])
|
||||||
|
ini->Set(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputSystem::PrintJoySettings(JoySettings *settings)
|
void CInputSystem::PrintJoySettings(JoySettings *settings)
|
||||||
|
@ -1093,18 +1130,20 @@ void CInputSystem::PrintJoySettings(JoySettings *settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print all common settings and any settings that are different to common/default settings
|
// Print all common settings and any settings that are different to common/default settings
|
||||||
if (common == NULL || settings->xDeadZone != common->xDeadZone) printf(" X-Axis Dead Zone = %d %%\n", settings->xDeadZone);
|
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||||
if (common == NULL || settings->xSaturation != common->xSaturation) printf(" X-Axis Saturation = %d %%\n", settings->xSaturation);
|
{
|
||||||
if (common == NULL || settings->yDeadZone != common->yDeadZone) printf(" Y-Axis Dead Zone = %d %%\n", settings->yDeadZone);
|
const char *axisName = s_axisNames[axisNum];
|
||||||
if (common == NULL || settings->ySaturation != common->ySaturation) printf(" Y-Axis Saturation = %d %%\n", settings->ySaturation);
|
if (common == NULL || settings->axisMinVals[axisNum] != common->axisMinVals[axisNum])
|
||||||
if (common == NULL || settings->zDeadZone != common->zDeadZone) printf(" Z-Axis Dead Zone = %d %%\n", settings->zDeadZone);
|
printf(" %-2s-Axis Min Value = %d\n", axisName, settings->axisMinVals[axisNum]);
|
||||||
if (common == NULL || settings->zSaturation != common->zSaturation) printf(" Z-Axis Saturation = %d %%\n", settings->zSaturation);
|
if (common == NULL || settings->axisOffVals[axisNum] != common->axisOffVals[axisNum])
|
||||||
if (common == NULL || settings->rxDeadZone != common->rxDeadZone) printf(" RX-Axis Dead Zone = %d %%\n", settings->rxDeadZone);
|
printf(" %-2s-Axis Center/Off Value = %d\n", axisName, settings->axisOffVals[axisNum]);
|
||||||
if (common == NULL || settings->rxSaturation != common->rxSaturation) printf(" RX-Axis Saturation = %d %%\n", settings->rxSaturation);
|
if (common == NULL || settings->axisMaxVals[axisNum] != common->axisMaxVals[axisNum])
|
||||||
if (common == NULL || settings->ryDeadZone != common->ryDeadZone) printf(" RY-Axis Dead Zone = %d %%\n", settings->ryDeadZone);
|
printf(" %-2s-Axis Max Value = %d\n", axisName, settings->axisMaxVals[axisNum]);
|
||||||
if (common == NULL || settings->rySaturation != common->rySaturation) printf(" RY-Axis Saturation = %d %%\n", settings->rySaturation);
|
if (common == NULL || settings->deadZones[axisNum] != common->deadZones[axisNum])
|
||||||
if (common == NULL || settings->rzDeadZone != common->rzDeadZone) printf(" RZ-Axis Dead Zone = %d %%\n", settings->rzDeadZone);
|
printf(" %-2s-Axis Dead Zone = %d %%\n", axisName, settings->deadZones[axisNum]);
|
||||||
if (common == NULL || settings->rzSaturation != common->rzSaturation) printf(" RZ-Axis Saturation = %d %%\n", settings->rzSaturation);
|
if (common == NULL || settings->saturations[axisNum] != common->saturations[axisNum])
|
||||||
|
printf(" %-2s-Axis Saturation = %d %%\n", axisName, settings->saturations[axisNum]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JoySettings *CInputSystem::ReadJoySettings(CINIFile *ini, const char *section, int joyNum)
|
JoySettings *CInputSystem::ReadJoySettings(CINIFile *ini, const char *section, int joyNum)
|
||||||
|
@ -1119,18 +1158,15 @@ JoySettings *CInputSystem::ReadJoySettings(CINIFile *ini, const char *section, i
|
||||||
if (joyNum != ANY_JOYSTICK)
|
if (joyNum != ANY_JOYSTICK)
|
||||||
baseKey.append(IntToString(joyNum + 1));
|
baseKey.append(IntToString(joyNum + 1));
|
||||||
bool read = false;
|
bool read = false;
|
||||||
read |= ini->Get(section, baseKey + "XDeadZone", settings->xDeadZone) == OKAY;
|
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||||
read |= ini->Get(section, baseKey + "XSaturation", settings->xSaturation) == OKAY;
|
{
|
||||||
read |= ini->Get(section, baseKey + "YDeadZone", settings->yDeadZone) == OKAY;
|
const char *axisName = s_axisNames[axisNum];
|
||||||
read |= ini->Get(section, baseKey + "YSaturation", settings->ySaturation) == OKAY;
|
read |= ini->Get(section, baseKey + axisName + "MinVal", settings->axisMinVals[axisNum]) == OKAY;
|
||||||
read |= ini->Get(section, baseKey + "ZDeadZone", settings->zDeadZone) == OKAY;
|
read |= ini->Get(section, baseKey + axisName + "OffVal", settings->axisOffVals[axisNum]) == OKAY;
|
||||||
read |= ini->Get(section, baseKey + "ZSaturation", settings->zSaturation) == OKAY;
|
read |= ini->Get(section, baseKey + axisName + "MaxVal", settings->axisMaxVals[axisNum]) == OKAY;
|
||||||
read |= ini->Get(section, baseKey + "RXDeadZone", settings->rxDeadZone) == OKAY;
|
read |= ini->Get(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]) == OKAY;
|
||||||
read |= ini->Get(section, baseKey + "RXSaturation", settings->rxSaturation) == OKAY;
|
read |= ini->Get(section, baseKey + axisName + "Saturation", settings->saturations[axisNum]) == OKAY;
|
||||||
read |= ini->Get(section, baseKey + "RYDeadZone", settings->ryDeadZone) == OKAY;
|
}
|
||||||
read |= ini->Get(section, baseKey + "RYSaturation", settings->rySaturation) == OKAY;
|
|
||||||
read |= ini->Get(section, baseKey + "RZDeadZone", settings->rzDeadZone) == OKAY;
|
|
||||||
read |= ini->Get(section, baseKey + "RZSaturation", settings->rzSaturation) == OKAY;
|
|
||||||
if (read)
|
if (read)
|
||||||
return settings;
|
return settings;
|
||||||
delete settings;
|
delete settings;
|
||||||
|
@ -1146,18 +1182,20 @@ void CInputSystem::WriteJoySettings(CINIFile *ini, const char *section, JoySetti
|
||||||
string baseKey("InputJoy");
|
string baseKey("InputJoy");
|
||||||
if (settings->joyNum != ANY_JOYSTICK)
|
if (settings->joyNum != ANY_JOYSTICK)
|
||||||
baseKey.append(IntToString(settings->joyNum + 1));
|
baseKey.append(IntToString(settings->joyNum + 1));
|
||||||
if (settings->xDeadZone != common->xDeadZone) ini->Set(section, baseKey + "XDeadZone", settings->xDeadZone);
|
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||||
if (settings->xSaturation != common->xSaturation) ini->Set(section, baseKey + "XSaturation", settings->xSaturation);
|
{
|
||||||
if (settings->yDeadZone != common->yDeadZone) ini->Set(section, baseKey + "YDeadZone", settings->yDeadZone);
|
const char *axisName = s_axisNames[axisNum];
|
||||||
if (settings->ySaturation != common->ySaturation) ini->Set(section, baseKey + "YSaturation", settings->ySaturation);
|
if (settings->axisMinVals[axisNum] != common->axisMinVals[axisNum])
|
||||||
if (settings->zDeadZone != common->zDeadZone) ini->Set(section, baseKey + "ZDeadZone", settings->zDeadZone);
|
ini->Set(section, baseKey + axisName + "MinVal", settings->axisMinVals[axisNum]);
|
||||||
if (settings->zSaturation != common->zSaturation) ini->Set(section, baseKey + "ZSaturation", settings->zSaturation);
|
if (settings->axisOffVals[axisNum] != common->axisOffVals[axisNum])
|
||||||
if (settings->rxDeadZone != common->rxDeadZone) ini->Set(section, baseKey + "RXDeadZone", settings->rxDeadZone);
|
ini->Set(section, baseKey + axisName + "OffVal", settings->axisOffVals[axisNum]);
|
||||||
if (settings->rxSaturation != common->rxSaturation) ini->Set(section, baseKey + "RXSaturation", settings->rxSaturation);
|
if (settings->axisMaxVals[axisNum] != common->axisMaxVals[axisNum])
|
||||||
if (settings->ryDeadZone != common->ryDeadZone) ini->Set(section, baseKey + "RYDeadZone", settings->ryDeadZone);
|
ini->Set(section, baseKey + axisName + "MaxVal", settings->axisMaxVals[axisNum]);
|
||||||
if (settings->rySaturation != common->rySaturation) ini->Set(section, baseKey + "RYSaturation", settings->rySaturation);
|
if (settings->deadZones[axisNum] != common->deadZones[axisNum])
|
||||||
if (settings->rzDeadZone != common->rzDeadZone) ini->Set(section, baseKey + "RZDeadZone", settings->rzDeadZone);
|
ini->Set(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]);
|
||||||
if (settings->rzSaturation != common->rzSaturation) ini->Set(section, baseKey + "RZSaturation", settings->rzSaturation);
|
if (settings->saturations[axisNum] != common->saturations[axisNum])
|
||||||
|
ini->Set(section, baseKey + axisName + "Saturation", settings->saturations[axisNum]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KeySettings *CInputSystem::GetKeySettings(int kbdNum, bool useDefault)
|
KeySettings *CInputSystem::GetKeySettings(int kbdNum, bool useDefault)
|
||||||
|
@ -1338,7 +1376,7 @@ CInputSource *CInputSystem::CreateAnyKeySource(int keyIndex)
|
||||||
if (keySrc != NULL)
|
if (keySrc != NULL)
|
||||||
keySrcs.push_back(keySrc);
|
keySrcs.push_back(keySrc);
|
||||||
}
|
}
|
||||||
return new CMultiInputSource(this, true, keySrcs);
|
return new CMultiInputSource(true, keySrcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
CInputSource *CInputSystem::CreateAnyMouseSource(EMousePart msePart)
|
CInputSource *CInputSystem::CreateAnyMouseSource(EMousePart msePart)
|
||||||
|
@ -1351,7 +1389,7 @@ CInputSource *CInputSystem::CreateAnyMouseSource(EMousePart msePart)
|
||||||
if (mseSrc != NULL)
|
if (mseSrc != NULL)
|
||||||
mseSrcs.push_back(mseSrc);
|
mseSrcs.push_back(mseSrc);
|
||||||
}
|
}
|
||||||
return new CMultiInputSource(this, true, mseSrcs);
|
return new CMultiInputSource(true, mseSrcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
CInputSource *CInputSystem::CreateAnyJoySource(EJoyPart joyPart)
|
CInputSource *CInputSystem::CreateAnyJoySource(EJoyPart joyPart)
|
||||||
|
@ -1364,7 +1402,7 @@ CInputSource *CInputSystem::CreateAnyJoySource(EJoyPart joyPart)
|
||||||
if (joySrc != NULL)
|
if (joySrc != NULL)
|
||||||
joySrcs.push_back(joySrc);
|
joySrcs.push_back(joySrc);
|
||||||
}
|
}
|
||||||
return new CMultiInputSource(this, true, joySrcs);
|
return new CMultiInputSource(true, joySrcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
CInputSource *CInputSystem::CreateKeySource(int kbdNum, int keyIndex)
|
CInputSource *CInputSystem::CreateKeySource(int kbdNum, int keyIndex)
|
||||||
|
@ -1386,16 +1424,8 @@ CInputSource *CInputSystem::CreateMouseSource(int mseNum, EMousePart msePart)
|
||||||
int axisDir;
|
int axisDir;
|
||||||
if (GetAxisDetails(msePart, axisNum, axisDir))
|
if (GetAxisDetails(msePart, axisNum, axisDir))
|
||||||
{
|
{
|
||||||
// Part is mouse axis so get the deadzone setting for it
|
// Part is mouse axis so create axis source with appropriate deadzone setting
|
||||||
unsigned deadZone;
|
return new CMseAxisInputSource(this, mseNum, axisNum, axisDir, settings->deadZones[axisNum]);
|
||||||
switch (axisNum)
|
|
||||||
{
|
|
||||||
case AXIS_X: deadZone = settings->xDeadZone; break;
|
|
||||||
case AXIS_Y: deadZone = settings->yDeadZone; break;
|
|
||||||
case AXIS_Z: deadZone = settings->zDeadZone; break;
|
|
||||||
default: return NULL; // Any other axis numbers are invalid
|
|
||||||
}
|
|
||||||
return new CMseAxisInputSource(this, mseNum, axisNum, axisDir, deadZone);
|
|
||||||
}
|
}
|
||||||
else if (IsButton(msePart))
|
else if (IsButton(msePart))
|
||||||
{
|
{
|
||||||
|
@ -1423,23 +1453,13 @@ CInputSource *CInputSystem::CreateJoySource(int joyNum, EJoyPart joyPart)
|
||||||
int povDir;
|
int povDir;
|
||||||
if (GetAxisDetails(joyPart, axisNum, axisDir))
|
if (GetAxisDetails(joyPart, axisNum, axisDir))
|
||||||
{
|
{
|
||||||
// Part is joystick axis so get the deadzone and saturation settings for it
|
// Part is joystick axis, so see whether joystick actually has this axis
|
||||||
unsigned axisDZone;
|
|
||||||
unsigned axisSat;
|
|
||||||
switch (axisNum)
|
|
||||||
{
|
|
||||||
case AXIS_X: axisDZone = settings->xDeadZone; axisSat = settings->xSaturation; break;
|
|
||||||
case AXIS_Y: axisDZone = settings->yDeadZone; axisSat = settings->ySaturation; break;
|
|
||||||
case AXIS_Z: axisDZone = settings->zDeadZone; axisSat = settings->zSaturation; break;
|
|
||||||
case AXIS_RX: axisDZone = settings->rxDeadZone; axisSat = settings->rxSaturation; break;
|
|
||||||
case AXIS_RY: axisDZone = settings->ryDeadZone; axisSat = settings->rySaturation; break;
|
|
||||||
case AXIS_RZ: axisDZone = settings->rzDeadZone; axisSat = settings->rzSaturation; break;
|
|
||||||
default: return NULL; // Any other axis numbers are invalid
|
|
||||||
}
|
|
||||||
// See whether joystick has this axis
|
|
||||||
if (!joyDetails->hasAxis[axisNum])
|
if (!joyDetails->hasAxis[axisNum])
|
||||||
return m_emptySource; // If joystick doesn't have axis, then return empty source rather than NULL as not really an error
|
return m_emptySource; // If joystick doesn't have axis, then return empty source rather than NULL as not really an error
|
||||||
return new CJoyAxisInputSource(this, joyNum, axisNum, axisDir, axisDZone, axisSat);
|
// Otherwise, create axis source with appropriate axis range, deadzone and saturation settings
|
||||||
|
return new CJoyAxisInputSource(this, joyNum, axisNum, axisDir,
|
||||||
|
settings->axisMinVals[axisNum], settings->axisOffVals[axisNum], settings->axisMaxVals[axisNum],
|
||||||
|
settings->deadZones[axisNum], settings->saturations[axisNum]);
|
||||||
}
|
}
|
||||||
else if (GetPOVDetails(joyPart, povNum, povDir))
|
else if (GetPOVDetails(joyPart, povNum, povDir))
|
||||||
{
|
{
|
||||||
|
@ -1452,7 +1472,7 @@ CInputSource *CInputSystem::CreateJoySource(int joyNum, EJoyPart joyPart)
|
||||||
{
|
{
|
||||||
// Part is joystick button so map it to a button number
|
// Part is joystick button so map it to a button number
|
||||||
int butNum = GetButtonNumber(joyPart);
|
int butNum = GetButtonNumber(joyPart);
|
||||||
if (butNum < 0)
|
if (butNum < 0 || butNum >= NUM_JOY_BUTTONS)
|
||||||
return NULL; // Buttons out of range are invalid
|
return NULL; // Buttons out of range are invalid
|
||||||
if (butNum >= joyDetails->numButtons)
|
if (butNum >= joyDetails->numButtons)
|
||||||
return m_emptySource; // If joystick doesn't have button, then return empty source rather than NULL as not really an error
|
return m_emptySource; // If joystick doesn't have button, then return empty source rather than NULL as not really an error
|
||||||
|
@ -1493,13 +1513,6 @@ CInputSource* CInputSystem::ParseSource(const char *mapping, bool fullAxisOnly)
|
||||||
return ParseMultiSource(mapping, fullAxisOnly, true);
|
return ParseMultiSource(mapping, fullAxisOnly, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputSystem::ReleaseSource(CInputSource *source)
|
|
||||||
{
|
|
||||||
// If source is not being cached then delete it
|
|
||||||
if (!IsInSourceCache(source))
|
|
||||||
DeleteSource(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CInputSystem::ClearSettings()
|
void CInputSystem::ClearSettings()
|
||||||
{
|
{
|
||||||
// Delete all key settings
|
// Delete all key settings
|
||||||
|
@ -1568,6 +1581,7 @@ void CInputSystem::PrintSettings()
|
||||||
void CInputSystem::ReadFromINIFile(CINIFile *ini, const char *section)
|
void CInputSystem::ReadFromINIFile(CINIFile *ini, const char *section)
|
||||||
{
|
{
|
||||||
ClearSettings();
|
ClearSettings();
|
||||||
|
ClearSourceCache();
|
||||||
|
|
||||||
// Read all key settings for attached keyboards
|
// Read all key settings for attached keyboards
|
||||||
KeySettings *keySettings = ReadKeySettings(ini, section, ANY_KEYBOARD);
|
KeySettings *keySettings = ReadKeySettings(ini, section, ANY_KEYBOARD);
|
||||||
|
@ -1622,17 +1636,33 @@ bool CInputSystem::ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly
|
||||||
{
|
{
|
||||||
// Map given escape mapping to an input source
|
// Map given escape mapping to an input source
|
||||||
CInputSource *escape = ParseSource(escapeMapping);
|
CInputSource *escape = ParseSource(escapeMapping);
|
||||||
|
escape->Acquire();
|
||||||
|
|
||||||
|
string badMapping;
|
||||||
string mapping;
|
string mapping;
|
||||||
|
vector<CInputSource*> badSources;
|
||||||
vector<CInputSource*> sources;
|
vector<CInputSource*> sources;
|
||||||
bool mseCentered = false;
|
bool mseCentered = false;
|
||||||
|
|
||||||
|
// See which sources activated to begin with and from here on ignore these (this stops badly calibrated axes that are constantly "active"
|
||||||
|
// from preventing the user from exiting read loop)
|
||||||
|
if (!Poll())
|
||||||
|
{
|
||||||
|
escape->Release();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckAllSources(readFlags, fullAxisOnly, mseCentered, badSources, badMapping, sources);
|
||||||
|
|
||||||
// Loop until have received meaningful inputs
|
// Loop until have received meaningful inputs
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
// Poll inputs
|
// Poll inputs
|
||||||
if (!Poll())
|
if (!Poll())
|
||||||
|
{
|
||||||
|
escape->Release();
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if escape source was triggered
|
// Check if escape source was triggered
|
||||||
if (escape != NULL && escape->IsActive())
|
if (escape != NULL && escape->IsActive())
|
||||||
|
@ -1641,56 +1671,20 @@ bool CInputSystem::ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly
|
||||||
while (escape->IsActive())
|
while (escape->IsActive())
|
||||||
{
|
{
|
||||||
if (!Poll())
|
if (!Poll())
|
||||||
|
{
|
||||||
|
escape->Release();
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
Wait(1000/60);
|
Wait(1000/60);
|
||||||
}
|
}
|
||||||
|
escape->Release();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if should read keyboards
|
// Check all active sources
|
||||||
if (readFlags & READ_KEYBOARD)
|
CheckAllSources(readFlags, fullAxisOnly, mseCentered, sources, mapping, badSources);
|
||||||
{
|
|
||||||
// Check all keyboard sources for inputs, merging devices if required
|
|
||||||
if ((readFlags & READ_MERGE_KEYBOARD) || m_numKbds == ANY_KEYBOARD)
|
|
||||||
CheckKeySources(ANY_KEYBOARD, fullAxisOnly, sources, mapping);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
|
|
||||||
CheckKeySources(kbdNum, fullAxisOnly, sources, mapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if should read mice
|
// When some inputs have been activated, keep looping until they have all been released again.
|
||||||
if (readFlags & READ_MOUSE)
|
|
||||||
{
|
|
||||||
// For mouse input, wait until mouse is in centre of display before parsing X- and Y-axis movements
|
|
||||||
if (!mseCentered)
|
|
||||||
mseCentered = ConfigMouseCentered();
|
|
||||||
|
|
||||||
// Check all mouse sources for input, merging devices if required
|
|
||||||
if ((readFlags & READ_MERGE_MOUSE) || m_numMice == ANY_MOUSE)
|
|
||||||
CheckMouseSources(ANY_MOUSE, fullAxisOnly, mseCentered, sources, mapping);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int mseNum = 0; mseNum < m_numMice; mseNum++)
|
|
||||||
CheckMouseSources(mseNum, fullAxisOnly, mseCentered, sources, mapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if should read joysticks
|
|
||||||
if (readFlags & READ_JOYSTICK)
|
|
||||||
{
|
|
||||||
// Check all joystick sources, merging devices if required
|
|
||||||
if ((readFlags & READ_MERGE_JOYSTICK) || m_numJoys == ANY_JOYSTICK)
|
|
||||||
CheckJoySources(ANY_JOYSTICK, fullAxisOnly, sources, mapping);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int joyNum = 0; joyNum < m_numJoys; joyNum++)
|
|
||||||
CheckJoySources(joyNum, fullAxisOnly, sources, mapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// When some inputs have been activated, keep lopping until they have all been released again.
|
|
||||||
if (sources.size() > 0)
|
if (sources.size() > 0)
|
||||||
{
|
{
|
||||||
// Check each source is no longer active
|
// Check each source is no longer active
|
||||||
|
@ -1723,6 +1717,8 @@ bool CInputSystem::ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly
|
||||||
// Copy mapping to buffer and return
|
// Copy mapping to buffer and return
|
||||||
strncpy(buffer, mapping.c_str(), bufSize - 1);
|
strncpy(buffer, mapping.c_str(), bufSize - 1);
|
||||||
buffer[bufSize - 1] = '\0';
|
buffer[bufSize - 1] = '\0';
|
||||||
|
|
||||||
|
escape->Release();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1739,6 +1735,62 @@ void CInputSystem::UngrabMouse()
|
||||||
SetMouseVisibility(true);
|
SetMouseVisibility(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CInputSystem::SendForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd)
|
||||||
|
{
|
||||||
|
const JoyDetails *joyDetails = GetJoyDetails(joyNum);
|
||||||
|
if (!joyDetails->hasFFeedback || !joyDetails->axisHasFF[axisNum])
|
||||||
|
return false;
|
||||||
|
return ProcessForceFeedbackCmd(joyNum, axisNum, ffCmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CInputSystem::PrintDevices()
|
||||||
|
{
|
||||||
|
puts("Keyboards:");
|
||||||
|
if (m_numKbds == 0)
|
||||||
|
puts(" None");
|
||||||
|
else if (m_numKbds == ANY_KEYBOARD)
|
||||||
|
puts(" System Keyboard");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
|
||||||
|
{
|
||||||
|
const KeyDetails *keyDetails = GetKeyDetails(kbdNum);
|
||||||
|
printf(" %d: %s\n", kbdNum + 1, keyDetails->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("Mice:");
|
||||||
|
if (m_numMice == 0)
|
||||||
|
puts(" None");
|
||||||
|
else if (m_numMice == ANY_MOUSE)
|
||||||
|
puts(" System Mouse");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int mseNum = 0; mseNum < m_numMice; mseNum++)
|
||||||
|
{
|
||||||
|
const MouseDetails *mseDetails = GetMouseDetails(mseNum);
|
||||||
|
printf(" %d: %s\n", mseNum + 1, mseDetails->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("Joysticks:");
|
||||||
|
if (m_numJoys == 0)
|
||||||
|
puts(" None");
|
||||||
|
else if (m_numJoys == ANY_JOYSTICK)
|
||||||
|
puts(" System Joystick");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int joyNum = 0; joyNum < m_numJoys; joyNum++)
|
||||||
|
{
|
||||||
|
const JoyDetails *joyDetails = GetJoyDetails(joyNum);
|
||||||
|
if (joyDetails->hasFFeedback)
|
||||||
|
printf(" %d: %s [Force Feedback Available]\n", joyNum + 1, joyDetails->name);
|
||||||
|
else
|
||||||
|
printf(" %d: %s\n", joyNum + 1, joyDetails->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CInputSystem::CKeyInputSource
|
* CInputSystem::CKeyInputSource
|
||||||
*/
|
*/
|
||||||
|
@ -1888,26 +1940,28 @@ bool CInputSystem::CMseButInputSource::GetValueAsAnalog(int &val, int minVal, in
|
||||||
/*
|
/*
|
||||||
* CInputSystem::CJoyAxisInputSource
|
* CInputSystem::CJoyAxisInputSource
|
||||||
*/
|
*/
|
||||||
CInputSystem::CJoyAxisInputSource::CJoyAxisInputSource(CInputSystem *system, int joyNum, int axisNum, int axisDir, unsigned deadZone, unsigned saturation) :
|
CInputSystem::CJoyAxisInputSource::CJoyAxisInputSource(CInputSystem *system, int joyNum, int axisNum, int axisDir,
|
||||||
|
int axisMinVal, int axisOffVal, int axisMaxVal, unsigned deadZone, unsigned saturation) :
|
||||||
CInputSource(axisDir == AXIS_FULL || axisDir == AXIS_INVERTED ? SourceFullAxis : SourceHalfAxis),
|
CInputSource(axisDir == AXIS_FULL || axisDir == AXIS_INVERTED ? SourceFullAxis : SourceHalfAxis),
|
||||||
m_system(system), m_joyNum(joyNum), m_axisNum(axisNum), m_axisDir(axisDir)
|
m_system(system), m_joyNum(joyNum), m_axisNum(axisNum), m_axisDir(axisDir), m_axisMinVal(axisMinVal), m_axisOffVal(axisOffVal), m_axisMaxVal(axisMaxVal)
|
||||||
{
|
{
|
||||||
// Calculate pos/neg deadzone and saturation points (joystick raw values range from -32768 to 32767, deadzone given as
|
m_axisInverted = m_axisMaxVal < m_axisMinVal;
|
||||||
// percentage 0-99 and saturation given as percentage 1-100)
|
// Calculate pos/neg deadzone and saturation points (joystick raw values range from axisMinVal to axisMasVal (centered/off at axisOffVal),
|
||||||
|
// deadzone given as percentage 0-99 and saturation given as percentage 1-100)
|
||||||
double dDeadZone = (double)Clamp((int)deadZone, 0, 99) / 100.0;
|
double dDeadZone = (double)Clamp((int)deadZone, 0, 99) / 100.0;
|
||||||
double dSaturation = (double)Clamp((int)saturation, (int)deadZone + 1, 100) / 100.0;
|
double dSaturation = (double)Clamp((int)saturation, (int)deadZone + 1, 100) / 100.0;
|
||||||
m_posDZone = (int)(dDeadZone * 32767.0);
|
m_posDZone = m_axisOffVal + (int)(dDeadZone * (m_axisMaxVal - m_axisOffVal));
|
||||||
m_negDZone = (int)(dDeadZone * -32768.0);
|
m_negDZone = m_axisOffVal + (int)(dDeadZone * (m_axisMinVal - m_axisOffVal));
|
||||||
m_posSat = (int)(dSaturation * 32767.0);
|
m_posSat = m_axisOffVal + (int)(dSaturation * (m_axisMaxVal - m_axisOffVal));
|
||||||
m_negSat = (int)(dSaturation * -32868.0);
|
m_negSat = m_axisOffVal + (int)(dSaturation * (m_axisMinVal - m_axisOffVal));
|
||||||
}
|
}
|
||||||
|
|
||||||
int CInputSystem::CJoyAxisInputSource::ScaleAxisValue(int minVal, int offVal, int maxVal)
|
int CInputSystem::CJoyAxisInputSource::ScaleAxisValue(int minVal, int offVal, int maxVal)
|
||||||
{
|
{
|
||||||
// Get raw axis value from input system (values range from -32768 to 32767)
|
// Get raw axis value from input system
|
||||||
int joyVal = m_system->GetJoyAxisValue(m_joyNum, m_axisNum);
|
int joyVal = m_system->GetJoyAxisValue(m_joyNum, m_axisNum);
|
||||||
// Check value is not zero
|
// Check if value is at axis off value
|
||||||
if (joyVal == 0)
|
if (joyVal == m_axisOffVal)
|
||||||
return offVal;
|
return offVal;
|
||||||
// Scale value between deadzone and saturation points, taking positive or negative values only or using the whole axis range as required
|
// Scale value between deadzone and saturation points, taking positive or negative values only or using the whole axis range as required
|
||||||
if (m_axisDir == AXIS_POS) return Scale(joyVal, m_posDZone, m_posDZone, m_posSat, minVal, offVal, maxVal);
|
if (m_axisDir == AXIS_POS) return Scale(joyVal, m_posDZone, m_posDZone, m_posSat, minVal, offVal, maxVal);
|
||||||
|
@ -1915,14 +1969,18 @@ int CInputSystem::CJoyAxisInputSource::ScaleAxisValue(int minVal, int offVal, in
|
||||||
else if (m_axisDir == AXIS_FULL)
|
else if (m_axisDir == AXIS_FULL)
|
||||||
{
|
{
|
||||||
// Full axis range
|
// Full axis range
|
||||||
if (joyVal > 0) return Scale(joyVal, m_posDZone, m_posDZone, m_posSat, minVal, offVal, maxVal);
|
if (!m_axisInverted && joyVal > m_axisOffVal || m_axisInverted && joyVal < m_axisOffVal)
|
||||||
else return Scale(joyVal, m_negSat, m_negDZone, m_negDZone, minVal, offVal, maxVal);
|
return Scale(joyVal, m_posDZone, m_posDZone, m_posSat, minVal, offVal, maxVal);
|
||||||
|
else
|
||||||
|
return Scale(joyVal, m_negSat, m_negDZone, m_negDZone, minVal, offVal, maxVal);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Full axis range, but inverted
|
// Full axis range, but inverted
|
||||||
if (joyVal > 0) return Scale(joyVal, m_posDZone, m_posDZone, m_posSat, maxVal, offVal, minVal);
|
if (!m_axisInverted && joyVal > m_axisOffVal || m_axisInverted && joyVal < m_axisOffVal)
|
||||||
else return Scale(joyVal, m_negSat, m_negDZone, m_negDZone, maxVal, offVal, minVal);
|
return Scale(joyVal, m_posDZone, m_posDZone, m_posSat, maxVal, offVal, minVal);
|
||||||
|
else
|
||||||
|
return Scale(joyVal, m_negSat, m_negDZone, m_negDZone, maxVal, offVal, minVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1943,7 +2001,7 @@ bool CInputSystem::CJoyAxisInputSource::GetValueAsAnalog(int &val, int minVal, i
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CInputSystem::CJoyAxisInputSource::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
|
bool CInputSystem::CJoyAxisInputSource::SendForceFeedbackCmd(ForceFeedbackCmd ffCmd)
|
||||||
{
|
{
|
||||||
return m_system->SendForceFeedbackCmd(m_joyNum, m_axisNum, ffCmd);
|
return m_system->SendForceFeedbackCmd(m_joyNum, m_axisNum, ffCmd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,9 @@ class CINIFile;
|
||||||
#define DEFAULT_KEY_SENSITIVITY 25
|
#define DEFAULT_KEY_SENSITIVITY 25
|
||||||
#define DEFAULT_KEY_DECAYSPEED 50
|
#define DEFAULT_KEY_DECAYSPEED 50
|
||||||
#define DEFAULT_MSE_DEADZONE 0
|
#define DEFAULT_MSE_DEADZONE 0
|
||||||
|
#define DEFAULT_JOY_AXISMINVAL -32768
|
||||||
|
#define DEFAULT_JOY_AXISOFFVAL 0
|
||||||
|
#define DEFAULT_JOY_AXISMAXVAL 32767
|
||||||
#define DEFAULT_JOY_DEADZONE 3
|
#define DEFAULT_JOY_DEADZONE 3
|
||||||
#define DEFAULT_JOY_SATURATION 100
|
#define DEFAULT_JOY_SATURATION 100
|
||||||
|
|
||||||
|
@ -209,9 +212,7 @@ struct KeySettings
|
||||||
struct MouseSettings
|
struct MouseSettings
|
||||||
{
|
{
|
||||||
int mseNum; // Mouse number (or ANY_MOUSE for settings that apply to all mice)
|
int mseNum; // Mouse number (or ANY_MOUSE for settings that apply to all mice)
|
||||||
unsigned xDeadZone; // X-Axis dead zone as a percentage 0-99 of display width
|
unsigned deadZones[NUM_MOUSE_AXES]; // Axis dead zone as a percentage 0-99 of display width (X)/height (Y) or axis range (Z)
|
||||||
unsigned yDeadZone; // Y-Axis dead zone as a percentage 0-99 of display height
|
|
||||||
unsigned zDeadZone; // Z-Axis dead zone as a percentage 0-99 of axis range
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates a MouseSettings with default settings
|
* Creates a MouseSettings with default settings
|
||||||
|
@ -219,9 +220,9 @@ struct MouseSettings
|
||||||
MouseSettings()
|
MouseSettings()
|
||||||
{
|
{
|
||||||
mseNum = ANY_MOUSE;
|
mseNum = ANY_MOUSE;
|
||||||
xDeadZone = DEFAULT_MSE_DEADZONE;
|
deadZones[AXIS_X] = DEFAULT_MSE_DEADZONE;
|
||||||
yDeadZone = DEFAULT_MSE_DEADZONE;
|
deadZones[AXIS_Y] = DEFAULT_MSE_DEADZONE;
|
||||||
zDeadZone = 0;
|
deadZones[AXIS_Z] = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -231,18 +232,11 @@ struct MouseSettings
|
||||||
struct JoySettings
|
struct JoySettings
|
||||||
{
|
{
|
||||||
int joyNum; // Joystick number (or ANY_JOYSTICK for settings that apply to all joysticks)
|
int joyNum; // Joystick number (or ANY_JOYSTICK for settings that apply to all joysticks)
|
||||||
unsigned xDeadZone; // X-Axis dead zone as a percentage 0-99 of axis positive/negative ranges
|
int axisMinVals[NUM_JOY_AXES]; // Axis min raw value (default -32768)
|
||||||
unsigned xSaturation; // X-Axis saturation as a percentage 1-100 of axis positive/negative ranges
|
int axisOffVals[NUM_JOY_AXES]; // Axis center/off value (default 0)
|
||||||
unsigned yDeadZone; // Y-Axis dead zone as a percentage 0-99 of axis positive/negative ranges
|
int axisMaxVals[NUM_JOY_AXES]; // Axis max raw value (default 32767)
|
||||||
unsigned ySaturation; // Y-Axis saturation as a percentage 1-100 of axis positive/negative ranges
|
unsigned deadZones[NUM_JOY_AXES]; // Axis dead zone as a percentage 0-99 of axis positive/negative ranges
|
||||||
unsigned zDeadZone; // Z-Axis dead zone as a percentage 0-99 of axis positive/negative ranges
|
unsigned saturations[NUM_JOY_AXES]; // Axis saturation as a percentage 1-100 of axis positive/negative ranges
|
||||||
unsigned zSaturation; // Z-Axis saturation as a percentage 1-100 of axis positive/negative ranges
|
|
||||||
unsigned rxDeadZone; // RX-Axis dead zone as a percentage 0-99 of axis positive/negative ranges
|
|
||||||
unsigned rxSaturation; // RX-Axis saturation as a percentage 1-100 of joystick axis positive/negative ranges
|
|
||||||
unsigned ryDeadZone; // RY-Axis dead zone as a percentage 0-99 of axis positive/negative ranges
|
|
||||||
unsigned rySaturation; // RY-Axis saturation as a percentage 1-100 of joystick axis positive/negative ranges
|
|
||||||
unsigned rzDeadZone; // RZ-Axis dead zone as a percentage 0-99 of axis positive/negative ranges
|
|
||||||
unsigned rzSaturation; // RZ-Axis saturation as a percentage 1-100 of joystick axis positive/negative ranges
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates a JoySettings with default settings
|
* Creates a JoySettings with default settings
|
||||||
|
@ -250,35 +244,31 @@ struct JoySettings
|
||||||
JoySettings()
|
JoySettings()
|
||||||
{
|
{
|
||||||
joyNum = ANY_JOYSTICK;
|
joyNum = ANY_JOYSTICK;
|
||||||
xDeadZone = DEFAULT_JOY_DEADZONE;
|
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||||
xSaturation = DEFAULT_JOY_SATURATION;
|
{
|
||||||
yDeadZone = DEFAULT_JOY_DEADZONE;
|
axisMinVals[axisNum] = DEFAULT_JOY_AXISMINVAL;
|
||||||
ySaturation = DEFAULT_JOY_SATURATION;
|
axisOffVals[axisNum] = DEFAULT_JOY_AXISOFFVAL;
|
||||||
zDeadZone = DEFAULT_JOY_DEADZONE;
|
axisMaxVals[axisNum] = DEFAULT_JOY_AXISMAXVAL;
|
||||||
zSaturation = DEFAULT_JOY_SATURATION;
|
deadZones[axisNum] = DEFAULT_JOY_DEADZONE;
|
||||||
rxDeadZone = DEFAULT_JOY_DEADZONE;
|
saturations[axisNum] = DEFAULT_JOY_SATURATION;
|
||||||
rxSaturation = DEFAULT_JOY_SATURATION;
|
}
|
||||||
ryDeadZone = DEFAULT_JOY_DEADZONE;
|
|
||||||
rySaturation = DEFAULT_JOY_SATURATION;
|
|
||||||
rzDeadZone = DEFAULT_JOY_DEADZONE;
|
|
||||||
rzSaturation = DEFAULT_JOY_SATURATION;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KeyDetails
|
struct KeyDetails
|
||||||
{
|
{
|
||||||
char name[MAX_NAME_LENGTH]; // Keyboard name (if available)
|
char name[MAX_NAME_LENGTH + 1]; // Keyboard name (if available)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MouseDetails
|
struct MouseDetails
|
||||||
{
|
{
|
||||||
char name[MAX_NAME_LENGTH]; // Mouse name (if available)
|
char name[MAX_NAME_LENGTH + 1]; // Mouse name (if available)
|
||||||
bool isAbsolute; // True if uses absolute positions (ie lightgun)
|
bool isAbsolute; // True if uses absolute positions (ie lightgun)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JoyDetails
|
struct JoyDetails
|
||||||
{
|
{
|
||||||
char name[MAX_NAME_LENGTH]; // Joystick name (if available)
|
char name[MAX_NAME_LENGTH + 1]; // Joystick name (if available)
|
||||||
int numAxes; // Total number of axes on joystick
|
int numAxes; // Total number of axes on joystick
|
||||||
int numPOVs; // Total number of POV hat controllers on joystick
|
int numPOVs; // Total number of POV hat controllers on joystick
|
||||||
int numButtons; // Total number of buttons on joystick
|
int numButtons; // Total number of buttons on joystick
|
||||||
|
@ -303,6 +293,9 @@ private:
|
||||||
// Lookup table for translating joystick mapping strings to their respective joystick parts
|
// Lookup table for translating joystick mapping strings to their respective joystick parts
|
||||||
static JoyPartsStruct s_joyParts[];
|
static JoyPartsStruct s_joyParts[];
|
||||||
|
|
||||||
|
// Names of axes
|
||||||
|
static const char *s_axisNames[];
|
||||||
|
|
||||||
// Number of keyboards, mice and joysticks
|
// Number of keyboards, mice and joysticks
|
||||||
int m_numKbds;
|
int m_numKbds;
|
||||||
int m_numMice;
|
int m_numMice;
|
||||||
|
@ -334,24 +327,19 @@ private:
|
||||||
//
|
//
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates cache for all sources.
|
* Creates source cache.
|
||||||
*/
|
*/
|
||||||
void CreateSourceCache();
|
void CreateSourceCache();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if the given source is in the source cache.
|
* Clears cache of all sources and optionally deletes cache itself.
|
||||||
*/
|
*/
|
||||||
bool IsInSourceCache(CInputSource *source);
|
void ClearSourceCache(bool deleteCache = false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deletes cache for all sources.
|
* Releases a source from the cache.
|
||||||
*/
|
*/
|
||||||
void DeleteSourceCache();
|
void ReleaseSource(CInputSource *&source);
|
||||||
|
|
||||||
/*
|
|
||||||
* Deletes an input source.
|
|
||||||
*/
|
|
||||||
void DeleteSource(CInputSource *source);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns a key source for the given keyboard number (or all keyboards if ANY_KEYBOARD supplied) and key index.
|
* Returns a key source for the given keyboard number (or all keyboards if ANY_KEYBOARD supplied) and key index.
|
||||||
|
@ -371,26 +359,28 @@ private:
|
||||||
*/
|
*/
|
||||||
CInputSource *GetJoySource(int joyNum, EJoyPart joyPart);
|
CInputSource *GetJoySource(int joyNum, EJoyPart joyPart);
|
||||||
|
|
||||||
|
void CheckAllSources(unsigned readFlags, bool fullAxisOnly, bool &mseCentered, vector<CInputSource*> &sources, string &mapping, vector<CInputSource*> &badSources);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finds any currently activated key sources for the given keyboard number (or all keyboards if ANY_KEYBOARD supplied)
|
* Finds any currently activated key sources for the given keyboard number (or all keyboards if ANY_KEYBOARD supplied)
|
||||||
* and adds them to the sources vector, aswell as constructing the corresponding mapping(s) in the given string.
|
* and adds them to the sources vector, aswell as constructing the corresponding mapping(s) in the given string.
|
||||||
* If fullAxisOnly is true, then only sources that represent a full axis range (eg MouseXAxis) are considered.
|
* If fullAxisOnly is true, then only sources that represent a full axis range (eg MouseXAxis) are considered.
|
||||||
*/
|
*/
|
||||||
void CheckKeySources(int kbdNum, bool fullAxisOnly, vector<CInputSource*> &sources, string &mapping);
|
void CheckKeySources(int kbdNum, bool fullAxisOnly, vector<CInputSource*> &sources, string &mapping, vector<CInputSource*> &badSources);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finds any currently activated mouse sources for the given mouse number (or all mice if ANY_MOUSE supplied)
|
* Finds any currently activated mouse sources for the given mouse number (or all mice if ANY_MOUSE supplied)
|
||||||
* and adds them to the sources vector, aswell as constructing the corresponding mapping(s) in the given string.
|
* and adds them to the sources vector, aswell as constructing the corresponding mapping(s) in the given string.
|
||||||
* If fullAxisOnly is true, then only sources that represent a full axis range (eg MouseXAxis) are considered.
|
* If fullAxisOnly is true, then only sources that represent a full axis range (eg MouseXAxis) are considered.
|
||||||
*/
|
*/
|
||||||
void CheckMouseSources(int mseNum, bool fullAxisOnly, bool mseCentered, vector<CInputSource*> &sources, string &mapping);
|
void CheckMouseSources(int mseNum, bool fullAxisOnly, bool mseCentered, vector<CInputSource*> &sources, string &mapping, vector<CInputSource*> &badSources);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finds any currently activated joystick sources for the given joystick number (or all joysticks if ANY_JOYSTICK supplied)
|
* Finds any currently activated joystick sources for the given joystick number (or all joysticks if ANY_JOYSTICK supplied)
|
||||||
* and adds them to the sources vector, aswell as constructing the corresponding mapping(s) in the given string.
|
* and adds them to the sources vector, aswell as constructing the corresponding mapping(s) in the given string.
|
||||||
* If fullAxisOnly is true, then only sources that represent a full axis range (eg MouseXAxis) are considered.
|
* If fullAxisOnly is true, then only sources that represent a full axis range (eg MouseXAxis) are considered.
|
||||||
*/
|
*/
|
||||||
void CheckJoySources(int joyNum, bool fullAxisOnly, vector<CInputSource*> &sources, string &mapping);
|
void CheckJoySources(int joyNum, bool fullAxisOnly, vector<CInputSource*> &sources, string &mapping, vector<CInputSource*> &badSources);
|
||||||
|
|
||||||
bool ParseInt(string str, int &num);
|
bool ParseInt(string str, int &num);
|
||||||
|
|
||||||
|
@ -653,7 +643,7 @@ protected:
|
||||||
/*
|
/*
|
||||||
* Processes the given force feedback command for the given joystick and axis number.
|
* Processes the given force feedback command for the given joystick and axis number.
|
||||||
*/
|
*/
|
||||||
virtual bool ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd) = 0;
|
virtual bool ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Waits for the given time in milliseconds
|
* Waits for the given time in milliseconds
|
||||||
|
@ -700,6 +690,10 @@ protected:
|
||||||
virtual CInputSource *CreateJoySource(int joyNum, EJoyPart joyPart);
|
virtual CInputSource *CreateJoySource(int joyNum, EJoyPart joyPart);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
#ifdef DEBUG
|
||||||
|
static unsigned totalSrcsAcquired;
|
||||||
|
static unsigned totalSrcsReleased;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Name of this input system
|
// Name of this input system
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -793,11 +787,6 @@ public:
|
||||||
*/
|
*/
|
||||||
CInputSource* ParseSource(const char *mapping, bool fullAxisOnly = false);
|
CInputSource* ParseSource(const char *mapping, bool fullAxisOnly = false);
|
||||||
|
|
||||||
/*
|
|
||||||
* Releases the given source when it is no longer in use.
|
|
||||||
*/
|
|
||||||
void ReleaseSource(CInputSource *source);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Waits for any input from the user and once received copies a mapping configuration representing the input (eg KEY_A or JOY1_AXIS_POS)
|
* Waits for any input from the user and once received copies a mapping configuration representing the input (eg KEY_A or JOY1_AXIS_POS)
|
||||||
* into the given buffer.
|
* into the given buffer.
|
||||||
|
@ -809,7 +798,7 @@ public:
|
||||||
bool ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly = false, unsigned readFlags = READ_ALL, const char *escapeMapping = "KEY_ESCAPE");
|
bool ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly = false, unsigned readFlags = READ_ALL, const char *escapeMapping = "KEY_ESCAPE");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Updates the current state of the input system (called by CInputs::Poll).
|
* Updates the current state of the input system (called by CInputs.Poll).
|
||||||
*/
|
*/
|
||||||
virtual bool Poll() = 0;
|
virtual bool Poll() = 0;
|
||||||
|
|
||||||
|
@ -822,61 +811,9 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void SetMouseVisibility(bool visible) = 0;
|
virtual void SetMouseVisibility(bool visible) = 0;
|
||||||
|
|
||||||
virtual bool SendForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd)
|
virtual bool SendForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd);
|
||||||
{
|
|
||||||
const JoyDetails *joyDetails = GetJoyDetails(joyNum);
|
|
||||||
if (!joyDetails->hasFFeedback || !joyDetails->axisHasFF[axisNum])
|
|
||||||
return false;
|
|
||||||
return ProcessForceFeedbackCmd(joyNum, axisNum, ffCmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrintDevices()
|
void PrintDevices();
|
||||||
{
|
|
||||||
puts("Keyboards:");
|
|
||||||
if (m_numKbds == 0)
|
|
||||||
puts(" None");
|
|
||||||
else if (m_numKbds == ANY_KEYBOARD)
|
|
||||||
puts(" System Keyboard");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
|
|
||||||
{
|
|
||||||
const KeyDetails *keyDetails = GetKeyDetails(kbdNum);
|
|
||||||
printf(" %d: %s\n", kbdNum + 1, keyDetails->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
puts("Mice:");
|
|
||||||
if (m_numMice == 0)
|
|
||||||
puts(" None");
|
|
||||||
else if (m_numMice == ANY_MOUSE)
|
|
||||||
puts(" System Mouse");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int mseNum = 0; mseNum < m_numMice; mseNum++)
|
|
||||||
{
|
|
||||||
const MouseDetails *mseDetails = GetMouseDetails(mseNum);
|
|
||||||
printf(" %d: %s\n", mseNum + 1, mseDetails->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
puts("Joysticks:");
|
|
||||||
if (m_numJoys == 0)
|
|
||||||
puts(" None");
|
|
||||||
else if (m_numJoys == ANY_JOYSTICK)
|
|
||||||
puts(" System Joystick");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int joyNum = 0; joyNum < m_numJoys; joyNum++)
|
|
||||||
{
|
|
||||||
const JoyDetails *joyDetails = GetJoyDetails(joyNum);
|
|
||||||
if (joyDetails->hasFFeedback)
|
|
||||||
printf(" %d: %s [Force Feedback Available]\n", joyNum + 1, joyDetails->name);
|
|
||||||
else
|
|
||||||
printf(" %d: %s\n", joyNum + 1, joyDetails->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Nested Classes
|
// Nested Classes
|
||||||
|
@ -957,10 +894,14 @@ public:
|
||||||
int m_joyNum; // Joystick number
|
int m_joyNum; // Joystick number
|
||||||
int m_axisNum; // Axis number (AXIS_X, AXIS_Y, AXIS_Z, AXIS_RX, AXIS_RY or AXIS_RZ)
|
int m_axisNum; // Axis number (AXIS_X, AXIS_Y, AXIS_Z, AXIS_RX, AXIS_RY or AXIS_RZ)
|
||||||
int m_axisDir; // Axis direction (AXIS_FULL, AXIS_INVERTED, AXIS_POSITIVE or AXIS_NEGATIVE)
|
int m_axisDir; // Axis direction (AXIS_FULL, AXIS_INVERTED, AXIS_POSITIVE or AXIS_NEGATIVE)
|
||||||
int m_posDZone; // Dead zone for positive range
|
int m_axisMinVal; // Axis min raw value (default -32768)
|
||||||
int m_negDZone; // Dead zone for negative range
|
int m_axisOffVal; // Axis center/off raw value (default 0)
|
||||||
int m_posSat; // Saturation for positive range
|
int m_axisMaxVal; // Axis max raw value (default 32767)
|
||||||
int m_negSat; // Saturation for negative range
|
bool m_axisInverted; // True if axis max raw value less than axis min raw value
|
||||||
|
int m_posDZone; // Dead zone for positive range (0-99%)
|
||||||
|
int m_negDZone; // Dead zone for negative range (0-99%)
|
||||||
|
int m_posSat; // Saturation for positive range (1-100%)
|
||||||
|
int m_negSat; // Saturation for negative range (1-100%)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scales the joystick axis value to the given range.
|
* Scales the joystick axis value to the given range.
|
||||||
|
@ -968,13 +909,14 @@ public:
|
||||||
int ScaleAxisValue(int minVal, int offVal, int maxVal);
|
int ScaleAxisValue(int minVal, int offVal, int maxVal);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CJoyAxisInputSource(CInputSystem *system, int joyNum, int axisNum, int axisDir, unsigned deadZone, unsigned saturation);
|
CJoyAxisInputSource(CInputSystem *system, int joyNum, int axisNum, int axisDir, int axisMinVal, int axisOffVal, int axisMaxVal,
|
||||||
|
unsigned deadZone, unsigned saturation);
|
||||||
|
|
||||||
bool GetValueAsSwitch(bool &val);
|
bool GetValueAsSwitch(bool &val);
|
||||||
|
|
||||||
bool GetValueAsAnalog(int &val, int minVal, int offVal, int maxVal);
|
bool GetValueAsAnalog(int &val, int minVal, int offVal, int maxVal);
|
||||||
|
|
||||||
bool SendForceFeedbackCmd(ForceFeedbackCmd *fFeedback);
|
bool SendForceFeedbackCmd(ForceFeedbackCmd ffCmd);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -161,7 +161,7 @@ void CTriggerInput::ReadFromINIFile(CINIFile *ini, const char *section)
|
||||||
|
|
||||||
string key("Input");
|
string key("Input");
|
||||||
key.append(id);
|
key.append(id);
|
||||||
unsigned int autoTrigger;
|
unsigned autoTrigger;
|
||||||
if (ini->Get(section, key, autoTrigger) == OKAY)
|
if (ini->Get(section, key, autoTrigger) == OKAY)
|
||||||
m_autoTrigger = !!autoTrigger;
|
m_autoTrigger = !!autoTrigger;
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ public:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Represents a trigger input, with both a trigger value and an offscreen value. If required, it can simulate pointing offscreen and pulling
|
* Represents a trigger input, with both a trigger value and an offscreen value. If required, it can simulate pointing offscreen and pulling
|
||||||
* the trigger (in that order, which lightgun games require to reload properly) when just the offscreen input is activated. This makes
|
* the trigger (in that order, which lightgun games require to reload properly) just when the offscreen input is activated. This makes
|
||||||
* reloading the gun easier when playing with just the mouse for example.
|
* reloading the gun easier when playing with just the mouse for example.
|
||||||
*/
|
*/
|
||||||
class CTriggerInput : public CInput
|
class CTriggerInput : public CInput
|
||||||
|
|
|
@ -252,12 +252,16 @@ bool CInputs::Initialize()
|
||||||
|
|
||||||
void CInputs::ReadFromINIFile(CINIFile *ini, const char *section)
|
void CInputs::ReadFromINIFile(CINIFile *ini, const char *section)
|
||||||
{
|
{
|
||||||
|
m_system->ReadFromINIFile(ini, section);
|
||||||
|
|
||||||
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
|
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
|
||||||
(*it)->ReadFromINIFile(ini, section);
|
(*it)->ReadFromINIFile(ini, section);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputs::WriteToINIFile(CINIFile *ini, const char *section)
|
void CInputs::WriteToINIFile(CINIFile *ini, const char *section)
|
||||||
{
|
{
|
||||||
|
m_system->WriteToINIFile(ini, section);
|
||||||
|
|
||||||
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
|
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
|
||||||
(*it)->WriteToINIFile(ini, section);
|
(*it)->WriteToINIFile(ini, section);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,13 @@ ESourceType CMultiInputSource::GetCombinedType(vector<CInputSource*> &sources)
|
||||||
else return SourceEmpty;
|
else return SourceEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMultiInputSource::CMultiInputSource(CInputSystem *system) : CInputSource(SourceEmpty), m_system(system), m_isOr(true), m_numSrcs(0), m_srcArray(NULL) { }
|
CMultiInputSource::CMultiInputSource() : CInputSource(SourceEmpty), m_isOr(true), m_numSrcs(0), m_srcArray(NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
CMultiInputSource::CMultiInputSource(CInputSystem *system, bool isOr, vector<CInputSource*> &sources) :
|
CMultiInputSource::CMultiInputSource(bool isOr, vector<CInputSource*> &sources) :
|
||||||
CInputSource(GetCombinedType(sources)), m_system(system), m_isOr(isOr), m_numSrcs(sources.size())
|
CInputSource(GetCombinedType(sources)), m_isOr(isOr), m_numSrcs(sources.size())
|
||||||
{
|
{
|
||||||
m_srcArray = new CInputSource*[m_numSrcs];
|
m_srcArray = new CInputSource*[m_numSrcs];
|
||||||
copy(sources.begin(), sources.end(), m_srcArray);
|
copy(sources.begin(), sources.end(), m_srcArray);
|
||||||
|
@ -51,13 +54,33 @@ CMultiInputSource::CMultiInputSource(CInputSystem *system, bool isOr, vector<CIn
|
||||||
CMultiInputSource::~CMultiInputSource()
|
CMultiInputSource::~CMultiInputSource()
|
||||||
{
|
{
|
||||||
if (m_srcArray != NULL)
|
if (m_srcArray != NULL)
|
||||||
{
|
|
||||||
for (int i = 0; i < m_numSrcs; i++)
|
|
||||||
m_system->ReleaseSource(m_srcArray[i]);
|
|
||||||
delete m_srcArray;
|
delete m_srcArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMultiInputSource::Acquire()
|
||||||
|
{
|
||||||
|
CInputSource::Acquire();
|
||||||
|
|
||||||
|
if (m_acquired == 1)
|
||||||
|
{
|
||||||
|
// Acquire all sources
|
||||||
|
for (int i = 0; i < m_numSrcs; i++)
|
||||||
|
m_srcArray[i]->Acquire();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMultiInputSource::Release()
|
||||||
|
{
|
||||||
|
if (m_acquired == 1)
|
||||||
|
{
|
||||||
|
// Release all sources
|
||||||
|
for (int i = 0; i < m_numSrcs; i++)
|
||||||
|
m_srcArray[i]->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
CInputSource::Release();
|
||||||
|
}
|
||||||
|
|
||||||
bool CMultiInputSource::GetValueAsSwitch(bool &val)
|
bool CMultiInputSource::GetValueAsSwitch(bool &val)
|
||||||
{
|
{
|
||||||
if (m_isOr)
|
if (m_isOr)
|
||||||
|
@ -113,7 +136,7 @@ bool CMultiInputSource::GetValueAsAnalog(int &val, int minVal, int offVal, int m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMultiInputSource::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
|
bool CMultiInputSource::SendForceFeedbackCmd(ForceFeedbackCmd ffCmd)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
for (int i = 0; i < m_numSrcs; i++)
|
for (int i = 0; i < m_numSrcs; i++)
|
||||||
|
@ -121,11 +144,28 @@ bool CMultiInputSource::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CNegInputSource::CNegInputSource(CInputSystem *system, CInputSource *source) : CInputSource(source->type), m_system(system), m_source(source) { }
|
CNegInputSource::CNegInputSource(CInputSource *source) : CInputSource(source->type), m_source(source)
|
||||||
|
|
||||||
CNegInputSource::~CNegInputSource()
|
|
||||||
{
|
{
|
||||||
m_system->ReleaseSource(m_source);
|
// Acquire source
|
||||||
|
m_source->Acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNegInputSource::Acquire()
|
||||||
|
{
|
||||||
|
CInputSource::Acquire();
|
||||||
|
|
||||||
|
// Acquire source
|
||||||
|
if (m_acquired == 1)
|
||||||
|
m_source->Acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNegInputSource::Release()
|
||||||
|
{
|
||||||
|
// Release source
|
||||||
|
if (m_acquired == 1)
|
||||||
|
m_source->Release();
|
||||||
|
|
||||||
|
CInputSource::Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CNegInputSource::GetValueAsSwitch(bool &val)
|
bool CNegInputSource::GetValueAsSwitch(bool &val)
|
||||||
|
|
|
@ -9,15 +9,12 @@ using namespace std;
|
||||||
/*
|
/*
|
||||||
* Represents a collection of input sources and combines their values into a single value.
|
* Represents a collection of input sources and combines their values into a single value.
|
||||||
* When multiple mappings are assigned to an input, this is the input source that is created.
|
* When multiple mappings are assigned to an input, this is the input source that is created.
|
||||||
* Can either represent a combination of multiple assignments that all map to the same input, eg KEY_ALT,JOY1_BUTTON1 or be
|
* Can represent either a combination of multiple assignments that all map to the same input, eg KEY_ALT,JOY1_BUTTON1 or to
|
||||||
* used specify that controls must be activated together, eg KEY_ALT+KEY_P.
|
* specify that controls must be combined together, eg KEY_ALT+KEY_P.
|
||||||
*/
|
*/
|
||||||
class CMultiInputSource : public CInputSource
|
class CMultiInputSource : public CInputSource
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Input system that created this source
|
|
||||||
CInputSystem *m_system;
|
|
||||||
|
|
||||||
// Controls how the inputs sources are combined
|
// Controls how the inputs sources are combined
|
||||||
bool m_isOr;
|
bool m_isOr;
|
||||||
|
|
||||||
|
@ -36,7 +33,7 @@ public:
|
||||||
/*
|
/*
|
||||||
* Constructs an 'empty' source (ie one which is always 'off').
|
* Constructs an 'empty' source (ie one which is always 'off').
|
||||||
*/
|
*/
|
||||||
CMultiInputSource(CInputSystem *system);
|
CMultiInputSource();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructs a multiple input source from the given vector of sources.
|
* Constructs a multiple input source from the given vector of sources.
|
||||||
|
@ -44,15 +41,19 @@ public:
|
||||||
* switch inputs must be active for this input to have a value (which will be the value of the first non-switch input in the list,
|
* switch inputs must be active for this input to have a value (which will be the value of the first non-switch input in the list,
|
||||||
* or the first switch input if there are none).
|
* or the first switch input if there are none).
|
||||||
*/
|
*/
|
||||||
CMultiInputSource(CInputSystem *system, bool isOr, vector<CInputSource*> &sources);
|
CMultiInputSource(bool isOr, vector<CInputSource*> &sources);
|
||||||
|
|
||||||
~CMultiInputSource();
|
~CMultiInputSource();
|
||||||
|
|
||||||
|
void Acquire();
|
||||||
|
|
||||||
|
void Release();
|
||||||
|
|
||||||
bool GetValueAsSwitch(bool &val);
|
bool GetValueAsSwitch(bool &val);
|
||||||
|
|
||||||
bool GetValueAsAnalog(int &val, int minVal, int offVal, int maxVal);
|
bool GetValueAsAnalog(int &val, int minVal, int offVal, int maxVal);
|
||||||
|
|
||||||
bool SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd);
|
bool SendForceFeedbackCmd(ForceFeedbackCmd ffCmd);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -63,16 +64,15 @@ public:
|
||||||
class CNegInputSource : public CInputSource
|
class CNegInputSource : public CInputSource
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Input system that created this source
|
|
||||||
CInputSystem *m_system;
|
|
||||||
|
|
||||||
// Input source being negated
|
// Input source being negated
|
||||||
CInputSource *m_source;
|
CInputSource *m_source;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CNegInputSource(CInputSystem *system, CInputSource *source);
|
CNegInputSource(CInputSource *source);
|
||||||
|
|
||||||
~CNegInputSource();
|
void Acquire();
|
||||||
|
|
||||||
|
void Release();
|
||||||
|
|
||||||
bool GetValueAsSwitch(bool &val);
|
bool GetValueAsSwitch(bool &val);
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,6 @@ static CInputs *CreateInputs(CInputSystem *InputSystem, BOOL configure)
|
||||||
INI.Parse();
|
INI.Parse();
|
||||||
|
|
||||||
Inputs->ReadFromINIFile(&INI, "Global");
|
Inputs->ReadFromINIFile(&INI, "Global");
|
||||||
InputSystem->ReadFromINIFile(&INI, "Global");
|
|
||||||
|
|
||||||
// If the user wants to configure the inputs, do that now
|
// If the user wants to configure the inputs, do that now
|
||||||
if (configure)
|
if (configure)
|
||||||
|
@ -199,7 +198,6 @@ static CInputs *CreateInputs(CInputSystem *InputSystem, BOOL configure)
|
||||||
{
|
{
|
||||||
// Write input configuration and input system settings to config file
|
// Write input configuration and input system settings to config file
|
||||||
Inputs->WriteToINIFile(&INI, "Global");
|
Inputs->WriteToINIFile(&INI, "Global");
|
||||||
InputSystem->WriteToINIFile(&INI, "Global");
|
|
||||||
|
|
||||||
if (OKAY != INI.Write(CONFIG_FILE_COMMENT))
|
if (OKAY != INI.Write(CONFIG_FILE_COMMENT))
|
||||||
ErrorLog("Unable to save configuration to %s.", CONFIG_FILE_PATH);
|
ErrorLog("Unable to save configuration to %s.", CONFIG_FILE_PATH);
|
||||||
|
@ -1090,10 +1088,10 @@ int main(int argc, char **argv)
|
||||||
exitCode = Supermodel(argv[fileIdx],Inputs,ppcFrequency,xRes,yRes,cmdFullScreen,cmdNoThrottle,cmdShowFPS,vsFile,fsFile);
|
exitCode = Supermodel(argv[fileIdx],Inputs,ppcFrequency,xRes,yRes,cmdFullScreen,cmdNoThrottle,cmdShowFPS,vsFile,fsFile);
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
if (InputSystem != NULL)
|
|
||||||
delete InputSystem;
|
|
||||||
if (Inputs != NULL)
|
if (Inputs != NULL)
|
||||||
delete Inputs;
|
delete Inputs;
|
||||||
|
if (InputSystem != NULL)
|
||||||
|
delete InputSystem;
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,8 +181,8 @@ void CSDLInputSystem::OpenJoysticks()
|
||||||
// Gather joystick details (name, num POVs & buttons and which axes are available)
|
// Gather joystick details (name, num POVs & buttons and which axes are available)
|
||||||
JoyDetails joyDetails;
|
JoyDetails joyDetails;
|
||||||
const char *pName = SDL_JoystickName(joyNum);
|
const char *pName = SDL_JoystickName(joyNum);
|
||||||
strncpy(joyDetails.name, pName, MAX_NAME_LENGTH - 1);
|
strncpy(joyDetails.name, pName, MAX_NAME_LENGTH);
|
||||||
joyDetails.name[MAX_NAME_LENGTH - 1] = '\0';
|
joyDetails.name[MAX_NAME_LENGTH] = '\0';
|
||||||
joyDetails.numAxes = SDL_JoystickNumAxes(joystick);
|
joyDetails.numAxes = SDL_JoystickNumAxes(joystick);
|
||||||
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||||
{
|
{
|
||||||
|
@ -313,7 +313,7 @@ bool CSDLInputSystem::IsJoyButPressed(int joyNum, int butNum)
|
||||||
return !!SDL_JoystickGetButton(joystick, butNum);
|
return !!SDL_JoystickGetButton(joystick, butNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSDLInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd)
|
bool CSDLInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd)
|
||||||
{
|
{
|
||||||
// SDL 1.2 does not support force feedback
|
// SDL 1.2 does not support force feedback
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -81,7 +81,7 @@ protected:
|
||||||
|
|
||||||
bool IsJoyButPressed(int joyNum, int butNum);
|
bool IsJoyButPressed(int joyNum, int butNum);
|
||||||
|
|
||||||
bool ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd);
|
bool ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd);
|
||||||
|
|
||||||
void Wait(int ms);
|
void Wait(int ms);
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,7 @@ DIKeyMapStruct CDirectInputSystem::s_keyMap[] =
|
||||||
|
|
||||||
bool IsXInputDevice(const GUID &devProdGUID)
|
bool IsXInputDevice(const GUID &devProdGUID)
|
||||||
{
|
{
|
||||||
|
// Following code taken from MSDN
|
||||||
IWbemLocator* pIWbemLocator = NULL;
|
IWbemLocator* pIWbemLocator = NULL;
|
||||||
IEnumWbemClassObject* pEnumDevices = NULL;
|
IEnumWbemClassObject* pEnumDevices = NULL;
|
||||||
IWbemClassObject* pDevices[20] = {0};
|
IWbemClassObject* pDevices[20] = {0};
|
||||||
|
@ -191,7 +192,7 @@ bool IsXInputDevice(const GUID &devProdGUID)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
// Loop over all devices
|
// Loop over all devices
|
||||||
while (true)
|
for (;;)
|
||||||
{
|
{
|
||||||
// Get 20 at a time
|
// Get 20 at a time
|
||||||
DWORD uReturned;
|
DWORD uReturned;
|
||||||
|
@ -259,12 +260,13 @@ exit:
|
||||||
BOOL CALLBACK DI8EnumDevicesCallback(LPCDIDEVICEINSTANCE instance, LPVOID context)
|
BOOL CALLBACK DI8EnumDevicesCallback(LPCDIDEVICEINSTANCE instance, LPVOID context)
|
||||||
{
|
{
|
||||||
// Keep track of all joystick device GUIDs
|
// Keep track of all joystick device GUIDs
|
||||||
vector<DIJoyInfo> *infos = (vector<DIJoyInfo>*)context;
|
DIEnumDevsContext *diContext = (DIEnumDevsContext*)context;
|
||||||
DIJoyInfo info;
|
DIJoyInfo info;
|
||||||
memset(&info, 0, sizeof(DIJoyInfo));
|
memset(&info, 0, sizeof(DIJoyInfo));
|
||||||
info.guid = instance->guidInstance;
|
info.guid = instance->guidInstance;
|
||||||
info.isXInput = IsXInputDevice(instance->guidProduct);
|
// If XInput is enabled, see if device is an XInput device
|
||||||
infos->push_back(info);
|
info.isXInput = diContext->useXInput && IsXInputDevice(instance->guidProduct);
|
||||||
|
diContext->infos->push_back(info);
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +297,8 @@ BOOL CALLBACK DI8EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE instance, LPVOID con
|
||||||
BOOL CALLBACK DI8EnumEffectsCallback(LPCDIEFFECTINFO effectInfo, LPVOID context)
|
BOOL CALLBACK DI8EnumEffectsCallback(LPCDIEFFECTINFO effectInfo, LPVOID context)
|
||||||
{
|
{
|
||||||
JoyDetails *joyDetails = (JoyDetails*)context;
|
JoyDetails *joyDetails = (JoyDetails*)context;
|
||||||
if (effectInfo->dwEffType == DIEFT_CONSTANTFORCE)
|
// Check joystick has at least one of required types of effects
|
||||||
|
if (!!(effectInfo->dwEffType & (DIEFT_CONSTANTFORCE | DIEFT_PERIODIC | DIEFT_CONDITION)))
|
||||||
joyDetails->hasFFeedback = true;
|
joyDetails->hasFFeedback = true;
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
}
|
}
|
||||||
|
@ -651,7 +654,7 @@ void CDirectInputSystem::PollKeyboardsAndMice()
|
||||||
if (m_useRawInput)
|
if (m_useRawInput)
|
||||||
{
|
{
|
||||||
// For RawInput, only thing to do is update wheelDir from wheelData for each mouse state. Everything else is updated via WM events.
|
// For RawInput, only thing to do is update wheelDir from wheelData for each mouse state. Everything else is updated via WM events.
|
||||||
for (vector<RawMseState>::iterator it = m_rawMseStates.begin(); it < m_rawMseStates.end(); it++)
|
for (vector<RawMseState>::iterator it = m_rawMseStates.begin(); it != m_rawMseStates.end(); it++)
|
||||||
{
|
{
|
||||||
if (it->wheelDelta != 0)
|
if (it->wheelDelta != 0)
|
||||||
{
|
{
|
||||||
|
@ -745,7 +748,7 @@ void CDirectInputSystem::CloseKeyboardsAndMice()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete storage for keyboards
|
// Delete storage for keyboards
|
||||||
for (vector<BOOL*>::iterator it = m_rawKeyStates.begin(); it < m_rawKeyStates.end(); it++)
|
for (vector<BOOL*>::iterator it = m_rawKeyStates.begin(); it != m_rawKeyStates.end(); it++)
|
||||||
delete[] *it;
|
delete[] *it;
|
||||||
m_keyDetails.clear();
|
m_keyDetails.clear();
|
||||||
m_rawKeyboards.clear();
|
m_rawKeyboards.clear();
|
||||||
|
@ -785,7 +788,7 @@ void CDirectInputSystem::ResetMice()
|
||||||
m_combRawMseState.x = p.x;
|
m_combRawMseState.x = p.x;
|
||||||
m_combRawMseState.y = p.y;
|
m_combRawMseState.y = p.y;
|
||||||
m_combRawMseState.z = 0;
|
m_combRawMseState.z = 0;
|
||||||
for (vector<RawMseState>::iterator it = m_rawMseStates.begin(); it < m_rawMseStates.end(); it++)
|
for (vector<RawMseState>::iterator it = m_rawMseStates.begin(); it != m_rawMseStates.end(); it++)
|
||||||
{
|
{
|
||||||
it->x = p.x;
|
it->x = p.x;
|
||||||
it->y = p.y;
|
it->y = p.y;
|
||||||
|
@ -927,7 +930,7 @@ void CDirectInputSystem::ProcessRawInput(HRAWINPUT hInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
m_combRawMseState.buttons = 0;
|
m_combRawMseState.buttons = 0;
|
||||||
for (vector<RawMseState>::iterator it = m_rawMseStates.begin(); it < m_rawMseStates.end(); it++)
|
for (vector<RawMseState>::iterator it = m_rawMseStates.begin(); it != m_rawMseStates.end(); it++)
|
||||||
m_combRawMseState.buttons |= it->buttons;
|
m_combRawMseState.buttons |= it->buttons;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -940,14 +943,17 @@ void CDirectInputSystem::ProcessRawInput(HRAWINPUT hInput)
|
||||||
void CDirectInputSystem::OpenJoysticks()
|
void CDirectInputSystem::OpenJoysticks()
|
||||||
{
|
{
|
||||||
// Get the info about all attached joystick devices
|
// Get the info about all attached joystick devices
|
||||||
|
DIEnumDevsContext diContext;
|
||||||
|
diContext.infos = &m_diJoyInfos;
|
||||||
|
diContext.useXInput = m_useXInput;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
if (FAILED(hr = m_di8->EnumDevices(DI8DEVCLASS_GAMECTRL, DI8EnumDevicesCallback, &m_diJoyInfos, DIEDFL_ATTACHEDONLY)))
|
if (FAILED(hr = m_di8->EnumDevices(DI8DEVCLASS_GAMECTRL, DI8EnumDevicesCallback, &diContext, DIEDFL_ATTACHEDONLY)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Loop through those found
|
// Loop through those found
|
||||||
int joyNum = 0;
|
int joyNum = 0;
|
||||||
int xNum = 0;
|
int xNum = 0;
|
||||||
for (vector<DIJoyInfo>::iterator it = m_diJoyInfos.begin(); it < m_diJoyInfos.end(); it++)
|
for (vector<DIJoyInfo>::iterator it = m_diJoyInfos.begin(); it != m_diJoyInfos.end(); it++)
|
||||||
{
|
{
|
||||||
joyNum++;
|
joyNum++;
|
||||||
|
|
||||||
|
@ -955,14 +961,14 @@ void CDirectInputSystem::OpenJoysticks()
|
||||||
memset(&joyDetails, 0, sizeof(joyDetails));
|
memset(&joyDetails, 0, sizeof(joyDetails));
|
||||||
|
|
||||||
// See if can use XInput for device
|
// See if can use XInput for device
|
||||||
if (m_useXInput && it->isXInput)
|
if (it->isXInput)
|
||||||
{
|
{
|
||||||
// If so, set joystick details (currently XBox controller is only gamepad handled by XInput and so its capabilities are fixed)
|
// If so, set joystick details (currently XBox controller is only gamepad handled by XInput and so its capabilities are fixed)
|
||||||
sprintf(joyDetails.name, "Xbox 360 Controller %d (via XInput)", (xNum + 1));
|
sprintf(joyDetails.name, "Xbox 360 Controller %d (via XInput)", (xNum + 1));
|
||||||
joyDetails.numAxes = 6; // Left & right triggers are mapped to axes in addition to the two analog sticks, giving a total of 6 axes
|
joyDetails.numAxes = 6; // Left & right triggers are mapped to axes in addition to the two analog sticks, giving a total of 6 axes
|
||||||
joyDetails.numPOVs = 1; // Digital D-pad
|
joyDetails.numPOVs = 1; // Digital D-pad
|
||||||
joyDetails.numButtons = 10;
|
joyDetails.numButtons = 10;
|
||||||
joyDetails.hasFFeedback = true;
|
joyDetails.hasFFeedback = m_enableFFeedback;
|
||||||
joyDetails.hasAxis[AXIS_X] = true;
|
joyDetails.hasAxis[AXIS_X] = true;
|
||||||
joyDetails.hasAxis[AXIS_Y] = true;
|
joyDetails.hasAxis[AXIS_Y] = true;
|
||||||
joyDetails.hasAxis[AXIS_Z] = true;
|
joyDetails.hasAxis[AXIS_Z] = true;
|
||||||
|
@ -982,28 +988,28 @@ void CDirectInputSystem::OpenJoysticks()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Otherwise, open joystick with DirectInput for given GUID and set its data format
|
// Otherwise, open joystick with DirectInput for given GUID and set its data format
|
||||||
LPDIRECTINPUTDEVICE8 di8Joystick;
|
LPDIRECTINPUTDEVICE8 joystick;
|
||||||
if (FAILED(hr = m_di8->CreateDevice(it->guid, &di8Joystick, NULL)))
|
if (FAILED(hr = m_di8->CreateDevice(it->guid, &joystick, NULL)))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to create DirectInput joystick device %d (error %d) - skipping joystick.\n", joyNum, hr);
|
ErrorLog("Unable to create DirectInput joystick device %d (error %d) - skipping joystick.\n", joyNum, hr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (FAILED(hr = di8Joystick->SetDataFormat(&c_dfDIJoystick2)))
|
if (FAILED(hr = joystick->SetDataFormat(&c_dfDIJoystick2)))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to set data format for DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
ErrorLog("Unable to set data format for DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
||||||
|
|
||||||
di8Joystick->Release();
|
joystick->Release();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get joystick's capabilities
|
// Get joystick's capabilities
|
||||||
DIDEVCAPS devCaps;
|
DIDEVCAPS devCaps;
|
||||||
devCaps.dwSize = sizeof(DIDEVCAPS);
|
devCaps.dwSize = sizeof(DIDEVCAPS);
|
||||||
if (FAILED(hr = di8Joystick->GetCapabilities(&devCaps)))
|
if (FAILED(hr = joystick->GetCapabilities(&devCaps)))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to query capabilities of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
ErrorLog("Unable to query capabilities of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
||||||
|
|
||||||
di8Joystick->Release();
|
joystick->Release();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1013,11 +1019,11 @@ void CDirectInputSystem::OpenJoysticks()
|
||||||
didps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
didps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||||
didps.diph.dwHow = DIPH_DEVICE;
|
didps.diph.dwHow = DIPH_DEVICE;
|
||||||
didps.diph.dwObj = 0;
|
didps.diph.dwObj = 0;
|
||||||
if (FAILED(hr = di8Joystick->GetProperty(DIPROP_INSTANCENAME, &didps.diph)))
|
if (FAILED(hr = joystick->GetProperty(DIPROP_INSTANCENAME, &didps.diph)))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to get name of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
ErrorLog("Unable to get name of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
||||||
|
|
||||||
di8Joystick->Release();
|
joystick->Release();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// DInput returns name as Unicode, convert to ASCII
|
// DInput returns name as Unicode, convert to ASCII
|
||||||
|
@ -1028,20 +1034,24 @@ void CDirectInputSystem::OpenJoysticks()
|
||||||
joyDetails.numButtons = devCaps.dwButtons;
|
joyDetails.numButtons = devCaps.dwButtons;
|
||||||
|
|
||||||
// Enumerate axes
|
// Enumerate axes
|
||||||
if (FAILED(hr = di8Joystick->EnumObjects(DI8EnumAxesCallback, &joyDetails, DIDFT_AXIS)))
|
if (FAILED(hr = joystick->EnumObjects(DI8EnumAxesCallback, &joyDetails, DIDFT_AXIS)))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to enumerate axes of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
ErrorLog("Unable to enumerate axes of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
||||||
|
|
||||||
di8Joystick->Release();
|
joystick->Release();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
joyDetails.numAxes = 0;
|
joyDetails.numAxes = 0;
|
||||||
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||||
joyDetails.numAxes += joyDetails.hasAxis[axisNum];
|
joyDetails.numAxes += joyDetails.hasAxis[axisNum];
|
||||||
|
|
||||||
// See if force feedback available for joystick
|
// See if force feedback enabled and is available for joystick
|
||||||
if (FAILED(hr = di8Joystick->EnumEffects(DI8EnumEffectsCallback, &joyDetails, DIEFT_ALL)))
|
if (m_enableFFeedback && (devCaps.dwFlags & DIDC_FORCEFEEDBACK))
|
||||||
|
{
|
||||||
|
// If so, see what types of effects are available and for which axes
|
||||||
|
if (FAILED(hr = joystick->EnumEffects(DI8EnumEffectsCallback, &joyDetails, DIEFT_ALL)))
|
||||||
ErrorLog("Unable to enumerate effects of DirectInput joystick %d (error %d) - force feedback will be unavailable for joystick.\n", joyNum, hr);
|
ErrorLog("Unable to enumerate effects of DirectInput joystick %d (error %d) - force feedback will be unavailable for joystick.\n", joyNum, hr);
|
||||||
|
}
|
||||||
|
|
||||||
// Configure axes, if any
|
// Configure axes, if any
|
||||||
if (joyDetails.numAxes > 0)
|
if (joyDetails.numAxes > 0)
|
||||||
|
@ -1054,11 +1064,11 @@ void CDirectInputSystem::OpenJoysticks()
|
||||||
didpr.diph.dwObj = 0;
|
didpr.diph.dwObj = 0;
|
||||||
didpr.lMin = -32768;
|
didpr.lMin = -32768;
|
||||||
didpr.lMax = 32767;
|
didpr.lMax = 32767;
|
||||||
if (FAILED(hr = di8Joystick->SetProperty(DIPROP_RANGE, &didpr.diph)))
|
if (FAILED(hr = joystick->SetProperty(DIPROP_RANGE, &didpr.diph)))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to set axis range of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
ErrorLog("Unable to set axis range of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
||||||
|
|
||||||
di8Joystick->Release();
|
joystick->Release();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1069,40 +1079,40 @@ void CDirectInputSystem::OpenJoysticks()
|
||||||
dipdw.diph.dwHow = DIPH_DEVICE;
|
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||||
dipdw.diph.dwObj = 0;
|
dipdw.diph.dwObj = 0;
|
||||||
dipdw.dwData = DIPROPAXISMODE_ABS;
|
dipdw.dwData = DIPROPAXISMODE_ABS;
|
||||||
if (FAILED(hr = di8Joystick->SetProperty(DIPROP_AXISMODE, &dipdw.diph)))
|
if (FAILED(hr = joystick->SetProperty(DIPROP_AXISMODE, &dipdw.diph)))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to set axis mode of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
ErrorLog("Unable to set axis mode of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
||||||
|
|
||||||
di8Joystick->Release();
|
joystick->Release();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn off deadzone as handled by this class
|
// Turn off deadzone as handled by this class
|
||||||
dipdw.dwData = 0;
|
dipdw.dwData = 0;
|
||||||
if (FAILED(hr = di8Joystick->SetProperty(DIPROP_DEADZONE, &dipdw.diph)))
|
if (FAILED(hr = joystick->SetProperty(DIPROP_DEADZONE, &dipdw.diph)))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to set deadzone of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
ErrorLog("Unable to set deadzone of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
||||||
|
|
||||||
di8Joystick->Release();
|
joystick->Release();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn off saturation as handle by this class
|
// Turn off saturation as handle by this class
|
||||||
dipdw.dwData = 10000;
|
dipdw.dwData = 10000;
|
||||||
if (FAILED(hr = di8Joystick->SetProperty(DIPROP_SATURATION, &dipdw.diph)))
|
if (FAILED(hr = joystick->SetProperty(DIPROP_SATURATION, &dipdw.diph)))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to set saturation of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
ErrorLog("Unable to set saturation of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr);
|
||||||
|
|
||||||
di8Joystick->Release();
|
joystick->Release();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If joystick force feedback is enabled and joystick has force feedback capabilities then disable auto-center
|
// If joystick has force feedback capabilities then disable auto-center
|
||||||
if (m_enableFFeedback && joyDetails.hasFFeedback)
|
if (joyDetails.hasFFeedback)
|
||||||
{
|
{
|
||||||
dipdw.dwData = FALSE;
|
dipdw.dwData = FALSE;
|
||||||
|
|
||||||
if (FAILED(hr = di8Joystick->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph)))
|
if (FAILED(hr = joystick->SetProperty(DIPROP_AUTOCENTER, &dipdw.diph)))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to unset auto-center of DirectInput joystick %d (error %d) - force feedback will be unavailable for joystick.\n", joyNum, hr);
|
ErrorLog("Unable to unset auto-center of DirectInput joystick %d (error %d) - force feedback will be unavailable for joystick.\n", joyNum, hr);
|
||||||
|
|
||||||
|
@ -1114,7 +1124,7 @@ void CDirectInputSystem::OpenJoysticks()
|
||||||
// Keep track of DirectInput device number
|
// Keep track of DirectInput device number
|
||||||
it->dInputNum = m_di8Joysticks.size();
|
it->dInputNum = m_di8Joysticks.size();
|
||||||
|
|
||||||
m_di8Joysticks.push_back(di8Joystick);
|
m_di8Joysticks.push_back(joystick);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create initial blank joystick state
|
// Create initial blank joystick state
|
||||||
|
@ -1131,20 +1141,31 @@ void CDirectInputSystem::OpenJoysticks()
|
||||||
void CDirectInputSystem::ActivateJoysticks()
|
void CDirectInputSystem::ActivateJoysticks()
|
||||||
{
|
{
|
||||||
// Set DirectInput cooperative level of joysticks
|
// Set DirectInput cooperative level of joysticks
|
||||||
for (vector<LPDIRECTINPUTDEVICE8>::iterator it = m_di8Joysticks.begin(); it < m_di8Joysticks.end(); it++)
|
unsigned joyNum = 0;
|
||||||
(*it)->SetCooperativeLevel(m_hwnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
for (vector<DIJoyInfo>::iterator it = m_diJoyInfos.begin(); it != m_diJoyInfos.end(); it++)
|
||||||
|
{
|
||||||
|
if (!it->isXInput)
|
||||||
|
{
|
||||||
|
LPDIRECTINPUTDEVICE8 joystick = m_di8Joysticks[it->dInputNum];
|
||||||
|
if (m_joyDetails[joyNum].hasFFeedback)
|
||||||
|
joystick->SetCooperativeLevel(m_hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
||||||
|
else
|
||||||
|
joystick->SetCooperativeLevel(m_hwnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
||||||
|
}
|
||||||
|
joyNum++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDirectInputSystem::PollJoysticks()
|
void CDirectInputSystem::PollJoysticks()
|
||||||
{
|
{
|
||||||
// Get current joystick states from XInput and DirectInput
|
// Get current joystick states from XInput and DirectInput
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (vector<DIJoyInfo>::iterator it = m_diJoyInfos.begin(); it < m_diJoyInfos.end(); it++)
|
for (vector<DIJoyInfo>::iterator it = m_diJoyInfos.begin(); it != m_diJoyInfos.end(); it++)
|
||||||
{
|
{
|
||||||
LPDIJOYSTATE2 pJoyState = &m_diJoyStates[i++];
|
LPDIJOYSTATE2 pJoyState = &m_diJoyStates[i++];
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
if (m_useXInput && it->isXInput)
|
if (it->isXInput)
|
||||||
{
|
{
|
||||||
// Use XInput to query joystick
|
// Use XInput to query joystick
|
||||||
XINPUT_STATE xState;
|
XINPUT_STATE xState;
|
||||||
|
@ -1219,8 +1240,24 @@ void CDirectInputSystem::PollJoysticks()
|
||||||
|
|
||||||
void CDirectInputSystem::CloseJoysticks()
|
void CDirectInputSystem::CloseJoysticks()
|
||||||
{
|
{
|
||||||
|
// Release any DirectInput force feedback effects that were created
|
||||||
|
for (vector<DIJoyInfo>::iterator it = m_diJoyInfos.begin(); it != m_diJoyInfos.end(); it++)
|
||||||
|
{
|
||||||
|
for (unsigned axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||||
|
{
|
||||||
|
for (unsigned effNum = 0; effNum < NUM_FF_EFFECTS; effNum++)
|
||||||
|
{
|
||||||
|
if (it->dInputEffects[axisNum][effNum] != NULL)
|
||||||
|
{
|
||||||
|
it->dInputEffects[axisNum][effNum]->Release();
|
||||||
|
it->dInputEffects[axisNum][effNum] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Release each DirectInput joystick
|
// Release each DirectInput joystick
|
||||||
for (vector<LPDIRECTINPUTDEVICE8>::iterator it = m_di8Joysticks.begin(); it < m_di8Joysticks.end(); it++)
|
for (vector<LPDIRECTINPUTDEVICE8>::iterator it = m_di8Joysticks.begin(); it != m_di8Joysticks.end(); it++)
|
||||||
{
|
{
|
||||||
(*it)->Unacquire();
|
(*it)->Unacquire();
|
||||||
(*it)->Release();
|
(*it)->Release();
|
||||||
|
@ -1232,47 +1269,102 @@ void CDirectInputSystem::CloseJoysticks()
|
||||||
m_di8Joysticks.clear();
|
m_di8Joysticks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CDirectInputSystem::CreateJoystickEffect(LPDIRECTINPUTDEVICE8 di8Joystick, int axisNum, LPDIRECTINPUTEFFECT *di8Effect)
|
HRESULT CDirectInputSystem::CreateJoystickEffect(LPDIRECTINPUTDEVICE8 joystick, int axisNum, ForceFeedbackCmd ffCmd, LPDIRECTINPUTEFFECT *pEffect)
|
||||||
{
|
{
|
||||||
// TODO - following is not finished
|
// Map axis number to DI object offset
|
||||||
DWORD axisOfs;
|
DWORD axisOfs;
|
||||||
switch (axisNum)
|
switch (axisNum)
|
||||||
{
|
{
|
||||||
case AXIS_X: axisOfs = DIJOFS_X; break;
|
case AXIS_X: axisOfs = DIJOFS_X; break;
|
||||||
case AXIS_Y: axisNum = DIJOFS_Y; break;
|
case AXIS_Y: axisOfs = DIJOFS_Y; break;
|
||||||
case AXIS_Z: axisNum = DIJOFS_Z; break;
|
case AXIS_Z: axisOfs = DIJOFS_Z; break;
|
||||||
case AXIS_RX: axisNum = DIJOFS_RX; break;
|
case AXIS_RX: axisOfs = DIJOFS_RX; break;
|
||||||
case AXIS_RY: axisNum = DIJOFS_RY; break;
|
case AXIS_RY: axisOfs = DIJOFS_RY; break;
|
||||||
case AXIS_RZ: axisNum = DIJOFS_RZ; break;
|
case AXIS_RZ: axisOfs = DIJOFS_RZ; break;
|
||||||
default: return E_FAIL;
|
default: return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD rgdwAxes[1] = { axisOfs };
|
DWORD rgdwAxes[1] = { axisOfs };
|
||||||
LONG rglDirection[1] = { 0 };
|
LONG rglDirection[1] = { 0 };
|
||||||
DICONSTANTFORCE cf = { 0 };
|
DICONSTANTFORCE dicf;
|
||||||
|
DICONDITION dic;
|
||||||
|
DIPERIODIC dip;
|
||||||
|
DIENVELOPE die;
|
||||||
|
GUID guid;
|
||||||
|
|
||||||
|
// Set common effects parameters
|
||||||
DIEFFECT eff;
|
DIEFFECT eff;
|
||||||
memset(&eff, 0, sizeof(eff));
|
memset(&eff, 0, sizeof(eff));
|
||||||
eff.dwSize = sizeof(DIEFFECT);
|
eff.dwSize = sizeof(DIEFFECT);
|
||||||
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||||
eff.dwDuration = INFINITE;
|
|
||||||
eff.dwSamplePeriod = 0;
|
|
||||||
eff.dwGain = DI_FFNOMINALMAX;
|
|
||||||
eff.dwTriggerButton = DIEB_NOTRIGGER;
|
eff.dwTriggerButton = DIEB_NOTRIGGER;
|
||||||
eff.dwTriggerRepeatInterval = 0;
|
eff.dwTriggerRepeatInterval = 0;
|
||||||
|
eff.dwGain = DI_FFNOMINALMAX;
|
||||||
eff.cAxes = 1;
|
eff.cAxes = 1;
|
||||||
eff.rgdwAxes = rgdwAxes;
|
eff.rgdwAxes = rgdwAxes;
|
||||||
eff.rglDirection = rglDirection;
|
eff.rglDirection = rglDirection;
|
||||||
eff.lpEnvelope = 0;
|
eff.dwDuration = INFINITE;
|
||||||
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
|
|
||||||
eff.lpvTypeSpecificParams = &cf;
|
|
||||||
eff.dwStartDelay = 0;
|
eff.dwStartDelay = 0;
|
||||||
|
|
||||||
// Create the prepared effect
|
// Set specific effects parameters
|
||||||
HRESULT hr;
|
switch (ffCmd.id)
|
||||||
if (FAILED(hr = di8Joystick->CreateEffect(GUID_ConstantForce, &eff, di8Effect, NULL)))
|
{
|
||||||
return hr;
|
case FFStop:
|
||||||
if (di8Effect == NULL)
|
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
|
case FFSelfCenter:
|
||||||
|
guid = GUID_Spring;
|
||||||
|
|
||||||
|
dic.lOffset = 0;
|
||||||
|
dic.lPositiveCoefficient = 0;
|
||||||
|
dic.lNegativeCoefficient = 0;
|
||||||
|
dic.dwPositiveSaturation = DI_FFNOMINALMAX;
|
||||||
|
dic.dwNegativeSaturation = DI_FFNOMINALMAX;
|
||||||
|
dic.lDeadBand = (LONG)0.05 * DI_FFNOMINALMAX;
|
||||||
|
|
||||||
|
eff.lpEnvelope = NULL;
|
||||||
|
eff.cbTypeSpecificParams = sizeof(DICONDITION);
|
||||||
|
eff.lpvTypeSpecificParams = &dic;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFConstantForce:
|
||||||
|
guid = GUID_ConstantForce;
|
||||||
|
|
||||||
|
dicf.lMagnitude = 0;
|
||||||
|
|
||||||
|
eff.lpEnvelope = NULL;
|
||||||
|
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
|
||||||
|
eff.lpvTypeSpecificParams = &dicf;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFVibrate:
|
||||||
|
guid = GUID_Sine;
|
||||||
|
|
||||||
|
dip.dwMagnitude = 0;
|
||||||
|
dip.lOffset = 0;
|
||||||
|
dip.dwPhase = 0;
|
||||||
|
dip.dwPeriod = (DWORD)0.1 * DI_SECONDS; // 1/10th second
|
||||||
|
|
||||||
|
die.dwSize = sizeof(die);
|
||||||
|
die.dwAttackLevel = 0;
|
||||||
|
die.dwAttackTime = (DWORD)0.5 * DI_SECONDS;
|
||||||
|
die.dwFadeLevel = 0;
|
||||||
|
die.dwFadeTime = (DWORD)0.5 * DI_SECONDS;
|
||||||
|
|
||||||
|
eff.lpEnvelope = ¨
|
||||||
|
eff.cbTypeSpecificParams = sizeof(DIPERIODIC);
|
||||||
|
eff.lpvTypeSpecificParams = &dip;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
joystick->Acquire();
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
if (FAILED(hr = joystick->CreateEffect(guid, &eff, pEffect, NULL)))
|
||||||
|
return hr;
|
||||||
|
if (*pEffect == NULL)
|
||||||
|
return E_FAIL;
|
||||||
|
(*pEffect)->Start(1, 0);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1490,18 +1582,15 @@ bool CDirectInputSystem::IsJoyButPressed(int joyNum, int butNum)
|
||||||
return !!m_diJoyStates[joyNum].rgbButtons[butNum];
|
return !!m_diJoyStates[joyNum].rgbButtons[butNum];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd)
|
bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd)
|
||||||
{
|
{
|
||||||
if (!m_enableFFeedback)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
DIJoyInfo *pInfo = &m_diJoyInfos[joyNum];
|
DIJoyInfo *pInfo = &m_diJoyInfos[joyNum];
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
if (m_useXInput && pInfo->isXInput)
|
if (pInfo->isXInput)
|
||||||
{
|
{
|
||||||
XINPUT_VIBRATION vibration;
|
XINPUT_VIBRATION vibration;
|
||||||
switch (ffCmd->id)
|
switch (ffCmd.id)
|
||||||
{
|
{
|
||||||
case FFStop:
|
case FFStop:
|
||||||
if (axisNum == AXIS_X || axisNum == AXIS_Y)
|
if (axisNum == AXIS_X || axisNum == AXIS_Y)
|
||||||
|
@ -1510,70 +1599,101 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
|
||||||
vibration.wRightMotorSpeed = 0;
|
vibration.wRightMotorSpeed = 0;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
if (FAILED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration)))
|
return SUCCEEDED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration));
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFConstantForce:
|
case FFConstantForce:
|
||||||
if (axisNum == AXIS_X || axisNum == AXIS_Y)
|
if (axisNum == AXIS_X || axisNum == AXIS_Y)
|
||||||
vibration.wLeftMotorSpeed = ffCmd->data; // TODO - scale data to 0-65535
|
vibration.wLeftMotorSpeed = ffCmd.data; // TODO - scale data to 0-65535
|
||||||
else if (axisNum == AXIS_RX || axisNum == AXIS_RY)
|
else if (axisNum == AXIS_RX || axisNum == AXIS_RY)
|
||||||
vibration.wRightMotorSpeed = ffCmd->data; // TODO - scale data to 0-65535
|
vibration.wRightMotorSpeed = ffCmd.data; // TODO - scale data to 0-65535
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
if (FAILED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration)))
|
return SUCCEEDED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration));
|
||||||
|
|
||||||
|
default:
|
||||||
|
// TODO - other force feedback types
|
||||||
return false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LPDIRECTINPUTDEVICE8 di8Joystick = m_di8Joysticks[pInfo->dInputNum];
|
LPDIRECTINPUTDEVICE8 joystick = m_di8Joysticks[pInfo->dInputNum];
|
||||||
switch (ffCmd->id)
|
|
||||||
{
|
|
||||||
case FFStop:
|
|
||||||
if (FAILED(hr = di8Joystick->SendForceFeedbackCommand(DISFFC_STOPALL)))
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFConstantForce:
|
// See if command is to stop all force feedback
|
||||||
LPDIRECTINPUTEFFECT di8Effect;
|
if (ffCmd.id == -1)
|
||||||
if (FAILED(hr = CreateJoystickEffect(di8Joystick, axisNum, &di8Effect)))
|
return SUCCEEDED(hr = joystick->SendForceFeedbackCommand(DISFFC_STOPALL));
|
||||||
|
|
||||||
|
// Create effect for given axis if has not already been created
|
||||||
|
int effNum = (int)ffCmd.id;
|
||||||
|
LPDIRECTINPUTEFFECT *pEffect = &pInfo->dInputEffects[axisNum][effNum];
|
||||||
|
if ((*pEffect) == NULL)
|
||||||
{
|
{
|
||||||
// TODO
|
if (FAILED(hr = CreateJoystickEffect(joystick, axisNum, ffCmd, pEffect)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DICONSTANTFORCE cf;
|
|
||||||
cf.lMagnitude = ffCmd->data; // TODO - scale data to what?
|
|
||||||
LONG rglDirection[1] = { 0 };
|
LONG rglDirection[1] = { 0 };
|
||||||
|
DICONSTANTFORCE dicf;
|
||||||
|
DICONDITION dic;
|
||||||
|
DIPERIODIC dip;
|
||||||
|
DIENVELOPE die;
|
||||||
|
|
||||||
|
// Set common parameters
|
||||||
DIEFFECT eff;
|
DIEFFECT eff;
|
||||||
memset(&eff, 0, sizeof(eff));
|
memset(&eff, 0, sizeof(eff));
|
||||||
eff.dwSize = sizeof(DIEFFECT);
|
eff.dwSize = sizeof(DIEFFECT);
|
||||||
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||||
eff.cAxes = 1;
|
eff.cAxes = 1;
|
||||||
eff.rglDirection = rglDirection;
|
eff.rglDirection = rglDirection;
|
||||||
eff.lpEnvelope = 0;
|
|
||||||
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
|
|
||||||
eff.lpvTypeSpecificParams = &cf;
|
|
||||||
eff.dwStartDelay = 0;
|
eff.dwStartDelay = 0;
|
||||||
|
|
||||||
// Now set the new parameters and start the effect immediately.
|
switch (ffCmd.id)
|
||||||
if (FAILED(hr = di8Effect->SetParameters(&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START)))
|
|
||||||
{
|
{
|
||||||
// TODO
|
case FFSelfCenter:
|
||||||
|
dic.lPositiveCoefficient = ffCmd.data;
|
||||||
|
dic.lNegativeCoefficient = ffCmd.data;
|
||||||
|
dic.dwPositiveSaturation = DI_FFNOMINALMAX;
|
||||||
|
dic.dwNegativeSaturation = DI_FFNOMINALMAX;
|
||||||
|
dic.lDeadBand = (LONG)0.05 * DI_FFNOMINALMAX;
|
||||||
|
|
||||||
|
eff.lpEnvelope = NULL;
|
||||||
|
eff.cbTypeSpecificParams = sizeof(DICONDITION);
|
||||||
|
eff.lpvTypeSpecificParams = &dic;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFConstantForce:
|
||||||
|
dicf.lMagnitude = ffCmd.data; // TODO - scale & cap at +/- DI_FFNOMINALMAX
|
||||||
|
|
||||||
|
eff.lpEnvelope = NULL;
|
||||||
|
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
|
||||||
|
eff.lpvTypeSpecificParams = &dicf;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FFVibrate:
|
||||||
|
dip.dwMagnitude = ffCmd.data;
|
||||||
|
dip.lOffset = 0;
|
||||||
|
dip.dwPhase = 0;
|
||||||
|
dip.dwPeriod = (DWORD)0.1 * DI_SECONDS; // 1/10th second
|
||||||
|
|
||||||
|
die.dwSize = sizeof(die);
|
||||||
|
die.dwAttackLevel = 0;
|
||||||
|
die.dwAttackTime = (DWORD)0.5 * DI_SECONDS;
|
||||||
|
die.dwFadeLevel = 0;
|
||||||
|
die.dwFadeTime = (DWORD)0.5 * DI_SECONDS;
|
||||||
|
|
||||||
|
eff.lpEnvelope = ¨
|
||||||
|
eff.cbTypeSpecificParams = sizeof(DIPERIODIC);
|
||||||
|
eff.lpvTypeSpecificParams = &dip;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//di8Effect->Release();
|
// Now set the new parameters and start the effect immediately.
|
||||||
break;
|
return SUCCEEDED(hr = (*pEffect)->SetParameters(&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDirectInputSystem::Wait(int ms)
|
void CDirectInputSystem::Wait(int ms)
|
||||||
|
|
|
@ -46,9 +46,16 @@ struct DIJoyInfo
|
||||||
GUID guid;
|
GUID guid;
|
||||||
bool isXInput;
|
bool isXInput;
|
||||||
int dInputNum;
|
int dInputNum;
|
||||||
|
LPDIRECTINPUTEFFECT dInputEffects[NUM_JOY_AXES][NUM_FF_EFFECTS];
|
||||||
int xInputNum;
|
int xInputNum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DIEnumDevsContext
|
||||||
|
{
|
||||||
|
vector<DIJoyInfo> *infos;
|
||||||
|
bool useXInput;
|
||||||
|
};
|
||||||
|
|
||||||
// RawInput API
|
// RawInput API
|
||||||
typedef /*WINUSERAPI*/ INT (WINAPI *GetRawInputDeviceListPtr)(OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PUINT puiNumDevices, IN UINT cbSize);
|
typedef /*WINUSERAPI*/ INT (WINAPI *GetRawInputDeviceListPtr)(OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PUINT puiNumDevices, IN UINT cbSize);
|
||||||
typedef /*WINUSERAPI*/ INT (WINAPI *GetRawInputDeviceInfoPtr)(IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PUINT pcbSize);
|
typedef /*WINUSERAPI*/ INT (WINAPI *GetRawInputDeviceInfoPtr)(IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PUINT pcbSize);
|
||||||
|
@ -151,7 +158,7 @@ private:
|
||||||
|
|
||||||
void CloseJoysticks();
|
void CloseJoysticks();
|
||||||
|
|
||||||
HRESULT CreateJoystickEffect(LPDIRECTINPUTDEVICE8 di8Joystick, int axisNum, LPDIRECTINPUTEFFECT *di8Effect);
|
HRESULT CreateJoystickEffect(LPDIRECTINPUTDEVICE8 di8Joystick, int axisNum, ForceFeedbackCmd ffCmd, LPDIRECTINPUTEFFECT *di8Effect);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*
|
/*
|
||||||
|
@ -177,7 +184,7 @@ protected:
|
||||||
|
|
||||||
bool IsJoyButPressed(int joyNum, int butNum);
|
bool IsJoyButPressed(int joyNum, int butNum);
|
||||||
|
|
||||||
bool ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd);
|
bool ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd);
|
||||||
|
|
||||||
void Wait(int ms);
|
void Wait(int ms);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue