mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 13:55: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 "").
|
||||
void CINIFile::Set(string SectionName, string SettingName, unsigned value)
|
||||
void CINIFile::Set(string SectionName, string SettingName, int value)
|
||||
{
|
||||
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.
|
||||
BOOL CINIFile::Get(string SectionName, string SettingName, unsigned& value)
|
||||
BOOL CINIFile::Get(string SectionName, string SettingName, int& value)
|
||||
{
|
||||
unsigned sectionIdx, settingIdx;
|
||||
|
||||
|
@ -248,6 +248,17 @@ BOOL CINIFile::Get(string SectionName, string SettingName, unsigned& value)
|
|||
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.
|
||||
BOOL CINIFile::Get(string SectionName, string SettingName, string& String)
|
||||
{
|
||||
|
@ -323,15 +334,24 @@ CINIFile::CToken CINIFile::GetString(void)
|
|||
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)
|
||||
{
|
||||
CToken T;
|
||||
unsigned long long number = 0;
|
||||
BOOL isNeg = FALSE;
|
||||
int overflow = 0;
|
||||
|
||||
T.type = TOKEN_NUMBER;
|
||||
|
||||
// See if begins with minus sign
|
||||
if (linePtr[0]=='-')
|
||||
{
|
||||
isNeg = TRUE;
|
||||
linePtr++;
|
||||
}
|
||||
|
||||
// Hexadecimal?
|
||||
if ((linePtr[0]=='0') && ((linePtr[1]=='X') || (linePtr[1]=='x')))
|
||||
{
|
||||
|
@ -360,7 +380,7 @@ CINIFile::CToken CINIFile::GetNumber(void)
|
|||
++linePtr;
|
||||
|
||||
// Check for overflows
|
||||
if (number > 0x00000000FFFFFFFFULL)
|
||||
if (!isNeg && number > 0x000000007FFFFFFFULL || isNeg && number > 0x0000000080000000ULL)
|
||||
overflow = 1;
|
||||
}
|
||||
else if (IsBlank(linePtr[0]))
|
||||
|
@ -387,7 +407,7 @@ CINIFile::CToken CINIFile::GetNumber(void)
|
|||
++linePtr;
|
||||
|
||||
// Check for overflows
|
||||
if (number > 0x00000000FFFFFFFFULL)
|
||||
if (!isNeg && number > 0x000000007FFFFFFFULL || isNeg && number > 0x0000000080000000ULL)
|
||||
overflow = 1;
|
||||
}
|
||||
else if (IsBlank(linePtr[0]))
|
||||
|
@ -404,7 +424,7 @@ CINIFile::CToken CINIFile::GetNumber(void)
|
|||
//if (overflow)
|
||||
// printf("tokenizer: number exceeds 32 bits and has been truncated\n");
|
||||
|
||||
T.number = (unsigned) number;
|
||||
T.number = (isNeg ? -(int)number : (int)number);
|
||||
return T;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
* OKAY if the setting was found, FAIL otherwise. The type is not
|
||||
* checked.
|
||||
*/
|
||||
BOOL Get(string SectionName, string SettingName, int& value);
|
||||
BOOL Get(string SectionName, string SettingName, unsigned& value);
|
||||
BOOL Get(string SectionName, string SettingName, string& String);
|
||||
|
||||
|
@ -82,7 +83,7 @@ public:
|
|||
* value Value to write. String will be set to "".
|
||||
* 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);
|
||||
|
||||
/*
|
||||
|
@ -146,7 +147,7 @@ private:
|
|||
{
|
||||
public:
|
||||
int type; // token type (defined privately in INIFile.cpp)
|
||||
unsigned number; // numbers and bools
|
||||
int number; // numbers and bools
|
||||
string String; // strings and identifiers
|
||||
|
||||
// Constructor (initialize to null token)
|
||||
|
@ -177,7 +178,7 @@ private:
|
|||
{
|
||||
string Name; // setting name
|
||||
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
|
||||
|
||||
Setting(void)
|
||||
|
|
|
@ -7,11 +7,18 @@ CInput::CInput(const char *inputId, const char *inputLabel, unsigned inputFlags,
|
|||
ResetToDefaultMapping();
|
||||
}
|
||||
|
||||
CInput::~CInput()
|
||||
{
|
||||
// Release source, if any
|
||||
if (m_source != NULL)
|
||||
m_source->Release();
|
||||
}
|
||||
|
||||
void CInput::CreateSource()
|
||||
{
|
||||
// If already have a source, then release it now
|
||||
if (m_system != NULL && m_source != NULL)
|
||||
m_system->ReleaseSource(m_source);
|
||||
if (m_source != NULL)
|
||||
m_source->Release();
|
||||
|
||||
// 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)
|
||||
|
@ -21,12 +28,18 @@ void CInput::CreateSource()
|
|||
// Otherwise, ask system to parse mapping into appropriate input source
|
||||
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
|
||||
if (m_source == NULL && stricmp(m_mapping, m_defaultMapping) != 0)
|
||||
// Check that mapping was parsed okay and if so acquire it
|
||||
if (m_source != NULL)
|
||||
m_source->Acquire();
|
||||
else
|
||||
{
|
||||
ErrorLog("Unable to map input %s to [%s] - switching to default [%s].\n", id, m_mapping, m_defaultMapping);
|
||||
// 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);
|
||||
|
||||
ResetToDefaultMapping();
|
||||
ResetToDefaultMapping();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,8 +85,8 @@ void CInput::ClearMapping()
|
|||
|
||||
void CInput::SetMapping(const char *mapping)
|
||||
{
|
||||
strncpy(m_mapping, mapping, MAX_MAPPING_LENGTH - 1);
|
||||
m_mapping[MAX_MAPPING_LENGTH - 1] = '\0';
|
||||
strncpy(m_mapping, mapping, MAX_MAPPING_LENGTH);
|
||||
m_mapping[MAX_MAPPING_LENGTH] = '\0';
|
||||
CreateSource();
|
||||
}
|
||||
|
||||
|
@ -99,13 +112,23 @@ void CInput::ResetToDefaultMapping()
|
|||
|
||||
void CInput::ReadFromINIFile(CINIFile *ini, const char *section)
|
||||
{
|
||||
if (!IsConfigurable())
|
||||
return;
|
||||
string key("Input");
|
||||
key.append(id);
|
||||
string mapping;
|
||||
if (ini->Get(section, key, mapping) == OKAY)
|
||||
SetMapping(mapping.c_str());
|
||||
// See if input is configurable
|
||||
if (IsConfigurable())
|
||||
{
|
||||
// If so, check INI file for mapping string
|
||||
string key("Input");
|
||||
key.append(id);
|
||||
string mapping;
|
||||
if (ini->Get(section, key, mapping) == OKAY)
|
||||
{
|
||||
// If found, then set mapping string
|
||||
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)
|
||||
|
@ -134,7 +157,7 @@ bool CInput::Changed()
|
|||
return value != prevValue;
|
||||
}
|
||||
|
||||
bool CInput::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
|
||||
bool CInput::SendForceFeedbackCmd(ForceFeedbackCmd ffCmd)
|
||||
{
|
||||
if (m_source == NULL)
|
||||
return false;
|
||||
|
|
|
@ -18,10 +18,14 @@ class CINIFile;
|
|||
|
||||
#define MAX_MAPPING_LENGTH 255
|
||||
|
||||
#define NUM_FF_EFFECTS 3
|
||||
|
||||
enum EForceFeedback
|
||||
{
|
||||
FFStop,
|
||||
FFConstantForce
|
||||
FFStop = -1,
|
||||
FFSelfCenter = 0,
|
||||
FFConstantForce = 1,
|
||||
FFVibrate = 2
|
||||
};
|
||||
|
||||
struct ForceFeedbackCmd
|
||||
|
@ -37,7 +41,7 @@ class CInput
|
|||
{
|
||||
private:
|
||||
// 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
|
||||
const char *m_defaultMapping;
|
||||
|
@ -53,8 +57,16 @@ private:
|
|||
protected:
|
||||
// Current input 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:
|
||||
virtual ~CInput();
|
||||
|
||||
// Input identifier
|
||||
const char *id;
|
||||
|
||||
|
@ -72,12 +84,6 @@ public:
|
|||
|
||||
// Previous input value
|
||||
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.
|
||||
|
@ -161,7 +167,7 @@ public:
|
|||
/*
|
||||
* 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>
|
||||
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)
|
||||
{
|
||||
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 fromRange;
|
||||
double fromRange;
|
||||
double frac;
|
||||
if (fromMaxVal > fromMinVal)
|
||||
{
|
||||
val = Clamp(val, fromMinVal, fromMaxVal);
|
||||
if (val > fromOffVal)
|
||||
{
|
||||
fromRange = fromMaxVal - fromOffVal;
|
||||
fromRange = (double)(fromMaxVal - fromOffVal);
|
||||
frac = (double)(val - fromOffVal) / fromRange;
|
||||
}
|
||||
else if (val < fromOffVal)
|
||||
{
|
||||
fromRange = fromOffVal - fromMinVal;
|
||||
fromRange = (double)(fromOffVal - fromMinVal);
|
||||
frac = (double)(val - fromOffVal) / fromRange;
|
||||
}
|
||||
else
|
||||
|
@ -45,12 +64,12 @@ int CInputSource::Scale(int val, int fromMinVal, int fromOffVal, int fromMaxVal,
|
|||
val = Clamp(val, fromMaxVal, fromMinVal);
|
||||
if (val > fromOffVal)
|
||||
{
|
||||
fromRange = fromMinVal - fromOffVal;
|
||||
fromRange = (double)(fromMinVal - fromOffVal);
|
||||
frac = (double)(fromOffVal - val) / fromRange;
|
||||
}
|
||||
else if (val < fromOffVal)
|
||||
{
|
||||
fromRange = fromOffVal - fromMaxVal;
|
||||
fromRange = (double)(fromOffVal - fromMaxVal);
|
||||
frac = (double)(fromOffVal - val) / fromRange;
|
||||
}
|
||||
else
|
||||
|
@ -83,7 +102,7 @@ bool CInputSource::IsActive()
|
|||
return GetValueAsSwitch(boolVal);
|
||||
}
|
||||
|
||||
bool CInputSource::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
|
||||
bool CInputSource::SendForceFeedbackCmd(ForceFeedbackCmd ffCmd)
|
||||
{
|
||||
return false;
|
||||
}
|
|
@ -25,6 +25,8 @@ enum ESourceType
|
|||
class CInputSource
|
||||
{
|
||||
protected:
|
||||
unsigned m_acquired;
|
||||
|
||||
CInputSource(ESourceType sourceType);
|
||||
|
||||
public:
|
||||
|
@ -33,6 +35,10 @@ public:
|
|||
*/
|
||||
const ESourceType type;
|
||||
|
||||
virtual void Acquire();
|
||||
|
||||
virtual void Release();
|
||||
|
||||
//
|
||||
// Static helper methods
|
||||
//
|
||||
|
@ -73,7 +79,7 @@ public:
|
|||
/*
|
||||
* Sends a force feedback command to the input source.
|
||||
*/
|
||||
virtual bool SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd);
|
||||
virtual bool SendForceFeedbackCmd(ForceFeedbackCmd ffCmd);
|
||||
};
|
||||
|
||||
#endif // INCLUDED_INPUTSOURCE_H
|
|
@ -6,6 +6,11 @@
|
|||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#ifdef DEBUG
|
||||
unsigned CInputSystem::totalSrcsAcquired = 0;
|
||||
unsigned CInputSystem::totalSrcsReleased = 0;
|
||||
#endif
|
||||
|
||||
const char *CInputSystem::s_validKeyNames[] =
|
||||
{
|
||||
// General keys
|
||||
|
@ -343,17 +348,26 @@ JoyPartsStruct CInputSystem::s_joyParts[] =
|
|||
{ NULL, JoyUnknown }
|
||||
};
|
||||
|
||||
const char *CInputSystem::s_axisNames[] = { "X", "Y", "Z", "RX", "RY", "RZ" };
|
||||
|
||||
CInputSystem::CInputSystem(const char *systemName) :
|
||||
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()
|
||||
{
|
||||
DeleteSourceCache();
|
||||
m_emptySource->Release();
|
||||
|
||||
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()
|
||||
|
@ -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)
|
||||
{
|
||||
for (int keyIndex = 0; keyIndex < NUM_VALID_KEYS; keyIndex++)
|
||||
ReleaseSource(m_anyKeySources[keyIndex]);
|
||||
if (deleteCache)
|
||||
{
|
||||
if (source == m_anyKeySources[keyIndex])
|
||||
return true;
|
||||
delete[] m_anyKeySources;
|
||||
m_anyKeySources = NULL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
ReleaseSource(m_keySources[kbdNum][keyIndex]);
|
||||
if (deleteCache)
|
||||
delete[] m_keySources[kbdNum];
|
||||
}
|
||||
if (deleteCache)
|
||||
{
|
||||
delete[] m_keySources;
|
||||
m_keySources = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check mouse source cache
|
||||
// Clear cache of mouse sources
|
||||
if (m_anyMseSources != NULL)
|
||||
{
|
||||
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
||||
ReleaseSource(m_anyMseSources[mseIndex]);
|
||||
if (deleteCache)
|
||||
{
|
||||
if (source == m_anyMseSources[mseIndex])
|
||||
return true;
|
||||
delete[] m_anyMseSources;
|
||||
m_anyMseSources = NULL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
ReleaseSource(m_mseSources[mseNum][mseIndex]);
|
||||
if (deleteCache)
|
||||
delete[] m_mseSources[mseNum];
|
||||
}
|
||||
if (deleteCache)
|
||||
{
|
||||
delete[] m_mseSources;
|
||||
m_mseSources = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check joystick source cache
|
||||
// Clear cache of joystick sources
|
||||
if (m_anyJoySources != NULL)
|
||||
{
|
||||
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
||||
ReleaseSource(m_anyJoySources[joyIndex]);
|
||||
if (deleteCache)
|
||||
{
|
||||
if (source == m_anyJoySources[joyIndex])
|
||||
return true;
|
||||
delete[] m_anyJoySources;
|
||||
m_anyJoySources = NULL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
ReleaseSource(m_joySources[joyNum][joyIndex]);
|
||||
if (deleteCache)
|
||||
delete[] m_joySources[joyNum];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
m_anyKeySources = NULL;
|
||||
if (m_numKbds != ANY_KEYBOARD)
|
||||
{
|
||||
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
|
||||
if (deleteCache)
|
||||
{
|
||||
for (int keyIndex = 0; keyIndex < NUM_VALID_KEYS; keyIndex++)
|
||||
DeleteSource(m_keySources[kbdNum][keyIndex]);
|
||||
delete[] m_keySources[kbdNum];
|
||||
delete[] m_joySources;
|
||||
m_joySources = NULL;
|
||||
}
|
||||
delete[] m_keySources;
|
||||
m_keySources = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete cache for mouse sources
|
||||
if (m_anyMseSources != NULL)
|
||||
{
|
||||
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
||||
DeleteSource(m_anyMseSources[mseIndex]);
|
||||
delete[] m_anyMseSources;
|
||||
m_anyMseSources = NULL;
|
||||
if (m_numMice != ANY_MOUSE)
|
||||
{
|
||||
for (int mseNum = 0; mseNum < m_numMice; mseNum++)
|
||||
{
|
||||
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
|
||||
DeleteSource(m_mseSources[mseNum][mseIndex]);
|
||||
delete[] m_mseSources[mseNum];
|
||||
}
|
||||
delete[] m_mseSources;
|
||||
m_mseSources = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete cache for joystick sources
|
||||
if (m_anyJoySources != NULL)
|
||||
{
|
||||
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
||||
DeleteSource(m_anyJoySources[joyIndex]);
|
||||
delete[] m_anyJoySources;
|
||||
m_anyJoySources = NULL;
|
||||
if (m_numJoys != ANY_JOYSTICK)
|
||||
{
|
||||
for (int joyNum = 0; joyNum < m_numJoys; joyNum++)
|
||||
{
|
||||
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
|
||||
DeleteSource(m_joySources[joyNum][joyIndex]);
|
||||
delete[] m_joySources[joyNum];
|
||||
}
|
||||
delete[] m_joySources;
|
||||
m_joySources = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputSystem::DeleteSource(CInputSource *source)
|
||||
void CInputSystem::ReleaseSource(CInputSource *&source)
|
||||
{
|
||||
if (source != NULL && source != m_emptySource)
|
||||
delete source;
|
||||
if (source != NULL)
|
||||
source->Release();
|
||||
source = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
else
|
||||
m_anyKeySources[keyIndex] = CreateAnyKeySource(keyIndex);
|
||||
m_anyKeySources[keyIndex]->Acquire();
|
||||
}
|
||||
return m_anyKeySources[keyIndex];
|
||||
}
|
||||
|
@ -553,7 +522,10 @@ CInputSource *CInputSystem::GetKeySource(int kbdNum, int keyIndex)
|
|||
{
|
||||
// Check keyboard source cache first
|
||||
if (m_keySources[kbdNum][keyIndex] == NULL)
|
||||
{
|
||||
m_keySources[kbdNum][keyIndex] = CreateKeySource(kbdNum, keyIndex);
|
||||
m_keySources[kbdNum][keyIndex]->Acquire();
|
||||
}
|
||||
return m_keySources[kbdNum][keyIndex];
|
||||
}
|
||||
else
|
||||
|
@ -572,6 +544,7 @@ CInputSource *CInputSystem::GetMouseSource(int mseNum, EMousePart msePart)
|
|||
m_anyMseSources[mseIndex] = CreateMouseSource(ANY_MOUSE, msePart);
|
||||
else
|
||||
m_anyMseSources[mseIndex] = CreateAnyMouseSource(msePart);
|
||||
m_anyMseSources[mseIndex]->Acquire();
|
||||
}
|
||||
return m_anyMseSources[mseIndex];
|
||||
}
|
||||
|
@ -579,7 +552,10 @@ CInputSource *CInputSystem::GetMouseSource(int mseNum, EMousePart msePart)
|
|||
{
|
||||
// Check mouse source cache first
|
||||
if (m_mseSources[mseNum][mseIndex] == NULL)
|
||||
{
|
||||
m_mseSources[mseNum][mseIndex] = CreateMouseSource(mseNum, msePart);
|
||||
m_mseSources[mseNum][mseIndex]->Acquire();
|
||||
}
|
||||
return m_mseSources[mseNum][mseIndex];
|
||||
}
|
||||
else
|
||||
|
@ -598,6 +574,7 @@ CInputSource *CInputSystem::GetJoySource(int joyNum, EJoyPart joyPart)
|
|||
m_anyJoySources[joyIndex] = CreateJoySource(ANY_JOYSTICK, joyPart);
|
||||
else
|
||||
m_anyJoySources[joyIndex] = CreateAnyJoySource(joyPart);
|
||||
m_anyJoySources[joyIndex]->Acquire();
|
||||
}
|
||||
return m_anyJoySources[joyIndex];
|
||||
}
|
||||
|
@ -605,14 +582,63 @@ CInputSource *CInputSystem::GetJoySource(int joyNum, EJoyPart joyPart)
|
|||
{
|
||||
// Check joystick source cache first
|
||||
if (m_joySources[joyNum][joyIndex] == NULL)
|
||||
{
|
||||
m_joySources[joyNum][joyIndex] = CreateJoySource(joyNum, joyPart);
|
||||
m_joySources[joyNum][joyIndex]->Acquire();
|
||||
}
|
||||
return m_joySources[joyNum][joyIndex];
|
||||
}
|
||||
else
|
||||
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
|
||||
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);
|
||||
if (keyIndex < 0)
|
||||
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);
|
||||
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
|
||||
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
|
||||
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
|
||||
if (isXYAxis && !mseCentered || isAxis && (IsFullAxis(msePart) && !fullAxisOnly || !IsFullAxis(msePart) && fullAxisOnly))
|
||||
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);
|
||||
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
|
||||
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
|
||||
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
|
||||
if (IsAxis(joyPart) && (IsFullAxis(joyPart) && !fullAxisOnly || !IsFullAxis(joyPart) && fullAxisOnly))
|
||||
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);
|
||||
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
|
||||
const char *partName = LookupName(joyPart);
|
||||
|
@ -870,7 +899,7 @@ CInputSource* CInputSystem::ParseMultiSource(string str, bool fullAxisOnly, bool
|
|||
while (start < size);
|
||||
|
||||
// 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)
|
||||
|
@ -886,7 +915,7 @@ CInputSource *CInputSystem::ParseSingleSource(string str)
|
|||
|
||||
CInputSource *source = ParseSingleSource(str);
|
||||
if (source != NULL && source != m_emptySource)
|
||||
return new CNegInputSource(this, source);
|
||||
return new CNegInputSource(source);
|
||||
else
|
||||
return source;
|
||||
}
|
||||
|
@ -924,7 +953,7 @@ CInputSource *CInputSystem::ParseSingleSource(string str)
|
|||
sources.push_back(rightSource);
|
||||
}
|
||||
if (sources.size() > 0)
|
||||
return new CMultiInputSource(this, true, sources);
|
||||
return new CMultiInputSource(true, sources);
|
||||
}
|
||||
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
|
||||
if (common == NULL || settings->xDeadZone != common->xDeadZone) printf(" X Dead Zone = %d %%\n", settings->xDeadZone);
|
||||
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);
|
||||
for (int axisNum = 0; axisNum < NUM_MOUSE_AXES; axisNum++)
|
||||
{
|
||||
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)
|
||||
|
@ -1054,9 +1086,11 @@ MouseSettings *CInputSystem::ReadMouseSettings(CINIFile *ini, const char *sectio
|
|||
if (mseNum != ANY_MOUSE)
|
||||
baseKey.append(IntToString(mseNum + 1));
|
||||
bool read = false;
|
||||
read |= ini->Get(section, baseKey + "XDeadZone", settings->xDeadZone) == OKAY;
|
||||
read |= ini->Get(section, baseKey + "YDeadZone", settings->yDeadZone) == OKAY;
|
||||
read |= ini->Get(section, baseKey + "ZDeadZone", settings->zDeadZone) == OKAY;
|
||||
for (int axisNum = 0; axisNum < NUM_MOUSE_AXES; axisNum++)
|
||||
{
|
||||
const char *axisName = s_axisNames[axisNum];
|
||||
read |= ini->Get(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]) == OKAY;
|
||||
}
|
||||
if (read)
|
||||
return settings;
|
||||
delete settings;
|
||||
|
@ -1072,9 +1106,12 @@ void CInputSystem::WriteMouseSettings(CINIFile *ini, const char *section, MouseS
|
|||
string baseKey("InputMouse");
|
||||
if (settings->mseNum != ANY_MOUSE)
|
||||
baseKey.append(IntToString(settings->mseNum + 1));
|
||||
if (settings->xDeadZone != common->xDeadZone) ini->Set(section, baseKey + "XDeadZone", settings->xDeadZone);
|
||||
if (settings->yDeadZone != common->yDeadZone) ini->Set(section, baseKey + "YDeadZone", settings->yDeadZone);
|
||||
if (settings->zDeadZone != common->zDeadZone) ini->Set(section, baseKey + "ZDeadZone", settings->zDeadZone);
|
||||
for (int axisNum = 0; axisNum < NUM_MOUSE_AXES; axisNum++)
|
||||
{
|
||||
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)
|
||||
|
@ -1093,18 +1130,20 @@ void CInputSystem::PrintJoySettings(JoySettings *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);
|
||||
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);
|
||||
if (common == NULL || settings->ySaturation != common->ySaturation) printf(" Y-Axis Saturation = %d %%\n", settings->ySaturation);
|
||||
if (common == NULL || settings->zDeadZone != common->zDeadZone) printf(" Z-Axis Dead Zone = %d %%\n", settings->zDeadZone);
|
||||
if (common == NULL || settings->zSaturation != common->zSaturation) printf(" Z-Axis Saturation = %d %%\n", settings->zSaturation);
|
||||
if (common == NULL || settings->rxDeadZone != common->rxDeadZone) printf(" RX-Axis Dead Zone = %d %%\n", settings->rxDeadZone);
|
||||
if (common == NULL || settings->rxSaturation != common->rxSaturation) printf(" RX-Axis Saturation = %d %%\n", settings->rxSaturation);
|
||||
if (common == NULL || settings->ryDeadZone != common->ryDeadZone) printf(" RY-Axis Dead Zone = %d %%\n", settings->ryDeadZone);
|
||||
if (common == NULL || settings->rySaturation != common->rySaturation) printf(" RY-Axis Saturation = %d %%\n", settings->rySaturation);
|
||||
if (common == NULL || settings->rzDeadZone != common->rzDeadZone) printf(" RZ-Axis Dead Zone = %d %%\n", settings->rzDeadZone);
|
||||
if (common == NULL || settings->rzSaturation != common->rzSaturation) printf(" RZ-Axis Saturation = %d %%\n", settings->rzSaturation);
|
||||
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||
{
|
||||
const char *axisName = s_axisNames[axisNum];
|
||||
if (common == NULL || settings->axisMinVals[axisNum] != common->axisMinVals[axisNum])
|
||||
printf(" %-2s-Axis Min Value = %d\n", axisName, settings->axisMinVals[axisNum]);
|
||||
if (common == NULL || settings->axisOffVals[axisNum] != common->axisOffVals[axisNum])
|
||||
printf(" %-2s-Axis Center/Off Value = %d\n", axisName, settings->axisOffVals[axisNum]);
|
||||
if (common == NULL || settings->axisMaxVals[axisNum] != common->axisMaxVals[axisNum])
|
||||
printf(" %-2s-Axis Max Value = %d\n", axisName, settings->axisMaxVals[axisNum]);
|
||||
if (common == NULL || settings->deadZones[axisNum] != common->deadZones[axisNum])
|
||||
printf(" %-2s-Axis Dead Zone = %d %%\n", axisName, settings->deadZones[axisNum]);
|
||||
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)
|
||||
|
@ -1119,18 +1158,15 @@ JoySettings *CInputSystem::ReadJoySettings(CINIFile *ini, const char *section, i
|
|||
if (joyNum != ANY_JOYSTICK)
|
||||
baseKey.append(IntToString(joyNum + 1));
|
||||
bool read = false;
|
||||
read |= ini->Get(section, baseKey + "XDeadZone", settings->xDeadZone) == OKAY;
|
||||
read |= ini->Get(section, baseKey + "XSaturation", settings->xSaturation) == OKAY;
|
||||
read |= ini->Get(section, baseKey + "YDeadZone", settings->yDeadZone) == OKAY;
|
||||
read |= ini->Get(section, baseKey + "YSaturation", settings->ySaturation) == OKAY;
|
||||
read |= ini->Get(section, baseKey + "ZDeadZone", settings->zDeadZone) == OKAY;
|
||||
read |= ini->Get(section, baseKey + "ZSaturation", settings->zSaturation) == OKAY;
|
||||
read |= ini->Get(section, baseKey + "RXDeadZone", settings->rxDeadZone) == OKAY;
|
||||
read |= ini->Get(section, baseKey + "RXSaturation", settings->rxSaturation) == 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;
|
||||
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||
{
|
||||
const char *axisName = s_axisNames[axisNum];
|
||||
read |= ini->Get(section, baseKey + axisName + "MinVal", settings->axisMinVals[axisNum]) == OKAY;
|
||||
read |= ini->Get(section, baseKey + axisName + "OffVal", settings->axisOffVals[axisNum]) == OKAY;
|
||||
read |= ini->Get(section, baseKey + axisName + "MaxVal", settings->axisMaxVals[axisNum]) == OKAY;
|
||||
read |= ini->Get(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]) == OKAY;
|
||||
read |= ini->Get(section, baseKey + axisName + "Saturation", settings->saturations[axisNum]) == OKAY;
|
||||
}
|
||||
if (read)
|
||||
return settings;
|
||||
delete settings;
|
||||
|
@ -1146,18 +1182,20 @@ void CInputSystem::WriteJoySettings(CINIFile *ini, const char *section, JoySetti
|
|||
string baseKey("InputJoy");
|
||||
if (settings->joyNum != ANY_JOYSTICK)
|
||||
baseKey.append(IntToString(settings->joyNum + 1));
|
||||
if (settings->xDeadZone != common->xDeadZone) ini->Set(section, baseKey + "XDeadZone", settings->xDeadZone);
|
||||
if (settings->xSaturation != common->xSaturation) ini->Set(section, baseKey + "XSaturation", settings->xSaturation);
|
||||
if (settings->yDeadZone != common->yDeadZone) ini->Set(section, baseKey + "YDeadZone", settings->yDeadZone);
|
||||
if (settings->ySaturation != common->ySaturation) ini->Set(section, baseKey + "YSaturation", settings->ySaturation);
|
||||
if (settings->zDeadZone != common->zDeadZone) ini->Set(section, baseKey + "ZDeadZone", settings->zDeadZone);
|
||||
if (settings->zSaturation != common->zSaturation) ini->Set(section, baseKey + "ZSaturation", settings->zSaturation);
|
||||
if (settings->rxDeadZone != common->rxDeadZone) ini->Set(section, baseKey + "RXDeadZone", settings->rxDeadZone);
|
||||
if (settings->rxSaturation != common->rxSaturation) ini->Set(section, baseKey + "RXSaturation", settings->rxSaturation);
|
||||
if (settings->ryDeadZone != common->ryDeadZone) ini->Set(section, baseKey + "RYDeadZone", settings->ryDeadZone);
|
||||
if (settings->rySaturation != common->rySaturation) ini->Set(section, baseKey + "RYSaturation", settings->rySaturation);
|
||||
if (settings->rzDeadZone != common->rzDeadZone) ini->Set(section, baseKey + "RZDeadZone", settings->rzDeadZone);
|
||||
if (settings->rzSaturation != common->rzSaturation) ini->Set(section, baseKey + "RZSaturation", settings->rzSaturation);
|
||||
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||
{
|
||||
const char *axisName = s_axisNames[axisNum];
|
||||
if (settings->axisMinVals[axisNum] != common->axisMinVals[axisNum])
|
||||
ini->Set(section, baseKey + axisName + "MinVal", settings->axisMinVals[axisNum]);
|
||||
if (settings->axisOffVals[axisNum] != common->axisOffVals[axisNum])
|
||||
ini->Set(section, baseKey + axisName + "OffVal", settings->axisOffVals[axisNum]);
|
||||
if (settings->axisMaxVals[axisNum] != common->axisMaxVals[axisNum])
|
||||
ini->Set(section, baseKey + axisName + "MaxVal", settings->axisMaxVals[axisNum]);
|
||||
if (settings->deadZones[axisNum] != common->deadZones[axisNum])
|
||||
ini->Set(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]);
|
||||
if (settings->saturations[axisNum] != common->saturations[axisNum])
|
||||
ini->Set(section, baseKey + axisName + "Saturation", settings->saturations[axisNum]);
|
||||
}
|
||||
}
|
||||
|
||||
KeySettings *CInputSystem::GetKeySettings(int kbdNum, bool useDefault)
|
||||
|
@ -1338,7 +1376,7 @@ CInputSource *CInputSystem::CreateAnyKeySource(int keyIndex)
|
|||
if (keySrc != NULL)
|
||||
keySrcs.push_back(keySrc);
|
||||
}
|
||||
return new CMultiInputSource(this, true, keySrcs);
|
||||
return new CMultiInputSource(true, keySrcs);
|
||||
}
|
||||
|
||||
CInputSource *CInputSystem::CreateAnyMouseSource(EMousePart msePart)
|
||||
|
@ -1351,7 +1389,7 @@ CInputSource *CInputSystem::CreateAnyMouseSource(EMousePart msePart)
|
|||
if (mseSrc != NULL)
|
||||
mseSrcs.push_back(mseSrc);
|
||||
}
|
||||
return new CMultiInputSource(this, true, mseSrcs);
|
||||
return new CMultiInputSource(true, mseSrcs);
|
||||
}
|
||||
|
||||
CInputSource *CInputSystem::CreateAnyJoySource(EJoyPart joyPart)
|
||||
|
@ -1364,7 +1402,7 @@ CInputSource *CInputSystem::CreateAnyJoySource(EJoyPart joyPart)
|
|||
if (joySrc != NULL)
|
||||
joySrcs.push_back(joySrc);
|
||||
}
|
||||
return new CMultiInputSource(this, true, joySrcs);
|
||||
return new CMultiInputSource(true, joySrcs);
|
||||
}
|
||||
|
||||
CInputSource *CInputSystem::CreateKeySource(int kbdNum, int keyIndex)
|
||||
|
@ -1386,16 +1424,8 @@ CInputSource *CInputSystem::CreateMouseSource(int mseNum, EMousePart msePart)
|
|||
int axisDir;
|
||||
if (GetAxisDetails(msePart, axisNum, axisDir))
|
||||
{
|
||||
// Part is mouse axis so get the deadzone setting for it
|
||||
unsigned deadZone;
|
||||
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);
|
||||
// Part is mouse axis so create axis source with appropriate deadzone setting
|
||||
return new CMseAxisInputSource(this, mseNum, axisNum, axisDir, settings->deadZones[axisNum]);
|
||||
}
|
||||
else if (IsButton(msePart))
|
||||
{
|
||||
|
@ -1423,23 +1453,13 @@ CInputSource *CInputSystem::CreateJoySource(int joyNum, EJoyPart joyPart)
|
|||
int povDir;
|
||||
if (GetAxisDetails(joyPart, axisNum, axisDir))
|
||||
{
|
||||
// Part is joystick axis so get the deadzone and saturation settings for it
|
||||
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
|
||||
// Part is joystick axis, so see whether joystick actually has this axis
|
||||
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 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))
|
||||
{
|
||||
|
@ -1452,7 +1472,7 @@ CInputSource *CInputSystem::CreateJoySource(int joyNum, EJoyPart joyPart)
|
|||
{
|
||||
// Part is joystick button so map it to a button number
|
||||
int butNum = GetButtonNumber(joyPart);
|
||||
if (butNum < 0)
|
||||
if (butNum < 0 || butNum >= NUM_JOY_BUTTONS)
|
||||
return NULL; // Buttons out of range are invalid
|
||||
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
|
||||
|
@ -1493,13 +1513,6 @@ CInputSource* CInputSystem::ParseSource(const char *mapping, bool fullAxisOnly)
|
|||
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()
|
||||
{
|
||||
// Delete all key settings
|
||||
|
@ -1568,6 +1581,7 @@ void CInputSystem::PrintSettings()
|
|||
void CInputSystem::ReadFromINIFile(CINIFile *ini, const char *section)
|
||||
{
|
||||
ClearSettings();
|
||||
ClearSourceCache();
|
||||
|
||||
// Read all key settings for attached keyboards
|
||||
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
|
||||
CInputSource *escape = ParseSource(escapeMapping);
|
||||
escape->Acquire();
|
||||
|
||||
string badMapping;
|
||||
string mapping;
|
||||
vector<CInputSource*> badSources;
|
||||
vector<CInputSource*> sources;
|
||||
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
|
||||
for (;;)
|
||||
{
|
||||
// Poll inputs
|
||||
if (!Poll())
|
||||
{
|
||||
escape->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if escape source was triggered
|
||||
if (escape != NULL && escape->IsActive())
|
||||
|
@ -1641,56 +1671,20 @@ bool CInputSystem::ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly
|
|||
while (escape->IsActive())
|
||||
{
|
||||
if (!Poll())
|
||||
{
|
||||
escape->Release();
|
||||
return false;
|
||||
}
|
||||
Wait(1000/60);
|
||||
}
|
||||
escape->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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);
|
||||
else
|
||||
{
|
||||
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
|
||||
CheckKeySources(kbdNum, fullAxisOnly, sources, mapping);
|
||||
}
|
||||
}
|
||||
// Check all active sources
|
||||
CheckAllSources(readFlags, fullAxisOnly, mseCentered, 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);
|
||||
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.
|
||||
// When some inputs have been activated, keep looping until they have all been released again.
|
||||
if (sources.size() > 0)
|
||||
{
|
||||
// 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
|
||||
strncpy(buffer, mapping.c_str(), bufSize - 1);
|
||||
buffer[bufSize - 1] = '\0';
|
||||
|
||||
escape->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1739,6 +1735,62 @@ void CInputSystem::UngrabMouse()
|
|||
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
|
||||
*/
|
||||
|
@ -1888,26 +1940,28 @@ bool CInputSystem::CMseButInputSource::GetValueAsAnalog(int &val, int minVal, in
|
|||
/*
|
||||
* 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),
|
||||
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
|
||||
// percentage 0-99 and saturation given as percentage 1-100)
|
||||
m_axisInverted = m_axisMaxVal < m_axisMinVal;
|
||||
// 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 dSaturation = (double)Clamp((int)saturation, (int)deadZone + 1, 100) / 100.0;
|
||||
m_posDZone = (int)(dDeadZone * 32767.0);
|
||||
m_negDZone = (int)(dDeadZone * -32768.0);
|
||||
m_posSat = (int)(dSaturation * 32767.0);
|
||||
m_negSat = (int)(dSaturation * -32868.0);
|
||||
m_posDZone = m_axisOffVal + (int)(dDeadZone * (m_axisMaxVal - m_axisOffVal));
|
||||
m_negDZone = m_axisOffVal + (int)(dDeadZone * (m_axisMinVal - m_axisOffVal));
|
||||
m_posSat = m_axisOffVal + (int)(dSaturation * (m_axisMaxVal - m_axisOffVal));
|
||||
m_negSat = m_axisOffVal + (int)(dSaturation * (m_axisMinVal - m_axisOffVal));
|
||||
}
|
||||
|
||||
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);
|
||||
// Check value is not zero
|
||||
if (joyVal == 0)
|
||||
// Check if value is at axis off value
|
||||
if (joyVal == m_axisOffVal)
|
||||
return offVal;
|
||||
// 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);
|
||||
|
@ -1915,14 +1969,18 @@ int CInputSystem::CJoyAxisInputSource::ScaleAxisValue(int minVal, int offVal, in
|
|||
else if (m_axisDir == AXIS_FULL)
|
||||
{
|
||||
// Full axis range
|
||||
if (joyVal > 0) 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);
|
||||
if (!m_axisInverted && joyVal > m_axisOffVal || m_axisInverted && joyVal < m_axisOffVal)
|
||||
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
|
||||
{
|
||||
// Full axis range, but inverted
|
||||
if (joyVal > 0) 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);
|
||||
if (!m_axisInverted && joyVal > m_axisOffVal || m_axisInverted && joyVal < m_axisOffVal)
|
||||
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;
|
||||
}
|
||||
|
||||
bool CInputSystem::CJoyAxisInputSource::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
|
||||
bool CInputSystem::CJoyAxisInputSource::SendForceFeedbackCmd(ForceFeedbackCmd ffCmd)
|
||||
{
|
||||
return m_system->SendForceFeedbackCmd(m_joyNum, m_axisNum, ffCmd);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ class CINIFile;
|
|||
#define DEFAULT_KEY_SENSITIVITY 25
|
||||
#define DEFAULT_KEY_DECAYSPEED 50
|
||||
#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_SATURATION 100
|
||||
|
||||
|
@ -208,10 +211,8 @@ struct KeySettings
|
|||
*/
|
||||
struct MouseSettings
|
||||
{
|
||||
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 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
|
||||
int mseNum; // Mouse number (or ANY_MOUSE for settings that apply to all mice)
|
||||
unsigned deadZones[NUM_MOUSE_AXES]; // Axis dead zone as a percentage 0-99 of display width (X)/height (Y) or axis range (Z)
|
||||
|
||||
/*
|
||||
* Creates a MouseSettings with default settings
|
||||
|
@ -219,9 +220,9 @@ struct MouseSettings
|
|||
MouseSettings()
|
||||
{
|
||||
mseNum = ANY_MOUSE;
|
||||
xDeadZone = DEFAULT_MSE_DEADZONE;
|
||||
yDeadZone = DEFAULT_MSE_DEADZONE;
|
||||
zDeadZone = 0;
|
||||
deadZones[AXIS_X] = DEFAULT_MSE_DEADZONE;
|
||||
deadZones[AXIS_Y] = DEFAULT_MSE_DEADZONE;
|
||||
deadZones[AXIS_Z] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -230,19 +231,12 @@ struct MouseSettings
|
|||
*/
|
||||
struct JoySettings
|
||||
{
|
||||
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
|
||||
unsigned xSaturation; // X-Axis saturation as a percentage 1-100 of axis positive/negative ranges
|
||||
unsigned yDeadZone; // Y-Axis dead zone as a percentage 0-99 of axis positive/negative ranges
|
||||
unsigned ySaturation; // Y-Axis saturation as a percentage 1-100 of axis positive/negative ranges
|
||||
unsigned zDeadZone; // Z-Axis dead zone as a percentage 0-99 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
|
||||
int joyNum; // Joystick number (or ANY_JOYSTICK for settings that apply to all joysticks)
|
||||
int axisMinVals[NUM_JOY_AXES]; // Axis min raw value (default -32768)
|
||||
int axisOffVals[NUM_JOY_AXES]; // Axis center/off value (default 0)
|
||||
int axisMaxVals[NUM_JOY_AXES]; // Axis max raw value (default 32767)
|
||||
unsigned deadZones[NUM_JOY_AXES]; // 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
|
||||
|
||||
/*
|
||||
* Creates a JoySettings with default settings
|
||||
|
@ -250,41 +244,37 @@ struct JoySettings
|
|||
JoySettings()
|
||||
{
|
||||
joyNum = ANY_JOYSTICK;
|
||||
xDeadZone = DEFAULT_JOY_DEADZONE;
|
||||
xSaturation = DEFAULT_JOY_SATURATION;
|
||||
yDeadZone = DEFAULT_JOY_DEADZONE;
|
||||
ySaturation = DEFAULT_JOY_SATURATION;
|
||||
zDeadZone = DEFAULT_JOY_DEADZONE;
|
||||
zSaturation = DEFAULT_JOY_SATURATION;
|
||||
rxDeadZone = DEFAULT_JOY_DEADZONE;
|
||||
rxSaturation = DEFAULT_JOY_SATURATION;
|
||||
ryDeadZone = DEFAULT_JOY_DEADZONE;
|
||||
rySaturation = DEFAULT_JOY_SATURATION;
|
||||
rzDeadZone = DEFAULT_JOY_DEADZONE;
|
||||
rzSaturation = DEFAULT_JOY_SATURATION;
|
||||
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||
{
|
||||
axisMinVals[axisNum] = DEFAULT_JOY_AXISMINVAL;
|
||||
axisOffVals[axisNum] = DEFAULT_JOY_AXISOFFVAL;
|
||||
axisMaxVals[axisNum] = DEFAULT_JOY_AXISMAXVAL;
|
||||
deadZones[axisNum] = DEFAULT_JOY_DEADZONE;
|
||||
saturations[axisNum] = DEFAULT_JOY_SATURATION;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct KeyDetails
|
||||
{
|
||||
char name[MAX_NAME_LENGTH]; // Keyboard name (if available)
|
||||
char name[MAX_NAME_LENGTH + 1]; // Keyboard name (if available)
|
||||
};
|
||||
|
||||
struct MouseDetails
|
||||
{
|
||||
char name[MAX_NAME_LENGTH]; // Mouse name (if available)
|
||||
bool isAbsolute; // True if uses absolute positions (ie lightgun)
|
||||
char name[MAX_NAME_LENGTH + 1]; // Mouse name (if available)
|
||||
bool isAbsolute; // True if uses absolute positions (ie lightgun)
|
||||
};
|
||||
|
||||
struct JoyDetails
|
||||
{
|
||||
char name[MAX_NAME_LENGTH]; // Joystick name (if available)
|
||||
int numAxes; // Total number of axes on joystick
|
||||
int numPOVs; // Total number of POV hat controllers on joystick
|
||||
int numButtons; // Total number of buttons on joystick
|
||||
bool hasFFeedback; // True if joystick supports force feedback
|
||||
bool hasAxis[NUM_JOY_AXES]; // Flags to indicate which axes available on joystick
|
||||
bool axisHasFF[NUM_JOY_AXES]; // Flags to indicate which axes are force feedback enabled
|
||||
char name[MAX_NAME_LENGTH + 1]; // Joystick name (if available)
|
||||
int numAxes; // Total number of axes on joystick
|
||||
int numPOVs; // Total number of POV hat controllers on joystick
|
||||
int numButtons; // Total number of buttons on joystick
|
||||
bool hasFFeedback; // True if joystick supports force feedback
|
||||
bool hasAxis[NUM_JOY_AXES]; // Flags to indicate which axes available on joystick
|
||||
bool axisHasFF[NUM_JOY_AXES]; // Flags to indicate which axes are force feedback enabled
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -303,6 +293,9 @@ private:
|
|||
// Lookup table for translating joystick mapping strings to their respective joystick parts
|
||||
static JoyPartsStruct s_joyParts[];
|
||||
|
||||
// Names of axes
|
||||
static const char *s_axisNames[];
|
||||
|
||||
// Number of keyboards, mice and joysticks
|
||||
int m_numKbds;
|
||||
int m_numMice;
|
||||
|
@ -334,24 +327,19 @@ private:
|
|||
//
|
||||
|
||||
/*
|
||||
* Creates cache for all sources.
|
||||
* Creates source cache.
|
||||
*/
|
||||
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);
|
||||
|
||||
/*
|
||||
* Deletes cache for all sources.
|
||||
*/
|
||||
void DeleteSourceCache();
|
||||
void ClearSourceCache(bool deleteCache = false);
|
||||
|
||||
/*
|
||||
* Deletes an input source.
|
||||
* Releases a source from the cache.
|
||||
*/
|
||||
void DeleteSource(CInputSource *source);
|
||||
void ReleaseSource(CInputSource *&source);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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)
|
||||
* 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.
|
||||
*/
|
||||
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)
|
||||
* 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.
|
||||
*/
|
||||
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)
|
||||
* 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.
|
||||
*/
|
||||
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);
|
||||
|
||||
|
@ -653,7 +643,7 @@ protected:
|
|||
/*
|
||||
* 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
|
||||
|
@ -700,6 +690,10 @@ protected:
|
|||
virtual CInputSource *CreateJoySource(int joyNum, EJoyPart joyPart);
|
||||
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
static unsigned totalSrcsAcquired;
|
||||
static unsigned totalSrcsReleased;
|
||||
#endif
|
||||
|
||||
// Name of this input system
|
||||
const char *name;
|
||||
|
@ -793,11 +787,6 @@ public:
|
|||
*/
|
||||
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)
|
||||
* 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");
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
@ -822,61 +811,9 @@ public:
|
|||
*/
|
||||
virtual void SetMouseVisibility(bool visible) = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
virtual bool SendForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
void PrintDevices();
|
||||
|
||||
//
|
||||
// Nested Classes
|
||||
|
@ -957,10 +894,14 @@ public:
|
|||
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_axisDir; // Axis direction (AXIS_FULL, AXIS_INVERTED, AXIS_POSITIVE or AXIS_NEGATIVE)
|
||||
int m_posDZone; // Dead zone for positive range
|
||||
int m_negDZone; // Dead zone for negative range
|
||||
int m_posSat; // Saturation for positive range
|
||||
int m_negSat; // Saturation for negative range
|
||||
int m_axisMinVal; // Axis min raw value (default -32768)
|
||||
int m_axisOffVal; // Axis center/off raw value (default 0)
|
||||
int m_axisMaxVal; // Axis max raw value (default 32767)
|
||||
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.
|
||||
|
@ -968,13 +909,14 @@ public:
|
|||
int ScaleAxisValue(int minVal, int offVal, int maxVal);
|
||||
|
||||
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 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");
|
||||
key.append(id);
|
||||
unsigned int autoTrigger;
|
||||
unsigned autoTrigger;
|
||||
if (ini->Get(section, key, autoTrigger) == OKAY)
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
class CTriggerInput : public CInput
|
||||
|
|
|
@ -252,12 +252,16 @@ bool CInputs::Initialize()
|
|||
|
||||
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++)
|
||||
(*it)->ReadFromINIFile(ini, 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++)
|
||||
(*it)->WriteToINIFile(ini, section);
|
||||
}
|
||||
|
|
|
@ -39,10 +39,13 @@ ESourceType CMultiInputSource::GetCombinedType(vector<CInputSource*> &sources)
|
|||
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) :
|
||||
CInputSource(GetCombinedType(sources)), m_system(system), m_isOr(isOr), m_numSrcs(sources.size())
|
||||
CMultiInputSource::CMultiInputSource(bool isOr, vector<CInputSource*> &sources) :
|
||||
CInputSource(GetCombinedType(sources)), m_isOr(isOr), m_numSrcs(sources.size())
|
||||
{
|
||||
m_srcArray = new CInputSource*[m_numSrcs];
|
||||
copy(sources.begin(), sources.end(), m_srcArray);
|
||||
|
@ -51,13 +54,33 @@ CMultiInputSource::CMultiInputSource(CInputSystem *system, bool isOr, vector<CIn
|
|||
CMultiInputSource::~CMultiInputSource()
|
||||
{
|
||||
if (m_srcArray != NULL)
|
||||
{
|
||||
for (int i = 0; i < m_numSrcs; i++)
|
||||
m_system->ReleaseSource(m_srcArray[i]);
|
||||
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)
|
||||
{
|
||||
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;
|
||||
for (int i = 0; i < m_numSrcs; i++)
|
||||
|
@ -121,11 +144,28 @@ bool CMultiInputSource::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
|
|||
return result;
|
||||
}
|
||||
|
||||
CNegInputSource::CNegInputSource(CInputSystem *system, CInputSource *source) : CInputSource(source->type), m_system(system), m_source(source) { }
|
||||
|
||||
CNegInputSource::~CNegInputSource()
|
||||
CNegInputSource::CNegInputSource(CInputSource *source) : CInputSource(source->type), m_source(source)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -9,15 +9,12 @@ using namespace std;
|
|||
/*
|
||||
* 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.
|
||||
* Can either represent a combination of multiple assignments that all map to the same input, eg KEY_ALT,JOY1_BUTTON1 or be
|
||||
* used specify that controls must be activated together, eg KEY_ALT+KEY_P.
|
||||
* Can represent either a combination of multiple assignments that all map to the same input, eg KEY_ALT,JOY1_BUTTON1 or to
|
||||
* specify that controls must be combined together, eg KEY_ALT+KEY_P.
|
||||
*/
|
||||
class CMultiInputSource : public CInputSource
|
||||
{
|
||||
private:
|
||||
// Input system that created this source
|
||||
CInputSystem *m_system;
|
||||
|
||||
// Controls how the inputs sources are combined
|
||||
bool m_isOr;
|
||||
|
||||
|
@ -36,7 +33,7 @@ public:
|
|||
/*
|
||||
* 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.
|
||||
|
@ -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,
|
||||
* or the first switch input if there are none).
|
||||
*/
|
||||
CMultiInputSource(CInputSystem *system, bool isOr, vector<CInputSource*> &sources);
|
||||
CMultiInputSource(bool isOr, vector<CInputSource*> &sources);
|
||||
|
||||
~CMultiInputSource();
|
||||
|
||||
void Acquire();
|
||||
|
||||
void Release();
|
||||
|
||||
bool GetValueAsSwitch(bool &val);
|
||||
|
||||
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
|
||||
{
|
||||
private:
|
||||
// Input system that created this source
|
||||
CInputSystem *m_system;
|
||||
|
||||
// Input source being negated
|
||||
CInputSource *m_source;
|
||||
|
||||
public:
|
||||
CNegInputSource(CInputSystem *system, CInputSource *source);
|
||||
|
||||
~CNegInputSource();
|
||||
CNegInputSource(CInputSource *source);
|
||||
|
||||
void Acquire();
|
||||
|
||||
void Release();
|
||||
|
||||
bool GetValueAsSwitch(bool &val);
|
||||
|
||||
|
|
|
@ -181,7 +181,6 @@ static CInputs *CreateInputs(CInputSystem *InputSystem, BOOL configure)
|
|||
INI.Parse();
|
||||
|
||||
Inputs->ReadFromINIFile(&INI, "Global");
|
||||
InputSystem->ReadFromINIFile(&INI, "Global");
|
||||
|
||||
// If the user wants to configure the inputs, do that now
|
||||
if (configure)
|
||||
|
@ -199,14 +198,13 @@ static CInputs *CreateInputs(CInputSystem *InputSystem, BOOL configure)
|
|||
{
|
||||
// Write input configuration and input system settings to config file
|
||||
Inputs->WriteToINIFile(&INI, "Global");
|
||||
InputSystem->WriteToINIFile(&INI, "Global");
|
||||
|
||||
if (OKAY != INI.Write(CONFIG_FILE_COMMENT))
|
||||
ErrorLog("Unable to save configuration to %s.", CONFIG_FILE_PATH);
|
||||
if (OKAY != INI.Write(CONFIG_FILE_COMMENT))
|
||||
ErrorLog("Unable to save configuration to %s.", CONFIG_FILE_PATH);
|
||||
else
|
||||
printf("Configuration successfully saved to %s.\n", CONFIG_FILE_PATH);
|
||||
}
|
||||
else
|
||||
printf("Configuration successfully saved to %s.\n", CONFIG_FILE_PATH);
|
||||
}
|
||||
else
|
||||
puts("Configuration aborted...");
|
||||
puts("");
|
||||
}
|
||||
|
@ -1090,10 +1088,10 @@ int main(int argc, char **argv)
|
|||
exitCode = Supermodel(argv[fileIdx],Inputs,ppcFrequency,xRes,yRes,cmdFullScreen,cmdNoThrottle,cmdShowFPS,vsFile,fsFile);
|
||||
|
||||
Exit:
|
||||
if (InputSystem != NULL)
|
||||
delete InputSystem;
|
||||
if (Inputs != NULL)
|
||||
delete Inputs;
|
||||
if (InputSystem != NULL)
|
||||
delete InputSystem;
|
||||
SDL_Quit();
|
||||
return exitCode;
|
||||
}
|
||||
|
|
|
@ -181,8 +181,8 @@ void CSDLInputSystem::OpenJoysticks()
|
|||
// Gather joystick details (name, num POVs & buttons and which axes are available)
|
||||
JoyDetails joyDetails;
|
||||
const char *pName = SDL_JoystickName(joyNum);
|
||||
strncpy(joyDetails.name, pName, MAX_NAME_LENGTH - 1);
|
||||
joyDetails.name[MAX_NAME_LENGTH - 1] = '\0';
|
||||
strncpy(joyDetails.name, pName, MAX_NAME_LENGTH);
|
||||
joyDetails.name[MAX_NAME_LENGTH] = '\0';
|
||||
joyDetails.numAxes = SDL_JoystickNumAxes(joystick);
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
return false;
|
||||
|
|
|
@ -81,7 +81,7 @@ protected:
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ DIKeyMapStruct CDirectInputSystem::s_keyMap[] =
|
|||
|
||||
bool IsXInputDevice(const GUID &devProdGUID)
|
||||
{
|
||||
// Following code taken from MSDN
|
||||
IWbemLocator* pIWbemLocator = NULL;
|
||||
IEnumWbemClassObject* pEnumDevices = NULL;
|
||||
IWbemClassObject* pDevices[20] = {0};
|
||||
|
@ -191,7 +192,7 @@ bool IsXInputDevice(const GUID &devProdGUID)
|
|||
goto exit;
|
||||
|
||||
// Loop over all devices
|
||||
while (true)
|
||||
for (;;)
|
||||
{
|
||||
// Get 20 at a time
|
||||
DWORD uReturned;
|
||||
|
@ -259,12 +260,13 @@ exit:
|
|||
BOOL CALLBACK DI8EnumDevicesCallback(LPCDIDEVICEINSTANCE instance, LPVOID context)
|
||||
{
|
||||
// Keep track of all joystick device GUIDs
|
||||
vector<DIJoyInfo> *infos = (vector<DIJoyInfo>*)context;
|
||||
DIEnumDevsContext *diContext = (DIEnumDevsContext*)context;
|
||||
DIJoyInfo info;
|
||||
memset(&info, 0, sizeof(DIJoyInfo));
|
||||
info.guid = instance->guidInstance;
|
||||
info.isXInput = IsXInputDevice(instance->guidProduct);
|
||||
infos->push_back(info);
|
||||
// If XInput is enabled, see if device is an XInput device
|
||||
info.isXInput = diContext->useXInput && IsXInputDevice(instance->guidProduct);
|
||||
diContext->infos->push_back(info);
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -295,7 +297,8 @@ BOOL CALLBACK DI8EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE instance, LPVOID con
|
|||
BOOL CALLBACK DI8EnumEffectsCallback(LPCDIEFFECTINFO effectInfo, LPVOID 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;
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
@ -651,7 +654,7 @@ void CDirectInputSystem::PollKeyboardsAndMice()
|
|||
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 (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)
|
||||
{
|
||||
|
@ -745,7 +748,7 @@ void CDirectInputSystem::CloseKeyboardsAndMice()
|
|||
}
|
||||
|
||||
// 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;
|
||||
m_keyDetails.clear();
|
||||
m_rawKeyboards.clear();
|
||||
|
@ -785,7 +788,7 @@ void CDirectInputSystem::ResetMice()
|
|||
m_combRawMseState.x = p.x;
|
||||
m_combRawMseState.y = p.y;
|
||||
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->y = p.y;
|
||||
|
@ -927,7 +930,7 @@ void CDirectInputSystem::ProcessRawInput(HRAWINPUT hInput)
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -940,14 +943,17 @@ void CDirectInputSystem::ProcessRawInput(HRAWINPUT hInput)
|
|||
void CDirectInputSystem::OpenJoysticks()
|
||||
{
|
||||
// Get the info about all attached joystick devices
|
||||
DIEnumDevsContext diContext;
|
||||
diContext.infos = &m_diJoyInfos;
|
||||
diContext.useXInput = m_useXInput;
|
||||
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;
|
||||
|
||||
// Loop through those found
|
||||
int joyNum = 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++;
|
||||
|
||||
|
@ -955,14 +961,14 @@ void CDirectInputSystem::OpenJoysticks()
|
|||
memset(&joyDetails, 0, sizeof(joyDetails));
|
||||
|
||||
// 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)
|
||||
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.numPOVs = 1; // Digital D-pad
|
||||
joyDetails.numButtons = 10;
|
||||
joyDetails.hasFFeedback = true;
|
||||
joyDetails.hasFFeedback = m_enableFFeedback;
|
||||
joyDetails.hasAxis[AXIS_X] = true;
|
||||
joyDetails.hasAxis[AXIS_Y] = true;
|
||||
joyDetails.hasAxis[AXIS_Z] = true;
|
||||
|
@ -982,28 +988,28 @@ void CDirectInputSystem::OpenJoysticks()
|
|||
else
|
||||
{
|
||||
// Otherwise, open joystick with DirectInput for given GUID and set its data format
|
||||
LPDIRECTINPUTDEVICE8 di8Joystick;
|
||||
if (FAILED(hr = m_di8->CreateDevice(it->guid, &di8Joystick, NULL)))
|
||||
LPDIRECTINPUTDEVICE8 joystick;
|
||||
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);
|
||||
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);
|
||||
|
||||
di8Joystick->Release();
|
||||
joystick->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get joystick's capabilities
|
||||
DIDEVCAPS devCaps;
|
||||
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);
|
||||
|
||||
di8Joystick->Release();
|
||||
joystick->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1013,11 +1019,11 @@ void CDirectInputSystem::OpenJoysticks()
|
|||
didps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
didps.diph.dwHow = DIPH_DEVICE;
|
||||
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);
|
||||
|
||||
di8Joystick->Release();
|
||||
joystick->Release();
|
||||
continue;
|
||||
}
|
||||
// DInput returns name as Unicode, convert to ASCII
|
||||
|
@ -1028,20 +1034,24 @@ void CDirectInputSystem::OpenJoysticks()
|
|||
joyDetails.numButtons = devCaps.dwButtons;
|
||||
|
||||
// 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);
|
||||
|
||||
di8Joystick->Release();
|
||||
joystick->Release();
|
||||
continue;
|
||||
}
|
||||
joyDetails.numAxes = 0;
|
||||
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||
joyDetails.numAxes += joyDetails.hasAxis[axisNum];
|
||||
|
||||
// See if force feedback available for joystick
|
||||
if (FAILED(hr = di8Joystick->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);
|
||||
// See if force feedback enabled and is available for joystick
|
||||
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);
|
||||
}
|
||||
|
||||
// Configure axes, if any
|
||||
if (joyDetails.numAxes > 0)
|
||||
|
@ -1054,11 +1064,11 @@ void CDirectInputSystem::OpenJoysticks()
|
|||
didpr.diph.dwObj = 0;
|
||||
didpr.lMin = -32768;
|
||||
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);
|
||||
|
||||
di8Joystick->Release();
|
||||
joystick->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1069,40 +1079,40 @@ void CDirectInputSystem::OpenJoysticks()
|
|||
dipdw.diph.dwHow = DIPH_DEVICE;
|
||||
dipdw.diph.dwObj = 0;
|
||||
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);
|
||||
|
||||
di8Joystick->Release();
|
||||
joystick->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Turn off deadzone as handled by this class
|
||||
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);
|
||||
|
||||
di8Joystick->Release();
|
||||
joystick->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Turn off saturation as handle by this class
|
||||
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);
|
||||
|
||||
di8Joystick->Release();
|
||||
joystick->Release();
|
||||
continue;
|
||||
}
|
||||
|
||||
// If joystick force feedback is enabled and joystick has force feedback capabilities then disable auto-center
|
||||
if (m_enableFFeedback && joyDetails.hasFFeedback)
|
||||
// If joystick has force feedback capabilities then disable auto-center
|
||||
if (joyDetails.hasFFeedback)
|
||||
{
|
||||
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);
|
||||
|
||||
|
@ -1114,7 +1124,7 @@ void CDirectInputSystem::OpenJoysticks()
|
|||
// Keep track of DirectInput device number
|
||||
it->dInputNum = m_di8Joysticks.size();
|
||||
|
||||
m_di8Joysticks.push_back(di8Joystick);
|
||||
m_di8Joysticks.push_back(joystick);
|
||||
}
|
||||
|
||||
// Create initial blank joystick state
|
||||
|
@ -1131,20 +1141,31 @@ void CDirectInputSystem::OpenJoysticks()
|
|||
void CDirectInputSystem::ActivateJoysticks()
|
||||
{
|
||||
// Set DirectInput cooperative level of joysticks
|
||||
for (vector<LPDIRECTINPUTDEVICE8>::iterator it = m_di8Joysticks.begin(); it < m_di8Joysticks.end(); it++)
|
||||
(*it)->SetCooperativeLevel(m_hwnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
||||
unsigned joyNum = 0;
|
||||
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()
|
||||
{
|
||||
// Get current joystick states from XInput and DirectInput
|
||||
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++];
|
||||
|
||||
HRESULT hr;
|
||||
if (m_useXInput && it->isXInput)
|
||||
if (it->isXInput)
|
||||
{
|
||||
// Use XInput to query joystick
|
||||
XINPUT_STATE xState;
|
||||
|
@ -1219,8 +1240,24 @@ void CDirectInputSystem::PollJoysticks()
|
|||
|
||||
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
|
||||
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)->Release();
|
||||
|
@ -1232,47 +1269,102 @@ void CDirectInputSystem::CloseJoysticks()
|
|||
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;
|
||||
switch (axisNum)
|
||||
{
|
||||
case AXIS_X: axisOfs = DIJOFS_X; break;
|
||||
case AXIS_Y: axisNum = DIJOFS_Y; break;
|
||||
case AXIS_Z: axisNum = DIJOFS_Z; break;
|
||||
case AXIS_RX: axisNum = DIJOFS_RX; break;
|
||||
case AXIS_RY: axisNum = DIJOFS_RY; break;
|
||||
case AXIS_RZ: axisNum = DIJOFS_RZ; break;
|
||||
case AXIS_Y: axisOfs = DIJOFS_Y; break;
|
||||
case AXIS_Z: axisOfs = DIJOFS_Z; break;
|
||||
case AXIS_RX: axisOfs = DIJOFS_RX; break;
|
||||
case AXIS_RY: axisOfs = DIJOFS_RY; break;
|
||||
case AXIS_RZ: axisOfs = DIJOFS_RZ; break;
|
||||
default: return E_FAIL;
|
||||
}
|
||||
|
||||
DWORD rgdwAxes[1] = { axisOfs };
|
||||
LONG rglDirection[1] = { 0 };
|
||||
DICONSTANTFORCE cf = { 0 };
|
||||
DICONSTANTFORCE dicf;
|
||||
DICONDITION dic;
|
||||
DIPERIODIC dip;
|
||||
DIENVELOPE die;
|
||||
GUID guid;
|
||||
|
||||
// Set common effects parameters
|
||||
DIEFFECT eff;
|
||||
memset(&eff, 0, sizeof(eff));
|
||||
eff.dwSize = sizeof(DIEFFECT);
|
||||
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||
eff.dwDuration = INFINITE;
|
||||
eff.dwSamplePeriod = 0;
|
||||
eff.dwGain = DI_FFNOMINALMAX;
|
||||
eff.dwTriggerButton = DIEB_NOTRIGGER;
|
||||
eff.dwTriggerRepeatInterval = 0;
|
||||
eff.dwGain = DI_FFNOMINALMAX;
|
||||
eff.cAxes = 1;
|
||||
eff.rgdwAxes = rgdwAxes;
|
||||
eff.rglDirection = rglDirection;
|
||||
eff.lpEnvelope = 0;
|
||||
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
|
||||
eff.lpvTypeSpecificParams = &cf;
|
||||
eff.dwDuration = INFINITE;
|
||||
eff.dwStartDelay = 0;
|
||||
|
||||
// Set specific effects parameters
|
||||
switch (ffCmd.id)
|
||||
{
|
||||
case FFStop:
|
||||
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();
|
||||
|
||||
// Create the prepared effect
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = di8Joystick->CreateEffect(GUID_ConstantForce, &eff, di8Effect, NULL)))
|
||||
if (FAILED(hr = joystick->CreateEffect(guid, &eff, pEffect, NULL)))
|
||||
return hr;
|
||||
if (di8Effect == NULL)
|
||||
if (*pEffect == NULL)
|
||||
return E_FAIL;
|
||||
(*pEffect)->Start(1, 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -1490,18 +1582,15 @@ bool CDirectInputSystem::IsJoyButPressed(int joyNum, int 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];
|
||||
|
||||
HRESULT hr;
|
||||
if (m_useXInput && pInfo->isXInput)
|
||||
if (pInfo->isXInput)
|
||||
{
|
||||
XINPUT_VIBRATION vibration;
|
||||
switch (ffCmd->id)
|
||||
switch (ffCmd.id)
|
||||
{
|
||||
case FFStop:
|
||||
if (axisNum == AXIS_X || axisNum == AXIS_Y)
|
||||
|
@ -1510,70 +1599,101 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
|
|||
vibration.wRightMotorSpeed = 0;
|
||||
else
|
||||
return false;
|
||||
if (FAILED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration)))
|
||||
return false;
|
||||
break;
|
||||
return SUCCEEDED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration));
|
||||
|
||||
case FFConstantForce:
|
||||
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)
|
||||
vibration.wRightMotorSpeed = ffCmd->data; // TODO - scale data to 0-65535
|
||||
vibration.wRightMotorSpeed = ffCmd.data; // TODO - scale data to 0-65535
|
||||
else
|
||||
return false;
|
||||
if (FAILED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration)))
|
||||
return false;
|
||||
break;
|
||||
return SUCCEEDED(hr = m_xiSetStatePtr(pInfo->xInputNum, &vibration));
|
||||
|
||||
default:
|
||||
// TODO - other force feedback types
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 di8Joystick = m_di8Joysticks[pInfo->dInputNum];
|
||||
switch (ffCmd->id)
|
||||
LPDIRECTINPUTDEVICE8 joystick = m_di8Joysticks[pInfo->dInputNum];
|
||||
|
||||
// See if command is to stop all force feedback
|
||||
if (ffCmd.id == -1)
|
||||
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)
|
||||
{
|
||||
case FFStop:
|
||||
if (FAILED(hr = di8Joystick->SendForceFeedbackCommand(DISFFC_STOPALL)))
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
if (FAILED(hr = CreateJoystickEffect(joystick, axisNum, ffCmd, pEffect)))
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
LONG rglDirection[1] = { 0 };
|
||||
DICONSTANTFORCE dicf;
|
||||
DICONDITION dic;
|
||||
DIPERIODIC dip;
|
||||
DIENVELOPE die;
|
||||
|
||||
// Set common parameters
|
||||
DIEFFECT eff;
|
||||
memset(&eff, 0, sizeof(eff));
|
||||
eff.dwSize = sizeof(DIEFFECT);
|
||||
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||
eff.cAxes = 1;
|
||||
eff.rglDirection = rglDirection;
|
||||
eff.dwStartDelay = 0;
|
||||
|
||||
switch (ffCmd.id)
|
||||
{
|
||||
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:
|
||||
LPDIRECTINPUTEFFECT di8Effect;
|
||||
if (FAILED(hr = CreateJoystickEffect(di8Joystick, axisNum, &di8Effect)))
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
DICONSTANTFORCE cf;
|
||||
cf.lMagnitude = ffCmd->data; // TODO - scale data to what?
|
||||
LONG rglDirection[1] = { 0 };
|
||||
DIEFFECT eff;
|
||||
memset(&eff, 0, sizeof(eff));
|
||||
eff.dwSize = sizeof(DIEFFECT);
|
||||
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||
eff.cAxes = 1;
|
||||
eff.rglDirection = rglDirection;
|
||||
eff.lpEnvelope = 0;
|
||||
dicf.lMagnitude = ffCmd.data; // TODO - scale & cap at +/- DI_FFNOMINALMAX
|
||||
|
||||
eff.lpEnvelope = NULL;
|
||||
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
|
||||
eff.lpvTypeSpecificParams = &cf;
|
||||
eff.dwStartDelay = 0;
|
||||
|
||||
// Now set the new parameters and start the effect immediately.
|
||||
if (FAILED(hr = di8Effect->SetParameters(&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START)))
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
//di8Effect->Release();
|
||||
eff.lpvTypeSpecificParams = &dicf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
|
||||
// Now set the new parameters and start the effect immediately.
|
||||
return SUCCEEDED(hr = (*pEffect)->SetParameters(&eff, DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_START));
|
||||
}
|
||||
}
|
||||
|
||||
void CDirectInputSystem::Wait(int ms)
|
||||
|
|
|
@ -46,9 +46,16 @@ struct DIJoyInfo
|
|||
GUID guid;
|
||||
bool isXInput;
|
||||
int dInputNum;
|
||||
LPDIRECTINPUTEFFECT dInputEffects[NUM_JOY_AXES][NUM_FF_EFFECTS];
|
||||
int xInputNum;
|
||||
};
|
||||
|
||||
struct DIEnumDevsContext
|
||||
{
|
||||
vector<DIJoyInfo> *infos;
|
||||
bool useXInput;
|
||||
};
|
||||
|
||||
// RawInput API
|
||||
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);
|
||||
|
@ -151,7 +158,7 @@ private:
|
|||
|
||||
void CloseJoysticks();
|
||||
|
||||
HRESULT CreateJoystickEffect(LPDIRECTINPUTDEVICE8 di8Joystick, int axisNum, LPDIRECTINPUTEFFECT *di8Effect);
|
||||
HRESULT CreateJoystickEffect(LPDIRECTINPUTDEVICE8 di8Joystick, int axisNum, ForceFeedbackCmd ffCmd, LPDIRECTINPUTEFFECT *di8Effect);
|
||||
|
||||
protected:
|
||||
/*
|
||||
|
@ -177,7 +184,7 @@ protected:
|
|||
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue