1
2////////////////////////////////////////////////////////////
3// Headers
4////////////////////////////////////////////////////////////
5#include <SFML/Graphics.hpp>
6#include <algorithm>
7#include <sstream>
8#include <iomanip>
9#include <string>
10#include <map>
11
12
13namespace
14{
15 struct JoystickObject
16 {
17 sf::Text label;
18 sf::Text value;
19 };
20
21 typedef std::map<std::string, JoystickObject> Texts;
22 Texts texts;
23 std::ostringstream sstr;
24 float threshold = 0.1f;
25
26 // Axes labels in as C strings
27 const char* axislabels[] = {"X", "Y", "Z", "R", "U", "V", "PovX", "PovY"};
28
29 // Helper to set text entries to a specified value
30 template<typename T>
31 void set(const char* label, const T& value)
32 {
33 sstr.str("");
34 sstr << value;
35 texts[label].value.setString(sstr.str());
36 }
37
38 // Update joystick identification
39 void updateIdentification(unsigned int index)
40 {
41 sstr.str("");
42 sstr << "Joystick " << index << ":";
43 texts["ID"].label.setString(sstr.str());
44 texts["ID"].value.setString(sf::Joystick::getIdentification(index).name);
45 }
46
47 // Update joystick axes
48 void updateAxes(unsigned int index)
49 {
50 for (unsigned int j = 0; j < sf::Joystick::AxisCount; ++j)
51 {
52 if (sf::Joystick::hasAxis(index, static_cast<sf::Joystick::Axis>(j)))
53 set(axislabels[j], sf::Joystick::getAxisPosition(index, static_cast<sf::Joystick::Axis>(j)));
54 }
55 }
56
57 // Update joystick buttons
58 void updateButtons(unsigned int index)
59 {
60 for (unsigned int j = 0; j < sf::Joystick::getButtonCount(index); ++j)
61 {
62 sstr.str("");
63 sstr << "Button " << j;
64
65 set(sstr.str().c_str(), sf::Joystick::isButtonPressed(index, j));
66 }
67 }
68
69 // Helper to update displayed joystick values
70 void updateValues(unsigned int index)
71 {
72 if (sf::Joystick::isConnected(index)) {
73 // Update the label-value sf::Text objects based on the current joystick state
74 updateIdentification(index);
75 updateAxes(index);
76 updateButtons(index);
77 }
78 }
79}
80
81
82////////////////////////////////////////////////////////////
83/// Entry point of application
84///
85/// \return Application exit code
86///
87////////////////////////////////////////////////////////////
88int main()
89{
90 // Create the window of the application
91 sf::RenderWindow window(sf::VideoMode(400, 680), "Joystick", sf::Style::Close);
92 window.setVerticalSyncEnabled(true);
93
94 // Load the text font
95 sf::Font font;
96 if (!font.loadFromFile("resources/sansation.ttf"))
97 return EXIT_FAILURE;
98
99 // Set up our string conversion parameters
100 sstr.precision(2);
101 sstr.setf(std::ios::fixed | std::ios::boolalpha);
102
103 // Set up our joystick identification sf::Text objects
104 texts["ID"].label.setPosition(5.f, 5.f);
105 texts["ID"].value.setPosition(80.f, 5.f);
106
107 texts["ID"].label.setString("<Not Connected>");
108 texts["ID"].value.setString("");
109
110 // Set up our threshold sf::Text objects
111 sstr.str("");
112 sstr << threshold << " (Change with up/down arrow keys)";
113
114 texts["Threshold"].label.setPosition(5.f, 5.f + 2 * font.getLineSpacing(14));
115 texts["Threshold"].value.setPosition(80.f, 5.f + 2 * font.getLineSpacing(14));
116
117 texts["Threshold"].label.setString("Threshold:");
118 texts["Threshold"].value.setString(sstr.str());
119
120 // Set up our label-value sf::Text objects
121 for (unsigned int i = 0; i < sf::Joystick::AxisCount; ++i)
122 {
123 JoystickObject& object = texts[axislabels[i]];
124
125 object.label.setPosition(5.f, 5.f + ((i + 4) * font.getLineSpacing(14)));
126 object.label.setString(std::string(axislabels[i]) + ":");
127
128 object.value.setPosition(80.f, 5.f + ((i + 4) * font.getLineSpacing(14)));
129 object.value.setString("N/A");
130 }
131
132 for (unsigned int i = 0; i < sf::Joystick::ButtonCount; ++i)
133 {
134 sstr.str("");
135 sstr << "Button " << i;
136 JoystickObject& object = texts[sstr.str()];
137
138 object.label.setPosition(5.f, 5.f + ((sf::Joystick::AxisCount + i + 4) * font.getLineSpacing(14)));
139 object.label.setString(sstr.str() + ":");
140
141 object.value.setPosition(80.f, 5.f + ((sf::Joystick::AxisCount + i + 4) * font.getLineSpacing(14)));
142 object.value.setString("N/A");
143 }
144
145 for (Texts::iterator it = texts.begin(); it != texts.end(); ++it)
146 {
147 it->second.label.setFont(font);
148 it->second.label.setCharacterSize(14);
149 it->second.label.setFillColor(sf::Color::White);
150
151 it->second.value.setFont(font);
152 it->second.value.setCharacterSize(14);
153 it->second.value.setFillColor(sf::Color::White);
154 }
155
156 // Update initially displayed joystick values if a joystick is already connected on startup
157 for (unsigned int i = 0; i < sf::Joystick::Count; ++i)
158 {
159 if (sf::Joystick::isConnected(i))
160 {
161 updateValues(i);
162 break;
163 }
164 }
165
166 while (window.isOpen())
167 {
168 // Handle events
169 sf::Event event;
170 while (window.pollEvent(event))
171 {
172 // Window closed or escape key pressed: exit
173 if ((event.type == sf::Event::Closed) ||
174 ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)))
175 {
176 window.close();
177 break;
178 }
179 else if ((event.type == sf::Event::JoystickButtonPressed) ||
180 (event.type == sf::Event::JoystickButtonReleased) ||
181 (event.type == sf::Event::JoystickMoved) ||
182 (event.type == sf::Event::JoystickConnected))
183 {
184 // Update displayed joystick values
185 updateValues(event.joystickConnect.joystickId);
186 }
187 else if (event.type == sf::Event::JoystickDisconnected)
188 {
189 // Reset displayed joystick values to empty
190 for (Texts::iterator it = texts.begin(); it != texts.end(); ++it)
191 it->second.value.setString("N/A");
192
193 texts["ID"].label.setString("<Not Connected>");
194 texts["ID"].value.setString("");
195
196 sstr.str("");
197 sstr << threshold << " (Change with up/down arrow keys)";
198
199 texts["Threshold"].value.setString(sstr.str());
200 }
201 }
202
203 // Update threshold if the user wants to change it
204 float newThreshold = threshold;
205
206 if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
207 newThreshold += 0.1f;
208
209 if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
210 newThreshold -= 0.1f;
211
212 newThreshold = std::min(std::max(newThreshold, 0.1f), 100.0f);
213
214 if (newThreshold != threshold)
215 {
216 threshold = newThreshold;
217 window.setJoystickThreshold(threshold);
218
219 sstr.str("");
220 sstr << threshold << " (Change with up/down arrow keys)";
221
222 texts["Threshold"].value.setString(sstr.str());
223 }
224
225 // Clear the window
226 window.clear();
227
228 // Draw the label-value sf::Text objects
229 for (Texts::const_iterator it = texts.begin(); it != texts.end(); ++it)
230 {
231 window.draw(it->second.label);
232 window.draw(it->second.value);
233 }
234
235 // Display things on screen
236 window.display();
237 }
238}
239