added default mapping controller port option (resolves #897)

This commit is contained in:
thrust26 2023-08-02 17:03:57 +02:00
parent 55e3874097
commit f7e46338b8
16 changed files with 237 additions and 57 deletions

View File

@ -30,6 +30,8 @@
* Enhanced Kid Vid support to play tape audio. * Enhanced Kid Vid support to play tape audio.
* Added port selection, used for controller default mapping
* Added missing PlusROM support for E7 bankswitching. * Added missing PlusROM support for E7 bankswitching.
* Acclerated emulation up to ~15% (ARM). * Acclerated emulation up to ~15% (ARM).

View File

@ -4041,7 +4041,7 @@
<tr><td>Allow all 4 directions ...</td><td>Allow all 4 joystick directions to be pressed simultaneously</td><td>-joyallow4</td></tr> <tr><td>Allow all 4 directions ...</td><td>Allow all 4 joystick directions to be pressed simultaneously</td><td>-joyallow4</td></tr>
<tr><td>Use modifier key combos</td><td>Enable using modifier keys in keyboard actions</td><td>-modcombo</td></tr> <tr><td>Use modifier key combos</td><td>Enable using modifier keys in keyboard actions</td><td>-modcombo</td></tr>
<tr><td>Swap Stelladaptor ports</td><td>Swap the order of the detected Stelladaptors/2600-daptors (see <b>Advanced Configuration - <a href="#Adaptor">Stelladaptor/2600-daptor Support</a></b>)</td><td>-saport</td></tr> <tr><td>Swap Stelladaptor ports</td><td>Swap the order of the detected Stelladaptors/2600-daptors (see <b>Advanced Configuration - <a href="#Adaptor">Stelladaptor/2600-daptor Support</a></b>)</td><td>-saport</td></tr>
<tr><td>Controller Database</td><td>Show all controllers that Stella knows about, with the option to remove them</td><td>&nbsp;</td></tr> <tr><td>Controller Database</td><td>Show all controllers that Stella knows about and allow assigning them to a default mapping port and removing them</td><td>&nbsp;</td></tr>
<tr><td>Erase EEPROM</td><td>Erase the whole AtariVox/SaveKey flash memory</td><td>&nbsp;</td></tr> <tr><td>Erase EEPROM</td><td>Erase the whole AtariVox/SaveKey flash memory</td><td>&nbsp;</td></tr>
<tr><td>AtariVox serial port</td><td>Described in further detail in <b>Advanced Configuration - <a href="#AtariVox">AtariVox/SaveKey Support</a></b> </td><td>-avoxport</td></tr> <tr><td>AtariVox serial port</td><td>Described in further detail in <b>Advanced Configuration - <a href="#AtariVox">AtariVox/SaveKey Support</a></b> </td><td>-avoxport</td></tr>
</table> </table>

View File

@ -228,6 +228,17 @@ bool PhysicalJoystickHandler::remove(string_view name)
return false; return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalJoystickHandler::setPort(string_view name, PhysicalJoystick::Port port)
{
const auto it = myDatabase.find(name);
if(it != myDatabase.end() && it->second.joy != nullptr)
{
it->second.joy->setPort(port);
// TODO: update mappings
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalJoystickHandler::mapStelladaptors(string_view saport, int ID) bool PhysicalJoystickHandler::mapStelladaptors(string_view saport, int ID)
{ {
@ -359,35 +370,42 @@ void PhysicalJoystickHandler::setStickDefaultMapping(
if(j) if(j)
{ {
switch (mode) switch(mode)
{ {
case EventMode::kEmulationMode: case EventMode::kEmulationMode:
{ {
// A regular joystick defaults to left or right based on the // A regular joystick defaults to left or right based on
// stick number being even or odd; 'daptor joysticks request a // the defined port or stick number being even or odd;
// specific port // 'daptor' joysticks request a specific port
const bool useLeftMappings = bool useLeftMappings;
j->type == PhysicalJoystick::Type::REGULAR ? ((stick % 2) == 0) : if(j->type == PhysicalJoystick::Type::REGULAR)
(j->type == PhysicalJoystick::Type::LEFT_STELLADAPTOR || {
j->type == PhysicalJoystick::Type::LEFT_2600DAPTOR); useLeftMappings = j->port == PhysicalJoystick::Port::LEFT
|| (j->port == PhysicalJoystick::Port::AUTO && (stick % 2) == 0);
}
else
useLeftMappings =
j->type == PhysicalJoystick::Type::LEFT_STELLADAPTOR ||
j->type == PhysicalJoystick::Type::LEFT_2600DAPTOR;
if(useLeftMappings) if(useLeftMappings)
{ {
// 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)
setDefaultAction(stick, item, event, EventMode::kJoystickMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kJoystickMode, updateDefaults);
for (const auto& item : DefaultLeftKeyboardMapping) for(const auto& item : DefaultLeftKeyboardMapping)
setDefaultAction(stick, item, event, EventMode::kKeyboardMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kKeyboardMode, updateDefaults);
for (const auto& item : DefaultLeftDrivingMapping) for(const auto& item : DefaultLeftDrivingMapping)
setDefaultAction(stick, item, event, EventMode::kDrivingMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kDrivingMode, updateDefaults);
} }
else else
{ {
// put all controller events into their own mode's mappings // put all controller events into their own mode's mappings
for (const auto& item : DefaultRightJoystickMapping) for(const auto& item : DefaultRightJoystickMapping)
setDefaultAction(stick, item, event, EventMode::kJoystickMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kJoystickMode, updateDefaults);
for (const auto& item : DefaultRightKeyboardMapping) for(const auto& item : DefaultRightKeyboardMapping)
setDefaultAction(stick, item, event, EventMode::kKeyboardMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kKeyboardMode, updateDefaults);
for (const auto& item : DefaultRightDrivingMapping) for(const auto& item : DefaultRightDrivingMapping)
setDefaultAction(stick, item, event, EventMode::kDrivingMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kDrivingMode, updateDefaults);
} }
@ -404,16 +422,16 @@ void PhysicalJoystickHandler::setStickDefaultMapping(
// and 2600-daptors support two players natively. // and 2600-daptors support two players natively.
const int paddlesPerJoystick = (j->type == PhysicalJoystick::Type::REGULAR && !retron77) ? 1 : 2; const int paddlesPerJoystick = (j->type == PhysicalJoystick::Type::REGULAR && !retron77) ? 1 : 2;
if( paddlesPerJoystick == 2 ) if(paddlesPerJoystick == 2)
{ {
if( useLeftMappings ) if(useLeftMappings)
{ {
for (const auto& item : DefaultLeftPaddlesMapping) for(const auto& item : DefaultLeftPaddlesMapping)
setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults);
} }
else else
{ {
for (const auto& item : DefaultRightPaddlesMapping) for(const auto& item : DefaultRightPaddlesMapping)
setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults);
} }
} }
@ -430,29 +448,29 @@ void PhysicalJoystickHandler::setStickDefaultMapping(
const bool useLeftPaddleMappings = (stick % 4) < 2; const bool useLeftPaddleMappings = (stick % 4) < 2;
const bool useAPaddleMappings = (stick % 2) == 0; const bool useAPaddleMappings = (stick % 2) == 0;
if( useLeftPaddleMappings ) if(useLeftPaddleMappings)
{ {
if( useAPaddleMappings ) if(useAPaddleMappings)
{ {
for (const auto& item : DefaultLeftAPaddlesMapping) for(const auto& item : DefaultLeftAPaddlesMapping)
setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults);
} }
else else
{ {
for (const auto& item : DefaultLeftBPaddlesMapping) for(const auto& item : DefaultLeftBPaddlesMapping)
setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults);
} }
} }
else else
{ {
if( useAPaddleMappings ) if(useAPaddleMappings)
{ {
for (const auto& item : DefaultRightAPaddlesMapping) for(const auto& item : DefaultRightAPaddlesMapping)
setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults);
} }
else else
{ {
for (const auto& item : DefaultRightBPaddlesMapping) for(const auto& item : DefaultRightBPaddlesMapping)
setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults);
} }
} }
@ -466,7 +484,7 @@ void PhysicalJoystickHandler::setStickDefaultMapping(
} }
case EventMode::kMenuMode: case EventMode::kMenuMode:
for (const auto& item : DefaultMenuMapping) for(const auto& item : DefaultMenuMapping)
setDefaultAction(stick, item, event, EventMode::kMenuMode, updateDefaults); setDefaultAction(stick, item, event, EventMode::kMenuMode, updateDefaults);
break; break;
@ -1071,13 +1089,19 @@ void PhysicalJoystickHandler::handleHatEvent(int stick, int hat, int value)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VariantList PhysicalJoystickHandler::database() const PhysicalJoystickHandler::MinStrickInfoList PhysicalJoystickHandler::minStickList() const
{ {
VariantList db; MinStrickInfoList list;
for(const auto& [_name, _info]: myDatabase)
VarList::push_back(db, _name, _info.joy ? _info.joy->ID : -1);
return db; for(const auto& [_name, _info] : myDatabase)
{
MinStrickInfo stick(_name,
_info.joy ? _info.joy->ID : -1,
_info.joy ? _info.joy->port : PhysicalJoystick::Port::AUTO);
list.push_back(stick);
}
return list;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -46,6 +46,18 @@ using PhysicalJoystickPtr = shared_ptr<PhysicalJoystick>;
*/ */
class PhysicalJoystickHandler class PhysicalJoystickHandler
{ {
public:
struct MinStrickInfo
{
string name;
int ID;
PhysicalJoystick::Port port;
explicit MinStrickInfo(string _name, int _id, PhysicalJoystick::Port _port)
: name{_name}, ID{_id}, port{_port} {}
};
using MinStrickInfoList = std::vector<MinStrickInfo>;
private: private:
struct StickInfo struct StickInfo
{ {
@ -74,6 +86,7 @@ class PhysicalJoystickHandler
int add(const PhysicalJoystickPtr& stick); int add(const PhysicalJoystickPtr& stick);
bool remove(int id); bool remove(int id);
bool remove(string_view name); bool remove(string_view name);
void setPort(string_view name, PhysicalJoystick::Port port);
bool mapStelladaptors(string_view saport, int ID = -1); bool mapStelladaptors(string_view saport, int ID = -1);
bool hasStelladaptors() const; bool hasStelladaptors() const;
void setDefaultMapping(Event::Type event, EventMode mode); void setDefaultMapping(Event::Type event, EventMode mode);
@ -112,8 +125,8 @@ class PhysicalJoystickHandler
return j->joyMap.get(mode, button, hat, hatDir); return j->joyMap.get(mode, button, hat, hatDir);
} }
/** Returns a list of pairs consisting of joystick name and associated ID. */ /** Returns a list containing minimal controller info (name, ID, port). */
VariantList database() const; MinStrickInfoList minStickList() const;
void changeDigitalDeadZone(int direction = +1); void changeDigitalDeadZone(int direction = +1);
void changeAnalogPaddleDeadZone(int direction = +1); void changeAnalogPaddleDeadZone(int direction = +1);

View File

@ -221,7 +221,7 @@ void PhysicalKeyboardHandler::defineControllerMappings(
const Controller::Type type, Controller::Jack port, const Properties& properties) const Controller::Type type, Controller::Jack port, const Properties& properties)
{ {
// Determine controller events to use // Determine controller events to use
if(type == Controller::Type::QuadTari) if(type == Controller::Type::QuadTari)
{ {
if(port == Controller::Jack::Left) if(port == Controller::Jack::Left)
{ {
@ -233,7 +233,7 @@ void PhysicalKeyboardHandler::defineControllerMappings(
myRightMode = getMode(properties, PropType::Controller_Right1); myRightMode = getMode(properties, PropType::Controller_Right1);
myRight2ndMode = getMode(properties, PropType::Controller_Right2); myRight2ndMode = getMode(properties, PropType::Controller_Right2);
} }
} }
else else
{ {
const EventMode mode = getMode(type); const EventMode mode = getMode(type);
@ -459,7 +459,7 @@ bool PhysicalKeyboardHandler::isDrivingEvent(const Event::Type event)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalKeyboardHandler::isCommonEvent(const Event::Type event) bool PhysicalKeyboardHandler::isCommonEvent(const Event::Type event)
{ {
return !(isJoystickEvent(event) || isPaddleEvent(event) return !(isJoystickEvent(event) || isPaddleEvent(event)
|| isKeyboardEvent(event) || isDrivingEvent(event)); || isKeyboardEvent(event) || isDrivingEvent(event));
} }

View File

@ -69,6 +69,7 @@ json PhysicalJoystick::getMap() const
json mapping = json::object(); json mapping = json::object();
mapping["name"] = name; mapping["name"] = name;
mapping["port"] = getName(port);
for (const auto& mode: { for (const auto& mode: {
EventMode::kMenuMode, EventMode::kJoystickMode, EventMode::kPaddlesMode, EventMode::kKeyboardMode, EventMode::kDrivingMode, EventMode::kCommonMode EventMode::kMenuMode, EventMode::kJoystickMode, EventMode::kPaddlesMode, EventMode::kKeyboardMode, EventMode::kDrivingMode, EventMode::kCommonMode
@ -84,14 +85,19 @@ bool PhysicalJoystick::setMap(const json& map)
int i = 0; int i = 0;
for (const auto& entry: map.items()) { for (const auto& entry: map.items()) {
if (entry.key() == "name") continue; if (entry.key() == "name")
continue;
if(entry.key() == "port")
{
port = getPort(entry.value());
continue;
}
try { try {
joyMap.loadMapping(entry.value(), eventModeFromJsonName(entry.key())); joyMap.loadMapping(entry.value(), eventModeFromJsonName(entry.key()));
} catch (const json::exception&) { } catch (const json::exception&) {
Logger::error("ignoring invalid json mapping for " + entry.key()); Logger::error("ignoring invalid json mapping for " + entry.key());
} }
i++; i++;
} }
@ -107,6 +113,34 @@ bool PhysicalJoystick::setMap(const json& map)
return true; return true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string PhysicalJoystick::getName(const PhysicalJoystick::Port _port) const
{
static constexpr std::array<string_view,
static_cast<int>(PhysicalJoystick::Port::NUM_PORTS)> NAMES =
{
"Auto", "Left", "Right"
};
return string{NAMES[static_cast<int>(_port)]};
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalJoystick::Port PhysicalJoystick::getPort(string_view portName) const
{
static constexpr std::array<string_view,
static_cast<int>(PhysicalJoystick::Port::NUM_PORTS)> NAMES =
{
"Auto", "Left", "Right"
};
for(int i = 0; i < static_cast<int>(PhysicalJoystick::Port::NUM_PORTS); ++i)
if (BSPF::equalsIgnoreCase(portName, NAMES[i]))
return PhysicalJoystick::Port{i};
return PhysicalJoystick::Port::AUTO;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
json PhysicalJoystick::convertLegacyMapping(string_view mapping, string_view name) json PhysicalJoystick::convertLegacyMapping(string_view mapping, string_view name)
{ {
@ -167,7 +201,22 @@ void PhysicalJoystick::getValues(string_view list, IntArray& map)
string PhysicalJoystick::about() const string PhysicalJoystick::about() const
{ {
ostringstream buf; ostringstream buf;
buf << "'" << name << "' with: " << numAxes << " axes, " << numButtons << " buttons, "
buf << "'" << name << "' in ";
switch(port)
{
case Port::LEFT:
buf << "left";
break;
case Port::RIGHT:
buf << "right";
break;
default:
buf << "auto";
break;
}
buf << " port with: "
<< numAxes << " axes, " << numButtons << " buttons, "
<< numHats << " hats"; << numHats << " hats";
return buf.str(); return buf.str();

View File

@ -43,10 +43,18 @@ class PhysicalJoystick
static constexpr char MODE_DELIM = '>'; // must not be '^', '|' or '#' static constexpr char MODE_DELIM = '>'; // must not be '^', '|' or '#'
public: public:
enum class Port {
AUTO,
LEFT,
RIGHT,
NUM_PORTS
};
PhysicalJoystick() = default; PhysicalJoystick() = default;
nlohmann::json getMap() const; nlohmann::json getMap() const;
bool setMap(const nlohmann::json& map); bool setMap(const nlohmann::json& map);
void setPort(const Port _port) { port = _port; }
static nlohmann::json convertLegacyMapping(string_view mapping, static nlohmann::json convertLegacyMapping(string_view mapping,
string_view name); string_view name);
@ -69,6 +77,7 @@ class PhysicalJoystick
Type type{Type::REGULAR}; Type type{Type::REGULAR};
int ID{-1}; int ID{-1};
string name{"None"}; string name{"None"};
Port port{Port::AUTO};
int numAxes{0}, numButtons{0}, numHats{0}; int numAxes{0}, numButtons{0}, numHats{0};
IntArray axisLastValue; IntArray axisLastValue;
IntArray buttonLast; IntArray buttonLast;
@ -79,6 +88,10 @@ class PhysicalJoystick
private: private:
static void getValues(string_view list, IntArray& map); static void getValues(string_view list, IntArray& map);
// Convert from string to Port type and vice versa
string getName(const Port _port) const;
Port getPort(string_view portName) const;
friend ostream& operator<<(ostream& os, const PhysicalJoystick& s) { friend ostream& operator<<(ostream& os, const PhysicalJoystick& s) {
os << " ID: " << s.ID << ", name: " << s.name << ", numaxis: " << s.numAxes os << " ID: " << s.ID << ", name: " << s.name << ", numaxis: " << s.numAxes
<< ", numbtns: " << s.numButtons << ", numhats: " << s.numHats; << ", numbtns: " << s.numButtons << ", numhats: " << s.numHats;

View File

@ -84,7 +84,7 @@ class Event
UIUp, UIDown, UILeft, UIRight, UIHome, UIEnd, UIPgUp, UIPgDown, UIUp, UIDown, UILeft, UIRight, UIHome, UIEnd, UIPgUp, UIPgDown,
UISelect, UINavPrev, UINavNext, UIOK, UICancel, UIPrevDir, UISelect, UINavPrev, UINavNext, UIOK, UICancel, UIPrevDir,
UITabPrev, UITabNext, UITabPrev, UITabNext, UIReload,
NextMouseControl, ToggleGrabMouse, NextMouseControl, ToggleGrabMouse,
MouseAxisXMove, MouseAxisYMove, MouseAxisXValue, MouseAxisYValue, MouseAxisXMove, MouseAxisYMove, MouseAxisXValue, MouseAxisYValue,

View File

@ -169,6 +169,9 @@ void EventHandler::addPhysicalJoystick(const PhysicalJoystickPtr& joy)
setActionMappings(EventMode::kEmulationMode); setActionMappings(EventMode::kEmulationMode);
setActionMappings(EventMode::kMenuMode); setActionMappings(EventMode::kMenuMode);
if(myOverlay)
myOverlay->handleEvent(Event::UIReload);
#endif #endif
} }
@ -177,6 +180,9 @@ void EventHandler::removePhysicalJoystick(int id)
{ {
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
myPJoyHandler->remove(id); myPJoyHandler->remove(id);
if(myOverlay)
myOverlay->handleEvent(Event::UIReload);
#endif #endif
} }
@ -2078,6 +2084,15 @@ void EventHandler::removePhysicalJoystickFromDatabase(string_view name)
#endif #endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setPhysicalJoystickPortInDatabase(string_view name,
PhysicalJoystick::Port port)
{
#ifdef JOYSTICK_SUPPORT
myPJoyHandler->setPort(name, port);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::addKeyMapping(Event::Type event, EventMode mode, StellaKey key, StellaMod mod) bool EventHandler::addKeyMapping(Event::Type event, EventMode mode, StellaKey key, StellaMod mod)
{ {

View File

@ -333,11 +333,10 @@ class EventHandler
bool hasOverlay() const { return myOverlay != nullptr; } bool hasOverlay() const { return myOverlay != nullptr; }
/** /**
Return a list of all physical joysticks currently in the internal database Return a simple list of all physical joysticks currently in the internal database
(first part of variant) and its internal ID (second part of variant).
*/ */
VariantList physicalJoystickDatabase() const { PhysicalJoystickHandler::MinStrickInfoList physicalJoystickList() const {
return myPJoyHandler->database(); return myPJoyHandler->minStickList();
} }
/** /**
@ -346,6 +345,12 @@ class EventHandler
*/ */
void removePhysicalJoystickFromDatabase(string_view name); void removePhysicalJoystickFromDatabase(string_view name);
/**
Change the port of the physical joystick identified by 'name' in
the joystick database, only if it is not currently active.
*/
void setPhysicalJoystickPortInDatabase(string_view name, PhysicalJoystick::Port port);
/** /**
Enable/disable text events (distinct from single-key events). Enable/disable text events (distinct from single-key events).
*/ */

View File

@ -168,6 +168,7 @@ class Dialog : public GuiObject
virtual void handleJoyUp(int stick, int button); virtual void handleJoyUp(int stick, int button);
virtual void handleJoyAxis(int stick, JoyAxis axis, JoyDir adir, int button = JOY_CTRL_NONE); virtual void handleJoyAxis(int stick, JoyAxis axis, JoyDir adir, int button = JOY_CTRL_NONE);
virtual bool handleJoyHat(int stick, int hat, JoyHatDir hdir, int button = JOY_CTRL_NONE); virtual bool handleJoyHat(int stick, int hat, JoyHatDir hdir, int button = JOY_CTRL_NONE);
virtual void handleEvent(Event::Type event) {};
void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
virtual Event::Type getJoyAxisEvent(int stick, JoyAxis axis, JoyDir adir, int button); virtual Event::Type getJoyAxisEvent(int stick, JoyAxis axis, JoyDir adir, int button);

View File

@ -425,6 +425,18 @@ void DialogContainer::handleJoyHatEvent(int stick, int hat, JoyHatDir hdir, int
activeDialog->handleJoyHat(stick, hat, hdir, button); activeDialog->handleJoyHat(stick, hat, hdir, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DialogContainer::handleEvent(Event::Type event)
{
if(myDialogStack.empty())
return;
// Send the event to the dialog box on the top of the stack
Dialog* activeDialog = myDialogStack.top();
activeDialog->handleEvent(event);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DialogContainer::reset() void DialogContainer::reset()
{ {

View File

@ -23,6 +23,7 @@ class OSystem;
class EventHandler; class EventHandler;
#include "EventHandlerConstants.hxx" #include "EventHandlerConstants.hxx"
#include "Event.hxx"
#include "StellaKeys.hxx" #include "StellaKeys.hxx"
#include "Stack.hxx" #include "Stack.hxx"
#include "bspf.hxx" #include "bspf.hxx"
@ -119,6 +120,13 @@ class DialogContainer
*/ */
void handleJoyHatEvent(int stick, int hat, JoyHatDir hdir, int button); void handleJoyHatEvent(int stick, int hat, JoyHatDir hdir, int button);
/**
Handle an arbitray dialog event.
@param event The send event
*/
void handleEvent(Event::Type event);
/** /**
Tick the dialog and all its widgets. Tick the dialog and all its widgets.
*/ */

View File

@ -20,6 +20,7 @@
#include "Widget.hxx" #include "Widget.hxx"
#include "Font.hxx" #include "Font.hxx"
#include "EditTextWidget.hxx" #include "EditTextWidget.hxx"
#include "PopUpWidget.hxx"
#include "StringListWidget.hxx" #include "StringListWidget.hxx"
#include "Variant.hxx" #include "Variant.hxx"
#include "JoystickDialog.hxx" #include "JoystickDialog.hxx"
@ -47,12 +48,23 @@ JoystickDialog::JoystickDialog(GuiObject* boss, const GUI::Font& font,
// Joystick ID // Joystick ID
ypos = _h - VBORDER - (buttonHeight + lineHeight) / 2; ypos = _h - VBORDER - (buttonHeight + lineHeight) / 2;
auto* t = new StaticTextWidget(this, font, xpos, ypos+2, "Controller ID "); auto* t = new StaticTextWidget(this, font, xpos, ypos, "Controller ID ");
xpos += t->getWidth(); xpos += t->getWidth();
myJoyText = new EditTextWidget(this, font, xpos, ypos, myJoyText = new EditTextWidget(this, font, xpos, ypos - 2,
font.getStringWidth("Unplugged "), font.getLineHeight(), ""); font.getStringWidth("Unplugged "), lineHeight, "");
myJoyText->setEditable(false); myJoyText->setEditable(false);
// Port
VariantList ports;
VarList::push_back(ports, "Auto", static_cast<Int32>(PhysicalJoystick::Port::AUTO));
VarList::push_back(ports, "Left", static_cast<Int32>(PhysicalJoystick::Port::LEFT));
VarList::push_back(ports, "Right", static_cast<Int32>(PhysicalJoystick::Port::RIGHT));
myJoyPort = new PopUpWidget(this, font, myJoyText->getRight() + fontWidth * 2, ypos - 1,
font.getStringWidth("Right"), lineHeight, ports, "Port ", 0, kPortCmd);
myJoyPort->setToolTip("Define default mapping port.");
wid.push_back(myJoyPort);
// Add buttons at bottom // Add buttons at bottom
xpos = _w - buttonWidth - HBORDER; xpos = _w - buttonWidth - HBORDER;
ypos = _h - VBORDER - buttonHeight; ypos = _h - VBORDER - buttonHeight;
@ -77,10 +89,11 @@ void JoystickDialog::loadConfig()
myJoyIDs.clear(); myJoyIDs.clear();
StringList sticks; StringList sticks;
for(const auto& [_name, _id]: instance().eventHandler().physicalJoystickDatabase()) for(const auto& _entry : instance().eventHandler().physicalJoystickList())
{ {
sticks.push_back(_name); sticks.push_back(_entry.name);
myJoyIDs.push_back(_id.toInt()); myJoyIDs.push_back(_entry.ID);
myJoyPorts.push_back(static_cast<int>(_entry.port));
} }
myJoyList->setList(sticks); myJoyList->setList(sticks);
myJoyList->setSelected(0); myJoyList->setSelected(0);
@ -91,6 +104,13 @@ void JoystickDialog::loadConfig()
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoystickDialog::handleEvent(Event::Type event)
{
if(event == Event::Type::UIReload)
loadConfig();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoystickDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) void JoystickDialog::handleCommand(CommandSender* sender, int cmd, int data, int id)
{ {
@ -100,6 +120,13 @@ void JoystickDialog::handleCommand(CommandSender* sender, int cmd, int data, int
close(); close();
break; break;
case kPortCmd:
myJoyPorts[myJoyList->getSelected()] = myJoyPort->getSelected();
instance().eventHandler().setPhysicalJoystickPortInDatabase(
myJoyList->getSelectedString(),
static_cast<PhysicalJoystick::Port>(myJoyPort->getSelected()));
break;
case kRemoveCmd: case kRemoveCmd:
instance().eventHandler().removePhysicalJoystickFromDatabase( instance().eventHandler().removePhysicalJoystickFromDatabase(
myJoyList->getSelectedString()); myJoyList->getSelectedString());
@ -107,20 +134,24 @@ void JoystickDialog::handleCommand(CommandSender* sender, int cmd, int data, int
break; break;
case ListWidget::kSelectionChangedCmd: case ListWidget::kSelectionChangedCmd:
if(myJoyIDs[data] >= 0) {
const bool isPlugged = myJoyIDs[data] >= 0;
if(isPlugged)
{ {
myRemoveBtn->setEnabled(false);
ostringstream buf; ostringstream buf;
buf << "C" << myJoyIDs[data]; buf << "C" << myJoyIDs[data];
myJoyText->setText(buf.str()); myJoyText->setText(buf.str());
myJoyPort->setSelected(myJoyPorts[data]);
} }
else else
{ {
myRemoveBtn->setEnabled(true);
myJoyText->setText("Unplugged"); myJoyText->setText("Unplugged");
myJoyPort->setText("");
} }
myJoyPort->setEnabled(isPlugged);
myRemoveBtn->setEnabled(!isPlugged);
break; break;
}
default: default:
Dialog::handleCommand(sender, cmd, data, id); Dialog::handleCommand(sender, cmd, data, id);
break; break;

View File

@ -22,6 +22,7 @@ class CommandSender;
class GuiObject; class GuiObject;
class ButtonWidget; class ButtonWidget;
class EditTextWidgetWidget; class EditTextWidgetWidget;
class PopUpWidget;
class StringListWidget; class StringListWidget;
#include "Dialog.hxx" #include "Dialog.hxx"
@ -43,17 +44,23 @@ class JoystickDialog : public Dialog
private: private:
void loadConfig() override; void loadConfig() override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void handleEvent(Event::Type event) override;
private: private:
StringListWidget* myJoyList{nullptr}; StringListWidget* myJoyList{nullptr};
EditTextWidget* myJoyText{nullptr}; EditTextWidget* myJoyText{nullptr};
PopUpWidget* myJoyPort{nullptr};
ButtonWidget* myRemoveBtn{nullptr}; ButtonWidget* myRemoveBtn{nullptr};
ButtonWidget* myCloseBtn{nullptr}; ButtonWidget* myCloseBtn{nullptr};
IntArray myJoyIDs; IntArray myJoyIDs;
IntArray myJoyPorts;
enum { kRemoveCmd = 'JDrm' }; enum {
kRemoveCmd = 'JDrm',
kPortCmd = 'JDpt'
};
private: private:
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported

View File

@ -646,7 +646,7 @@
<DataExecutionPrevention> <DataExecutionPrevention>
</DataExecutionPrevention> </DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine> <TargetMachine>MachineX64</TargetMachine>
<LinkTimeCodeGeneration>PGUpdate</LinkTimeCodeGeneration> <LinkTimeCodeGeneration>PGOptimization</LinkTimeCodeGeneration>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-Sanitize|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-Sanitize|x64'">