mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-27 16:15:40 +00:00
d200dff89e
- Changed gear shifting behavior: neutral gear has its own button now. - Removed SUPERMODEL_SOUND. - DirectInput is the default input system for Windows now. - Multi-threading is on by default, replaced -multi-threaded w/ -no-threads. - Made crosshairs larger and more visible. - Added Nik to co-author list and began updating file copyright notices. - Fixed Virtua Striker 2 input names (player 2 inputs end with the number 2 instead of 1). - Added documentation to a Docs/ subdirectory. - Exported all default input configurations to Supermodel.ini and added that to the repository. Internally, Supermodel initializes all controls to "NONE" now.
212 lines
6.3 KiB
C++
212 lines
6.3 KiB
C++
#include "Supermodel.h"
|
|
|
|
// All the input subclasses have been grouped together here as they are very simple classes
|
|
|
|
/*
|
|
* CSwitchInput
|
|
*/
|
|
CSwitchInput::CSwitchInput(const char *inputId, const char *inputLabel, unsigned inputGameFlags, const char *defaultMapping, UINT16 offVal, UINT16 onVal) :
|
|
CInput(inputId, inputLabel, INPUT_FLAGS_SWITCH, inputGameFlags, defaultMapping), m_offVal(offVal), m_onVal(onVal)
|
|
{
|
|
//
|
|
}
|
|
|
|
void CSwitchInput::Poll()
|
|
{
|
|
prevValue = value;
|
|
|
|
bool boolValue = !!value;
|
|
if (m_source != NULL && m_source->GetValueAsSwitch(boolValue))
|
|
value = (boolValue ? m_onVal : m_offVal);
|
|
else
|
|
value = m_offVal;
|
|
}
|
|
|
|
bool CSwitchInput::Pressed()
|
|
{
|
|
return prevValue == m_offVal && value == m_onVal;
|
|
}
|
|
|
|
bool CSwitchInput::Released()
|
|
{
|
|
return prevValue == m_onVal && value == m_offVal;
|
|
}
|
|
|
|
/*
|
|
* CAnalogInput
|
|
*/
|
|
CAnalogInput::CAnalogInput(const char *inputId, const char *inputLabel, unsigned inputGameFlags, const char *defaultMapping, UINT16 minVal, UINT16 maxVal) :
|
|
CInput(inputId, inputLabel, INPUT_FLAGS_ANALOG, inputGameFlags, defaultMapping, minVal), m_minVal(minVal), m_maxVal(maxVal)
|
|
{
|
|
//
|
|
}
|
|
|
|
void CAnalogInput::Poll()
|
|
{
|
|
prevValue = value;
|
|
|
|
if (m_source == NULL)
|
|
{
|
|
value = m_minVal;
|
|
return;
|
|
}
|
|
int intValue = value;
|
|
if (m_source->GetValueAsAnalog(intValue, m_minVal, m_minVal, m_maxVal))
|
|
value = intValue;
|
|
else
|
|
value = m_minVal;
|
|
}
|
|
|
|
bool CAnalogInput::HasValue()
|
|
{
|
|
return value > m_minVal;
|
|
}
|
|
|
|
double CAnalogInput::ValueAsFraction()
|
|
{
|
|
double frac = (double)(value - m_minVal)/(double)(m_maxVal - m_minVal);
|
|
return (frac >= 0.0 ? frac : -frac);
|
|
}
|
|
|
|
/*
|
|
* CAxisInput
|
|
*/
|
|
CAxisInput::CAxisInput(const char *inputId, const char *inputLabel, unsigned inputGameFlags, const char *defaultMapping,
|
|
CAnalogInput *negInput, CAnalogInput *posInput, UINT16 minVal, UINT16 offVal, UINT16 maxVal) :
|
|
CInput(inputId, inputLabel, INPUT_FLAGS_AXIS, inputGameFlags, defaultMapping, offVal), m_negInput(negInput), m_posInput(posInput),
|
|
m_minVal(minVal), m_offVal(offVal), m_maxVal(maxVal)
|
|
{
|
|
//
|
|
}
|
|
|
|
void CAxisInput::Poll()
|
|
{
|
|
prevValue = value;
|
|
|
|
// Try getting value from analog inputs that represent negative and positive range of the axis first and then try the default input source
|
|
int intValue = value;
|
|
if ((m_negInput != NULL && m_negInput->HasValue()) || (m_posInput != NULL && m_posInput->HasValue()))
|
|
{
|
|
if (m_maxVal > m_minVal)
|
|
{
|
|
value = m_offVal;
|
|
if (m_posInput != NULL) value += (int)(m_posInput->ValueAsFraction() * (double)(m_maxVal - m_offVal));
|
|
if (m_negInput != NULL) value -= (int)(m_negInput->ValueAsFraction() * (double)(m_offVal - m_minVal));
|
|
}
|
|
else
|
|
{
|
|
value = m_offVal;
|
|
if (m_posInput != NULL) value += (int)(m_posInput->ValueAsFraction() * (double)(m_offVal - m_maxVal));
|
|
if (m_negInput != NULL) value -= (int)(m_negInput->ValueAsFraction() * (double)(m_minVal - m_offVal));
|
|
}
|
|
}
|
|
else if (m_source != NULL && m_source->GetValueAsAnalog(intValue, m_minVal, m_offVal, m_maxVal))
|
|
value = intValue;
|
|
else
|
|
value = m_offVal;
|
|
}
|
|
|
|
bool CAxisInput::HasValue()
|
|
{
|
|
return value != m_offVal;
|
|
}
|
|
|
|
double CAxisInput::ValueAsFraction()
|
|
{
|
|
double frac = (double)(value - m_minVal)/(double)(m_maxVal - m_minVal);
|
|
return (frac >= 0.0 ? frac : -frac);
|
|
}
|
|
|
|
/*
|
|
* CGearShift4Input
|
|
*/
|
|
CGearShift4Input::CGearShift4Input(const char *inputId, const char *inputLabel, unsigned inputGameFlags,
|
|
CSwitchInput *shift1Input, CSwitchInput *shift2Input, CSwitchInput *shift3Input, CSwitchInput *shift4Input, CSwitchInput *shiftNInput,
|
|
CSwitchInput *shiftUpInput, CSwitchInput *shiftDownInput) :
|
|
CInput(inputId, inputLabel, INPUT_FLAGS_VIRTUAL, inputGameFlags),
|
|
m_shift1Input(shift1Input), m_shift2Input(shift2Input), m_shift3Input(shift3Input), m_shift4Input(shift4Input), m_shiftNInput(shiftNInput),
|
|
m_shiftUpInput(shiftUpInput), m_shiftDownInput(shiftDownInput)
|
|
{
|
|
// Initialize to gear 1
|
|
prevValue = value = 1;
|
|
}
|
|
|
|
void CGearShift4Input::Poll()
|
|
{
|
|
prevValue = value;
|
|
|
|
// Gears (values 1-4) are set by pressing a button (lower gears have priority) and "stick" until a shift to another gear is made.
|
|
// Neutral is selected by pressing the neutral gear button. It means all gears are released (value 0).
|
|
if (m_shiftNInput->Pressed()) value = 0;
|
|
else if (m_shift1Input->Pressed()) value = 1;
|
|
else if (m_shift2Input->Pressed()) value = 2;
|
|
else if (m_shift3Input->Pressed()) value = 3;
|
|
else if (m_shift4Input->Pressed()) value = 4;
|
|
|
|
// Also the shift up/down controls can increase/decrease the gears too
|
|
if (m_shiftUpInput->Pressed()) value = CInputSource::Clamp(value + 1, 0, 4);
|
|
else if (m_shiftDownInput->Pressed()) value = CInputSource::Clamp(value - 1, 0, 4);
|
|
}
|
|
|
|
CTriggerInput::CTriggerInput(const char *inputId, const char *inputLabel, unsigned inputGameFlags,
|
|
CSwitchInput *triggerInput, CSwitchInput *offscreenInput, UINT16 offVal, UINT16 onVal) :
|
|
CInput(inputId, inputLabel, INPUT_FLAGS_VIRTUAL, inputGameFlags),
|
|
m_triggerInput(triggerInput), m_offscreenInput(offscreenInput), m_autoTrigger(false), m_offscreenCount(0), m_offVal(offVal), m_onVal(onVal)
|
|
{
|
|
//
|
|
}
|
|
|
|
void CTriggerInput::ReadFromINIFile(CINIFile *ini, const char *section)
|
|
{
|
|
CInput::ReadFromINIFile(ini, section);
|
|
|
|
string key("Input");
|
|
key.append(id);
|
|
unsigned autoTrigger;
|
|
if (ini->Get(section, key, autoTrigger) == OKAY)
|
|
m_autoTrigger = !!autoTrigger;
|
|
}
|
|
|
|
void CTriggerInput::WriteToINIFile(CINIFile *ini, const char *section)
|
|
{
|
|
CInput::WriteToINIFile(ini, section);
|
|
|
|
string key("Input");
|
|
key.append(id);
|
|
ini->Set(section, key, (unsigned)m_autoTrigger);
|
|
}
|
|
|
|
void CTriggerInput::Poll()
|
|
{
|
|
prevValue = value;
|
|
|
|
// See if auto-trigger on reload is enabled
|
|
if (m_autoTrigger)
|
|
{
|
|
// If so, when offscreen activated simulate triggered being pressed a short while afterwards
|
|
if (m_offscreenCount > 0)
|
|
{
|
|
value = m_offscreenCount < 5;
|
|
offscreenValue = m_onVal;
|
|
m_offscreenCount--;
|
|
}
|
|
else
|
|
{
|
|
value = m_triggerInput->value;
|
|
if (m_offscreenInput->Pressed())
|
|
{
|
|
offscreenValue = m_onVal;
|
|
m_offscreenCount = 10;
|
|
}
|
|
else
|
|
offscreenValue = m_offVal;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Otherwise if disabled, just take raw values from inputs
|
|
value = m_triggerInput->value;
|
|
offscreenValue = m_offscreenInput->value;
|
|
}
|
|
}
|