Supermodel/Src/Inputs/Input.cpp
Nik Henson e8782b98fa 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.
2011-06-22 13:06:52 +00:00

165 lines
4.5 KiB
C++

#include "Supermodel.h"
CInput::CInput(const char *inputId, const char *inputLabel, unsigned inputFlags, unsigned inputGameFlags, const char *defaultMapping, UINT16 initValue) :
id(inputId), label(inputLabel), flags(inputFlags), gameFlags(inputGameFlags), m_defaultMapping(defaultMapping), value(initValue), prevValue(initValue),
m_system(NULL), m_source(NULL)
{
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_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)
m_source = NULL;
else
{
// 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 so acquire it
if (m_source != NULL)
m_source->Acquire();
else
{
// Otherwise, fall back to default mapping
if (stricmp(m_mapping, m_defaultMapping) != 0)
{
ErrorLog("Unable to map input %s to [%s] - switching to default [%s].\n", id, m_mapping, m_defaultMapping);
ResetToDefaultMapping();
}
}
}
}
void CInput::Initialize(CInputSystem *system)
{
m_system = system;
CreateSource();
}
const char* CInput::GetInputGroup()
{
switch (gameFlags)
{
case GAME_INPUT_UI: return "User Interface Controls";
case GAME_INPUT_COMMON: return "Common Controls";
case GAME_INPUT_JOYSTICK1: // Fall through to below
case GAME_INPUT_JOYSTICK2: return "8-Way Joysticks";
case GAME_INPUT_FIGHTING: return "Fighting Game Buttons";
case GAME_INPUT_SOCCER: return "Virtua Striker Buttons";
case GAME_INPUT_VEHICLE: return "Racing Game Steering Controls";
case GAME_INPUT_SHIFT4: return "Racing Game Gear Shift";
case GAME_INPUT_VR: return "Racing Game VR View Buttons";
case GAME_INPUT_RALLY: return "Sega Rally Buttons";
case GAME_INPUT_TWIN_JOYSTICKS: return "Virtua On Controls";
case GAME_INPUT_ANALOG_JOYSTICK: return "Analog Joystick";
case GAME_INPUT_GUN1: // Fall through to below
case GAME_INPUT_GUN2: return "Lightguns";
default: return "Misc";
}
}
const char *CInput::GetMapping()
{
return m_mapping;
}
void CInput::ClearMapping()
{
SetMapping("NONE");
}
void CInput::SetMapping(const char *mapping)
{
strncpy(m_mapping, mapping, MAX_MAPPING_LENGTH);
m_mapping[MAX_MAPPING_LENGTH] = '\0';
CreateSource();
}
void CInput::AppendMapping(const char *mapping)
{
// If mapping is empty or NONE, then simply set mapping
if (m_mapping[0] == '\0' || stricmp(m_mapping, "NONE") == 0)
SetMapping(mapping);
else
{
// Otherwise, append to mapping string and recreate source from new mapping string
int size = MAX_MAPPING_LENGTH - strlen(m_mapping);
strncat(m_mapping, ",", size--);
strncat(m_mapping, mapping, size);
CreateSource();
}
}
void CInput::ResetToDefaultMapping()
{
SetMapping(m_defaultMapping);
}
void CInput::ReadFromINIFile(CINIFile *ini, const char *section)
{
// 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)
{
if (!IsConfigurable())
return;
string key("Input");
key.append(id);
ini->Set(section, key, m_mapping);
}
bool CInput::Configure(bool append, const char *escapeMapping)
{
char mapping[MAX_MAPPING_LENGTH];
if (!m_system->ReadMapping(mapping, MAX_MAPPING_LENGTH, !!(flags & INPUT_FLAGS_AXIS), READ_ALL, escapeMapping))
return false;
if (append)
AppendMapping(mapping);
else
SetMapping(mapping);
return true;
}
bool CInput::Changed()
{
return value != prevValue;
}
bool CInput::SendForceFeedbackCmd(ForceFeedbackCmd ffCmd)
{
if (m_source == NULL)
return false;
return m_source->SendForceFeedbackCmd(ffCmd);
}