Ha, found a way to detect analog vs digital axis input

This commit is contained in:
Thomas Jentzsch 2019-08-18 23:10:51 +02:00
parent 2f9bb04eb8
commit 1a706ab2f1
1 changed files with 50 additions and 63 deletions

View File

@ -197,7 +197,7 @@ void PhysicalJoystickHandler::mapStelladaptors(const string& saport)
// remove previously added emulated ports // remove previously added emulated ports
size_t pos = stick.second->name.find(" (emulates "); size_t pos = stick.second->name.find(" (emulates ");
if (pos != std::string::npos) if(pos != std::string::npos)
stick.second->name.erase(pos); stick.second->name.erase(pos);
if(BSPF::startsWithIgnoreCase(stick.second->name, "Stelladaptor")) if(BSPF::startsWithIgnoreCase(stick.second->name, "Stelladaptor"))
@ -245,17 +245,17 @@ void PhysicalJoystickHandler::setDefaultAction(const PhysicalJoystickPtr& j,
// Otherwise, only reset the given event // Otherwise, only reset the given event
bool eraseAll = !updateDefaults && (event == Event::NoType); bool eraseAll = !updateDefaults && (event == Event::NoType);
if (updateDefaults) if(updateDefaults)
{ {
// if there is no existing mapping for the event or // if there is no existing mapping for the event or
// the default mapping for the event is unused, set default key for event // the default mapping for the event is unused, set default key for event
if (j->joyMap.getEventMapping(map.event, mode).size() == 0 || if(j->joyMap.getEventMapping(map.event, mode).size() == 0 ||
!j->joyMap.check(mode, map.button, map.axis, map.adir, map.hat, map.hdir)) !j->joyMap.check(mode, map.button, map.axis, map.adir, map.hat, map.hdir))
{ {
j->joyMap.add(map.event, mode, map.button, map.axis, map.adir, map.hat, map.hdir); j->joyMap.add(map.event, mode, map.button, map.axis, map.adir, map.hat, map.hdir);
} }
} }
else if (eraseAll || map.event == event) else if(eraseAll || map.event == event)
{ {
// TODO: allow for multiple defaults // TODO: allow for multiple defaults
//j->joyMap.eraseEvent(map.event, mode); //j->joyMap.eraseEvent(map.event, mode);
@ -275,7 +275,7 @@ void PhysicalJoystickHandler::setStickDefaultMapping(int stick, Event::Type even
switch (mode) switch (mode)
{ {
case EventMode::kEmulationMode: case EventMode::kEmulationMode:
if ((stick % 2) == 0) // even sticks if((stick % 2) == 0) // even sticks
{ {
// put all controller events into their own mode's mappings // put all controller events into their own mode's mappings
for (const auto& item : DefaultLeftJoystickMapping) for (const auto& item : DefaultLeftJoystickMapping)
@ -408,7 +408,7 @@ void PhysicalJoystickHandler::enableCommonMappings()
{ {
Event::Type event = static_cast<Event::Type>(i); Event::Type event = static_cast<Event::Type>(i);
if (isCommonEvent(event)) if(isCommonEvent(event))
enableMapping(event, EventMode::kCommonMode); enableMapping(event, EventMode::kCommonMode);
} }
} }
@ -438,18 +438,18 @@ void PhysicalJoystickHandler::enableMapping(const Event::Type event, EventMode m
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventMode PhysicalJoystickHandler::getEventMode(const Event::Type event, const EventMode mode) const EventMode PhysicalJoystickHandler::getEventMode(const Event::Type event, const EventMode mode) const
{ {
if (mode == EventMode::kEmulationMode) if(mode == EventMode::kEmulationMode)
{ {
if (isJoystickEvent(event)) if(isJoystickEvent(event))
return EventMode::kJoystickMode; return EventMode::kJoystickMode;
if (isPaddleEvent(event)) if(isPaddleEvent(event))
return EventMode::kPaddlesMode; return EventMode::kPaddlesMode;
if (isKeypadEvent(event)) if(isKeypadEvent(event))
return EventMode::kKeypadMode; return EventMode::kKeypadMode;
if (isCommonEvent(event)) if(isCommonEvent(event))
return EventMode::kCommonMode; return EventMode::kCommonMode;
} }
@ -493,7 +493,7 @@ void PhysicalJoystickHandler::eraseMapping(Event::Type event, EventMode mode)
for (auto& stick : mySticks) for (auto& stick : mySticks)
{ {
stick.second->eraseMap(mode); // erase all events stick.second->eraseMap(mode); // erase all events
if (mode == EventMode::kEmulationMode) if(mode == EventMode::kEmulationMode)
{ {
stick.second->eraseMap(EventMode::kCommonMode); stick.second->eraseMap(EventMode::kCommonMode);
stick.second->eraseMap(EventMode::kJoystickMode); stick.second->eraseMap(EventMode::kJoystickMode);
@ -539,12 +539,12 @@ string PhysicalJoystickHandler::getMappingDesc(Event::Type event, EventMode mode
uInt32 stick = s.first; uInt32 stick = s.first;
const PhysicalJoystickPtr j = s.second; const PhysicalJoystickPtr j = s.second;
if (j) if(j)
{ {
//Joystick mapping / labeling //Joystick mapping / labeling
if (j->joyMap.getEventMapping(event, evMode).size()) if(j->joyMap.getEventMapping(event, evMode).size())
{ {
if (buf.str() != "") if(buf.str() != "")
buf << ", "; buf << ", ";
buf << j->joyMap.getEventMappingDesc(stick, event, evMode); buf << j->joyMap.getEventMappingDesc(stick, event, evMode);
} }
@ -559,7 +559,7 @@ bool PhysicalJoystickHandler::addJoyMapping(Event::Type event, EventMode mode, i
{ {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
if (j && event < Event::LastType && if(j && event < Event::LastType &&
button >= JOY_CTRL_NONE && button < j->numButtons && button >= JOY_CTRL_NONE && button < j->numButtons &&
axis >= JoyAxis::NONE && int(axis) < j->numAxes) axis >= JoyAxis::NONE && int(axis) < j->numAxes)
{ {
@ -567,30 +567,16 @@ bool PhysicalJoystickHandler::addJoyMapping(Event::Type event, EventMode mode, i
// This confusing code is because each axis has two associated values, // This confusing code is because each axis has two associated values,
// but analog events only affect one of the axis. // but analog events only affect one of the axis.
if (Event::isAnalog(event)) if(Event::isAnalog(event))
{ {
// Turn off the digital event(s) for this axis, because we cannot have both
if(j->joyMap.get(evMode, button, axis, JoyDir::NEG) != Event::NoType)
j->joyMap.erase(evMode, button, axis, JoyDir::NEG);
if(j->joyMap.get(evMode, button, axis, JoyDir::POS) != Event::NoType)
j->joyMap.erase(evMode, button, axis, JoyDir::POS);
j->joyMap.add(event, evMode, button, axis, JoyDir::ANALOG); j->joyMap.add(event, evMode, button, axis, JoyDir::ANALOG);
// update running emulation mapping too // update running emulation mapping too
if(j->joyMap.get(EventMode::kEmulationMode, button, axis, JoyDir::NEG) != Event::NoType)
j->joyMap.erase(EventMode::kEmulationMode, button, axis, JoyDir::NEG);
if(j->joyMap.get(EventMode::kEmulationMode, button, axis, JoyDir::POS) != Event::NoType)
j->joyMap.erase(EventMode::kEmulationMode, button, axis, JoyDir::POS);
j->joyMap.add(event, EventMode::kEmulationMode, button, axis, JoyDir::ANALOG); j->joyMap.add(event, EventMode::kEmulationMode, button, axis, JoyDir::ANALOG);
} }
else else
{ {
// Otherwise, turn off the analog event(s) for this axis, because we cannot have both
if (j->joyMap.get(evMode, button, axis, JoyDir::ANALOG) != Event::NoType)
j->joyMap.erase(evMode, button, axis, JoyDir::ANALOG);
j->joyMap.add(event, evMode, button, axis, adir); j->joyMap.add(event, evMode, button, axis, adir);
// update running emulation mapping too // update running emulation mapping too
if(j->joyMap.get(EventMode::kEmulationMode, button, axis, JoyDir::ANALOG) != Event::NoType)
j->joyMap.erase(EventMode::kEmulationMode, button, axis, JoyDir::ANALOG);
j->joyMap.add(event, EventMode::kEmulationMode, button, axis, adir); j->joyMap.add(event, EventMode::kEmulationMode, button, axis, adir);
} }
return true; return true;
@ -604,9 +590,9 @@ bool PhysicalJoystickHandler::addJoyHatMapping(Event::Type event, EventMode mode
{ {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
if (j && event < Event::LastType && if(j && event < Event::LastType &&
button >= JOY_CTRL_NONE && button < j->numButtons && button >= JOY_CTRL_NONE && button < j->numButtons &&
hat >= 0 && hat < j->numHats && hdir != JoyHatDir::CENTER) hat >= 0 && hat < j->numHats && hdir != JoyHatDir::CENTER)
{ {
j->joyMap.add(event, getEventMode(event, mode), button, hat, hdir); j->joyMap.add(event, getEventMode(event, mode), button, hat, hdir);
// update running emulation mapping too // update running emulation mapping too
@ -621,29 +607,30 @@ void PhysicalJoystickHandler::handleAxisEvent(int stick, int axis, int value)
{ {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
if (j) if(j)
{ {
int button = j->buttonLast[stick]; int button = j->buttonLast[stick];
if (myHandler.state() == EventHandlerState::EMULATION) if(myHandler.state() == EventHandlerState::EMULATION)
{ {
// Check for analog events, which are handled differently // Check for analog events, which are handled differently
Event::Type eventAxisAnalog = j->joyMap.get(EventMode::kEmulationMode, button, JoyAxis(axis), JoyDir::ANALOG); // A value change lower than ~90% indicates analog input
if(abs(j->axisLastValue[axis] - value) < 30000)
if (eventAxisAnalog != Event::NoType)
{ {
Event::Type eventAxisAnalog = j->joyMap.get(EventMode::kEmulationMode, button, JoyAxis(axis), JoyDir::ANALOG);
myHandler.handleEvent(eventAxisAnalog, value); myHandler.handleEvent(eventAxisAnalog, value);
} }
else else
{ {
// Otherwise, we know the event is digital // Otherwise, we assume the event is digital
// Every axis event has two associated values, negative and positive // Every axis event has two associated values, negative and positive
Event::Type eventAxisNeg = j->joyMap.get(EventMode::kEmulationMode, button, JoyAxis(axis), JoyDir::NEG); Event::Type eventAxisNeg = j->joyMap.get(EventMode::kEmulationMode, button, JoyAxis(axis), JoyDir::NEG);
Event::Type eventAxisPos = j->joyMap.get(EventMode::kEmulationMode, button, JoyAxis(axis), JoyDir::POS); Event::Type eventAxisPos = j->joyMap.get(EventMode::kEmulationMode, button, JoyAxis(axis), JoyDir::POS);
if (value > Joystick::deadzone()) if(value > Joystick::deadzone())
myHandler.handleEvent(eventAxisPos); myHandler.handleEvent(eventAxisPos);
else if (value < -Joystick::deadzone()) else if(value < -Joystick::deadzone())
myHandler.handleEvent(eventAxisNeg); myHandler.handleEvent(eventAxisNeg);
else else
{ {
@ -652,7 +639,7 @@ void PhysicalJoystickHandler::handleAxisEvent(int stick, int axis, int value)
// Now filter out consecutive, similar values // Now filter out consecutive, similar values
// (only pass on the event if the state has changed) // (only pass on the event if the state has changed)
if (j->axisLastValue[axis] != value) if(j->axisLastValue[axis] != value)
{ {
// Turn off both events, since we don't know exactly which one // Turn off both events, since we don't know exactly which one
// was previously activated. // was previously activated.
@ -660,23 +647,23 @@ void PhysicalJoystickHandler::handleAxisEvent(int stick, int axis, int value)
myHandler.handleEvent(eventAxisPos, false); myHandler.handleEvent(eventAxisPos, false);
} }
} }
j->axisLastValue[axis] = value;
} }
j->axisLastValue[axis] = value;
} }
else if (myHandler.hasOverlay()) else if(myHandler.hasOverlay())
{ {
// First, clamp the values to simulate digital input // First, clamp the values to simulate digital input
// (the only thing that the underlying code understands) // (the only thing that the underlying code understands)
if (value > Joystick::deadzone()) if(value > Joystick::deadzone())
value = 32000; value = 32000;
else if (value < -Joystick::deadzone()) else if(value < -Joystick::deadzone())
value = -32000; value = -32000;
else else
value = 0; value = 0;
// Now filter out consecutive, similar values // Now filter out consecutive, similar values
// (only pass on the event if the state has changed) // (only pass on the event if the state has changed)
if (value != j->axisLastValue[axis]) if(value != j->axisLastValue[axis])
{ {
#ifdef GUI_SUPPORT #ifdef GUI_SUPPORT
myHandler.overlay().handleJoyAxisEvent(stick, JoyAxis(axis), convertAxisValue(value), button); myHandler.overlay().handleJoyAxisEvent(stick, JoyAxis(axis), convertAxisValue(value), button);
@ -692,19 +679,19 @@ void PhysicalJoystickHandler::handleBtnEvent(int stick, int button, bool pressed
{ {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
if (j) if(j)
{ {
j->buttonLast[stick] = pressed ? button : JOY_CTRL_NONE; j->buttonLast[stick] = pressed ? button : JOY_CTRL_NONE;
// Handle buttons which switch eventhandler state // Handle buttons which switch eventhandler state
if (pressed && myHandler.changeStateByEvent(j->joyMap.get(EventMode::kEmulationMode, button))) if(pressed && myHandler.changeStateByEvent(j->joyMap.get(EventMode::kEmulationMode, button)))
return; return;
// Determine which mode we're in, then send the event to the appropriate place // Determine which mode we're in, then send the event to the appropriate place
if (myHandler.state() == EventHandlerState::EMULATION) if(myHandler.state() == EventHandlerState::EMULATION)
myHandler.handleEvent(j->joyMap.get(EventMode::kEmulationMode, button), pressed); myHandler.handleEvent(j->joyMap.get(EventMode::kEmulationMode, button), pressed);
#ifdef GUI_SUPPORT #ifdef GUI_SUPPORT
else if (myHandler.hasOverlay()) else if(myHandler.hasOverlay())
myHandler.overlay().handleJoyBtnEvent(stick, button, pressed); myHandler.overlay().handleJoyBtnEvent(stick, button, pressed);
#endif #endif
} }
@ -719,11 +706,11 @@ void PhysicalJoystickHandler::handleHatEvent(int stick, int hat, int value)
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
if (j) if(j)
{ {
const int button = j->buttonLast[stick]; const int button = j->buttonLast[stick];
if (myHandler.state() == EventHandlerState::EMULATION) if(myHandler.state() == EventHandlerState::EMULATION)
{ {
myHandler.handleEvent(j->joyMap.get(EventMode::kEmulationMode, button, hat, JoyHatDir::UP), myHandler.handleEvent(j->joyMap.get(EventMode::kEmulationMode, button, hat, JoyHatDir::UP),
value & EVENT_HATUP_M); value & EVENT_HATUP_M);
@ -735,19 +722,19 @@ void PhysicalJoystickHandler::handleHatEvent(int stick, int hat, int value)
value & EVENT_HATLEFT_M); value & EVENT_HATLEFT_M);
} }
#ifdef GUI_SUPPORT #ifdef GUI_SUPPORT
else if (myHandler.hasOverlay()) else if(myHandler.hasOverlay())
{ {
if (value == EVENT_HATCENTER_M) if(value == EVENT_HATCENTER_M)
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHatDir::CENTER, button); myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHatDir::CENTER, button);
else else
{ {
if (value & EVENT_HATUP_M) if(value & EVENT_HATUP_M)
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHatDir::UP, button); myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHatDir::UP, button);
if (value & EVENT_HATRIGHT_M) if(value & EVENT_HATRIGHT_M)
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHatDir::RIGHT, button); myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHatDir::RIGHT, button);
if (value & EVENT_HATDOWN_M) if(value & EVENT_HATDOWN_M)
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHatDir::DOWN, button); myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHatDir::DOWN, button);
if (value & EVENT_HATLEFT_M) if(value & EVENT_HATLEFT_M)
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHatDir::LEFT, button); myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHatDir::LEFT, button);
} }
} }
@ -827,8 +814,8 @@ PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultRight
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultLeftPaddlesMapping = { PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultLeftPaddlesMapping = {
{Event::PaddleZeroAnalog, JOY_CTRL_NONE, JoyAxis::X, JoyDir::ANALOG}, {Event::PaddleZeroAnalog, JOY_CTRL_NONE, JoyAxis::X, JoyDir::ANALOG},
// Current code does NOT allow digital and anlog events on the same axis at the same time // Current code does NOT allow digital and anlog events on the same axis at the same time
//{Event::PaddleZeroDecrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS}, {Event::PaddleZeroDecrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
//{Event::PaddleZeroIncrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG}, {Event::PaddleZeroIncrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
{Event::PaddleZeroFire, 0}, {Event::PaddleZeroFire, 0},
{Event::PaddleOneAnalog, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::ANALOG}, {Event::PaddleOneAnalog, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::ANALOG},
// Current code does NOT allow digital and anlog events on the same axis at the same // Current code does NOT allow digital and anlog events on the same axis at the same