First shot at configurable paddle input (#522)

This commit is contained in:
thrust26 2020-03-25 09:32:12 +01:00
parent b5ac004b01
commit 4ad59781d8
8 changed files with 310 additions and 165 deletions

View File

@ -12,6 +12,14 @@
Release History Release History
=========================================================================== ===========================================================================
6.1 to 6.2: (??? ??, 2020)
* Paddle centering and sensitivity can be adjusted now
* High scores: Score addresses, game variation etc. can be defined for a
game. This allows the user to save high scores for these games. For each
game and variation, the top 10 scores can be saved.
6.0.2 to 6.1: (March 22, 2020) 6.0.2 to 6.1: (March 22, 2020)
* IMPORTANT NOTES: * IMPORTANT NOTES:

View File

@ -124,7 +124,7 @@ MouseControl::MouseControl(Console& console, const string& mode)
int m_range = 100; int m_range = 100;
if(!(m_axis >> m_range)) if(!(m_axis >> m_range))
m_range = 100; m_range = 100;
Paddles::setPaddleRange(m_range); Paddles::setDigitalPaddleRange(m_range);
// If the mouse isn't used at all, we still need one item in the list // If the mouse isn't used at all, we still need one item in the list
if(myModeList.size() == 0) if(myModeList.size() == 0)

View File

@ -923,6 +923,10 @@ unique_ptr<Controller> Console::getControllerPort(const Controller::Type type,
swapAxis = true; swapAxis = true;
else if(type == Controller::Type::PaddlesIAxDr) else if(type == Controller::Type::PaddlesIAxDr)
swapAxis = swapDir = true; swapAxis = swapDir = true;
Paddles::setAnalogCenter(myOSystem.settings().getInt("pcenter"));
Paddles::setAnalogSensitivity(myOSystem.settings().getInt("psense"));
controller = make_unique<Paddles>(port, myEvent, *mySystem, controller = make_unique<Paddles>(port, myEvent, *mySystem,
swapPaddles, swapAxis, swapDir); swapPaddles, swapAxis, swapDir);
break; break;

View File

@ -234,12 +234,14 @@ void Paddles::update()
new_val = sa_xaxis * (1 - dejitter) + myLastAxisX * dejitter; new_val = sa_xaxis * (1 - dejitter) + myLastAxisX * dejitter;
// only use new dejittered value for larger differences // only use new dejittered value for larger differences
if (abs(new_val - sa_xaxis) > 10) if(abs(new_val - sa_xaxis) > 10)
sa_xaxis = new_val; sa_xaxis = new_val;
setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_xaxis)) / 65536.0))); setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE *
(BSPF::clamp(32768 - Int32(Int32(sa_xaxis) * SENSITIVITY + CENTER), 0, 65536) / 65536.0)));
sa_changed = true; sa_changed = true;
} }
if(abs(myLastAxisY - sa_yaxis) > 10) if(abs(myLastAxisY - sa_yaxis) > 10)
{ {
// dejitter, suppress small changes only // dejitter, suppress small changes only
@ -250,7 +252,8 @@ void Paddles::update()
if (abs(new_val - sa_yaxis) > 10) if (abs(new_val - sa_yaxis) > 10)
sa_yaxis = new_val; sa_yaxis = new_val;
setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_yaxis)) / 65536.0))); setPin(AnalogPin::Five, Int32(MAX_RESISTANCE *
(BSPF::clamp(32768 - Int32(Int32(sa_yaxis) * SENSITIVITY + CENTER), 0, 65536) / 65536.0)));
sa_changed = true; sa_changed = true;
} }
myLastAxisX = sa_xaxis; myLastAxisX = sa_xaxis;
@ -379,6 +382,22 @@ bool Paddles::setMouseControl(
return true; return true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Paddles::setAnalogCenter(int center)
{
// TODO: convert into ~5 pixel (also in Input Dialog!)
CENTER = BSPF::clamp(center, MIN_ANALOG_CENTER, MAX_ANALOG_CENTER) * 860;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
float Paddles::setAnalogSensitivity(int sensitivity)
{
// BASE_ANALOG_SENSE * (1.1 ^ 20) = 1.0
SENSITIVITY = BASE_ANALOG_SENSE * std::pow(1.1, BSPF::clamp(sensitivity, 0, MAX_ANALOG_SENSE));
return SENSITIVITY;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Paddles::setDejitterBase(int strength) void Paddles::setDejitterBase(int strength)
{ {
@ -405,13 +424,16 @@ void Paddles::setMouseSensitivity(int sensitivity)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Paddles::setPaddleRange(int range) void Paddles::setDigitalPaddleRange(int range)
{ {
range = BSPF::clamp(range, 1, 100); range = BSPF::clamp(range, 1, 100);
TRIGRANGE = int(TRIGMAX * (range / 100.0)); TRIGRANGE = int(TRIGMAX * (range / 100.0));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Paddles::CENTER = 0;
float Paddles::SENSITIVITY = 1.0;
int Paddles::TRIGRANGE = Paddles::TRIGMAX; int Paddles::TRIGRANGE = Paddles::TRIGMAX;
int Paddles::DIGITAL_SENSITIVITY = -1; int Paddles::DIGITAL_SENSITIVITY = -1;
int Paddles::DIGITAL_DISTANCE = -1; int Paddles::DIGITAL_DISTANCE = -1;

View File

@ -48,6 +48,10 @@ class Paddles : public Controller
virtual ~Paddles() = default; virtual ~Paddles() = default;
public: public:
static constexpr float BASE_ANALOG_SENSE = 0.148643628f;
static constexpr int MAX_ANALOG_SENSE = 30;
static constexpr int MIN_ANALOG_CENTER = -20;
static constexpr int MAX_ANALOG_CENTER = 20;
static constexpr int MAX_DIGITAL_SENSE = 20; static constexpr int MAX_DIGITAL_SENSE = 20;
static constexpr int MAX_MOUSE_SENSE = 20; static constexpr int MAX_MOUSE_SENSE = 20;
static constexpr int MIN_DEJITTER = 0; static constexpr int MIN_DEJITTER = 0;
@ -88,6 +92,21 @@ class Paddles : public Controller
bool setMouseControl(Controller::Type xtype, int xid, bool setMouseControl(Controller::Type xtype, int xid,
Controller::Type ytype, int yid) override; Controller::Type ytype, int yid) override;
/**
Sets the center for analog paddles.
@param center Value from -20 to 20, representing the center offset/860
*/
static void setAnalogCenter(int center);
/**
Sets the sensitivity for analog paddles.
@param sensitivity Value from 0 to 30, where 20 equals 1
@return Resulting sensitivity
*/
static float setAnalogSensitivity(int sensitivity);
/** /**
@param strength Value from 0 to 10 @param strength Value from 0 to 10
*/ */
@ -127,7 +146,7 @@ class Paddles : public Controller
@param range Value from 1 to 100, representing the percentage @param range Value from 1 to 100, representing the percentage
of the range to use of the range to use
*/ */
static void setPaddleRange(int range); static void setDigitalPaddleRange(int range);
static constexpr double MAX_RESISTANCE = 1400000.0; static constexpr double MAX_RESISTANCE = 1400000.0;
@ -156,6 +175,9 @@ class Paddles : public Controller
int myLastAxisX{0}, myLastAxisY{0}; int myLastAxisX{0}, myLastAxisY{0};
int myAxisDigitalZero{0}, myAxisDigitalOne{0}; int myAxisDigitalZero{0}, myAxisDigitalOne{0};
static int CENTER;
static float SENSITIVITY;
static int DIGITAL_SENSITIVITY, DIGITAL_DISTANCE; static int DIGITAL_SENSITIVITY, DIGITAL_DISTANCE;
static int DEJITTER_BASE, DEJITTER_DIFF; static int DEJITTER_BASE, DEJITTER_DIFF;
static int MOUSE_SENSITIVITY; static int MOUSE_SENSITIVITY;

View File

@ -21,6 +21,7 @@
#include "Version.hxx" #include "Version.hxx"
#include "Logger.hxx" #include "Logger.hxx"
#include "AudioSettings.hxx" #include "AudioSettings.hxx"
#include "Paddles.hxx"
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
#include "DebuggerDialog.hxx" #include "DebuggerDialog.hxx"
@ -102,6 +103,8 @@ Settings::Settings()
setPermanent("dejitter.base", "0"); setPermanent("dejitter.base", "0");
setPermanent("dejitter.diff", "0"); setPermanent("dejitter.diff", "0");
setPermanent("dsense", "10"); setPermanent("dsense", "10");
setPermanent("pcenter", "0");
setPermanent("psense", "20");
setPermanent("msense", "10"); setPermanent("msense", "10");
setPermanent("tsense", "10"); setPermanent("tsense", "10");
setPermanent("saport", "lr"); setPermanent("saport", "lr");
@ -321,6 +324,14 @@ void Settings::validate()
if(i < 0 || i > 3) if(i < 0 || i > 3)
setValue("cursor", "2"); setValue("cursor", "2");
i = getInt("pcenter");
if(i < Paddles::MIN_ANALOG_CENTER || i > Paddles::MAX_ANALOG_CENTER)
setValue("pcenter", "0");
i = getInt("psense");
if(i < 0|| i > Paddles::MAX_ANALOG_SENSE)
setValue("psense", "20");
i = getInt("dsense"); i = getInt("dsense");
if(i < 1 || i > 20) if(i < 1 || i > 20)
setValue("dsense", "10"); setValue("dsense", "10");
@ -445,8 +456,10 @@ void Settings::usage() const
<< " properties in given mode(see manual)\n" << " properties in given mode(see manual)\n"
<< " -grabmouse <1|0> Locks the mouse cursor in the TIA window\n" << " -grabmouse <1|0> Locks the mouse cursor in the TIA window\n"
<< " -cursor <0,1,2,3> Set cursor state in UI/emulation modes\n" << " -cursor <0,1,2,3> Set cursor state in UI/emulation modes\n"
<< " -dejitter.base <0-10> Strength of paddle value averaging\n" << " -dejitter.base <0-10> Strength of analog paddle value averaging\n"
<< " -dejitter.diff <0-10> Strength of paddle reaction to fast movements\n" << " -dejitter.diff <0-10> Strength of analog paddle reaction to fast movements\n"
<< " -pcenter <-20-20> Center of analog paddle\n"
<< " -psense <0-30> Sensitivity of analog paddle movement\n"
<< " -dsense <1-20> Sensitivity of digital emulated paddle movement\n" << " -dsense <1-20> Sensitivity of digital emulated paddle movement\n"
<< " -msense <1-20> Sensitivity of mouse emulated paddle movement\n" << " -msense <1-20> Sensitivity of mouse emulated paddle movement\n"
<< " -tsense <1-20> Sensitivity of mouse emulated trackball movement\n" << " -tsense <1-20> Sensitivity of mouse emulated trackball movement\n"
@ -486,7 +499,7 @@ void Settings::usage() const
<< " -launcherroms <1|0> Show only ROMs in the launcher (vs. all files)\n" << " -launcherroms <1|0> Show only ROMs in the launcher (vs. all files)\n"
<< " -romviewer <float> Show ROM info viewer at given zoom level in ROM\n" << " -romviewer <float> Show ROM info viewer at given zoom level in ROM\n"
<< " launcher (use 0 for off)\n" << " launcher (use 0 for off)\n"
<< " -lastrom <name> Last played ROM, automatically selected in\n" << " -lastrom <name> Last played ROM, automatically selected in\n"
<< " launcher\n" << " launcher\n"
<< " -romloadcount <number> Number of ROM to load next from multicard\n" << " -romloadcount <number> Number of ROM to load next from multicard\n"
<< " -uipalette <standard| Selects GUI theme\n" << " -uipalette <standard| Selects GUI theme\n"

View File

@ -42,9 +42,9 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
myMaxWidth(max_w), myMaxWidth(max_w),
myMaxHeight(max_h) myMaxHeight(max_h)
{ {
const int lineHeight = font.getLineHeight(), const int lineHeight = _font.getLineHeight(),
fontWidth = font.getMaxCharWidth(), fontWidth = _font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() + 4; buttonHeight = _font.getLineHeight() + 4;
const int vBorder = 4; const int vBorder = 4;
int xpos, ypos, tabID; int xpos, ypos, tabID;
@ -53,12 +53,12 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
// The tab widget // The tab widget
xpos = 2; ypos = vBorder + _th; xpos = 2; ypos = vBorder + _th;
myTab = new TabWidget(this, font, xpos, ypos, _w - 2*xpos, _h -_th - buttonHeight - 20); myTab = new TabWidget(this, _font, xpos, ypos, _w - 2*xpos, _h -_th - buttonHeight - 20);
addTabWidget(myTab); addTabWidget(myTab);
// 1) Event mapper for emulation actions // 1) Event mapper for emulation actions
tabID = myTab->addTab(" Emulation Events ", TabWidget::AUTO_WIDTH); tabID = myTab->addTab(" Emul. Events ", TabWidget::AUTO_WIDTH);
myEmulEventMapper = new EventMappingWidget(myTab, font, 2, 2, myEmulEventMapper = new EventMappingWidget(myTab, _font, 2, 2,
myTab->getWidth(), myTab->getWidth(),
myTab->getHeight() - 4, myTab->getHeight() - 4,
EventMode::kEmulationMode); EventMode::kEmulationMode);
@ -66,8 +66,8 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
addToFocusList(myEmulEventMapper->getFocusList(), myTab, tabID); addToFocusList(myEmulEventMapper->getFocusList(), myTab, tabID);
// 2) Event mapper for UI actions // 2) Event mapper for UI actions
tabID = myTab->addTab(" UI Events ", TabWidget::AUTO_WIDTH); tabID = myTab->addTab(" UI Events ", TabWidget::AUTO_WIDTH);
myMenuEventMapper = new EventMappingWidget(myTab, font, 2, 2, myMenuEventMapper = new EventMappingWidget(myTab, _font, 2, 2,
myTab->getWidth(), myTab->getWidth(),
myTab->getHeight() - 4, myTab->getHeight() - 4,
EventMode::kMenuMode); EventMode::kMenuMode);
@ -75,7 +75,10 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
addToFocusList(myMenuEventMapper->getFocusList(), myTab, tabID); addToFocusList(myMenuEventMapper->getFocusList(), myTab, tabID);
// 3) Devices & ports // 3) Devices & ports
addDevicePortTab(font); addDevicePortTab();
// 4) Mouse
addMouseTab();
// Finalize the tabs, and activate the first tab // Finalize the tabs, and activate the first tab
myTab->activateTabs(); myTab->activateTabs();
@ -83,7 +86,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
// Add Defaults, OK and Cancel buttons // Add Defaults, OK and Cancel buttons
WidgetArray wid; WidgetArray wid;
addDefaultsOKCancelBGroup(wid, font); addDefaultsOKCancelBGroup(wid, _font);
addBGroupToFocusList(wid); addBGroupToFocusList(wid);
} }
@ -93,135 +96,109 @@ InputDialog::~InputDialog()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::addDevicePortTab(const GUI::Font& font) void InputDialog::addDevicePortTab()
{ {
const int lineHeight = font.getLineHeight(), const int lineHeight = _font.getLineHeight(),
fontWidth = font.getMaxCharWidth(), fontWidth = _font.getMaxCharWidth(),
fontHeight = font.getFontHeight(); fontHeight = _font.getFontHeight();
int xpos, ypos, lwidth, pwidth, tabID; int xpos, ypos, lwidth, tabID;
WidgetArray wid; WidgetArray wid;
VariantList items;
const int VGAP = 4; const int VGAP = 4;
const int VBORDER = 9; const int VBORDER = 8;
const int HBORDER = 8; const int HBORDER = 8;
// Devices/ports // Devices/ports
tabID = myTab->addTab(" Devices & Ports ", TabWidget::AUTO_WIDTH); tabID = myTab->addTab("Devices & Ports", TabWidget::AUTO_WIDTH);
ypos = VBORDER; ypos = VBORDER;
lwidth = font.getStringWidth("Digital paddle sensitivity "); // was: "Use mouse as a controller " lwidth = _font.getStringWidth("Digital paddle sensitivity ");
pwidth = font.getStringWidth("-UI, -Emulation");
// Use mouse as controller
items.clear();
VarList::push_back(items, "Always", "always");
VarList::push_back(items, "Analog devices", "analog");
VarList::push_back(items, "Never", "never");
myMouseControl = new PopUpWidget(myTab, font, HBORDER, ypos, pwidth, lineHeight, items,
"Use mouse as a controller ", lwidth);
wid.push_back(myMouseControl);
// Mouse cursor state
ypos += lineHeight + VGAP;
items.clear();
VarList::push_back(items, "-UI, -Emulation", "0");
VarList::push_back(items, "-UI, +Emulation", "1");
VarList::push_back(items, "+UI, -Emulation", "2");
VarList::push_back(items, "+UI, +Emulation", "3");
myCursorState = new PopUpWidget(myTab, font, HBORDER, ypos, pwidth, lineHeight, items,
"Mouse cursor visibility ", lwidth, kCursorStateChanged);
wid.push_back(myCursorState);
#ifndef WINDOWED_SUPPORT
myCursorState->clearFlags(Widget::FLAG_ENABLED);
#endif
lwidth = font.getStringWidth("Digital paddle sensitivity ");
// Add joystick deadzone setting // Add joystick deadzone setting
ypos += lineHeight + VGAP*3; myDeadzone = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight,
myDeadzone = new SliderWidget(myTab, font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, "Joystick deadzone size", lwidth, kDeadzoneChanged, 5 * fontWidth);
"Joystick deadzone size ", lwidth, kDeadzoneChanged);
myDeadzone->setMinValue(0); myDeadzone->setMaxValue(29); myDeadzone->setMinValue(0); myDeadzone->setMaxValue(29);
myDeadzone->setTickmarkIntervals(4); myDeadzone->setTickmarkIntervals(4);
xpos = HBORDER + myDeadzone->getWidth() + 5; xpos = HBORDER + myDeadzone->getWidth() + 5;
myDeadzoneLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 5*fontWidth, lineHeight, "");
wid.push_back(myDeadzone); wid.push_back(myDeadzone);
xpos = HBORDER; ypos += lineHeight + VGAP * 2;
new StaticTextWidget(myTab, _font, xpos, ypos+1, "Analog paddle:");
// Add paddle center
xpos += fontWidth * 2;
ypos += lineHeight + VGAP;
myPaddleCenter = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight,
"Center",
lwidth - fontWidth * 2, kPCenterChanged, 6 * fontWidth, "px", 0, true);
myPaddleCenter->setMinValue(Paddles::MIN_ANALOG_CENTER);
myPaddleCenter->setMaxValue(Paddles::MAX_ANALOG_CENTER);
myPaddleCenter->setTickmarkIntervals(4);
wid.push_back(myPaddleCenter);
// Add paddle sensitivity
ypos += lineHeight + VGAP;
myPaddleSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight,
"Sensitivity",
lwidth - fontWidth * 2, kPSpeedChanged, 4 * fontWidth, "%");
myPaddleSpeed->setMinValue(0); myPaddleSpeed->setMaxValue(Paddles::MAX_ANALOG_SENSE);
myPaddleSpeed->setTickmarkIntervals(3);
wid.push_back(myPaddleSpeed);
// Add dejitter (Stelladaptor emulation for now only) // Add dejitter (Stelladaptor emulation for now only)
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
myDejitterBase = new SliderWidget(myTab, font, HBORDER, ypos - 1, 6 * fontWidth, lineHeight, myDejitterBase = new SliderWidget(myTab, _font, xpos, ypos - 1, 6 * fontWidth, lineHeight,
"Paddle dejitter strength", lwidth, kDejitterChanged); "Dejitter strength", lwidth - fontWidth * 2, kDejitterChanged);
myDejitterBase->setMinValue(Paddles::MIN_DEJITTER); myDejitterBase->setMaxValue(Paddles::MAX_DEJITTER); myDejitterBase->setMinValue(Paddles::MIN_DEJITTER);
myDejitterBase->setMaxValue(Paddles::MAX_DEJITTER);
myDejitterBase->setTickmarkIntervals(2); myDejitterBase->setTickmarkIntervals(2);
xpos = HBORDER + myDejitterBase->getWidth() + fontWidth - 4; xpos += myDejitterBase->getWidth() + fontWidth - 4;
wid.push_back(myDejitterBase); wid.push_back(myDejitterBase);
myDejitterDiff = new SliderWidget(myTab, font, xpos, ypos - 1, 6 * fontWidth, lineHeight, myDejitterDiff = new SliderWidget(myTab, _font, xpos, ypos - 1, 6 * fontWidth, lineHeight,
"", 0, kDejitterChanged); "", 0, kDejitterChanged);
myDejitterDiff->setMinValue(Paddles::MIN_DEJITTER); myDejitterDiff->setMaxValue(Paddles::MAX_DEJITTER); myDejitterDiff->setMinValue(Paddles::MIN_DEJITTER);
myDejitterDiff->setMaxValue(Paddles::MAX_DEJITTER);
myDejitterDiff->setTickmarkIntervals(2); myDejitterDiff->setTickmarkIntervals(2);
xpos += myDejitterDiff->getWidth() + 5; xpos += myDejitterDiff->getWidth();
wid.push_back(myDejitterDiff); wid.push_back(myDejitterDiff);
myDejitterLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, 7 * fontWidth, lineHeight, ""); myDejitterLabel = new StaticTextWidget(myTab, _font, xpos, ypos + 1, 7 * fontWidth, lineHeight, "");
// Add paddle speed (digital emulation) // Add paddle speed (digital emulation)
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP * 4;
myDPaddleSpeed = new SliderWidget(myTab, font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, myDPaddleSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight,
"Digital paddle sensitivity ", "Digital paddle sensitivity",
lwidth, kDPSpeedChanged); lwidth, kDPSpeedChanged, 4 * fontWidth, "%");
myDPaddleSpeed->setMinValue(1); myDPaddleSpeed->setMaxValue(20); myDPaddleSpeed->setMinValue(1); myDPaddleSpeed->setMaxValue(20);
myDPaddleSpeed->setTickmarkIntervals(4); myDPaddleSpeed->setTickmarkIntervals(4);
xpos = HBORDER + myDPaddleSpeed->getWidth() + 5;
myDPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, "");
wid.push_back(myDPaddleSpeed); wid.push_back(myDPaddleSpeed);
// Add paddle speed (mouse emulation)
ypos += lineHeight + VGAP;
myMPaddleSpeed = new SliderWidget(myTab, font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight,
"Mouse paddle sensitivity ",
lwidth, kMPSpeedChanged);
myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20);
myMPaddleSpeed->setTickmarkIntervals(4);
xpos = HBORDER + myMPaddleSpeed->getWidth() + 5;
myMPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, "");
wid.push_back(myMPaddleSpeed);
// Add trackball speed // Add trackball speed
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP * 2;
myTrackBallSpeed = new SliderWidget(myTab, font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, myTrackBallSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight,
"Trackball sensitivity ", "Trackball sensitivity",
lwidth, kTBSpeedChanged); lwidth, kTBSpeedChanged, 4 * fontWidth, "%");
myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20); myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20);
myTrackBallSpeed->setTickmarkIntervals(4); myTrackBallSpeed->setTickmarkIntervals(4);
xpos = HBORDER + myTrackBallSpeed->getWidth() + 5;
myTrackBallLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, "");
wid.push_back(myTrackBallSpeed); wid.push_back(myTrackBallSpeed);
// Add 'allow all 4 directions' for joystick // Add 'allow all 4 directions' for joystick
ypos += lineHeight + VGAP*3; ypos += lineHeight + VGAP * 4;
myAllowAll4 = new CheckboxWidget(myTab, font, HBORDER, ypos, myAllowAll4 = new CheckboxWidget(myTab, _font, HBORDER, ypos,
"Allow all 4 directions on joystick"); "Allow all 4 directions on joystick");
wid.push_back(myAllowAll4); wid.push_back(myAllowAll4);
// Grab mouse (in windowed mode)
ypos += lineHeight + VGAP;
myGrabMouse = new CheckboxWidget(myTab, font, HBORDER, ypos,
"Grab mouse in emulation mode");
wid.push_back(myGrabMouse);
#ifndef WINDOWED_SUPPORT
myGrabMouse->clearFlags(Widget::FLAG_ENABLED);
#endif
// Enable/disable modifier key-combos // Enable/disable modifier key-combos
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
myModCombo = new CheckboxWidget(myTab, font, HBORDER, ypos, myModCombo = new CheckboxWidget(myTab, _font, HBORDER, ypos,
"Use modifier key combos"); "Use modifier key combos");
wid.push_back(myModCombo); wid.push_back(myModCombo);
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
// Stelladaptor mappings // Stelladaptor mappings
mySAPort = new CheckboxWidget(myTab, font, HBORDER, ypos, mySAPort = new CheckboxWidget(myTab, _font, HBORDER, ypos,
"Swap Stelladaptor ports"); "Swap Stelladaptor ports");
wid.push_back(mySAPort); wid.push_back(mySAPort);
@ -229,37 +206,101 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
// Add EEPROM erase (part 1/2) // Add EEPROM erase (part 1/2)
ypos += VGAP*4; ypos += VGAP*4;
fwidth = font.getStringWidth("AtariVox/SaveKey"); fwidth = _font.getStringWidth("AtariVox/SaveKey");
lwidth = font.getStringWidth("AtariVox/SaveKey"); lwidth = _font.getStringWidth("AtariVox/SaveKey");
new StaticTextWidget(myTab, font, _w - HBORDER - 4 - (fwidth + lwidth) / 2, ypos, new StaticTextWidget(myTab, _font, _w - HBORDER - 4 - (fwidth + lwidth) / 2, ypos,
"AtariVox/SaveKey"); "AtariVox/SaveKey");
// Show joystick database // Show joystick database
ypos += lineHeight; ypos += lineHeight;
myJoyDlgButton = new ButtonWidget(myTab, font, HBORDER, ypos, 20, myJoyDlgButton = new ButtonWidget(myTab, _font, HBORDER, ypos, 20,
"Joystick Database" + ELLIPSIS, kDBButtonPressed); "Joystick Database" + ELLIPSIS, kDBButtonPressed);
wid.push_back(myJoyDlgButton); wid.push_back(myJoyDlgButton);
// Add EEPROM erase (part 1/2) // Add EEPROM erase (part 1/2)
myEraseEEPROMButton = new ButtonWidget(myTab, font, _w - HBORDER - 4 - fwidth, ypos, myEraseEEPROMButton = new ButtonWidget(myTab, _font, _w - HBORDER - 4 - fwidth, ypos,
fwidth, lineHeight+4, fwidth, lineHeight+4,
"Erase EEPROM", kEEButtonPressed); "Erase EEPROM", kEEButtonPressed);
wid.push_back(myEraseEEPROMButton); wid.push_back(myEraseEEPROMButton);
// Add AtariVox serial port // Add AtariVox serial port
ypos += lineHeight + VGAP*2; ypos += lineHeight + VGAP * 2;
lwidth = font.getStringWidth("AVox serial port "); lwidth = _font.getStringWidth("AVox serial port ");
fwidth = _w - HBORDER * 2 - 4 - lwidth; fwidth = _w - HBORDER * 2 - 4 - lwidth;
new StaticTextWidget(myTab, font, HBORDER, ypos + 2, "AVox serial port "); new StaticTextWidget(myTab, _font, HBORDER, ypos + 2, "AVox serial port ");
myAVoxPort = new EditTextWidget(myTab, font, HBORDER + lwidth, ypos, myAVoxPort = new EditTextWidget(myTab, _font, HBORDER + lwidth, ypos,
fwidth, fontHeight); fwidth, fontHeight);
wid.push_back(myAVoxPort); wid.push_back(myAVoxPort);
// Add items for virtual device ports // Add items for virtual device ports
addToFocusList(wid, myTab, tabID); addToFocusList(wid, myTab, tabID);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::addMouseTab()
{
const int lineHeight = _font.getLineHeight(),
fontWidth = _font.getMaxCharWidth(),
fontHeight = _font.getFontHeight();
int ypos, lwidth, pwidth, tabID;
WidgetArray wid;
VariantList items;
const int VGAP = 4;
const int VBORDER = 8;
const int HBORDER = 8;
// Mouse
tabID = myTab->addTab(" Mouse ", TabWidget::AUTO_WIDTH);
ypos = VBORDER;
lwidth = _font.getStringWidth("Use mouse as a controller ");
pwidth = _font.getStringWidth("-UI, -Emulation");
// Use mouse as controller
VarList::push_back(items, "Always", "always");
VarList::push_back(items, "Analog devices", "analog");
VarList::push_back(items, "Never", "never");
myMouseControl = new PopUpWidget(myTab, _font, HBORDER, ypos, pwidth, lineHeight, items,
"Use mouse as a controller ", lwidth, kMouseCtrlChanged);
wid.push_back(myMouseControl);
// Add paddle speed (mouse emulation)
ypos += lineHeight + VGAP;
myMPaddleSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight,
"Mouse paddle sensitivity ",
lwidth, kMPSpeedChanged, 4 * fontWidth, "%");
myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20);
myMPaddleSpeed->setTickmarkIntervals(4);
wid.push_back(myMPaddleSpeed);
// Mouse cursor state
ypos += lineHeight + VGAP * 4;
items.clear();
VarList::push_back(items, "-UI, -Emulation", "0");
VarList::push_back(items, "-UI, +Emulation", "1");
VarList::push_back(items, "+UI, -Emulation", "2");
VarList::push_back(items, "+UI, +Emulation", "3");
myCursorState = new PopUpWidget(myTab, _font, HBORDER, ypos, pwidth, lineHeight, items,
"Mouse cursor visibility ", lwidth, kCursorStateChanged);
wid.push_back(myCursorState);
#ifndef WINDOWED_SUPPORT
myCursorState->clearFlags(Widget::FLAG_ENABLED);
#endif
// Grab mouse (in windowed mode)
ypos += lineHeight + VGAP;
myGrabMouse = new CheckboxWidget(myTab, _font, HBORDER, ypos,
"Grab mouse in emulation mode");
wid.push_back(myGrabMouse);
#ifndef WINDOWED_SUPPORT
myGrabMouse->clearFlags(Widget::FLAG_ENABLED);
#endif
// Add items for mouse
addToFocusList(wid, myTab, tabID);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::loadConfig() void InputDialog::loadConfig()
{ {
@ -269,6 +310,7 @@ void InputDialog::loadConfig()
// Use mouse as a controller // Use mouse as a controller
myMouseControl->setSelected( myMouseControl->setSelected(
instance().settings().getString("usemouse"), "analog"); instance().settings().getString("usemouse"), "analog");
handleMouseControlState();
// Mouse cursor state // Mouse cursor state
myCursorState->setSelected(instance().settings().getString("cursor"), "2"); myCursorState->setSelected(instance().settings().getString("cursor"), "2");
@ -276,20 +318,20 @@ void InputDialog::loadConfig()
// Joystick deadzone // Joystick deadzone
myDeadzone->setValue(instance().settings().getInt("joydeadzone")); myDeadzone->setValue(instance().settings().getInt("joydeadzone"));
myDeadzoneLabel->setValue(Joystick::deadzone());
// Paddle center & speed (analog)
myPaddleCenter->setValue(instance().settings().getInt("pcenter"));
myPaddleSpeed->setValue(instance().settings().getInt("psense"));
// Paddle speed (digital and mouse) // Paddle speed (digital and mouse)
myDejitterBase->setValue(instance().settings().getInt("dejitter.base")); myDejitterBase->setValue(instance().settings().getInt("dejitter.base"));
myDejitterDiff->setValue(instance().settings().getInt("dejitter.diff")); myDejitterDiff->setValue(instance().settings().getInt("dejitter.diff"));
updateDejitter(); updateDejitter();
myDPaddleSpeed->setValue(instance().settings().getInt("dsense")); myDPaddleSpeed->setValue(instance().settings().getInt("dsense"));
myDPaddleLabel->setLabel(instance().settings().getString("dsense"));
myMPaddleSpeed->setValue(instance().settings().getInt("msense")); myMPaddleSpeed->setValue(instance().settings().getInt("msense"));
myMPaddleLabel->setLabel(instance().settings().getString("msense"));
// Trackball speed // Trackball speed
myTrackBallSpeed->setValue(instance().settings().getInt("tsense")); myTrackBallSpeed->setValue(instance().settings().getInt("tsense"));
myTrackBallLabel->setLabel(instance().settings().getString("tsense"));
// AtariVox serial port // AtariVox serial port
myAVoxPort->setText(instance().settings().getString("avoxport")); myAVoxPort->setText(instance().settings().getString("avoxport"));
@ -334,6 +376,16 @@ void InputDialog::saveConfig()
instance().settings().setValue("joydeadzone", deadzone); instance().settings().setValue("joydeadzone", deadzone);
Joystick::setDeadZone(deadzone); Joystick::setDeadZone(deadzone);
// Paddle center (analog)
int center = myPaddleCenter->getValue();
instance().settings().setValue("pcenter", center);
Paddles::setAnalogCenter(center);
// Paddle speed (analog)
int sensitivity = myPaddleSpeed->getValue();
instance().settings().setValue("psense", sensitivity);
Paddles::setAnalogSensitivity(sensitivity);
// Paddle speed (digital and mouse) // Paddle speed (digital and mouse)
int dejitter = myDejitterBase->getValue(); int dejitter = myDejitterBase->getValue();
instance().settings().setValue("dejitter.base", dejitter); instance().settings().setValue("dejitter.base", dejitter);
@ -342,7 +394,7 @@ void InputDialog::saveConfig()
instance().settings().setValue("dejitter.diff", dejitter); instance().settings().setValue("dejitter.diff", dejitter);
Paddles::setDejitterDiff(dejitter); Paddles::setDejitterDiff(dejitter);
int sensitivity = myDPaddleSpeed->getValue(); sensitivity = myDPaddleSpeed->getValue();
instance().settings().setValue("dsense", sensitivity); instance().settings().setValue("dsense", sensitivity);
Paddles::setDigitalSensitivity(sensitivity); Paddles::setDigitalSensitivity(sensitivity);
@ -394,26 +446,19 @@ void InputDialog::setDefaults()
myMenuEventMapper->setDefaults(); myMenuEventMapper->setDefaults();
break; break;
case 2: // Virtual devices case 2: // Devices & Ports
{
// Left & right ports // Left & right ports
mySAPort->setState(false); mySAPort->setState(false);
// Use mouse as a controller
myMouseControl->setSelected("analog");
// Mouse cursor state
myCursorState->setSelected("2");
// Joystick deadzone // Joystick deadzone
myDeadzone->setValue(0); myDeadzone->setValue(0);
myDeadzoneLabel->setValue(3200);
// Paddle speed (digital and mouse) // Paddle center & speed (analog)
myPaddleCenter->setValue(0);
myPaddleSpeed->setValue(20);
// Paddle speed (digital)
myDPaddleSpeed->setValue(10); myDPaddleSpeed->setValue(10);
myDPaddleLabel->setLabel("10");
myMPaddleSpeed->setValue(10);
myMPaddleLabel->setLabel("10");
#if defined(RETRON77) #if defined(RETRON77)
myDejitterBase->setValue(2); myDejitterBase->setValue(2);
myDejitterDiff->setValue(6); myDejitterDiff->setValue(6);
@ -423,7 +468,6 @@ void InputDialog::setDefaults()
#endif #endif
updateDejitter(); updateDejitter();
myTrackBallSpeed->setValue(10); myTrackBallSpeed->setValue(10);
myTrackBallLabel->setLabel("10");
// AtariVox serial port // AtariVox serial port
myAVoxPort->setText(""); myAVoxPort->setText("");
@ -431,16 +475,27 @@ void InputDialog::setDefaults()
// Allow all 4 joystick directions // Allow all 4 joystick directions
myAllowAll4->setState(false); myAllowAll4->setState(false);
// Grab mouse
myGrabMouse->setState(true);
// Enable/disable modifier key-combos // Enable/disable modifier key-combos
myModCombo->setState(true); myModCombo->setState(true);
handleCursorState();
break; break;
}
case 3: // Mouse
// Use mouse as a controller
myMouseControl->setSelected("analog");
// Mouse cursor state
myCursorState->setSelected("2");
// Grab mouse
myGrabMouse->setState(true);
// Paddle speed (mouse)
myMPaddleSpeed->setValue(10);
handleMouseControlState();
handleCursorState();
break;
default: default:
break; break;
@ -566,28 +621,28 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd,
setDefaults(); setDefaults();
break; break;
case kCursorStateChanged:
handleCursorState();
break;
case kDeadzoneChanged: case kDeadzoneChanged:
myDeadzoneLabel->setValue(3200 + 1000*myDeadzone->getValue()); myDeadzone->setValueLabel(3200 + 1000 * myDeadzone->getValue());
break; break;
case kDPSpeedChanged: case kPCenterChanged:
myDPaddleLabel->setValue(myDPaddleSpeed->getValue()); myPaddleCenter->setValueLabel(myPaddleCenter->getValue() * 5);
break; break;
case kMPSpeedChanged: case kPSpeedChanged:
myMPaddleLabel->setValue(myMPaddleSpeed->getValue()); myPaddleSpeed->setValueLabel(Paddles::setAnalogSensitivity(myPaddleSpeed->getValue()) * 100.0 + 0.5);
break; break;
case kDejitterChanged: case kDejitterChanged:
updateDejitter(); updateDejitter();
break; break;
case kDPSpeedChanged:
myDPaddleSpeed->setValueLabel(myDPaddleSpeed->getValue() * 10);
break;
case kTBSpeedChanged: case kTBSpeedChanged:
myTrackBallLabel->setValue(myTrackBallSpeed->getValue()); myTrackBallSpeed->setValueLabel(myTrackBallSpeed->getValue() * 10);
break; break;
case kDBButtonPressed: case kDBButtonPressed:
@ -623,20 +678,23 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd,
eraseEEPROM(); eraseEEPROM();
break; break;
case kMouseCtrlChanged:
handleMouseControlState();
break;
case kCursorStateChanged:
handleCursorState();
break;
case kMPSpeedChanged:
myMPaddleSpeed->setValueLabel(myMPaddleSpeed->getValue() * 10);
break;
default: default:
Dialog::handleCommand(sender, cmd, data, 0); Dialog::handleCommand(sender, cmd, data, 0);
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::handleCursorState()
{
int state = myCursorState->getSelected();
bool enableGrab = state != 1 && state != 3;
myGrabMouse->setEnabled(enableGrab);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::updateDejitter() void InputDialog::updateDejitter()
{ {
@ -659,3 +717,17 @@ void InputDialog::updateDejitter()
myDejitterLabel->setLabel(label.str()); myDejitterLabel->setLabel(label.str());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::handleMouseControlState()
{
myMPaddleSpeed->setEnabled(myMouseControl->getSelected() != 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::handleCursorState()
{
int state = myCursorState->getSelected();
bool enableGrab = state != 1 && state != 3;
myGrabMouse->setEnabled(enableGrab);
}

View File

@ -59,23 +59,29 @@ class InputDialog : public Dialog
void saveConfig() override; void saveConfig() override;
void setDefaults() override; void setDefaults() override;
void addDevicePortTab(const GUI::Font& font); void addDevicePortTab();
void addMouseTab();
void handleMouseControlState();
void handleCursorState(); void handleCursorState();
void updateDejitter(); void updateDejitter();
void eraseEEPROM(); void eraseEEPROM();
private: private:
enum { enum {
kCursorStateChanged = 'CSch',
kDeadzoneChanged = 'DZch', kDeadzoneChanged = 'DZch',
kPCenterChanged = 'Pcch',
kPSpeedChanged = 'Ppch',
kDejitterChanged = 'Pjch', kDejitterChanged = 'Pjch',
kDPSpeedChanged = 'PDch', kDPSpeedChanged = 'PDch',
kMPSpeedChanged = 'PMch',
kTBSpeedChanged = 'TBch', kTBSpeedChanged = 'TBch',
kDBButtonPressed = 'DBbp', kDBButtonPressed = 'DBbp',
kEEButtonPressed = 'EEbp', kEEButtonPressed = 'EEbp',
kConfirmEEEraseCmd = 'EEcf' kConfirmEEEraseCmd = 'EEcf',
kMouseCtrlChanged = 'MCch',
kCursorStateChanged = 'CSch',
kMPSpeedChanged = 'PMch',
}; };
TabWidget* myTab{nullptr}; TabWidget* myTab{nullptr};
@ -90,16 +96,14 @@ class InputDialog : public Dialog
EditTextWidget* myAVoxPort{nullptr}; EditTextWidget* myAVoxPort{nullptr};
SliderWidget* myDeadzone{nullptr}; SliderWidget* myDeadzone{nullptr};
StaticTextWidget* myDeadzoneLabel{nullptr}; SliderWidget* myPaddleCenter{nullptr};
SliderWidget* myPaddleSpeed{nullptr};
SliderWidget* myDejitterBase{nullptr}; SliderWidget* myDejitterBase{nullptr};
SliderWidget* myDejitterDiff{nullptr}; SliderWidget* myDejitterDiff{nullptr};
SliderWidget* myDPaddleSpeed{nullptr}; SliderWidget* myDPaddleSpeed{nullptr};
SliderWidget* myMPaddleSpeed{nullptr}; SliderWidget* myMPaddleSpeed{nullptr};
SliderWidget* myTrackBallSpeed{nullptr}; SliderWidget* myTrackBallSpeed{nullptr};
StaticTextWidget* myDejitterLabel{nullptr}; StaticTextWidget* myDejitterLabel{nullptr};
StaticTextWidget* myDPaddleLabel{nullptr};
StaticTextWidget* myMPaddleLabel{nullptr};
StaticTextWidget* myTrackBallLabel{nullptr};
CheckboxWidget* myAllowAll4{nullptr}; CheckboxWidget* myAllowAll4{nullptr};
CheckboxWidget* myGrabMouse{nullptr}; CheckboxWidget* myGrabMouse{nullptr};
CheckboxWidget* myModCombo{nullptr}; CheckboxWidget* myModCombo{nullptr};