1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#ifndef PHYSICAL_JOYSTICK_HANDLER_HXX
19#define PHYSICAL_JOYSTICK_HANDLER_HXX
20
21#include <map>
22
23class OSystem;
24class EventHandler;
25class Event;
26
27#include "bspf.hxx"
28#include "EventHandlerConstants.hxx"
29#include "PhysicalJoystick.hxx"
30#include "Variant.hxx"
31
32using PhysicalJoystickPtr = shared_ptr<PhysicalJoystick>;
33
34/**
35 This class handles all physical joystick-related operations in Stella.
36
37 It is responsible for adding/accessing/removing PhysicalJoystick objects,
38 and getting/setting events associated with joystick actions (button presses,
39 axis/hat actions, etc).
40
41 Essentially, this class is an extension of the EventHandler class, but
42 handling only joystick-specific functionality.
43
44 @author Stephen Anthony, Thomas Jentzsch
45*/
46class PhysicalJoystickHandler
47{
48 private:
49 struct StickInfo
50 {
51 StickInfo(const string& map = EmptyString, PhysicalJoystickPtr stick = nullptr)
52 : mapping(map), joy(stick) {}
53
54 string mapping;
55 PhysicalJoystickPtr joy;
56
57 friend ostream& operator<<(ostream& os, const StickInfo& si) {
58 os << " joy: " << si.joy << endl << " map: " << si.mapping;
59 return os;
60 }
61 };
62
63 public:
64 PhysicalJoystickHandler(OSystem& system, EventHandler& handler);
65
66 /** Return stick ID on success, -1 on failure. */
67 int add(PhysicalJoystickPtr stick);
68 bool remove(int id);
69 bool remove(const string& name);
70 void mapStelladaptors(const string& saport);
71 void setDefaultMapping(Event::Type type, EventMode mode);
72
73 /** define mappings for current controllers */
74 void defineControllerMappings(const Controller::Type type, Controller::Jack port);
75 /** enable mappings for emulation mode */
76 void enableEmulationMappings();
77
78 void eraseMapping(Event::Type event, EventMode mode);
79 void saveMapping();
80 string getMappingDesc(Event::Type, EventMode mode) const;
81
82 /** Bind a physical joystick event to a virtual event/action. */
83 bool addJoyMapping(Event::Type event, EventMode mode, int stick,
84 int button, JoyAxis axis, JoyDir adir);
85 bool addJoyHatMapping(Event::Type event, EventMode mode, int stick,
86 int button, int hat, JoyHatDir hdir);
87
88 /** Handle a physical joystick event. */
89 void handleAxisEvent(int stick, int axis, int value);
90 void handleBtnEvent(int stick, int button, bool pressed);
91 void handleHatEvent(int stick, int hat, int value);
92
93 Event::Type eventForAxis(EventMode mode, int stick, JoyAxis axis, JoyDir adir, int button) const {
94 const PhysicalJoystickPtr j = joy(stick);
95 return j->joyMap.get(mode, button, axis, adir);
96 }
97 Event::Type eventForButton(EventMode mode, int stick, int button) const {
98 const PhysicalJoystickPtr j = joy(stick);
99 return j->joyMap.get(mode, button);
100 }
101 Event::Type eventForHat(EventMode mode, int stick, int hat, JoyHatDir hatDir, int button) const {
102 const PhysicalJoystickPtr j = joy(stick);
103 return j->joyMap.get(mode, button, hat, hatDir);
104 }
105
106 /** Returns a list of pairs consisting of joystick name and associated ID. */
107 VariantList database() const;
108
109 private:
110 using StickDatabase = std::map<string,StickInfo>;
111 using StickList = std::map<int, PhysicalJoystickPtr>;
112
113 OSystem& myOSystem;
114 EventHandler& myHandler;
115
116 // Contains all joysticks that Stella knows about, indexed by name
117 StickDatabase myDatabase;
118
119 // Contains only joysticks that are currently available, indexed by id
120 StickList mySticks;
121
122 // Get joystick corresponding to given id (or nullptr if it doesn't exist)
123 // Make this inline so it's as fast as possible
124 const PhysicalJoystickPtr joy(int id) const {
125 const auto& i = mySticks.find(id);
126 return i != mySticks.cend() ? i->second : nullptr;
127 }
128
129 // Set default mapping for given joystick when no mappings already exist
130 void setStickDefaultMapping(int stick, Event::Type type, EventMode mode,
131 bool updateDefaults = false);
132
133 friend ostream& operator<<(ostream& os, const PhysicalJoystickHandler& jh);
134
135 JoyDir convertAxisValue(int value) const {
136 return value == int(JoyDir::NONE) ? JoyDir::NONE : value > 0 ? JoyDir::POS : JoyDir::NEG;
137 }
138
139 // Structures used for action menu items
140 struct EventMapping {
141 Event::Type event;
142 int button;
143 JoyAxis axis = JoyAxis::NONE;
144 JoyDir adir = JoyDir::NONE;
145 int hat = JOY_CTRL_NONE;
146 JoyHatDir hdir = JoyHatDir::CENTER;
147 };
148 using EventMappingArray = std::vector<EventMapping>;
149
150 void setDefaultAction(const PhysicalJoystickPtr& j,
151 EventMapping map, Event::Type event = Event::NoType,
152 EventMode mode = EventMode::kEmulationMode, bool updateDefaults = false);
153
154 /** returns the event's controller mode */
155 EventMode getEventMode(const Event::Type event, const EventMode mode) const;
156 /** Checks event type. */
157 bool isJoystickEvent(const Event::Type event) const;
158 bool isPaddleEvent(const Event::Type event) const;
159 bool isKeypadEvent(const Event::Type event) const;
160 bool isCommonEvent(const Event::Type event) const;
161
162 void enableCommonMappings();
163
164 void enableMappings(const Event::EventSet events, EventMode mode);
165 void enableMapping(const Event::Type event, EventMode mode);
166
167 private:
168 EventMode myLeftMode;
169 EventMode myRightMode;
170
171 // Controller menu and common emulation mappings
172 static EventMappingArray DefaultMenuMapping;
173 static EventMappingArray DefaultCommonMapping;
174 // Controller specific mappings
175 static EventMappingArray DefaultLeftJoystickMapping;
176 static EventMappingArray DefaultRightJoystickMapping;
177 static EventMappingArray DefaultLeftPaddlesMapping;
178 static EventMappingArray DefaultRightPaddlesMapping;
179 static EventMappingArray DefaultLeftKeypadMapping;
180 static EventMappingArray DefaultRightKeypadMapping;
181};
182
183#endif
184