21 #include <JoystickTranslator.h> 23 #include <rapidjson/filereadstream.h> 24 #include <rapidjson/document.h> 25 #include <sys/types.h> 27 #include <SFML/Window.hpp> 28 #include <IJoystickTranslation.h> 29 #include <JoystickTranslation.h> 35 JoystickTranslator::JoystickTranslator() {
44 void JoystickTranslator::init(
string filePath) {
46 struct stat filestatus;
47 stat(filePath.c_str(), &filestatus);
48 const unsigned long long size = filestatus.st_size;
50 std::FILE *file = fopen(filePath.c_str(),
"r");
51 char readBuffer[100000];
52 FileReadStream rs(file, readBuffer, size);
54 jsonConfig =
new Document();
55 jsonConfig->ParseStream<kParseCommentsFlag>(rs);
57 readDocument(jsonConfig);
58 }
catch (std::string error) {
59 Logger::logError(
"Failed reading controls: " + error);
63 void JoystickTranslator::updateMapping() {
65 readDocument(jsonConfig);
66 }
catch (std::string error) {
67 Logger::logError(
"Failed reading controls: " + error);
71 JoystickTranslator::~JoystickTranslator() {
75 void JoystickTranslator::readDocument(Document *doc) {
76 check(doc->IsArray(),
"Document was not array.");
77 bool joysticksFound[8] = {
false,
false,
false,
false,
false,
false,
false,
false};
79 bool defFound =
false;
80 for (SizeType i = 0; i < doc->Size(); i++) {
81 int devId = (*doc)[i][
"deviceID"].GetInt();
82 int vendId = (*doc)[i][
"vendorID"].GetInt();
84 while ((js = getJoystick(devId, vendId, js + 1)) != -1) {
85 readMappings(&((*doc)[i][
"mappings"]), js,
false);
86 joysticksFound[js] =
true;
88 if ((*doc)[i].HasMember(
"default") && (*doc)[i][
"default"].GetBool()) {
90 def = &(*doc)[i][
"mappings"];
94 throw "There was no default mapping.";
95 for (
unsigned int found = 0; found < 8; found++) {
96 if (sf::Joystick::isConnected(found) && !joysticksFound[found])
97 readMappings(def, found,
true);
101 void JoystickTranslator::readMappings(Value *mappings,
unsigned int joystick,
bool defaultMapping) {
102 check(mappings->IsArray(),
"The mappings wasn't an array.");
104 for (SizeType i = 0; i < mappings->Size(); i++) {
105 string type = (*mappings)[i][
"type"].GetString();
106 string button = (*mappings)[i][
"xbox"].GetString();
107 if (type ==
"button") {
108 translations.back().addButton(buttonFromString(button),
109 decideOnButtonRetriever(&(*mappings)[i][
"generic"]));
110 }
else if (type ==
"axis") {
111 translations.back().addAxis(axisFromString(button),
112 decideOnAxisRetriever(&(*mappings)[i][
"generic"], button));
114 throw "Invalid type in button " + button;
119 JoystickTranslation::valueRetriever JoystickTranslator::decideOnButtonRetriever(Value *mapData) {
120 check(mapData->IsObject(),
"value wasn't object when checking button generic.");
121 string type = (*mapData)[
"type"].GetString();
122 if (type ==
"button")
123 return JoystickTranslation::buttonValueRetriever((*mapData)[
"buttonID"].GetUint());
124 else if (type ==
"axis") {
125 return JoystickTranslation::buttonFromAxisRetriever(
126 SFMLAxisFromString((*mapData)[
"name"].GetString()));
127 }
else if (type ==
"halfAxis") {
128 return JoystickTranslation::buttonFromHalfAxisRetriever(
129 SFMLAxisFromString((*mapData)[
"name"].GetString()),
130 (*mapData)[
"positiveElseNegative"].GetBool());
131 }
else if (type ==
"none") {
132 return JoystickTranslation::valRetriever(0.0f);
134 throw "Unknown type: " + type +
" when deciding button retriever.";
137 JoystickTranslation::valueRetriever JoystickTranslator::decideOnAxisRetriever(Value *mapData,
string axisName) {
138 check(mapData->IsObject(),
"value wasn't object when checking button generic.");
139 string type = (*mapData)[
"type"].GetString();
140 if (type ==
"button")
141 return JoystickTranslation::axisFromButtonRetriever((*mapData)[
"buttonID"].GetUint());
142 else if (type ==
"axis")
143 return JoystickTranslation::axisValueRetriever(
144 SFMLAxisFromString(
string((*mapData)[
"name"].GetString())), (*mapData)[
"inverted"].GetBool());
145 else if (type ==
"buttons")
146 return JoystickTranslation::axisFromButtonsRetriever((*mapData)[
"buttonNeg"].GetUint(),
147 (*mapData)[
"buttonPos"].GetUint());
148 else if (type ==
"none")
149 return JoystickTranslation::valRetriever(axisName ==
"RT" || axisName ==
"LT" ? -100.0f : 0.0f);
151 throw "Unknown type: " + type +
" when deciding axis retriever.";
154 int JoystickTranslator::getJoystick(
unsigned int devId,
unsigned int vendId,
unsigned int startAt = 0) {
155 for (
unsigned int i = startAt; i < sf::Joystick::Count; i++) {
156 sf::Joystick::Identification
id = sf::Joystick::getIdentification(i);
157 if (
id.productId == devId &&
id.vendorId == vendId)
163 void JoystickTranslator::check(
bool ch,
string message) {
169 if (joystickID >= sf::Joystick::Count)
170 throw std::invalid_argument(
"The parameter joystick was " + std::to_string(joystickID) +
171 " but must be less than " + std::to_string(sf::Joystick::Count));
172 for (
auto it = translations.begin(); it != translations.end(); ++it) {
173 if ((*it).getJoystickID() == joystickID)
176 throw std::invalid_argument(
"The joystick " + std::to_string(joystickID) +
" isn't connected.");
179 IJoystickTranslation::Button JoystickTranslator::buttonFromString(std::string name) {
181 return IJoystickTranslation::Button::X;
183 return IJoystickTranslation::Button::A;
185 return IJoystickTranslation::Button::B;
187 return IJoystickTranslation::Button::Y;
189 return IJoystickTranslation::Button::START;
191 return IJoystickTranslation::Button::BACK;
193 return IJoystickTranslation::Button::GUIDE;
195 return IJoystickTranslation::Button::LB;
197 return IJoystickTranslation::Button::RB;
198 if (name ==
"LEFT_THUMBSTICK_PUSH")
199 return IJoystickTranslation::Button::LEFT_THUMBSTICK_PUSH;
200 if (name ==
"RIGHT_THUMBSTICK_PUSH")
201 return IJoystickTranslation::Button::RIGHT_THUMBSTICK_PUSH;
202 throw std::invalid_argument(name +
" is not a button.");
205 IJoystickTranslation::Axis JoystickTranslator::axisFromString(std::string name) {
206 if (name ==
"DPAD_X")
207 return IJoystickTranslation::Axis::DPAD_X;
208 if (name ==
"DPAD_Y")
209 return IJoystickTranslation::Axis::DPAD_Y;
210 if (name ==
"LEFT_THUMBSTICK_X")
211 return IJoystickTranslation::Axis::LEFT_THUMBSTICK_X;
212 if (name ==
"LEFT_THUMBSTICK_Y")
213 return IJoystickTranslation::Axis::LEFT_THUMBSTICK_Y;
214 if (name ==
"RIGHT_THUMBSTICK_X")
215 return IJoystickTranslation::Axis::RIGHT_THUMBSTICK_X;
216 if (name ==
"RIGHT_THUMBSTICK_Y")
217 return IJoystickTranslation::Axis::RIGHT_THUMBSTICK_Y;
219 return IJoystickTranslation::Axis::LT;
221 return IJoystickTranslation::Axis::RT;
222 throw std::invalid_argument(name +
" is not an axis.");
225 sf::Joystick::Axis JoystickTranslator::SFMLAxisFromString(std::string name) {
227 return sf::Joystick::Axis::X;
229 return sf::Joystick::Axis::PovX;
231 return sf::Joystick::Axis::PovY;
233 return sf::Joystick::Axis::Y;
235 return sf::Joystick::Axis::Z;
237 return sf::Joystick::Axis::R;
239 return sf::Joystick::Axis::U;
241 return sf::Joystick::Axis::V;
242 throw std::invalid_argument(name +
" is not an SFML axis.");