allow button as modifier for direction and hat

load/save controller mappings
This commit is contained in:
thrust26 2019-06-22 10:37:42 +02:00
parent 8210a25f40
commit bb7bebb79f
21 changed files with 293 additions and 394 deletions

View File

@ -17,12 +17,6 @@
#include "JoyHatMap.hxx" #include "JoyHatMap.hxx"
// TODOs
// - two maps per controller (joydirs, hatdirs)
// - both maps combined with buttons
// - directions can work alone and with a button combination
// - buttons can work without a direction (mapped in joydir)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
JoyHatMap::JoyHatMap(void) JoyHatMap::JoyHatMap(void)
{ {
@ -91,8 +85,6 @@ string JoyHatMap::getDesc(const Event::Type event, const JoyHatMapping & mapping
{ {
ostringstream buf; ostringstream buf;
//buf << "J" << mapping.stick;
// hat description // hat description
if (mapping.hat != JOY_CTRL_NONE) if (mapping.hat != JOY_CTRL_NONE)
{ {
@ -158,7 +150,7 @@ string JoyHatMap::saveMapping(const EventMode mode) const
{ {
if (buf.str() != "") if (buf.str() != "")
buf << "|"; buf << "|";
buf << item.second << ":" /*<< item.first.stick*/ << "," << buf << item.second << ":" << item.first.button << "," <<
item.first.hat << "," << int(item.first.hdir); item.first.hat << "," << int(item.first.hdir);
} }
} }
@ -174,9 +166,9 @@ int JoyHatMap::loadMapping(string & list, const EventMode mode)
std::replace(list.begin(), list.end(), ':', ' '); std::replace(list.begin(), list.end(), ':', ' ');
std::replace(list.begin(), list.end(), ',', ' '); std::replace(list.begin(), list.end(), ',', ' ');
istringstream buf(list); istringstream buf(list);
int event, stick, button, hat, hdir, i = 0; int event, button, hat, hdir, i = 0;
while (buf >> event && buf >> stick && buf >> button && buf >> hat && buf >> hdir && ++i) while (buf >> event && buf >> button && buf >> hat && buf >> hdir && ++i)
add(Event::Type(event), EventMode(mode), button, hat, JoyHat(hdir)); add(Event::Type(event), EventMode(mode), button, hat, JoyHat(hdir));
return i; return i;

View File

@ -17,12 +17,6 @@
#include "JoyMap.hxx" #include "JoyMap.hxx"
// TODOs
// - two maps per controller (joydirs, hatdirs)
// - both maps combined with buttons
// - directions can work alone and with a button combination
// - buttons can work without a direction (mapped in joydir)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
JoyMap::JoyMap(void) JoyMap::JoyMap(void)
{ {
@ -183,9 +177,9 @@ int JoyMap::loadMapping(string& list, const EventMode mode)
std::replace(list.begin(), list.end(), ':', ' '); std::replace(list.begin(), list.end(), ':', ' ');
std::replace(list.begin(), list.end(), ',', ' '); std::replace(list.begin(), list.end(), ',', ' ');
istringstream buf(list); istringstream buf(list);
int event, stick, button, axis, adir, i = 0; int event, button, axis, adir, i = 0;
while (buf >> event && buf >> stick && buf >> button while (buf >> event && buf >> button
&& buf >> axis && buf >> adir && ++i) && buf >> axis && buf >> adir && ++i)
add(Event::Type(event), EventMode(mode), button, JoyAxis(axis), JoyDir(adir)); add(Event::Type(event), EventMode(mode), button, JoyAxis(axis), JoyDir(adir));

View File

@ -27,6 +27,8 @@
#include "DialogContainer.hxx" #include "DialogContainer.hxx"
#endif #endif
static constexpr char CTRL_DELIM = '^';
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalJoystickHandler::PhysicalJoystickHandler( PhysicalJoystickHandler::PhysicalJoystickHandler(
OSystem& system, EventHandler& handler, Event& event) OSystem& system, EventHandler& handler, Event& event)
@ -40,14 +42,14 @@ PhysicalJoystickHandler::PhysicalJoystickHandler(
string joymap, joyname; string joymap, joyname;
// First compare if event list version has changed, and disregard the entire mapping if true // First compare if event list version has changed, and disregard the entire mapping if true
getline(buf, joymap, '^'); // event list size, ignore getline(buf, joymap, CTRL_DELIM); // event list size, ignore
if(version != Event::VERSION) if(version != Event::VERSION)
{ {
// Otherwise, put each joystick mapping entry into the database // Otherwise, put each joystick mapping entry into the database
while(getline(buf, joymap, '^')) while(getline(buf, joymap, CTRL_DELIM))
{ {
istringstream namebuf(joymap); istringstream namebuf(joymap);
getline(namebuf, joyname, '|'); getline(namebuf, joyname, PhysicalJoystick::MODE_DELIM);
if(joyname.length() != 0) if(joyname.length() != 0)
myDatabase.emplace(joyname, StickInfo(joymap)); myDatabase.emplace(joyname, StickInfo(joymap));
} }
@ -205,6 +207,12 @@ void PhysicalJoystickHandler::mapStelladaptors(const string& saport)
for(auto& stick: mySticks) for(auto& stick: mySticks)
{ {
// remove previously added emulated ports
size_t pos = stick.second->name.find(" (emulates ");
if (pos != std::string::npos)
stick.second->name.erase(pos);
if(BSPF::startsWithIgnoreCase(stick.second->name, "Stelladaptor")) if(BSPF::startsWithIgnoreCase(stick.second->name, "Stelladaptor"))
{ {
if(saOrder[saCount] == 1) if(saOrder[saCount] == 1)
@ -254,26 +262,17 @@ void PhysicalJoystickHandler::setStickDefaultMapping(int stick,
auto setDefaultAxis = [&](Event::Type a_event, int stick, JoyAxis axis, JoyDir value, int button = JOY_CTRL_NONE) auto setDefaultAxis = [&](Event::Type a_event, int stick, JoyAxis axis, JoyDir value, int button = JOY_CTRL_NONE)
{ {
if (eraseAll || a_event == event) if (eraseAll || a_event == event)
{
//myHandler.addJoyAxisMapping(a_event, mode, stick, int(axis), int(value), false);
myHandler.addJoyMapping(a_event, mode, stick, button, axis, int(value), false); myHandler.addJoyMapping(a_event, mode, stick, button, axis, int(value), false);
}
}; };
auto setDefaultBtn = [&](Event::Type b_event, int stick, int button) auto setDefaultBtn = [&](Event::Type b_event, int stick, int button)
{ {
if (eraseAll || b_event == event) if (eraseAll || b_event == event)
{
//myHandler.addJoyButtonMapping(b_event, mode, stick, button, false);
myHandler.addJoyMapping(b_event, mode, stick, button, JoyAxis::NONE, int(JoyDir::NONE), false); myHandler.addJoyMapping(b_event, mode, stick, button, JoyAxis::NONE, int(JoyDir::NONE), false);
}
}; };
auto setDefaultHat = [&](Event::Type h_event, int stick, int hat, JoyHat dir, int button = JOY_CTRL_NONE) auto setDefaultHat = [&](Event::Type h_event, int stick, int hat, JoyHat dir, int button = JOY_CTRL_NONE)
{ {
if (eraseAll || h_event == event) if (eraseAll || h_event == event)
{
//myHandler.addJoyHatMapping(h_event, mode, stick, hat, dir, false);
myHandler.addJoyHatMapping(h_event, mode, stick, button, hat, dir, false); myHandler.addJoyHatMapping(h_event, mode, stick, button, hat, dir, false);
}
}; };
switch(mode) switch(mode)
@ -386,14 +385,12 @@ void PhysicalJoystickHandler::saveMapping()
// Save the joystick mapping hash table, making sure to update it with // Save the joystick mapping hash table, making sure to update it with
// any changes that have been made during the program run // any changes that have been made during the program run
ostringstream joybuf; ostringstream joybuf;
//joybuf << Event::LastType;
for(const auto& i: myDatabase) for(const auto& i: myDatabase)
{ {
const string& map = i.second.joy ? i.second.joy->getMap() : i.second.mapping; const string& map = i.second.joy ? i.second.joy->getMap() : i.second.mapping;
if(map != "") if(map != "")
//joybuf << "^" << map; joybuf << CTRL_DELIM << map;
joybuf << map;
} }
myOSystem.settings().setValue("joymap", joybuf.str()); myOSystem.settings().setValue("joymap", joybuf.str());
} }
@ -467,6 +464,8 @@ string PhysicalJoystickHandler::getMappingDesc(Event::Type event, EventMode mode
// new: // new:
//Joystick button + axis mapping / labeling //Joystick button + axis mapping / labeling
if (buf.str() != "")
buf << ", ";
if (j->joyMap.getEventMapping(event, mode).size()) if (j->joyMap.getEventMapping(event, mode).size())
buf << j->joyMap.getEventMappingDesc(stick, event, mode); buf << j->joyMap.getEventMappingDesc(stick, event, mode);
// Joystick hat mapping/labeling // Joystick hat mapping/labeling
@ -564,7 +563,8 @@ bool PhysicalJoystickHandler::addJoyMapping(Event::Type event, EventMode mode, i
if (Event::isAnalog(j->joyMap.get(mode, button, axis, JoyDir::POS))) if (Event::isAnalog(j->joyMap.get(mode, button, axis, JoyDir::POS)))
j->joyMap.erase(mode, button, axis, JoyDir::POS); j->joyMap.erase(mode, button, axis, JoyDir::POS);
j->joyMap.add(event, mode, button, axis, value == int(JoyDir::NONE) ? JoyDir::NONE : value > 0 ? JoyDir::POS : JoyDir::NEG); j->joyMap.add(event, mode, button, axis,
value == int(JoyDir::NONE) ? JoyDir::NONE : value > 0 ? JoyDir::POS : JoyDir::NEG);
} }
return true; return true;
} }
@ -591,104 +591,106 @@ bool PhysicalJoystickHandler::addJoyHatMapping(Event::Type event, EventMode mode
void PhysicalJoystickHandler::handleAxisEvent(int stick, int axis, int value) void PhysicalJoystickHandler::handleAxisEvent(int stick, int axis, int value)
{ {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
if(!j) return;
// Stelladaptors handle axis differently than regular joysticks if (j)
switch(j->type)
{ {
case PhysicalJoystick::JT_REGULAR: int button = j->buttonLast[stick];
if(myHandler.state() == EventHandlerState::EMULATION)
{
// Every axis event has two associated values, negative and positive
//Event::Type eventAxisNeg = j->axisTable[axis][int(JoyDir::NEG)][kEmulationMode];
//Event::Type eventAxisPos = j->axisTable[axis][int(JoyDir::POS)][kEmulationMode];
Event::Type eventAxisNeg = j->joyMap.get(kEmulationMode, j->buttonLast[stick], JoyAxis(axis), JoyDir::NEG);
Event::Type eventAxisPos = j->joyMap.get(kEmulationMode, j->buttonLast[stick], JoyAxis(axis), JoyDir::POS);
// Check for analog events, which are handled differently // Stelladaptors handle axis differently than regular joysticks
// We'll pass them off as Stelladaptor events, and let the controllers switch (j->type)
// handle it {
switch(int(eventAxisNeg)) case PhysicalJoystick::JT_REGULAR:
if (myHandler.state() == EventHandlerState::EMULATION)
{ {
case Event::PaddleZeroAnalog: // Every axis event has two associated values, negative and positive
myEvent.set(Event::SALeftAxis0Value, value); Event::Type eventAxisNeg = j->joyMap.get(kEmulationMode, button, JoyAxis(axis), JoyDir::NEG);
break; Event::Type eventAxisPos = j->joyMap.get(kEmulationMode, button, JoyAxis(axis), JoyDir::POS);
case Event::PaddleOneAnalog:
myEvent.set(Event::SALeftAxis1Value, value);
break;
case Event::PaddleTwoAnalog:
myEvent.set(Event::SARightAxis0Value, value);
break;
case Event::PaddleThreeAnalog:
myEvent.set(Event::SARightAxis1Value, value);
break;
default:
{
// Otherwise, we know the event is digital
if(value > Joystick::deadzone())
myHandler.handleEvent(eventAxisPos);
else if(value < -Joystick::deadzone())
myHandler.handleEvent(eventAxisNeg);
else
{
// Treat any deadzone value as zero
value = 0;
// Now filter out consecutive, similar values // Check for analog events, which are handled differently
// (only pass on the event if the state has changed) // We'll pass them off as Stelladaptor events, and let the controllers
if(j->axisLastValue[axis] != value) // handle it
switch (int(eventAxisNeg))
{
case Event::PaddleZeroAnalog:
myEvent.set(Event::SALeftAxis0Value, value);
break;
case Event::PaddleOneAnalog:
myEvent.set(Event::SALeftAxis1Value, value);
break;
case Event::PaddleTwoAnalog:
myEvent.set(Event::SARightAxis0Value, value);
break;
case Event::PaddleThreeAnalog:
myEvent.set(Event::SARightAxis1Value, value);
break;
default:
{
// Otherwise, we know the event is digital
if (value > Joystick::deadzone())
myHandler.handleEvent(eventAxisPos);
else if (value < -Joystick::deadzone())
myHandler.handleEvent(eventAxisNeg);
else
{ {
// Turn off both events, since we don't know exactly which one // Treat any deadzone value as zero
// was previously activated. value = 0;
myHandler.handleEvent(eventAxisNeg, false);
myHandler.handleEvent(eventAxisPos, false); // Now filter out consecutive, similar values
// (only pass on the event if the state has changed)
if (j->axisLastValue[axis] != value)
{
// Turn off both events, since we don't know exactly which one
// was previously activated.
myHandler.handleEvent(eventAxisNeg, false);
myHandler.handleEvent(eventAxisPos, false);
}
} }
j->axisLastValue[axis] = value;
break;
} }
j->axisLastValue[axis] = value;
break;
} }
} }
} else if (myHandler.hasOverlay())
else if(myHandler.hasOverlay())
{
// First, clamp the values to simulate digital input
// (the only thing that the underlying code understands)
if(value > Joystick::deadzone())
value = 32000;
else if(value < -Joystick::deadzone())
value = -32000;
else
value = 0;
// Now filter out consecutive, similar values
// (only pass on the event if the state has changed)
if(value != j->axisLastValue[axis])
{ {
#ifdef GUI_SUPPORT // First, clamp the values to simulate digital input
myHandler.overlay().handleJoyAxisEvent(stick, axis, value); // (the only thing that the underlying code understands)
#endif if (value > Joystick::deadzone())
j->axisLastValue[axis] = value; value = 32000;
} else if (value < -Joystick::deadzone())
} value = -32000;
break; // Regular joystick axis else
value = 0;
// Since the various controller classes deal with Stelladaptor // Now filter out consecutive, similar values
// devices differently, we send the raw X and Y axis data directly, // (only pass on the event if the state has changed)
// and let the controller handle it if (value != j->axisLastValue[axis])
// These events don't have to pass through handleEvent, since {
// they can never be remapped #ifdef GUI_SUPPORT
case PhysicalJoystick::JT_STELLADAPTOR_LEFT: myHandler.overlay().handleJoyAxisEvent(stick, axis, value, button);
case PhysicalJoystick::JT_2600DAPTOR_LEFT: #endif
if(axis < NUM_JOY_AXIS) j->axisLastValue[axis] = value;
myEvent.set(SA_Axis[int(Controller::Jack::Left)][axis], value); }
break; // axis on left controller (0) }
case PhysicalJoystick::JT_STELLADAPTOR_RIGHT: break; // Regular joystick axis
case PhysicalJoystick::JT_2600DAPTOR_RIGHT:
if(axis < NUM_JOY_AXIS) // Since the various controller classes deal with Stelladaptor
myEvent.set(SA_Axis[int(Controller::Jack::Right)][axis], value); // devices differently, we send the raw X and Y axis data directly,
break; // axis on right controller (1) // and let the controller handle it
default: // These events don't have to pass through handleEvent, since
break; // they can never be remapped
case PhysicalJoystick::JT_STELLADAPTOR_LEFT:
case PhysicalJoystick::JT_2600DAPTOR_LEFT:
if (axis < NUM_JOY_AXIS)
myEvent.set(SA_Axis[int(Controller::Jack::Left)][axis], value);
break; // axis on left controller (0)
case PhysicalJoystick::JT_STELLADAPTOR_RIGHT:
case PhysicalJoystick::JT_2600DAPTOR_RIGHT:
if (axis < NUM_JOY_AXIS)
myEvent.set(SA_Axis[int(Controller::Jack::Right)][axis], value);
break; // axis on right controller (1)
default:
break;
}
} }
} }
@ -696,67 +698,70 @@ void PhysicalJoystickHandler::handleAxisEvent(int stick, int axis, int value)
void PhysicalJoystickHandler::handleBtnEvent(int stick, int button, bool pressed) void PhysicalJoystickHandler::handleBtnEvent(int stick, int button, bool pressed)
{ {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
if(!j) return;
j->buttonLast[stick] = pressed ? button : JOY_CTRL_NONE;
// Stelladaptors handle buttons differently than regular joysticks if (j)
switch(j->type)
{ {
case PhysicalJoystick::JT_REGULAR: j->buttonLast[stick] = pressed ? button : JOY_CTRL_NONE;
// Handle buttons which switch eventhandler state
//if(pressed && myHandler.changeStateByEvent(j->btnTable[button][kEmulationMode]))
if (pressed && myHandler.changeStateByEvent(j->joyMap.get(kEmulationMode, button)))
return;
// Determine which mode we're in, then send the event to the appropriate place // Stelladaptors handle buttons differently than regular joysticks
if(myHandler.state() == EventHandlerState::EMULATION) switch (j->type)
//myHandler.handleEvent(j->btnTable[button][kEmulationMode], pressed); {
myHandler.handleEvent(j->joyMap.get(kEmulationMode, button), pressed); case PhysicalJoystick::JT_REGULAR:
#ifdef GUI_SUPPORT // Handle buttons which switch eventhandler state
else if(myHandler.hasOverlay()) if (pressed && myHandler.changeStateByEvent(j->joyMap.get(kEmulationMode, button)))
myHandler.overlay().handleJoyBtnEvent(stick, button, pressed); return;
#endif
break; // Regular button
// These events don't have to pass through handleEvent, since // Determine which mode we're in, then send the event to the appropriate place
// they can never be remapped if (myHandler.state() == EventHandlerState::EMULATION)
case PhysicalJoystick::JT_STELLADAPTOR_LEFT: myHandler.handleEvent(j->joyMap.get(kEmulationMode, button), pressed);
case PhysicalJoystick::JT_STELLADAPTOR_RIGHT: #ifdef GUI_SUPPORT
// The 'type-2' here refers to the fact that 'PhysicalJoystick::JT_STELLADAPTOR_LEFT' else if (myHandler.hasOverlay())
// and 'PhysicalJoystick::JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType myHandler.overlay().handleJoyBtnEvent(stick, button, pressed);
// enum; subtracting two gives us Controller 0 and 1 #endif
if(button < 2) break; // Regular button
myEvent.set(SA_Button[j->type-PhysicalJoystick::JT_STELLADAPTOR_LEFT][button], pressed ? 1 : 0);
break; // Stelladaptor button // These events don't have to pass through handleEvent, since
case PhysicalJoystick::JT_2600DAPTOR_LEFT: // they can never be remapped
case PhysicalJoystick::JT_2600DAPTOR_RIGHT: case PhysicalJoystick::JT_STELLADAPTOR_LEFT:
// The 'type-4' here refers to the fact that 'PhysicalJoystick::JT_2600DAPTOR_LEFT' case PhysicalJoystick::JT_STELLADAPTOR_RIGHT:
// and 'PhysicalJoystick::JT_2600DAPTOR_RIGHT' are at index 4 and 5 in the JoyType // The 'type-2' here refers to the fact that 'PhysicalJoystick::JT_STELLADAPTOR_LEFT'
// enum; subtracting four gives us Controller 0 and 1 // and 'PhysicalJoystick::JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType
if(myHandler.state() == EventHandlerState::EMULATION) // enum; subtracting two gives us Controller 0 and 1
{ if (button < 2)
switch(myOSystem.console().leftController().type()) myEvent.set(SA_Button[j->type - PhysicalJoystick::JT_STELLADAPTOR_LEFT][button], pressed ? 1 : 0);
break; // Stelladaptor button
case PhysicalJoystick::JT_2600DAPTOR_LEFT:
case PhysicalJoystick::JT_2600DAPTOR_RIGHT:
// The 'type-4' here refers to the fact that 'PhysicalJoystick::JT_2600DAPTOR_LEFT'
// and 'PhysicalJoystick::JT_2600DAPTOR_RIGHT' are at index 4 and 5 in the JoyType
// enum; subtracting four gives us Controller 0 and 1
if (myHandler.state() == EventHandlerState::EMULATION)
{ {
case Controller::Type::Keyboard: switch (myOSystem.console().leftController().type())
if(button < NUM_KEY_BTN) {
myEvent.set(SA_Key[j->type-PhysicalJoystick::JT_2600DAPTOR_LEFT][button], pressed ? 1 : 0); case Controller::Type::Keyboard:
break; if (button < NUM_KEY_BTN)
default: myEvent.set(SA_Key[j->type - PhysicalJoystick::JT_2600DAPTOR_LEFT][button], pressed ? 1 : 0);
if(button < NUM_JOY_BTN) myEvent.set(SA_Button[j->type-PhysicalJoystick::JT_2600DAPTOR_LEFT][button], pressed ? 1 : 0); break;
default:
if (button < NUM_JOY_BTN) myEvent.set(SA_Button[j->type - PhysicalJoystick::JT_2600DAPTOR_LEFT][button], pressed ? 1 : 0);
}
switch (myOSystem.console().rightController().type())
{
case Controller::Type::Keyboard:
if (button < NUM_KEY_BTN)
myEvent.set(SA_Key[j->type - PhysicalJoystick::JT_2600DAPTOR_LEFT][button], pressed ? 1 : 0);
break;
default:
if (button < NUM_JOY_BTN) myEvent.set(SA_Button[j->type - PhysicalJoystick::JT_2600DAPTOR_LEFT][button], pressed ? 1 : 0);
}
} }
switch(myOSystem.console().rightController().type()) break; // 2600DAPTOR button
{
case Controller::Type::Keyboard: default:
if(button < NUM_KEY_BTN) break;
myEvent.set(SA_Key[j->type-PhysicalJoystick::JT_2600DAPTOR_LEFT][button], pressed ? 1 : 0); }
break;
default:
if(button < NUM_JOY_BTN) myEvent.set(SA_Button[j->type-PhysicalJoystick::JT_2600DAPTOR_LEFT][button], pressed ? 1 : 0);
}
}
break; // 2600DAPTOR button
default:
break;
} }
} }
@ -766,38 +771,40 @@ void PhysicalJoystickHandler::handleHatEvent(int stick, int hat, int value)
// Preprocess all hat events, converting to Stella JoyHat type // Preprocess all hat events, converting to Stella JoyHat type
// Generate multiple equivalent hat events representing combined direction // Generate multiple equivalent hat events representing combined direction
// when we get a diagonal hat event // when we get a diagonal hat event
if(myHandler.state() == EventHandlerState::EMULATION)
{
const PhysicalJoystickPtr j = joy(stick);
if(!j) return;
/*myHandler.handleEvent(j->hatTable[hat][int(JoyHat::UP)][kEmulationMode], const PhysicalJoystickPtr j = joy(stick);
value & EVENT_HATUP_M);
myHandler.handleEvent(j->hatTable[hat][int(JoyHat::RIGHT)][kEmulationMode],
value & EVENT_HATRIGHT_M);
myHandler.handleEvent(j->hatTable[hat][int(JoyHat::DOWN)][kEmulationMode],
value & EVENT_HATDOWN_M);
myHandler.handleEvent(j->hatTable[hat][int(JoyHat::LEFT)][kEmulationMode],
value & EVENT_HATLEFT_M);*/
// TODO: 4 different events if (j)
myHandler.handleEvent(j->joyHatMap.get(kEmulationMode, JOY_CTRL_NONE, hat, JoyHat(value)));
}
#ifdef GUI_SUPPORT
else if(myHandler.hasOverlay())
{ {
if(value == EVENT_HATCENTER_M) const int button = j->buttonLast[stick];
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHat::CENTER);
else if (myHandler.state() == EventHandlerState::EMULATION)
{ {
if(value & EVENT_HATUP_M) myHandler.handleEvent(j->joyHatMap.get(kEmulationMode, button, hat, JoyHat::UP),
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHat::UP); value & EVENT_HATUP_M);
if(value & EVENT_HATRIGHT_M) myHandler.handleEvent(j->joyHatMap.get(kEmulationMode, button, hat, JoyHat::RIGHT),
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHat::RIGHT); value & EVENT_HATRIGHT_M);
if(value & EVENT_HATDOWN_M) myHandler.handleEvent(j->joyHatMap.get(kEmulationMode, button, hat, JoyHat::DOWN),
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHat::DOWN); value & EVENT_HATDOWN_M);
if(value & EVENT_HATLEFT_M) myHandler.handleEvent(j->joyHatMap.get(kEmulationMode, button, hat, JoyHat::LEFT),
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHat::LEFT); value & EVENT_HATLEFT_M);
}
#ifdef GUI_SUPPORT
else if (myHandler.hasOverlay())
{
if (value == EVENT_HATCENTER_M)
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHat::CENTER, button);
else
{
if (value & EVENT_HATUP_M)
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHat::UP, button);
if (value & EVENT_HATRIGHT_M)
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHat::RIGHT, button);
if (value & EVENT_HATDOWN_M)
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHat::DOWN, button);
if (value & EVENT_HATLEFT_M)
myHandler.overlay().handleJoyHatEvent(stick, hat, JoyHat::LEFT, button);
}
} }
} }
#endif #endif

View File

@ -41,7 +41,7 @@ using PhysicalJoystickPtr = shared_ptr<PhysicalJoystick>;
Essentially, this class is an extension of the EventHandler class, but Essentially, this class is an extension of the EventHandler class, but
handling only joystick-specific functionality. handling only joystick-specific functionality.
@author Stephen Anthony @author Stephen Anthony, Thomas Jentzsch
*/ */
class PhysicalJoystickHandler class PhysicalJoystickHandler
{ {
@ -74,11 +74,6 @@ class PhysicalJoystickHandler
string getMappingDesc(Event::Type, EventMode mode) const; string getMappingDesc(Event::Type, EventMode mode) const;
/** Bind a physical joystick event to a virtual event/action. */ /** Bind a physical joystick event to a virtual event/action. */
/*bool addAxisMapping(Event::Type event, EventMode mode, int stick, int axis, int value);
bool addBtnMapping(Event::Type event, EventMode mode, int stick, int button);
bool addHatMapping(Event::Type event, EventMode mode, int stick, int hat, JoyHat value);*/
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool addJoyMapping(Event::Type event, EventMode mode, int stick, bool addJoyMapping(Event::Type event, EventMode mode, int stick,
int button, JoyAxis axis, int value); int button, JoyAxis axis, int value);
bool addJoyHatMapping(Event::Type event, EventMode mode, int stick, bool addJoyHatMapping(Event::Type event, EventMode mode, int stick,
@ -89,21 +84,18 @@ class PhysicalJoystickHandler
void handleBtnEvent(int stick, int button, bool pressed); void handleBtnEvent(int stick, int button, bool pressed);
void handleHatEvent(int stick, int hat, int value); void handleHatEvent(int stick, int hat, int value);
Event::Type eventForAxis(int stick, int axis, int joyDir, EventMode mode) const { Event::Type eventForAxis(EventMode mode, int stick, int axis, int value, int button) const {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
//return (j && joyDir != int(JoyDir::NEG)) return j->joyMap.get(mode, button, JoyAxis(axis),
// ? j->axisTable[axis][(joyDir > int(JoyDir::NEG))][mode] : Event::NoType; value == int(JoyDir::NONE) ? JoyDir::NONE : value > 0 ? JoyDir::POS : JoyDir::NEG);
return j->joyMap.get(mode, JOY_CTRL_NONE, JoyAxis(axis), JoyDir(joyDir));
} }
Event::Type eventForButton(int stick, int button, EventMode mode) const { Event::Type eventForButton(EventMode mode, int stick, int button) const {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
// return j ? j->btnTable[button][mode] : Event::NoType;
return j->joyMap.get(mode, button); return j->joyMap.get(mode, button);
} }
Event::Type eventForHat(int stick, int hat, JoyHat hatDir, EventMode mode) const { Event::Type eventForHat(EventMode mode, int stick, int hat, JoyHat hatDir, int button) const {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
//return j ? j->hatTable[hat][int(hatDir)][mode] : Event::NoType; return j->joyHatMap.get(mode, button, hat, hatDir);
return j->joyHatMap.get(mode, JOY_CTRL_NONE, hat, hatDir);
} }
/** Returns a list of pairs consisting of joystick name and associated ID. */ /** Returns a list of pairs consisting of joystick name and associated ID. */

View File

@ -40,7 +40,7 @@ using EventSet = std::set<Event::Type>;
Essentially, this class is an extension of the EventHandler class, but Essentially, this class is an extension of the EventHandler class, but
handling only keyboard-specific functionality. handling only keyboard-specific functionality.
@author Stephen Anthony @author Stephen Anthony, Thomas Jentzsch
*/ */
class PhysicalKeyboardHandler class PhysicalKeyboardHandler
{ {

View File

@ -31,9 +31,6 @@ PhysicalJoystick::PhysicalJoystick()
numAxes(0), numAxes(0),
numButtons(0), numButtons(0),
numHats(0), numHats(0),
/*axisTable(nullptr),
btnTable(nullptr),
hatTable(nullptr),*/
axisLastValue(nullptr), axisLastValue(nullptr),
buttonLast(nullptr) buttonLast(nullptr)
{ {
@ -42,9 +39,6 @@ PhysicalJoystick::PhysicalJoystick()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalJoystick::~PhysicalJoystick() PhysicalJoystick::~PhysicalJoystick()
{ {
/*delete[] axisTable;
delete[] btnTable;
delete[] hatTable;*/
delete[] axisLastValue; delete[] axisLastValue;
delete[] buttonLast; delete[] buttonLast;
} }
@ -61,38 +55,18 @@ void PhysicalJoystick::initialize(int index, const string& desc,
numAxes = axes; numAxes = axes;
numButtons = buttons; numButtons = buttons;
numHats = hats; numHats = hats;
/*if(numAxes)
axisTable = new Event::Type[numAxes][NUM_JOY_DIRS][kNumModes];
if(numButtons)
btnTable = new Event::Type[numButtons][kNumModes];
if(numHats)
hatTable = new Event::Type[numHats][NUM_JOY_HAT_DIRS][kNumModes];*/
axisLastValue = new int[numAxes]; axisLastValue = new int[numAxes];
buttonLast = new int[numButtons]; buttonLast = new int[numButtons];
// Erase the last button
for (int b = 0; b < numButtons; ++b) for (int b = 0; b < numButtons; ++b)
buttonLast[b] = JOY_CTRL_NONE; buttonLast[b] = JOY_CTRL_NONE;
// Erase the joystick axis mapping array and last axis value // Erase the last axis value
for(int a = 0; a < numAxes; ++a) for(int a = 0; a < numAxes; ++a)
{
axisLastValue[a] = 0; axisLastValue[a] = 0;
/*for(int m = 0; m < kNumModes; ++m)
for (int d = 0; d < NUM_JOY_DIRS; ++d)
axisTable[a][d][m] = Event::NoType;*/
}
/*// Erase the joystick button mapping array
for(int b = 0; b < numButtons; ++b)
for(int m = 0; m < kNumModes; ++m)
btnTable[b][m] = Event::NoType;
// Erase the joystick hat mapping array
for(int h = 0; h < numHats; ++h)
for(int m = 0; m < kNumModes; ++m)
for (int d = 0; d < NUM_JOY_HAT_DIRS; ++d)
hatTable[h][d][m] = Event::NoType;*/
// Erase the mappings
for (int m = 0; m < kNumModes; ++m) for (int m = 0; m < kNumModes; ++m)
eraseMap(EventMode(m)); eraseMap(EventMode(m));
} }
@ -101,102 +75,54 @@ void PhysicalJoystick::initialize(int index, const string& desc,
string PhysicalJoystick::getMap() const string PhysicalJoystick::getMap() const
{ {
// The mapping structure (for remappable devices) is defined as follows: // The mapping structure (for remappable devices) is defined as follows:
// NAME | AXIS # + values | BUTTON # + values | HAT # + values, // <NAME>'$'<MODE>['|'(<EVENT>':'<BUTTON>','<AXIS>','<VALUE>)|(<EVENT>':'<BUTTON>','<HAT>','<HATDIR>)]
// where each subsection of values is separated by ':'
if(type == JT_REGULAR) /* if(type == JT_REGULAR)
{ {*/
ostringstream joybuf; ostringstream joybuf;
/*joybuf << name << "|" << numAxes;
for(int m = 0; m < kNumModes; ++m)
for(int a = 0; a < numAxes; ++a)
for (int d = 0; d < NUM_JOY_DIRS; ++d)
joybuf << " " << axisTable[a][d][m];
joybuf << "|" << numButtons;
for(int m = 0; m < kNumModes; ++m)
for(int b = 0; b < numButtons; ++b)
joybuf << " " << btnTable[b][m];
joybuf << "|" << numHats;
for(int m = 0; m < kNumModes; ++m)
for(int h = 0; h < numHats; ++h)
for (int d = 0; d < NUM_JOY_HAT_DIRS; ++d)
joybuf << " " << hatTable[h][d][m];*/
// new: // new:
joybuf << name; joybuf << name;
for (int m = 0; m < kNumModes; ++m) for (int m = 0; m < kNumModes; ++m)
joybuf << "|" << m << "|" << joyMap.saveMapping(EventMode(m)); {
joybuf << MODE_DELIM << m << "|" << joyMap.saveMapping(EventMode(m));
joybuf << MODE_DELIM << m << "|" << joyHatMap.saveMapping(EventMode(m));
}
return joybuf.str(); return joybuf.str();
} /*}
return EmptyString; return EmptyString;*/
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalJoystick::setMap(const string& mapString) bool PhysicalJoystick::setMap(const string& mapString)
{ {
istringstream buf(mapString); istringstream buf(mapString);
StringList items; StringList mappings;
string item; string map;
while(getline(buf, item, '|'))
items.push_back(item);
while (getline(buf, map, MODE_DELIM))
{
// remove leading "<mode>|" string
map.erase(0, 2);
mappings.push_back(map);
}
// Error checking // Error checking
if(items.size() != 4) if(mappings.size() != 1 + kNumModes * 2)
return false; return false;
IntArray map; for (int m = 0; m < kNumModes; ++m)
// Parse axis/button/hat values
/*getValues(items[1], map);
if(int(map.size()) == numAxes * NUM_JOY_DIRS * kNumModes)
{ {
// Fill the axes table with events joyMap.loadMapping(mappings[1 + m * 2], EventMode(m));
auto event = map.cbegin(); joyHatMap.loadMapping(mappings[2 + m * 2], EventMode(m));
for(int m = 0; m < kNumModes; ++m)
for(int a = 0; a < numAxes; ++a)
for (int d = 0; d < NUM_JOY_DIRS; ++d)
axisTable[a][d][m] = Event::Type(*event++);
} }
getValues(items[2], map);
if(int(map.size()) == numButtons * kNumModes)
{
auto event = map.cbegin();
for(int m = 0; m < kNumModes; ++m)
for(int b = 0; b < numButtons; ++b)
btnTable[b][m] = Event::Type(*event++);
}
getValues(items[3], map);
if(int(map.size()) == numHats * NUM_JOY_HAT_DIRS * kNumModes)
{
auto event = map.cbegin();
for(int m = 0; m < kNumModes; ++m)
for(int h = 0; h < numHats; ++h)
for (int d = 0; d < NUM_JOY_HAT_DIRS; ++d)
hatTable[h][d][m] = Event::Type(*event++);
}*/
return true; return true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalJoystick::eraseMap(EventMode mode) void PhysicalJoystick::eraseMap(EventMode mode)
{ {
/*// Erase axis mappings
for(int a = 0; a < numAxes; ++a)
for (int d = 0; d < NUM_JOY_DIRS; ++d)
axisTable[a][d][mode] = Event::NoType;
// Erase button mappings
for(int b = 0; b < numButtons; ++b)
btnTable[b][mode] = Event::NoType;
// Erase hat mappings
for(int h = 0; h < numHats; ++h)
for (int d = 0; d < NUM_JOY_HAT_DIRS; ++d)
hatTable[h][d][mode] = Event::NoType;*/
// Erase button and axis mappings // Erase button and axis mappings
joyMap.eraseMode(mode); joyMap.eraseMode(mode);
// Erase button and axis mappings // Erase button and axis mappings
@ -206,23 +132,6 @@ void PhysicalJoystick::eraseMap(EventMode mode)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalJoystick::eraseEvent(Event::Type event, EventMode mode) void PhysicalJoystick::eraseEvent(Event::Type event, EventMode mode)
{ {
/*// Erase axis mappings
for(int a = 0; a < numAxes; ++a)
for (int d = 0; d < NUM_JOY_DIRS; ++d)
if(axisTable[a][d][mode] == event)
axisTable[a][d][mode] = Event::NoType;
// Erase button mappings
for(int b = 0; b < numButtons; ++b)
if(btnTable[b][mode] == event)
btnTable[b][mode] = Event::NoType;
// Erase hat mappings
for(int h = 0; h < numHats; ++h)
for (int d = 0; d < NUM_JOY_HAT_DIRS; ++d)
if(hatTable[h][d][mode] == event)
hatTable[h][d][mode] = Event::NoType;*/
// Erase button and axis mappings // Erase button and axis mappings
joyMap.eraseEvent(event, mode); joyMap.eraseEvent(event, mode);
// Erase hat mappings // Erase hat mappings
@ -246,7 +155,7 @@ string PhysicalJoystick::about() const
{ {
ostringstream buf; ostringstream buf;
buf << name; buf << name;
if(type == JT_REGULAR) //if(type == JT_REGULAR)
buf << " with: " << numAxes << " axes, " << numButtons << " buttons, " buf << " with: " << numAxes << " axes, " << numButtons << " buttons, "
<< numHats << " hats"; << numHats << " hats";

View File

@ -33,12 +33,17 @@
Specific backend class(es) will inherit from this class, and implement Specific backend class(es) will inherit from this class, and implement
functionality specific to the device. functionality specific to the device.
@author Stephen Anthony @author Stephen Anthony, Thomas Jentzsch
*/ */
class PhysicalJoystick class PhysicalJoystick
{ {
friend class PhysicalJoystickHandler; friend class PhysicalJoystickHandler;
static constexpr char MODE_DELIM = '§'; // must not be '^', '|' or '#'
public: public:
PhysicalJoystick(); PhysicalJoystick();
virtual ~PhysicalJoystick(); virtual ~PhysicalJoystick();
@ -67,9 +72,6 @@ class PhysicalJoystick
int ID; int ID;
string name; string name;
int numAxes, numButtons, numHats; int numAxes, numButtons, numHats;
/*Event::Type (*axisTable)[NUM_JOY_DIRS][kNumModes];
Event::Type (*btnTable)[kNumModes];
Event::Type (*hatTable)[NUM_JOY_HAT_DIRS][kNumModes];*/
int* axisLastValue; int* axisLastValue;
int* buttonLast; int* buttonLast;

View File

@ -47,7 +47,7 @@ class PhysicalJoystick;
unchanged to the menu class, where (among other things) changing key unchanged to the menu class, where (among other things) changing key
mapping can take place. mapping can take place.
@author Stephen Anthony @author Stephen Anthony, Thomas Jentzsch
*/ */
class EventHandler class EventHandler
{ {
@ -162,14 +162,14 @@ class EventHandler
Event::Type eventForKey(EventMode mode, StellaKey key, StellaMod mod) const { Event::Type eventForKey(EventMode mode, StellaKey key, StellaMod mod) const {
return myPKeyHandler->eventForKey(mode, key, mod); return myPKeyHandler->eventForKey(mode, key, mod);
} }
Event::Type eventForJoyAxis(int stick, int axis, int value, EventMode mode) const { Event::Type eventForJoyAxis(EventMode mode, int stick, int axis, int value, int button) const {
return myPJoyHandler->eventForAxis(stick, axis, value, mode); return myPJoyHandler->eventForAxis(mode, stick, axis, value, button);
} }
Event::Type eventForJoyButton(int stick, int button, EventMode mode) const { Event::Type eventForJoyButton(EventMode mode, int stick, int button) const {
return myPJoyHandler->eventForButton(stick, button, mode); return myPJoyHandler->eventForButton(mode, stick, button);
} }
Event::Type eventForJoyHat(int stick, int hat, JoyHat value, EventMode mode) const { Event::Type eventForJoyHat(EventMode mode, int stick, int hat, JoyHat value, int button) const {
return myPJoyHandler->eventForHat(stick, hat, value, mode); return myPJoyHandler->eventForHat(mode, stick, hat, value, button);
} }
/** Get description of given event and mode. */ /** Get description of given event and mode. */

View File

@ -288,20 +288,20 @@ void ContextMenu::handleKeyDown(StellaKey key, StellaMod mod)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::handleJoyDown(int stick, int button) void ContextMenu::handleJoyDown(int stick, int button)
{ {
handleEvent(instance().eventHandler().eventForJoyButton(stick, button, kMenuMode)); handleEvent(instance().eventHandler().eventForJoyButton(kMenuMode, stick, button));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::handleJoyAxis(int stick, int axis, int value) void ContextMenu::handleJoyAxis(int stick, int axis, int value, int button)
{ {
if(value != 0) // we don't care about 'axis up' events if(value != 0) // we don't care about 'axis up' events
handleEvent(instance().eventHandler().eventForJoyAxis(stick, axis, value, kMenuMode)); handleEvent(instance().eventHandler().eventForJoyAxis(kMenuMode, stick, axis, value, button));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool ContextMenu::handleJoyHat(int stick, int hat, JoyHat value) bool ContextMenu::handleJoyHat(int stick, int hat, JoyHat value, int button)
{ {
handleEvent(instance().eventHandler().eventForJoyHat(stick, hat, value, kMenuMode)); handleEvent(instance().eventHandler().eventForJoyHat(kMenuMode, stick, hat, value, button));
return true; return true;
} }

View File

@ -88,8 +88,8 @@ class ContextMenu : public Dialog, public CommandSender
void handleMouseWheel(int x, int y, int direction) override; void handleMouseWheel(int x, int y, int direction) override;
void handleKeyDown(StellaKey key, StellaMod mod) override; void handleKeyDown(StellaKey key, StellaMod mod) override;
void handleJoyDown(int stick, int button) override; void handleJoyDown(int stick, int button) override;
void handleJoyAxis(int stick, int axis, int value) override; void handleJoyAxis(int stick, int axis, int value, int button) override;
bool handleJoyHat(int stick, int hat, JoyHat value) override; bool handleJoyHat(int stick, int hat, JoyHat value, int button) override;
void handleEvent(Event::Type e); void handleEvent(Event::Type e);
void drawDialog() override; void drawDialog() override;

View File

@ -591,7 +591,7 @@ bool Dialog::handleMouseClicks(int x, int y, MouseButton b)
void Dialog::handleJoyDown(int stick, int button) void Dialog::handleJoyDown(int stick, int button)
{ {
Event::Type e = Event::Type e =
instance().eventHandler().eventForJoyButton(stick, button, kMenuMode); instance().eventHandler().eventForJoyButton(kMenuMode, stick, button);
// Unless a widget has claimed all responsibility for data, we assume // Unless a widget has claimed all responsibility for data, we assume
// that if an event exists for the given data, it should have priority. // that if an event exists for the given data, it should have priority.
@ -613,39 +613,39 @@ void Dialog::handleJoyUp(int stick, int button)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type Dialog::getJoyAxisEvent(int stick, int axis, int value) Event::Type Dialog::getJoyAxisEvent(int stick, int axis, int value, int button)
{ {
return instance().eventHandler().eventForJoyAxis(stick, axis, value, kMenuMode); return instance().eventHandler().eventForJoyAxis(kMenuMode, stick, axis, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::handleJoyAxis(int stick, int axis, int value) void Dialog::handleJoyAxis(int stick, int axis, int value, int button)
{ {
Event::Type e = getJoyAxisEvent(stick, axis, value); Event::Type e = getJoyAxisEvent(stick, axis, value, button);
// Unless a widget has claimed all responsibility for data, we assume // Unless a widget has claimed all responsibility for data, we assume
// that if an event exists for the given data, it should have priority. // that if an event exists for the given data, it should have priority.
if(!handleNavEvent(e) && _focusedWidget) if(!handleNavEvent(e) && _focusedWidget)
{ {
if(_focusedWidget->wantsRaw() || e == Event::NoType) if(_focusedWidget->wantsRaw() || e == Event::NoType)
_focusedWidget->handleJoyAxis(stick, axis, value); _focusedWidget->handleJoyAxis(stick, axis, value, button);
else if(value != 0) else if(value != 0)
_focusedWidget->handleEvent(e); _focusedWidget->handleEvent(e);
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Dialog::handleJoyHat(int stick, int hat, JoyHat value) bool Dialog::handleJoyHat(int stick, int hat, JoyHat value, int button)
{ {
Event::Type e = Event::Type e =
instance().eventHandler().eventForJoyHat(stick, hat, value, kMenuMode); instance().eventHandler().eventForJoyHat(kMenuMode, stick, hat, value, button);
// Unless a widget has claimed all responsibility for data, we assume // Unless a widget has claimed all responsibility for data, we assume
// that if an event exists for the given data, it should have priority. // that if an event exists for the given data, it should have priority.
if(!handleNavEvent(e) && _focusedWidget) if(!handleNavEvent(e) && _focusedWidget)
{ {
if(_focusedWidget->wantsRaw() || e == Event::NoType) if(_focusedWidget->wantsRaw() || e == Event::NoType)
return _focusedWidget->handleJoyHat(stick, hat, value); return _focusedWidget->handleJoyHat(stick, hat, value, button);
else else
return _focusedWidget->handleEvent(e); return _focusedWidget->handleEvent(e);
} }

View File

@ -139,10 +139,10 @@ class Dialog : public GuiObject
virtual bool handleMouseClicks(int x, int y, MouseButton b); virtual bool handleMouseClicks(int x, int y, MouseButton b);
virtual void handleJoyDown(int stick, int button); virtual void handleJoyDown(int stick, int button);
virtual void handleJoyUp(int stick, int button); virtual void handleJoyUp(int stick, int button);
virtual void handleJoyAxis(int stick, int axis, int value); virtual void handleJoyAxis(int stick, int axis, int value, int button = JOY_CTRL_NONE);
virtual bool handleJoyHat(int stick, int hat, JoyHat value); virtual bool handleJoyHat(int stick, int hat, JoyHat value, int button = JOY_CTRL_NONE);
virtual void handleCommand(CommandSender* sender, int cmd, int data, int id) override; virtual void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
virtual Event::Type getJoyAxisEvent(int stick, int axis, int value); virtual Event::Type getJoyAxisEvent(int stick, int axis, int value, int button);
Widget* findWidget(int x, int y) const; // Find the widget at pos x,y if any Widget* findWidget(int x, int y) const; // Find the widget at pos x,y if any

View File

@ -299,7 +299,7 @@ void DialogContainer::handleJoyBtnEvent(int stick, int button, bool pressed)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value) void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value, int button)
{ {
if(myDialogStack.empty()) if(myDialogStack.empty())
return; return;
@ -317,11 +317,11 @@ void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value)
myCurrentAxisDown.value = value; myCurrentAxisDown.value = value;
myAxisRepeatTime = myTime + kRepeatInitialDelay; myAxisRepeatTime = myTime + kRepeatInitialDelay;
} }
myDialogStack.top()->handleJoyAxis(stick, axis, value); myDialogStack.top()->handleJoyAxis(stick, axis, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DialogContainer::handleJoyHatEvent(int stick, int hat, JoyHat value) void DialogContainer::handleJoyHatEvent(int stick, int hat, JoyHat value, int button)
{ {
if(myDialogStack.empty()) if(myDialogStack.empty())
return; return;
@ -339,7 +339,7 @@ void DialogContainer::handleJoyHatEvent(int stick, int hat, JoyHat value)
myCurrentHatDown.value = value; myCurrentHatDown.value = value;
myHatRepeatTime = myTime + kRepeatInitialDelay; myHatRepeatTime = myTime + kRepeatInitialDelay;
} }
myDialogStack.top()->handleJoyHat(stick, hat, value); myDialogStack.top()->handleJoyHat(stick, hat, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -108,7 +108,7 @@ class DialogContainer
@param axis The joystick axis @param axis The joystick axis
@param value Value associated with given axis @param value Value associated with given axis
*/ */
void handleJoyAxisEvent(int stick, int axis, int value); void handleJoyAxisEvent(int stick, int axis, int value, int button);
/** /**
Handle a joystick hat event. Handle a joystick hat event.
@ -117,7 +117,7 @@ class DialogContainer
@param hat The joystick hat @param hat The joystick hat
@param value Value associated with given hat @param value Value associated with given hat
*/ */
void handleJoyHatEvent(int stick, int hat, JoyHat value); void handleJoyHatEvent(int stick, int hat, JoyHat value, int button);
/** /**
Draw the stack of menus (full indicates to redraw all items). Draw the stack of menus (full indicates to redraw all items).

View File

@ -152,6 +152,7 @@ void EventMappingWidget::setDefaults()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventMappingWidget::startRemapping() void EventMappingWidget::startRemapping()
{ {
cerr << "startRemapping" << endl;
if(myActionSelected < 0 || myRemapStatus) if(myActionSelected < 0 || myRemapStatus)
return; return;
@ -212,6 +213,7 @@ void EventMappingWidget::stopRemapping()
{ {
// Turn off remap mode // Turn off remap mode
myRemapStatus = false; myRemapStatus = false;
cerr << "stopRemapping " << myRemapStatus << endl;
// Reset all previous events for determining correct axis/hat values // Reset all previous events for determining correct axis/hat values
myLastStick = myLastAxis = myLastHat = myLastValue = -1; myLastStick = myLastAxis = myLastHat = myLastValue = -1;
@ -288,6 +290,7 @@ void EventMappingWidget::handleJoyDown(int stick, int button)
// Remap joystick buttons in remap mode // Remap joystick buttons in remap mode
if(myRemapStatus && myActionSelected >= 0) if(myRemapStatus && myActionSelected >= 0)
{ {
cerr << "remap button start " << myRemapStatus << endl;
myLastStick = stick; myLastStick = stick;
myLastButton = button; myLastButton = button;
} }
@ -305,7 +308,7 @@ void EventMappingWidget::handleJoyUp(int stick, int button)
EventHandler& eh = instance().eventHandler(); EventHandler& eh = instance().eventHandler();
Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode); Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode);
cerr << "remap" << endl; cerr << "remap button stop" << endl;
// This maps solo button presses only // This maps solo button presses only
if (eh.addJoyMapping(event, myEventMode, stick, button)) // new if (eh.addJoyMapping(event, myEventMode, stick, button)) // new
stopRemapping(); stopRemapping();
@ -317,7 +320,7 @@ void EventMappingWidget::handleJoyUp(int stick, int button)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventMappingWidget::handleJoyAxis(int stick, int axis, int value) void EventMappingWidget::handleJoyAxis(int stick, int axis, int value, int button)
{ {
cerr << "handleJoyAxis:" << axis << ", " << value << ", (" << stick << ", " << myLastStick << "), (" << axis << ", " << myLastAxis << ")" << endl; cerr << "handleJoyAxis:" << axis << ", " << value << ", (" << stick << ", " << myLastStick << "), (" << axis << ", " << myLastAxis << ")" << endl;
// Remap joystick axes in remap mode // Remap joystick axes in remap mode
@ -352,7 +355,7 @@ void EventMappingWidget::handleJoyAxis(int stick, int axis, int value)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventMappingWidget::handleJoyHat(int stick, int hat, JoyHat value) bool EventMappingWidget::handleJoyHat(int stick, int hat, JoyHat value, int button)
{ {
// Remap joystick hats in remap mode // Remap joystick hats in remap mode
// There are two phases to detection: // There are two phases to detection:

View File

@ -61,8 +61,8 @@ class EventMappingWidget : public Widget, public CommandSender
bool handleKeyUp(StellaKey key, StellaMod mod) override; bool handleKeyUp(StellaKey key, StellaMod mod) override;
void handleJoyDown(int stick, int button) override; void handleJoyDown(int stick, int button) override;
void handleJoyUp(int stick, int button) override; void handleJoyUp(int stick, int button) override;
void handleJoyAxis(int stick, int axis, int value) override; void handleJoyAxis(int stick, int axis, int value, int button) override;
bool handleJoyHat(int stick, int hat, JoyHat value) override; bool handleJoyHat(int stick, int hat, JoyHat value, int button) override;
void loadConfig() override; void loadConfig() override;
void saveConfig(); void saveConfig();

View File

@ -493,27 +493,27 @@ void InputDialog::handleJoyUp(int stick, int button)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::handleJoyAxis(int stick, int axis, int value) void InputDialog::handleJoyAxis(int stick, int axis, int value, int button)
{ {
// Remap joystick axis in remap mode, otherwise pass to parent dialog // Remap joystick axis in remap mode, otherwise pass to parent dialog
if(myEmulEventMapper->remapMode()) if(myEmulEventMapper->remapMode())
myEmulEventMapper->handleJoyAxis(stick, axis, value); myEmulEventMapper->handleJoyAxis(stick, axis, value, button);
else if(myMenuEventMapper->remapMode()) else if(myMenuEventMapper->remapMode())
myMenuEventMapper->handleJoyAxis(stick, axis, value); myMenuEventMapper->handleJoyAxis(stick, axis, value, button);
else else
Dialog::handleJoyAxis(stick, axis, value); Dialog::handleJoyAxis(stick, axis, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool InputDialog::handleJoyHat(int stick, int hat, JoyHat value) bool InputDialog::handleJoyHat(int stick, int hat, JoyHat value, int button)
{ {
// Remap joystick hat in remap mode, otherwise pass to parent dialog // Remap joystick hat in remap mode, otherwise pass to parent dialog
if(myEmulEventMapper->remapMode()) if(myEmulEventMapper->remapMode())
return myEmulEventMapper->handleJoyHat(stick, hat, value); return myEmulEventMapper->handleJoyHat(stick, hat, value, button);
else if(myMenuEventMapper->remapMode()) else if(myMenuEventMapper->remapMode())
return myMenuEventMapper->handleJoyHat(stick, hat, value); return myMenuEventMapper->handleJoyHat(stick, hat, value, button);
else else
return Dialog::handleJoyHat(stick, hat, value); return Dialog::handleJoyHat(stick, hat, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -47,8 +47,8 @@ class InputDialog : public Dialog
void handleKeyUp(StellaKey key, StellaMod mod) override; void handleKeyUp(StellaKey key, StellaMod mod) override;
void handleJoyDown(int stick, int button) override; void handleJoyDown(int stick, int button) override;
void handleJoyUp(int stick, int button) override; void handleJoyUp(int stick, int button) override;
void handleJoyAxis(int stick, int axis, int value) override; void handleJoyAxis(int stick, int axis, int value, int button) override;
bool handleJoyHat(int stick, int hat, JoyHat value) override; bool handleJoyHat(int stick, int hat, JoyHat value, int button) override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void loadConfig() override; void loadConfig() override;

View File

@ -496,7 +496,7 @@ void LauncherDialog::handleKeyDown(StellaKey key, StellaMod mod)
void LauncherDialog::handleJoyDown(int stick, int button) void LauncherDialog::handleJoyDown(int stick, int button)
{ {
// open power-up options and settings for 2nd and 4th button if not mapped otherwise // open power-up options and settings for 2nd and 4th button if not mapped otherwise
Event::Type e = instance().eventHandler().eventForJoyButton(stick, button, kMenuMode); Event::Type e = instance().eventHandler().eventForJoyButton(kMenuMode, stick, button);
if (button == 1 && (e == Event::UIOK || e == Event::NoType)) if (button == 1 && (e == Event::UIOK || e == Event::NoType))
myGlobalProps->open(); myGlobalProps->open();
@ -507,9 +507,9 @@ void LauncherDialog::handleJoyDown(int stick, int button)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type LauncherDialog::getJoyAxisEvent(int stick, int axis, int value) Event::Type LauncherDialog::getJoyAxisEvent(int stick, int axis, int value, int button)
{ {
Event::Type e = instance().eventHandler().eventForJoyAxis(stick, axis, value, kMenuMode); Event::Type e = instance().eventHandler().eventForJoyAxis(kMenuMode, stick, axis, value, button);
if(myUseMinimalUI) if(myUseMinimalUI)
{ {

View File

@ -90,7 +90,7 @@ class LauncherDialog : public Dialog
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override; void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void handleJoyDown(int stick, int button) override; void handleJoyDown(int stick, int button) override;
Event::Type getJoyAxisEvent(int stick, int axis, int value) override; Event::Type getJoyAxisEvent(int stick, int axis, int value, int button) override;
void loadConfig() override; void loadConfig() override;
void updateListing(const string& nameToSelect = ""); void updateListing(const string& nameToSelect = "");

View File

@ -79,8 +79,8 @@ class Widget : public GuiObject
virtual bool handleMouseClicks(int x, int y, MouseButton b) { return false; } virtual bool handleMouseClicks(int x, int y, MouseButton b) { return false; }
virtual void handleJoyDown(int stick, int button) { } virtual void handleJoyDown(int stick, int button) { }
virtual void handleJoyUp(int stick, int button) { } virtual void handleJoyUp(int stick, int button) { }
virtual void handleJoyAxis(int stick, int axis, int value) { } virtual void handleJoyAxis(int stick, int axis, int value, int button = JOY_CTRL_NONE) { }
virtual bool handleJoyHat(int stick, int hat, JoyHat value) { return false; } virtual bool handleJoyHat(int stick, int hat, JoyHat value, int button = JOY_CTRL_NONE) { return false; }
virtual bool handleEvent(Event::Type event) { return false; } virtual bool handleEvent(Event::Type event) { return false; }
void setDirty() override; void setDirty() override;