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 CONTROLLERMAP_HXX |
19 | #define CONTROLLERMAP_HXX |
20 | |
21 | #include <unordered_map> |
22 | #include "Event.hxx" |
23 | #include "EventHandlerConstants.hxx" |
24 | |
25 | /** |
26 | This class handles controller mappings in Stella. |
27 | |
28 | @author Thomas Jentzsch |
29 | */ |
30 | class JoyMap |
31 | { |
32 | public: |
33 | |
34 | struct JoyMapping |
35 | { |
36 | EventMode mode; |
37 | int button; // button number |
38 | JoyAxis axis; // horizontal/vertical |
39 | JoyDir adir; // axis direction (neg/pos) |
40 | int hat; // hat number |
41 | JoyHatDir hdir; // hat direction (left/right/up/down) |
42 | |
43 | JoyMapping() |
44 | : mode(EventMode(0)), button(0), |
45 | axis(JoyAxis(0)), adir(JoyDir(0)), |
46 | hat(0), hdir(JoyHatDir(0)) { } |
47 | JoyMapping(const JoyMapping& m) |
48 | : mode(m.mode), button(m.button), |
49 | axis(m.axis), adir(m.adir), |
50 | hat(m.hat), hdir(m.hdir) { } |
51 | explicit JoyMapping(EventMode c_mode, int c_button, |
52 | JoyAxis c_axis, JoyDir c_adir, |
53 | int c_hat, JoyHatDir c_hdir) |
54 | : mode(c_mode), button(c_button), |
55 | axis(c_axis), adir(c_adir), |
56 | hat(c_hat), hdir(c_hdir) { } |
57 | explicit JoyMapping(EventMode c_mode, int c_button, |
58 | JoyAxis c_axis, JoyDir c_adir) |
59 | : mode(c_mode), button(c_button), |
60 | axis(c_axis), adir(c_adir), |
61 | hat(JOY_CTRL_NONE), hdir(JoyHatDir::CENTER) { } |
62 | explicit JoyMapping(EventMode c_mode, int c_button, |
63 | int c_hat, JoyHatDir c_hdir) |
64 | : mode(c_mode), button(c_button), |
65 | axis(JoyAxis::NONE), adir(JoyDir::NONE), |
66 | hat(c_hat), hdir(c_hdir) { } |
67 | |
68 | bool operator==(const JoyMapping& other) const |
69 | { |
70 | return (mode == other.mode |
71 | && button == other.button |
72 | && axis == other.axis |
73 | && adir == other.adir |
74 | && hat == other.hat |
75 | && hdir == other.hdir |
76 | ); |
77 | } |
78 | }; |
79 | using JoyMappingArray = std::vector<JoyMapping>; |
80 | |
81 | JoyMap(); |
82 | virtual ~JoyMap() = default; |
83 | |
84 | /** Add new mapping for given event */ |
85 | void add(const Event::Type event, const JoyMapping& mapping); |
86 | void add(const Event::Type event, const EventMode mode, const int button, |
87 | const JoyAxis axis, const JoyDir adir, |
88 | const int hat = JOY_CTRL_NONE, const JoyHatDir hdir = JoyHatDir::CENTER); |
89 | void add(const Event::Type event, const EventMode mode, const int button, |
90 | const int hat, const JoyHatDir hdir); |
91 | |
92 | /** Erase mapping */ |
93 | void erase(const JoyMapping& mapping); |
94 | void erase(const EventMode mode, const int button, |
95 | const JoyAxis axis, const JoyDir adir); |
96 | void erase(const EventMode mode, const int button, |
97 | const int hat, const JoyHatDir hdir); |
98 | |
99 | /** Get event for mapping */ |
100 | Event::Type get(const JoyMapping& mapping) const; |
101 | Event::Type get(const EventMode mode, const int button, |
102 | const JoyAxis axis = JoyAxis::NONE, const JoyDir adir = JoyDir::NONE) const; |
103 | Event::Type get(const EventMode mode, const int button, |
104 | const int hat, const JoyHatDir hdir) const; |
105 | |
106 | /** Check if a mapping exists */ |
107 | bool check(const JoyMapping& mapping) const; |
108 | bool check(const EventMode mode, const int button, |
109 | const JoyAxis axis, const JoyDir adir, |
110 | const int hat = JOY_CTRL_NONE, const JoyHatDir hdir = JoyHatDir::CENTER) const; |
111 | |
112 | /** Get mapping description */ |
113 | string getEventMappingDesc(int stick, const Event::Type event, const EventMode mode) const; |
114 | |
115 | JoyMappingArray getEventMapping(const Event::Type event, const EventMode mode) const; |
116 | |
117 | string saveMapping(const EventMode mode) const; |
118 | int loadMapping(string& list, const EventMode mode); |
119 | |
120 | /** Erase all mappings for given mode */ |
121 | void eraseMode(const EventMode mode); |
122 | /** Erase given event's mapping for given mode */ |
123 | void eraseEvent(const Event::Type event, const EventMode mode); |
124 | /** clear all mappings for a modes */ |
125 | // void clear() { myMap.clear(); } |
126 | size_t size() { return myMap.size(); } |
127 | |
128 | private: |
129 | string getDesc(const Event::Type event, const JoyMapping& mapping) const; |
130 | |
131 | struct JoyHash { |
132 | size_t operator()(const JoyMapping& m)const { |
133 | return std::hash<uInt64>()((uInt64(m.mode)) // 3 bits |
134 | + ((uInt64(m.button)) * 7) // 3 bits |
135 | + (((uInt64(m.axis)) << 0) // 2 bits |
136 | | ((uInt64(m.adir)) << 2) // 2 bits |
137 | | ((uInt64(m.hat )) << 4) // 1 bit |
138 | | ((uInt64(m.hdir)) << 5) // 2 bits |
139 | ) * 61 |
140 | ); |
141 | } |
142 | }; |
143 | |
144 | std::unordered_map<JoyMapping, Event::Type, JoyHash> myMap; |
145 | }; |
146 | |
147 | #endif |
148 | |