Merge remote-tracking branch 'remotes/origin/feature/controller-mapping'

This commit is contained in:
Thomas Jentzsch 2019-08-05 10:01:43 +02:00
commit 36cc239066
36 changed files with 1286 additions and 756 deletions

248
src/common/JoyMap.cxx Normal file
View File

@ -0,0 +1,248 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "JoyMap.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
JoyMap::JoyMap(void)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::add(const Event::Type event, const JoyMapping& mapping)
{
myMap[mapping] = event;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::add(const Event::Type event, const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir,
const int hat, const JoyHat hdir)
{
add(event, JoyMapping(mode, button, axis, adir, hat, hdir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::add(const Event::Type event, const EventMode mode, const int button,
const int hat, const JoyHat hdir)
{
add(event, JoyMapping(mode, button, hat, hdir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::erase(const JoyMapping& mapping)
{
myMap.erase(mapping);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::erase(const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir)
{
erase(JoyMapping(mode, button, axis, adir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::erase(const EventMode mode, const int button,
const int hat, const JoyHat hdir)
{
erase(JoyMapping(mode, button, hat, hdir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type JoyMap::get(const JoyMapping& mapping) const
{
auto find = myMap.find(mapping);
if (find != myMap.end())
return find->second;
// try without button as modifier
JoyMapping m = mapping;
m.button = JOY_CTRL_NONE;
find = myMap.find(m);
if (find != myMap.end())
return find->second;
return Event::Type::NoType;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type JoyMap::get(const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir) const
{
return get(JoyMapping(mode, button, axis, adir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type JoyMap::get(const EventMode mode, const int button,
const int hat, const JoyHat hdir) const
{
return get(JoyMapping(mode, button, hat, hdir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool JoyMap::check(const JoyMapping & mapping) const
{
auto find = myMap.find(mapping);
return (find != myMap.end());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool JoyMap::check(const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir,
const int hat, const JoyHat hdir) const
{
return check(JoyMapping(mode, button, axis, adir, hat, hdir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string JoyMap::getDesc(const Event::Type event, const JoyMapping& mapping) const
{
ostringstream buf;
// button description
if (mapping.button != JOY_CTRL_NONE)
buf << "/B" << mapping.button;
// axis description
if (mapping.axis != JoyAxis::NONE)
{
buf << "/A";
switch (mapping.axis)
{
case JoyAxis::X: buf << "X"; break;
case JoyAxis::Y: buf << "Y"; break;
case JoyAxis::Z: buf << "Z"; break;
default: buf << int(mapping.axis); break;
}
if (Event::isAnalog(event))
buf << "+|-";
else if (mapping.adir == JoyDir::NEG)
buf << "-";
else
buf << "+";
}
// hat description
if (mapping.hat != JOY_CTRL_NONE)
{
buf << "/H" << mapping.hat;
switch (mapping.hdir)
{
case JoyHat::UP: buf << "/up"; break;
case JoyHat::DOWN: buf << "/down"; break;
case JoyHat::LEFT: buf << "/left"; break;
case JoyHat::RIGHT: buf << "/right"; break;
default: break;
}
}
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string JoyMap::getEventMappingDesc(int stick, const Event::Type event, const EventMode mode) const
{
ostringstream buf;
for (auto item : myMap)
{
if (item.second == event && item.first.mode == mode)
{
if (buf.str() != "")
buf << ", ";
buf << "J" << stick << getDesc(event, item.first);
}
}
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
JoyMap::JoyMappingArray JoyMap::getEventMapping(const Event::Type event, const EventMode mode) const
{
JoyMappingArray map;
for (auto item : myMap)
if (item.second == event && item.first.mode == mode)
map.push_back(item.first);
return map;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string JoyMap::saveMapping(const EventMode mode) const
{
ostringstream buf;
for (auto item : myMap)
{
if (item.first.mode == mode)
{
if (buf.str() != "")
buf << "|";
buf << item.second << ":" << item.first.button << ","
<< int(item.first.axis) << "," << int(item.first.adir) << ","
<< item.first.hat << "," << int(item.first.hdir);
}
}
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int JoyMap::loadMapping(string& list, const EventMode mode)
{
// Since istringstream swallows whitespace, we have to make the
// delimiters be spaces
std::replace(list.begin(), list.end(), '|', ' ');
std::replace(list.begin(), list.end(), ':', ' ');
std::replace(list.begin(), list.end(), ',', ' ');
istringstream buf(list);
int event, button, axis, adir, hat, hdir, i = 0;
while (buf >> event && buf >> button
&& buf >> axis && buf >> adir
&& buf >> hat && buf >> hdir && ++i)
add(Event::Type(event), EventMode(mode), button, JoyAxis(axis), JoyDir(adir), hat, JoyHat(hdir));
return i;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::eraseMode(const EventMode mode)
{
for (auto item = myMap.begin(); item != myMap.end();)
if (item->first.mode == mode) {
auto _item = item++;
erase(_item->first);
}
else item++;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::eraseEvent(const Event::Type event, const EventMode mode)
{
for (auto item = myMap.begin(); item != myMap.end();)
if (item->second == event && item->first.mode == mode) {
auto _item = item++;
erase(_item->first);
}
else item++;
}

147
src/common/JoyMap.hxx Normal file
View File

@ -0,0 +1,147 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef CONTROLLERMAP_HXX
#define CONTROLLERMAP_HXX
#include <unordered_map>
#include "Event.hxx"
#include "EventHandlerConstants.hxx"
/**
This class handles controller mappings in Stella.
@author Thomas Jentzsch
*/
class JoyMap
{
public:
struct JoyMapping
{
EventMode mode;
int button; // button number
JoyAxis axis; // horizontal/vertical
JoyDir adir; // axis direction (neg/pos)
int hat; // hat number
JoyHat hdir; // hat direction (left/right/up/down)
JoyMapping()
: mode(EventMode(0)), button(0),
axis(JoyAxis(0)), adir(JoyDir(0)),
hat(0), hdir(JoyHat(0)) { }
JoyMapping(const JoyMapping& m)
: mode(m.mode), button(m.button),
axis(m.axis), adir(m.adir),
hat(m.hat), hdir(m.hdir) { }
explicit JoyMapping(EventMode c_mode, int c_button,
JoyAxis c_axis, JoyDir c_adir,
int c_hat, JoyHat c_hdir)
: mode(c_mode), button(c_button),
axis(c_axis), adir(c_adir),
hat(c_hat), hdir(c_hdir) { }
explicit JoyMapping(EventMode c_mode, int c_button,
JoyAxis c_axis, JoyDir c_adir)
: mode(c_mode), button(c_button),
axis(c_axis), adir(c_adir),
hat(JOY_CTRL_NONE), hdir(JoyHat::CENTER) { }
explicit JoyMapping(EventMode c_mode, int c_button,
int c_hat, JoyHat c_hdir)
: mode(c_mode), button(c_button),
axis(JoyAxis::NONE), adir(JoyDir::NONE),
hat(c_hat), hdir(c_hdir) { }
bool operator==(const JoyMapping& other) const
{
return (mode == other.mode
&& button == other.button
&& axis == other.axis
&& adir == other.adir
&& hat == other.hat
&& hdir == other.hdir
);
}
};
using JoyMappingArray = std::vector<JoyMapping>;
JoyMap();
virtual ~JoyMap() = default;
/** Add new mapping for given event */
void add(const Event::Type event, const JoyMapping& mapping);
void add(const Event::Type event, const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir,
const int hat = JOY_CTRL_NONE, const JoyHat hdir = JoyHat::CENTER);
void add(const Event::Type event, const EventMode mode, const int button,
const int hat, const JoyHat hdir);
/** Erase mapping */
void erase(const JoyMapping& mapping);
void erase(const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir);
void erase(const EventMode mode, const int button,
const int hat, const JoyHat hdir);
/** Get event for mapping */
Event::Type get(const JoyMapping& mapping) const;
Event::Type get(const EventMode mode, const int button,
const JoyAxis axis = JoyAxis::NONE, const JoyDir adir = JoyDir::NONE) const;
Event::Type get(const EventMode mode, const int button,
const int hat, const JoyHat hdir) const;
/** Check if a mapping exists */
bool check(const JoyMapping& mapping) const;
bool check(const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir,
const int hat = JOY_CTRL_NONE, const JoyHat hdir = JoyHat::CENTER) const;
/** Get mapping description */
string getEventMappingDesc(int stick, const Event::Type event, const EventMode mode) const;
JoyMappingArray getEventMapping(const Event::Type event, const EventMode mode) const;
string saveMapping(const EventMode mode) const;
int loadMapping(string& list, const EventMode mode);
/** Erase all mappings for given mode */
void eraseMode(const EventMode mode);
/** Erase given event's mapping for given mode */
void eraseEvent(const Event::Type event, const EventMode mode);
/** clear all mappings for a modes */
// void clear() { myMap.clear(); }
size_t size() { return myMap.size(); }
private:
string getDesc(const Event::Type event, const JoyMapping& mapping) const;
struct JoyHash {
size_t operator()(const JoyMapping& m)const {
return std::hash<uInt64>()((uInt64(m.mode)) // 3 bit
^ ((uInt64(m.button)) << 2) // 2 bits
^ ((uInt64(m.axis)) << 4) // 1 bit
^ ((uInt64(m.adir)) << 5) // 1 bit
^ ((uInt64(m.hat)) << 6) // 1 bit
^ ((uInt64(m.hdir)) << 7) // 2 bits
);
}
};
std::unordered_map<JoyMapping, Event::Type, JoyHash> myMap;
};
#endif

View File

@ -161,9 +161,9 @@ string KeyMap::getEventMappingDesc(const Event::Type event, const int mode) cons
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::vector<KeyMap::Mapping> KeyMap::getEventMapping(const Event::Type event, const int mode) const
KeyMap::MappingArray KeyMap::getEventMapping(const Event::Type event, const int mode) const
{
std::vector<KeyMap::Mapping> map;
MappingArray map;
for (auto item : myMap)
if (item.second == event && item.first.mode == mode)

View File

@ -55,6 +55,7 @@ class KeyMap
);
}
};
using MappingArray = std::vector<Mapping>;
KeyMap();
virtual ~KeyMap() = default;
@ -82,7 +83,7 @@ class KeyMap
/** Get the mapping description(s) for given event and mode */
string getEventMappingDesc(const Event::Type event, const int mode) const;
std::vector<Mapping> getEventMapping(const Event::Type event, const int mode) const;
MappingArray getEventMapping(const Event::Type event, const int mode) const;
string saveMapping(const int mode) const;
int loadMapping(string& list, const int mode);

File diff suppressed because it is too large Load Diff

View File

@ -41,7 +41,7 @@ using PhysicalJoystickPtr = shared_ptr<PhysicalJoystick>;
Essentially, this class is an extension of the EventHandler class, but
handling only joystick-specific functionality.
@author Stephen Anthony
@author Stephen Anthony, Thomas Jentzsch
*/
class PhysicalJoystickHandler
{
@ -69,32 +69,38 @@ class PhysicalJoystickHandler
bool remove(const string& name);
void mapStelladaptors(const string& saport);
void setDefaultMapping(Event::Type type, EventMode mode);
/** define mappings for current controllers */
void defineControllerMappings(const string& controllerName, Controller::Jack port);
/** enable mappings for emulation mode */
void enableEmulationMappings();
void eraseMapping(Event::Type event, EventMode mode);
void saveMapping();
string getMappingDesc(Event::Type, EventMode mode) const;
/** 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,
int button, JoyAxis axis, int value);
bool addJoyHatMapping(Event::Type event, EventMode mode, int stick,
int button, int hat, JoyHat hdir);
/** Handle a physical joystick event. */
void handleAxisEvent(int stick, int axis, int value);
void handleBtnEvent(int stick, int button, bool pressed);
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);
return (j && joyDir != int(JoyDir::NEG))
? j->axisTable[axis][(joyDir > int(JoyDir::NEG))][mode] : Event::NoType;
return j->joyMap.get(mode, button, JoyAxis(axis), convertAxisValue(value));
}
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);
return j ? j->btnTable[button][mode] : Event::NoType;
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);
return j ? j->hatTable[hat][int(hatDir)][mode] : Event::NoType;
return j->joyMap.get(mode, button, hat, hatDir);
}
/** Returns a list of pairs consisting of joystick name and associated ID. */
@ -122,17 +128,56 @@ class PhysicalJoystickHandler
}
// Set default mapping for given joystick when no mappings already exist
void setStickDefaultMapping(int stick, Event::Type type, EventMode mode);
void setStickDefaultMapping(int stick, Event::Type type, EventMode mode,
bool updateDefaults = false);
friend ostream& operator<<(ostream& os, const PhysicalJoystickHandler& jh);
// Static lookup tables for Stelladaptor/2600-daptor axis/button support
static const int NUM_JOY_BTN = 4;
static const int NUM_KEY_BTN = 12;
JoyDir convertAxisValue(int value) const {
return value == int(JoyDir::NONE) ? JoyDir::NONE : value > 0 ? JoyDir::POS : JoyDir::NEG;
}
static const Event::Type SA_Axis[NUM_PORTS][NUM_JOY_AXIS];
static const Event::Type SA_Button[NUM_PORTS][NUM_JOY_BTN];
static const Event::Type SA_Key[NUM_PORTS][NUM_KEY_BTN];
// Structures used for action menu items
struct EventMapping {
Event::Type event;
int button;
JoyAxis axis = JoyAxis::NONE;
JoyDir adir = JoyDir::NONE;
int hat = JOY_CTRL_NONE;
JoyHat hdir = JoyHat::CENTER;
};
using EventMappingArray = std::vector<EventMapping>;
void setDefaultAction(const PhysicalJoystickPtr& j,
EventMapping map, Event::Type event = Event::NoType,
EventMode mode = kEmulationMode, bool updateDefaults = false);
/** returns the event's controller mode */
EventMode getEventMode(const Event::Type event, const EventMode mode) const;
/** Checks event type. */
bool isJoystickEvent(const Event::Type event) const;
bool isPaddleEvent(const Event::Type event) const;
bool isKeypadEvent(const Event::Type event) const;
bool isCommonEvent(const Event::Type event) const;
void enableCommonMappings();
void enableMappings(const Event::EventSet events, EventMode mode);
void enableMapping(const Event::Type event, EventMode mode);
private:
EventMode myLeftMode;
EventMode myRightMode;
// Controller menu and common emulation mappings
static EventMappingArray DefaultMenuMapping;
// Controller specific mappings
static EventMappingArray DefaultLeftJoystickMapping;
static EventMappingArray DefaultRightJoystickMapping;
static EventMappingArray DefaultLeftPaddlesMapping;
static EventMappingArray DefaultRightPaddlesMapping;
static EventMappingArray DefaultLeftKeypadMapping;
static EventMappingArray DefaultRightKeypadMapping;
};
#endif

View File

@ -26,7 +26,6 @@
#include "PNGLibrary.hxx"
#include "PKeyboardHandler.hxx"
#ifdef DEBUGGER_SUPPORT
#include "Debugger.hxx"
#endif
@ -94,7 +93,7 @@ void PhysicalKeyboardHandler::setDefaultKey(EventMapping map, Event::Type event,
}
else if (eraseAll || map.event == event)
{
myKeyMap.eraseEvent(map.event, mode);
//myKeyMap.eraseEvent(map.event, mode);
myKeyMap.add(map.event, mode, map.key, map.mod);
}
}
@ -107,6 +106,12 @@ void PhysicalKeyboardHandler::setDefaultKey(EventMapping map, Event::Type event,
void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mode,
bool updateDefaults)
{
if (!updateDefaults)
{
myKeyMap.eraseEvent(event, mode);
myKeyMap.eraseEvent(event, getEventMode(event, mode));
}
switch(mode)
{
case kEmulationMode:
@ -186,7 +191,6 @@ void PhysicalKeyboardHandler::enableEmulationMappings()
// see below
break;
default:
enableMappings(RightJoystickEvents, kJoystickMode);
break;
@ -226,7 +230,7 @@ void PhysicalKeyboardHandler::enableCommonMappings()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::enableMappings(const EventSet events, EventMode mode)
void PhysicalKeyboardHandler::enableMappings(const Event::EventSet events, EventMode mode)
{
for (const auto& event : events)
enableMapping(event, mode);
@ -236,7 +240,7 @@ void PhysicalKeyboardHandler::enableMappings(const EventSet events, EventMode mo
void PhysicalKeyboardHandler::enableMapping(const Event::Type event, EventMode mode)
{
// copy from controller mode into emulation mode
std::vector<KeyMap::Mapping> mappings = myKeyMap.getEventMapping(event, mode);
KeyMap::MappingArray mappings = myKeyMap.getEventMapping(event, mode);
for (const auto& mapping : mappings)
myKeyMap.add(event, kEmulationMode, mapping.key, mapping.mod);
@ -387,46 +391,6 @@ void PhysicalKeyboardHandler::handleEvent(StellaKey key, StellaMod mod, bool pre
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::LeftJoystickEvents = {
Event::JoystickZeroUp, Event::JoystickZeroDown, Event::JoystickZeroLeft, Event::JoystickZeroRight,
Event::JoystickZeroFire, Event::JoystickZeroFire5, Event::JoystickZeroFire9,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::RightJoystickEvents = {
Event::JoystickOneUp, Event::JoystickOneDown, Event::JoystickOneLeft, Event::JoystickOneRight,
Event::JoystickOneFire, Event::JoystickOneFire5, Event::JoystickOneFire9
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::LeftPaddlesEvents = {
Event::PaddleZeroDecrease, Event::PaddleZeroIncrease, Event::PaddleZeroAnalog, Event::PaddleZeroFire,
Event::PaddleOneDecrease, Event::PaddleOneIncrease, Event::PaddleOneAnalog, Event::PaddleOneFire,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::RightPaddlesEvents = {
Event::PaddleTwoDecrease, Event::PaddleTwoIncrease, Event::PaddleTwoAnalog, Event::PaddleTwoFire,
Event::PaddleThreeDecrease, Event::PaddleThreeIncrease, Event::PaddleThreeAnalog, Event::PaddleThreeFire,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::LeftKeypadEvents = {
Event::KeyboardZero1, Event::KeyboardZero2, Event::KeyboardZero3,
Event::KeyboardZero4, Event::KeyboardZero5, Event::KeyboardZero6,
Event::KeyboardZero7, Event::KeyboardZero8, Event::KeyboardZero9,
Event::KeyboardZeroStar, Event::KeyboardZero0, Event::KeyboardZeroPound,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::RightKeypadEvents = {
Event::KeyboardOne1, Event::KeyboardOne2, Event::KeyboardOne3,
Event::KeyboardOne4, Event::KeyboardOne5, Event::KeyboardOne6,
Event::KeyboardOne7, Event::KeyboardOne8, Event::KeyboardOne9,
Event::KeyboardOneStar, Event::KeyboardOne0, Event::KeyboardOnePound,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommonMapping = {
{Event::ConsoleSelect, KBDK_F1},
@ -544,6 +508,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultMenuM
{Event::UIPgDown, KBDK_PAGEDOWN},
{Event::UISelect, KBDK_RETURN},
{Event::UISelect, KBDK_KP_ENTER},
{Event::UICancel, KBDK_ESCAPE},
{Event::UINavPrev, KBDK_TAB, KBDM_SHIFT},
@ -579,11 +544,17 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoyst
{Event::JoystickZeroDown, KBDK_DOWN},
{Event::JoystickZeroLeft, KBDK_LEFT},
{Event::JoystickZeroRight, KBDK_RIGHT},
{Event::JoystickZeroUp, KBDK_KP_8},
{Event::JoystickZeroDown, KBDK_KP_2},
{Event::JoystickZeroLeft, KBDK_KP_4},
{Event::JoystickZeroRight, KBDK_KP_6},
{Event::JoystickZeroFire, KBDK_SPACE},
{Event::JoystickZeroFire, KBDK_LCTRL},
{Event::JoystickZeroFire, KBDK_KP_5},
{Event::JoystickZeroFire5, KBDK_4},
{Event::JoystickZeroFire5, KBDK_KP_9},
{Event::JoystickZeroFire9, KBDK_5},
{Event::JoystickZeroFire9, KBDK_KP_3},
{Event::JoystickOneUp, KBDK_Y},
{Event::JoystickOneDown, KBDK_H},
{Event::JoystickOneLeft, KBDK_G},
@ -641,7 +612,6 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultKeypa
{Event::KeyboardOnePound, KBDK_SLASH},
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::CompuMateMapping = {
{Event::CompuMateShift, KBDK_LSHIFT},

View File

@ -19,7 +19,6 @@
#define PHYSICAL_KEYBOARD_HANDLER_HXX
#include <map>
#include <set>
class OSystem;
class EventHandler;
@ -29,8 +28,6 @@ class EventHandler;
#include "EventHandlerConstants.hxx"
#include "KeyMap.hxx"
using EventSet = std::set<Event::Type>;
/**
This class handles all physical keyboard-related operations in Stella.
@ -40,7 +37,7 @@ using EventSet = std::set<Event::Type>;
Essentially, this class is an extension of the EventHandler class, but
handling only keyboard-specific functionality.
@author Stephen Anthony
@author Stephen Anthony, Thomas Jentzsch
*/
class PhysicalKeyboardHandler
{
@ -103,7 +100,7 @@ class PhysicalKeyboardHandler
void enableCommonMappings();
void enableMappings(const EventSet events, EventMode mode);
void enableMappings(const Event::EventSet events, EventMode mode);
void enableMapping(const Event::Type event, EventMode mode);
OSystem& myOSystem;
@ -130,16 +127,10 @@ class PhysicalKeyboardHandler
uInt8 myAltKeyCounter;
#endif
// Hold controller related events
static EventSet LeftJoystickEvents;
static EventSet RightJoystickEvents;
static EventSet LeftPaddlesEvents;
static EventSet RightPaddlesEvents;
static EventSet LeftKeypadEvents;
static EventSet RightKeypadEvents;
// Controller menu and common emulation mappings
static EventMappingArray DefaultMenuMapping;
static EventMappingArray DefaultCommonMapping;
// Controller specific mappings
static EventMappingArray DefaultJoystickMapping;
static EventMappingArray DefaultPaddleMapping;
static EventMappingArray DefaultKeypadMapping;

View File

@ -31,20 +31,16 @@ PhysicalJoystick::PhysicalJoystick()
numAxes(0),
numButtons(0),
numHats(0),
axisTable(nullptr),
btnTable(nullptr),
hatTable(nullptr),
axisLastValue(nullptr)
axisLastValue(nullptr),
buttonLast(nullptr)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalJoystick::~PhysicalJoystick()
{
delete[] axisTable;
delete[] btnTable;
delete[] hatTable;
delete[] axisLastValue;
delete[] buttonLast;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -59,109 +55,66 @@ void PhysicalJoystick::initialize(int index, const string& desc,
numAxes = axes;
numButtons = buttons;
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];
buttonLast = new int[numButtons];
// Erase the joystick axis mapping array and last axis value
// Erase the last button
for (int b = 0; b < numButtons; ++b)
buttonLast[b] = JOY_CTRL_NONE;
// Erase the last axis value
for(int a = 0; a < numAxes; ++a)
{
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 mappings
eraseMap(kJoystickMode);
eraseMap(kPaddlesMode);
eraseMap(kKeypadMode);
eraseMap(kMenuMode);
// 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;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string PhysicalJoystick::getMap() const
{
// The mapping structure (for remappable devices) is defined as follows:
// NAME | AXIS # + values | BUTTON # + values | HAT # + values,
// where each subsection of values is separated by ':'
if(type == JT_REGULAR)
{
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];
// <NAME>'$'<MODE>['|'(<EVENT>':'<BUTTON>','<AXIS>','<VALUE>)|(<EVENT>':'<BUTTON>','<HAT>','<HATDIR>)]
return joybuf.str();
}
return EmptyString;
ostringstream joybuf;
joybuf << name;
joybuf << MODE_DELIM << int(kMenuMode) << "|" << joyMap.saveMapping(kMenuMode);
joybuf << MODE_DELIM << int(kJoystickMode) << "|" << joyMap.saveMapping(kJoystickMode);
joybuf << MODE_DELIM << int(kPaddlesMode) << "|" << joyMap.saveMapping(kPaddlesMode);
joybuf << MODE_DELIM << int(kKeypadMode) << "|" << joyMap.saveMapping(kKeypadMode);
joybuf << MODE_DELIM << int(kCommonMode) << "|" << joyMap.saveMapping(kCommonMode);
return joybuf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalJoystick::setMap(const string& mapString)
{
istringstream buf(mapString);
StringList items;
string item;
while(getline(buf, item, '|'))
items.push_back(item);
StringList mappings;
string map;
while (getline(buf, map, MODE_DELIM))
{
// remove leading "<mode>|" string
map.erase(0, 2);
mappings.push_back(map);
}
// Error checking
if(items.size() != 4)
if(mappings.size() != 1 + 5)
return false;
IntArray map;
// Parse axis/button/hat values
getValues(items[1], map);
if(int(map.size()) == numAxes * NUM_JOY_DIRS * kNumModes)
{
// Fill the axes table with events
auto event = map.cbegin();
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++);
}
joyMap.loadMapping(mappings[1], kMenuMode);
joyMap.loadMapping(mappings[2], kJoystickMode);
joyMap.loadMapping(mappings[3], kPaddlesMode);
joyMap.loadMapping(mappings[4], kKeypadMode);
joyMap.loadMapping(mappings[5], kCommonMode);
return true;
}
@ -169,40 +122,13 @@ bool PhysicalJoystick::setMap(const string& mapString)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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;
joyMap.eraseMode(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;
joyMap.eraseEvent(event, mode);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -221,10 +147,8 @@ void PhysicalJoystick::getValues(const string& list, IntArray& map) const
string PhysicalJoystick::about() const
{
ostringstream buf;
buf << name;
if(type == JT_REGULAR)
buf << " with: " << numAxes << " axes, " << numButtons << " buttons, "
<< numHats << " hats";
buf << " with: " << numAxes << " axes, " << numButtons << " buttons, "
<< numHats << " hats";
return buf.str();
}

View File

@ -20,6 +20,7 @@
#include "Event.hxx"
#include "EventHandlerConstants.hxx"
#include "JoyMap.hxx"
/**
An abstraction of a physical (real) joystick in Stella.
@ -31,12 +32,17 @@
Specific backend class(es) will inherit from this class, and implement
functionality specific to the device.
@author Stephen Anthony
@author Stephen Anthony, Thomas Jentzsch
*/
class PhysicalJoystick
{
friend class PhysicalJoystickHandler;
static constexpr char MODE_DELIM = '§'; // must not be '^', '|' or '#'
public:
PhysicalJoystick();
virtual ~PhysicalJoystick();
@ -65,10 +71,12 @@ class PhysicalJoystick
int ID;
string name;
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* buttonLast;
// Hashmaps of controller events
JoyMap joyMap;
private:
void getValues(const string& list, IntArray& map) const;

View File

@ -6,6 +6,7 @@ MODULE_OBJS := \
src/common/FBSurfaceSDL2.o \
src/common/FrameBufferSDL2.o \
src/common/FSNodeZIP.o \
src/common/JoyMap.o \
src/common/KeyMap.o \
src/common/Logger.o \
src/common/main.o \

View File

@ -32,8 +32,8 @@ BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
myFireEvent = Event::JoystickZeroFire;
myTriggerEvent = Event::JoystickZeroFire5;
myBoosterEvent = Event::JoystickZeroFire9;
myXAxisValue = Event::SALeftAxis0Value;
myYAxisValue = Event::SALeftAxis1Value;
myXAxisValue = Event::PaddleZeroAnalog;
myYAxisValue = Event::PaddleOneAnalog;
}
else
{
@ -44,8 +44,8 @@ BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
myFireEvent = Event::JoystickOneFire;
myTriggerEvent = Event::JoystickOneFire5;
myBoosterEvent = Event::JoystickOneFire9;
myXAxisValue = Event::SARightAxis0Value;
myYAxisValue = Event::SARightAxis1Value;
myXAxisValue = Event::PaddleTwoAnalog;
myYAxisValue = Event::PaddleThreeAnalog;
}
setPin(AnalogPin::Five, MAX_RESISTANCE);

View File

@ -135,6 +135,7 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
setControllers(md5);
// now that we know the controllers, enable the event mappings
myOSystem.eventHandler().enableEmulationKeyMappings();
myOSystem.eventHandler().enableEmulationJoyMappings();
// Mute audio and clear framebuffer while autodetection runs
myOSystem.sound().mute(1);
@ -804,6 +805,7 @@ void Console::setControllers(const string& rommd5)
myLeftControl = std::move(myCMHandler->leftController());
myRightControl = std::move(myCMHandler->rightController());
myOSystem.eventHandler().defineKeyControllerMappings("CM", Controller::Jack::Left);
myOSystem.eventHandler().defineJoyControllerMappings("CM", Controller::Jack::Left);
}
else
{
@ -849,6 +851,7 @@ unique_ptr<Controller> Console::getControllerPort(const string& rommd5,
unique_ptr<Controller> controller = std::move(myLeftControl);
myOSystem.eventHandler().defineKeyControllerMappings(controllerName, port);
myOSystem.eventHandler().defineJoyControllerMappings(controllerName, port);
if(controllerName == "JOYSTICK")
{

View File

@ -35,16 +35,16 @@ Driving::Driving(Jack jack, const Event& event, const System& system)
myCCWEvent = Event::JoystickZeroLeft;
myCWEvent = Event::JoystickZeroRight;
myFireEvent = Event::JoystickZeroFire;
myXAxisValue = Event::SALeftAxis0Value;
myYAxisValue = Event::SALeftAxis1Value;
myXAxisValue = Event::PaddleZeroAnalog;
myYAxisValue = Event::PaddleOneAnalog;
}
else
{
myCCWEvent = Event::JoystickOneLeft;
myCWEvent = Event::JoystickOneRight;
myFireEvent = Event::JoystickOneFire;
myXAxisValue = Event::SARightAxis0Value;
myYAxisValue = Event::SARightAxis1Value;
myXAxisValue = Event::PaddleTwoAnalog;
myYAxisValue = Event::PaddleThreeAnalog;
}
// Digital pins 3 and 4 are not connected

View File

@ -19,12 +19,13 @@
#define EVENT_HXX
#include <mutex>
#include <set>
#include "bspf.hxx"
#include "StellaKeys.hxx"
/**
@author Stephen Anthony, Christian Speckner
@author Stephen Anthony, Christian Speckner, Thomas Jentzsch
*/
class Event
{
@ -67,9 +68,6 @@ class Event
Combo1, Combo2, Combo3, Combo4, Combo5, Combo6, Combo7, Combo8,
Combo9, Combo10, Combo11, Combo12, Combo13, Combo14, Combo15, Combo16,
SALeftAxis0Value, SALeftAxis1Value,
SARightAxis0Value, SARightAxis1Value,
MouseAxisXValue, MouseAxisYValue,
MouseButtonLeftValue, MouseButtonRightValue,
@ -127,7 +125,9 @@ class Event
};
// Event list version, update if the id of existing event types changed
static constexpr Int32 VERSION = 2;
static constexpr Int32 VERSION = 3;
using EventSet = std::set<Event::Type>;
public:
/**
@ -200,4 +200,44 @@ class Event
Event& operator=(Event&&) = delete;
};
// Hold controller related events
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet LeftJoystickEvents = {
Event::JoystickZeroUp, Event::JoystickZeroDown, Event::JoystickZeroLeft, Event::JoystickZeroRight,
Event::JoystickZeroFire, Event::JoystickZeroFire5, Event::JoystickZeroFire9,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet RightJoystickEvents = {
Event::JoystickOneUp, Event::JoystickOneDown, Event::JoystickOneLeft, Event::JoystickOneRight,
Event::JoystickOneFire, Event::JoystickOneFire5, Event::JoystickOneFire9
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet LeftPaddlesEvents = {
Event::PaddleZeroDecrease, Event::PaddleZeroIncrease, Event::PaddleZeroAnalog, Event::PaddleZeroFire,
Event::PaddleOneDecrease, Event::PaddleOneIncrease, Event::PaddleOneAnalog, Event::PaddleOneFire,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet RightPaddlesEvents = {
Event::PaddleTwoDecrease, Event::PaddleTwoIncrease, Event::PaddleTwoAnalog, Event::PaddleTwoFire,
Event::PaddleThreeDecrease, Event::PaddleThreeIncrease, Event::PaddleThreeAnalog, Event::PaddleThreeFire,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet LeftKeypadEvents = {
Event::KeyboardZero1, Event::KeyboardZero2, Event::KeyboardZero3,
Event::KeyboardZero4, Event::KeyboardZero5, Event::KeyboardZero6,
Event::KeyboardZero7, Event::KeyboardZero8, Event::KeyboardZero9,
Event::KeyboardZeroStar, Event::KeyboardZero0, Event::KeyboardZeroPound,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet RightKeypadEvents = {
Event::KeyboardOne1, Event::KeyboardOne2, Event::KeyboardOne3,
Event::KeyboardOne4, Event::KeyboardOne5, Event::KeyboardOne6,
Event::KeyboardOne7, Event::KeyboardOne8, Event::KeyboardOne9,
Event::KeyboardOneStar, Event::KeyboardOne0, Event::KeyboardOnePound,
};
#endif

View File

@ -331,10 +331,12 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::handleEvent(Event::Type event, bool pressed, bool repeated)
void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
{
// Take care of special events that aren't part of the emulation core
// or need to be preprocessed before passing them on
bool pressed = (value != 0);
switch(event)
{
////////////////////////////////////////////////////////////////////////
@ -896,7 +898,7 @@ void EventHandler::handleEvent(Event::Type event, bool pressed, bool repeated)
// Otherwise, pass it to the emulation core
if (!repeated)
myEvent.set(event, pressed);
myEvent.set(event, value);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1124,29 +1126,13 @@ bool EventHandler::addKeyMapping(Event::Type event, EventMode mode, StellaKey ke
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::addJoyAxisMapping(Event::Type event, EventMode mode,
int stick, int axis, int value,
bool updateMenus)
bool EventHandler::addJoyMapping(Event::Type event, EventMode mode,
int stick, int button, JoyAxis axis, int value,
bool updateMenus)
{
#ifdef JOYSTICK_SUPPORT
bool mapped = myPJoyHandler->addAxisMapping(event, mode, stick, axis, value);
if(mapped && updateMenus)
setActionMappings(mode);
return mapped;
#else
return false;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::addJoyButtonMapping(Event::Type event, EventMode mode,
int stick, int button,
bool updateMenus)
{
#ifdef JOYSTICK_SUPPORT
bool mapped = myPJoyHandler->addBtnMapping(event, mode, stick, button);
if(mapped && updateMenus)
bool mapped = myPJoyHandler->addJoyMapping(event, mode, stick, button, axis, value);
if (mapped && updateMenus)
setActionMappings(mode);
return mapped;
@ -1157,12 +1143,12 @@ bool EventHandler::addJoyButtonMapping(Event::Type event, EventMode mode,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::addJoyHatMapping(Event::Type event, EventMode mode,
int stick, int hat, JoyHat value,
int stick, int button, int hat, JoyHat dir,
bool updateMenus)
{
#ifdef JOYSTICK_SUPPORT
bool mapped = myPJoyHandler->addHatMapping(event, mode, stick, hat, value);
if(mapped && updateMenus)
bool mapped = myPJoyHandler->addJoyHatMapping(event, mode, stick, button, hat, dir);
if (mapped && updateMenus)
setActionMappings(mode);
return mapped;
@ -1171,6 +1157,7 @@ bool EventHandler::addJoyHatMapping(Event::Type event, EventMode mode,
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::eraseMapping(Event::Type event, EventMode mode)
{

View File

@ -47,7 +47,7 @@ class PhysicalJoystick;
unchanged to the menu class, where (among other things) changing key
mapping can take place.
@author Stephen Anthony
@author Stephen Anthony, Thomas Jentzsch
*/
class EventHandler
{
@ -141,7 +141,7 @@ class EventHandler
@param pressed Pressed (true) or released (false)
@param repeated Repeated key (true) or first press/release (false)
*/
void handleEvent(Event::Type type, bool pressed = true, bool repeated = false);
void handleEvent(Event::Type type, Int32 value = 1, bool repeated = false);
/**
Handle events that must be processed each time a new console is
@ -162,14 +162,14 @@ class EventHandler
Event::Type eventForKey(EventMode mode, StellaKey key, StellaMod mod) const {
return myPKeyHandler->eventForKey(mode, key, mod);
}
Event::Type eventForJoyAxis(int stick, int axis, int value, EventMode mode) const {
return myPJoyHandler->eventForAxis(stick, axis, value, mode);
Event::Type eventForJoyAxis(EventMode mode, int stick, int axis, int value, int button) const {
return myPJoyHandler->eventForAxis(mode, stick, axis, value, button);
}
Event::Type eventForJoyButton(int stick, int button, EventMode mode) const {
return myPJoyHandler->eventForButton(stick, button, mode);
Event::Type eventForJoyButton(EventMode mode, int stick, int button) const {
return myPJoyHandler->eventForButton(mode, stick, button);
}
Event::Type eventForJoyHat(int stick, int hat, JoyHat value, EventMode mode) const {
return myPJoyHandler->eventForHat(stick, hat, value, mode);
Event::Type eventForJoyHat(EventMode mode, int stick, int hat, JoyHat value, int button) const {
return myPJoyHandler->eventForHat(mode, stick, hat, value, button);
}
/** Get description of given event and mode. */
@ -208,53 +208,55 @@ class EventHandler
/**
Bind a physical joystick axis direction to an event/action and regenerate
the mapping array(s).
the mapping array(s). The axis can be combined with a button. The button
can also be mapped without an axis.
@param event The event we are remapping
@param mode The mode where this event is active
@param stick The joystick number
@param button The joystick button
@param axis The joystick axis
@param value The value on the given axis
@param updateMenus Whether to update the action mappings (normally
we want to do this, unless there are a batch of
'adds', in which case it's delayed until the end
*/
bool addJoyAxisMapping(Event::Type event, EventMode mode,
int stick, int axis, int value,
bool updateMenus = true);
bool addJoyMapping(Event::Type event, EventMode mode, int stick,
int button, JoyAxis axis = JoyAxis::NONE, int value = 0,
bool updateMenus = true);
/**
Bind a physical joystick button to an event/action and regenerate the
mapping array(s).
Bind a physical joystick hat direction to an event/action and regenerate
the mapping array(s). The hat can be combined with a button.
@param event The event we are remapping
@param mode The mode where this event is active
@param stick The joystick number
@param button The joystick button
@param updateMenus Whether to update the action mappings (normally
we want to do this, unless there are a batch of
'adds', in which case it's delayed until the end
*/
bool addJoyButtonMapping(Event::Type event, EventMode mode, int stick, int button,
bool updateMenus = true);
/**
Bind a physical joystick hat direction to an event/action and regenerate
the mapping array(s).
@param event The event we are remapping
@param mode The mode where this event is active
@param stick The joystick number
@param hat The joystick hat
@param value The value on the given hat
@param updateMenus Whether to update the action mappings (normally
we want to do this, unless there are a batch of
'adds', in which case it's delayed until the end
*/
bool addJoyHatMapping(Event::Type event, EventMode mode,
int stick, int hat, JoyHat value,
bool addJoyHatMapping(Event::Type event, EventMode mode, int stick,
int button, int hat, JoyHat dir,
bool updateMenus = true);
/**
Enable controller specific keyboard event mappings.
*/
void defineJoyControllerMappings(const string& controllerName, Controller::Jack port) {
myPJoyHandler->defineControllerMappings(controllerName, port);
}
/**
Enable emulation keyboard event mappings.
*/
void enableEmulationJoyMappings() {
myPJoyHandler->enableEmulationMappings();
}
/**
Erase the specified mapping.

View File

@ -38,14 +38,20 @@ enum class MouseButton {
NONE
};
static constexpr int JOY_CTRL_NONE = -1;
enum class JoyAxis {
X = 0,
Y = 1,
Z = 2,
NONE = JOY_CTRL_NONE
};
enum class JoyDir {
NEG = 0,
NEG = -1,
POS = 1,
NONE = 0,
ANALOG = 2
};

View File

@ -30,8 +30,8 @@ Joystick::Joystick(Jack jack, const Event& event, const System& system)
myLeftEvent = Event::JoystickZeroLeft;
myRightEvent = Event::JoystickZeroRight;
myFireEvent = Event::JoystickZeroFire;
myXAxisValue = Event::SALeftAxis0Value;
myYAxisValue = Event::SALeftAxis1Value;
myXAxisValue = Event::PaddleZeroAnalog;
myYAxisValue = Event::PaddleOneAnalog;
}
else
{
@ -40,8 +40,8 @@ Joystick::Joystick(Jack jack, const Event& event, const System& system)
myLeftEvent = Event::JoystickOneLeft;
myRightEvent = Event::JoystickOneRight;
myFireEvent = Event::JoystickOneFire;
myXAxisValue = Event::SARightAxis0Value;
myYAxisValue = Event::SARightAxis1Value;
myXAxisValue = Event::PaddleTwoAnalog;
myYAxisValue = Event::PaddleThreeAnalog;
}
}

View File

@ -53,8 +53,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
if(!swappaddle) // First paddle is 0, second is 1
{
// These aren't affected by changes in axis orientation
myP0AxisValue = Event::SALeftAxis0Value;
myP1AxisValue = Event::SALeftAxis1Value;
myP0AxisValue = Event::PaddleZeroAnalog;
myP1AxisValue = Event::PaddleOneAnalog;
myP0FireEvent1 = Event::PaddleZeroFire;
myP0FireEvent2 = Event::JoystickZeroFire;
myP1FireEvent1 = Event::PaddleOneFire;
@ -89,8 +89,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
else // First paddle is 1, second is 0
{
// These aren't affected by changes in axis orientation
myP0AxisValue = Event::SALeftAxis1Value;
myP1AxisValue = Event::SALeftAxis0Value;
myP0AxisValue = Event::PaddleOneAnalog;
myP1AxisValue = Event::PaddleZeroAnalog;
myP0FireEvent1 = Event::PaddleOneFire;
myP0FireEvent2 = Event::JoystickZeroFire9;
myP1FireEvent1 = Event::PaddleZeroFire;
@ -128,8 +128,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
if(!swappaddle) // First paddle is 2, second is 3
{
// These aren't affected by changes in axis orientation
myP0AxisValue = Event::SARightAxis0Value;
myP1AxisValue = Event::SARightAxis1Value;
myP0AxisValue = Event::PaddleTwoAnalog;
myP1AxisValue = Event::PaddleThreeAnalog;
myP0FireEvent1 = Event::PaddleTwoFire;
myP0FireEvent2 = Event::JoystickOneFire;
myP1FireEvent1 = Event::PaddleThreeFire;
@ -164,8 +164,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
else // First paddle is 3, second is 2
{
// These aren't affected by changes in axis orientation
myP0AxisValue = Event::SARightAxis1Value;
myP1AxisValue = Event::SARightAxis0Value;
myP0AxisValue = Event::PaddleThreeAnalog;
myP1AxisValue = Event::PaddleTwoAnalog;
myP0FireEvent1 = Event::PaddleThreeFire;
myP0FireEvent2 = Event::JoystickOneFire9;
myP1FireEvent1 = Event::PaddleTwoFire;

View File

@ -288,20 +288,20 @@ void ContextMenu::handleKeyDown(StellaKey key, StellaMod mod)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
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;
}

View File

@ -88,8 +88,8 @@ class ContextMenu : public Dialog, public CommandSender
void handleMouseWheel(int x, int y, int direction) override;
void handleKeyDown(StellaKey key, StellaMod mod) override;
void handleJoyDown(int stick, int button) override;
void handleJoyAxis(int stick, int axis, int value) override;
bool handleJoyHat(int stick, int hat, JoyHat value) override;
void handleJoyAxis(int stick, int axis, int value, int button) override;
bool handleJoyHat(int stick, int hat, JoyHat value, int button) override;
void handleEvent(Event::Type e);
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)
{
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
// 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
// that if an event exists for the given data, it should have priority.
if(!handleNavEvent(e) && _focusedWidget)
{
if(_focusedWidget->wantsRaw() || e == Event::NoType)
_focusedWidget->handleJoyAxis(stick, axis, value);
_focusedWidget->handleJoyAxis(stick, axis, value, button);
else if(value != 0)
_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 =
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
// that if an event exists for the given data, it should have priority.
if(!handleNavEvent(e) && _focusedWidget)
{
if(_focusedWidget->wantsRaw() || e == Event::NoType)
return _focusedWidget->handleJoyHat(stick, hat, value);
return _focusedWidget->handleJoyHat(stick, hat, value, button);
else
return _focusedWidget->handleEvent(e);
}

View File

@ -139,10 +139,10 @@ class Dialog : public GuiObject
virtual bool handleMouseClicks(int x, int y, MouseButton b);
virtual void handleJoyDown(int stick, int button);
virtual void handleJoyUp(int stick, int button);
virtual void handleJoyAxis(int stick, int axis, int value);
virtual bool handleJoyHat(int stick, int hat, JoyHat value);
virtual void handleJoyAxis(int stick, int axis, int value, int button = JOY_CTRL_NONE);
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 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

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())
return;
@ -307,21 +307,23 @@ void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value)
// Only stop firing events if it's the current stick
if(myCurrentAxisDown.stick == stick && value == 0)
{
cerr << "handleJoyAxisEvent 0" << endl;
myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1;
}
else if(value != 0) // never repeat the 'off' event
{
cerr << "handleJoyAxisEvent repeat" << endl;
// Now account for repeated axis events (press and hold)
myCurrentAxisDown.stick = stick;
myCurrentAxisDown.axis = axis;
myCurrentAxisDown.value = value;
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())
return;
@ -339,7 +341,7 @@ void DialogContainer::handleJoyHatEvent(int stick, int hat, JoyHat value)
myCurrentHatDown.value = value;
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 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.
@ -117,7 +117,7 @@ class DialogContainer
@param hat The joystick 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).

View File

@ -97,7 +97,7 @@ void EditTextWidget::drawWidget(bool hilite)
_changed && onTop && isEnabled()
? kDbgChangedTextColor
: onTop && isEnabled() ? _textcolor : kColor,
TextAlign::Left, -_editScrollOffset, false);
TextAlign::Left, isEditable() ? -_editScrollOffset : 0, !isEditable());
// Draw the caret
drawCaret();

View File

@ -47,6 +47,7 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
myLastAxis(0),
myLastHat(0),
myLastValue(0),
myLastButton(JOY_CTRL_NONE),
myFirstTime(true)
{
const int fontHeight = font.getFontHeight(),
@ -151,6 +152,7 @@ void EventMappingWidget::setDefaults()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventMappingWidget::startRemapping()
{
cerr << "startRemapping" << endl;
if(myActionSelected < 0 || myRemapStatus)
return;
@ -159,9 +161,10 @@ void EventMappingWidget::startRemapping()
// Reset all previous events for determining correct axis/hat values
myLastStick = myLastAxis = myLastHat = myLastValue = -1;
myLastButton = JOY_CTRL_NONE;
// Reset the previously aggregated key mappings
myMod = myKey = 0;
myMod = myLastKey = 0;
// Disable all other widgets while in remap mode, except enable 'Cancel'
enableButtons(false);
@ -210,9 +213,11 @@ void EventMappingWidget::stopRemapping()
{
// Turn off remap mode
myRemapStatus = false;
cerr << "stopRemapping " << myRemapStatus << endl;
// Reset all previous events for determining correct axis/hat values
myLastStick = myLastAxis = myLastHat = myLastValue = -1;
myLastButton = JOY_CTRL_NONE;
// And re-enable all the widgets
enableButtons(true);
@ -257,7 +262,7 @@ bool EventMappingWidget::handleKeyDown(StellaKey key, StellaMod mod)
// Remap keys in remap mode
if (myRemapStatus && myActionSelected >= 0)
{
myKey = key;
myLastKey = key;
myMod |= mod;
}
return true;
@ -272,7 +277,7 @@ bool EventMappingWidget::handleKeyUp(StellaKey key, StellaMod mod)
{
Event::Type event =
instance().eventHandler().eventAtIndex(myActionSelected, myEventMode);
if (instance().eventHandler().addKeyMapping(event, myEventMode, StellaKey(myKey), StellaMod(myMod)))
if (instance().eventHandler().addKeyMapping(event, myEventMode, StellaKey(myLastKey), StellaMod(myMod)))
stopRemapping();
}
return true;
@ -281,19 +286,40 @@ bool EventMappingWidget::handleKeyUp(StellaKey key, StellaMod mod)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventMappingWidget::handleJoyDown(int stick, int button)
{
cerr << "handleJoyDown" << endl;
// Remap joystick buttons in remap mode
if(myRemapStatus && myActionSelected >= 0)
{
Event::Type event =
instance().eventHandler().eventAtIndex(myActionSelected, myEventMode);
if(instance().eventHandler().addJoyButtonMapping(event, myEventMode, stick, button))
stopRemapping();
cerr << "remap button start " << myRemapStatus << endl;
myLastStick = stick;
myLastButton = button;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventMappingWidget::handleJoyAxis(int stick, int axis, int value)
void EventMappingWidget::handleJoyUp(int stick, int button)
{
cerr << "handleJoyUp" << endl;
// Remap joystick buttons in remap mode
if (myRemapStatus && myActionSelected >= 0)
{
if (myLastStick == stick && myLastButton == button)
{
EventHandler& eh = instance().eventHandler();
Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode);
cerr << "remap button stop" << endl;
// This maps solo button presses only
if (eh.addJoyMapping(event, myEventMode, stick, button))
stopRemapping();
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventMappingWidget::handleJoyAxis(int stick, int axis, int value, int button)
{
cerr << "handleJoyAxis:" << axis << ", " << value << ", (" << stick << ", " << myLastStick << "), (" << axis << ", " << myLastAxis << ")" << endl;
// Remap joystick axes in remap mode
// There are two phases to detection:
// First, detect an axis 'on' event
@ -301,8 +327,9 @@ void EventMappingWidget::handleJoyAxis(int stick, int axis, int value)
if(myRemapStatus && myActionSelected >= 0)
{
// Detect the first axis event that represents 'on'
if(myLastStick == -1 && myLastAxis == -1 && value != 0)
if((myLastStick == -1 || myLastStick == stick) && myLastAxis == -1 && value != 0)
{
cerr << "remap start" << endl;
myLastStick = stick;
myLastAxis = axis;
myLastValue = value;
@ -311,19 +338,18 @@ void EventMappingWidget::handleJoyAxis(int stick, int axis, int value)
// stick and axis, but turns the axis 'off'
else if(myLastStick == stick && axis == myLastAxis && value == 0)
{
value = myLastValue;
EventHandler& eh = instance().eventHandler();
Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode);
Event::Type event =
instance().eventHandler().eventAtIndex(myActionSelected, myEventMode);
if(instance().eventHandler().addJoyAxisMapping(event, myEventMode,
stick, axis, value))
cerr << "remap stop" << endl;
if (eh.addJoyMapping(event, myEventMode, stick, myLastButton, JoyAxis(axis), myLastValue))
stopRemapping();
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
// There are two phases to detection:
@ -332,7 +358,7 @@ bool EventMappingWidget::handleJoyHat(int stick, int hat, JoyHat value)
if(myRemapStatus && myActionSelected >= 0)
{
// Detect the first hat event that represents a valid direction
if(myLastStick == -1 && myLastHat == -1 && value != JoyHat::CENTER)
if((myLastStick == -1 || myLastStick == stick) && myLastHat == -1 && value != JoyHat::CENTER)
{
myLastStick = stick;
myLastHat = hat;
@ -344,12 +370,10 @@ bool EventMappingWidget::handleJoyHat(int stick, int hat, JoyHat value)
// stick and hat, but centers the hat
else if(myLastStick == stick && hat == myLastHat && value == JoyHat::CENTER)
{
value = JoyHat(myLastValue);
EventHandler& eh = instance().eventHandler();
Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode);
Event::Type event =
instance().eventHandler().eventAtIndex(myActionSelected, myEventMode);
if(instance().eventHandler().addJoyHatMapping(event, myEventMode,
stick, hat, value))
if (eh.addJoyHatMapping(event, myEventMode, stick, myLastButton, hat, JoyHat(myLastValue)))
{
stopRemapping();
return true;

View File

@ -60,8 +60,9 @@ class EventMappingWidget : public Widget, public CommandSender
bool handleKeyDown(StellaKey key, StellaMod mod) override;
bool handleKeyUp(StellaKey key, StellaMod mod) override;
void handleJoyDown(int stick, int button) override;
void handleJoyAxis(int stick, int axis, int value) override;
bool handleJoyHat(int stick, int hat, JoyHat value) override;
void handleJoyUp(int stick, int button) override;
void handleJoyAxis(int stick, int axis, int value, int button) override;
bool handleJoyHat(int stick, int hat, JoyHat value, int button) override;
void loadConfig() override;
void saveConfig();
@ -108,7 +109,9 @@ class EventMappingWidget : public Widget, public CommandSender
// Aggregates the modifier flags of the mapping
int myMod;
// Saves the last *pressed* key
int myKey;
int myLastKey;
// Saves the last *pressed* button
int myLastButton;
bool myFirstTime;

View File

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

View File

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

View File

@ -469,7 +469,7 @@ void LauncherDialog::handleKeyDown(StellaKey key, StellaMod mod)
void LauncherDialog::handleJoyDown(int stick, int button)
{
// 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))
myGlobalProps->open();
@ -480,9 +480,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)
{

View File

@ -92,7 +92,7 @@ class LauncherDialog : public Dialog
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) 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 updateUI();

View File

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

View File

@ -376,6 +376,7 @@
<ClCompile Include="..\common\FpsMeter.cxx" />
<ClCompile Include="..\common\FrameBufferSDL2.cxx" />
<ClCompile Include="..\common\FSNodeZIP.cxx" />
<ClCompile Include="..\common\JoyMap.cxx" />
<ClCompile Include="..\common\KeyMap.cxx" />
<ClCompile Include="..\common\Logger.cxx" />
<ClCompile Include="..\common\main.cxx" />
@ -1072,6 +1073,7 @@
<ClInclude Include="..\common\FrameBufferSDL2.hxx" />
<ClInclude Include="..\common\FSNodeFactory.hxx" />
<ClInclude Include="..\common\FSNodeZIP.hxx" />
<ClInclude Include="..\common\JoyMap.hxx" />
<ClInclude Include="..\common\KeyMap.hxx" />
<ClInclude Include="..\common\LinkedObjectPool.hxx" />
<ClInclude Include="..\common\Logger.hxx" />

View File

@ -975,6 +975,9 @@
<ClCompile Include="..\gui\R77HelpDialog.cxx">
<Filter>Source Files\gui</Filter>
</ClCompile>
<ClCompile Include="..\common\JoyMap.cxx">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\common\bspf.hxx">
@ -1994,6 +1997,9 @@
<ClInclude Include="..\common\KeyMap.hxx">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\common\JoyMap.hxx">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="stella.ico">