Switch Controller
Loading...
Searching...
No Matches
Controller.h
Go to the documentation of this file.
1#pragma once
2
3#include "pch.h"
4
5#include <boost/program_options.hpp>
6
8
9using namespace std::literals;
10
12private:
13 const std::array<std::function<bool()>, 14> buttons;
14 const std::array<std::function<std::array<uint8_t, 2>()>, 3> sticks;
15
16public:
17 constexpr static auto buttonMapping = std::array{
18 "controls.y"sv, "controls.b"sv, "controls.a"sv,
19 "controls.x"sv, "controls.l"sv, "controls.r"sv,
20 "controls.xl"sv, "controls.xr"sv, "controls.Select"sv,
21 "controls.start"sv, "controls.lClick"sv, "controls.rClick"sv,
22 "controls.home"sv, "controls.capture"sv,
23 };
24
26
27 constexpr static int JOYSTICK_DEADZONE = 30;
28
29 static auto getButtons(const boost::program_options::variables_map &vm) {
30 auto modifierButton =
31 static_cast<unsigned int>(vm["controls.modifier"].as<int>());
32 auto modifier = [modifierButton] {
33 return sf::Joystick::isButtonPressed(0, modifierButton);
34 };
35 auto turboToggle = ToggleEvent{
36 [modifier, turboButton = static_cast<unsigned int>(
37 vm["controls.turbo"].as<int>())] {
38 return sf::Joystick::isButtonPressed(0, turboButton) &&
39 modifier();
40 },
41 1000ms};
42
43 std::array<std::function<bool()>, 14> buttons;
44 auto transform = [&](auto button_str) {
45 auto button_id = static_cast<unsigned int>(
46 vm[std::string{button_str}].as<int>());
47 auto event = [modifier, button_id] {
48 return sf::Joystick::isButtonPressed(0, button_id) &&
49 !modifier();
50 };
51 return [turboToggle, event,
52 turboEvent = TurboEvent{event, 20ms}]() mutable {
53 return turboToggle() ? turboEvent() : event();
54 };
55 };
56 std::transform(buttonMapping.begin(), buttonMapping.end(),
57 buttons.begin(), transform);
58 return buttons;
59 }
60
61 constexpr static auto convertSFML_Axis(float pos) {
62 // SFML works on a [-100, 100] scale
63 // this scales it to [0, 255] scale
64 float SFML_RATIO = 255.0f / 200.0f;
65 float SCALE_FACTOR = 1.4f;
66 float SCALE = SCALE_FACTOR * SFML_RATIO;
67 int OFFSET = 128;
68
69 int scaled = static_cast<int>(pos * SCALE) + OFFSET;
70 return static_cast<uint8_t>(std::clamp(scaled, 0, 255));
71 }
72
73 static auto getSticks(const boost::program_options::variables_map &vm) {
74 std::array<std::function<std::array<uint8_t, 2>()>, 3> sticks;
75
76 auto left_x_axis =
77 static_cast<sf::Joystick::Axis>(vm["controls.leftXAxis"].as<int>());
78 auto left_y_axis =
79 static_cast<sf::Joystick::Axis>(vm["controls.leftYAxis"].as<int>());
81 return std::array<uint8_t, 2>{
82 convertSFML_Axis(sf::Joystick::getAxisPosition(0, left_x_axis)),
84 sf::Joystick::getAxisPosition(0, left_y_axis))};
85 };
86
87 auto right_x_axis = static_cast<sf::Joystick::Axis>(
88 vm["controls.rightXAxis"].as<int>());
89 auto right_y_axis = static_cast<sf::Joystick::Axis>(
90 vm["controls.rightYAxis"].as<int>());
92 return std::array<uint8_t, 2>{
94 sf::Joystick::getAxisPosition(0, right_x_axis)),
96 sf::Joystick::getAxisPosition(0, right_y_axis))};
97 };
98
99 auto hat_x_axis =
100 static_cast<sf::Joystick::Axis>(vm["controls.hatXAxis"].as<int>());
101 auto hat_y_axis =
102 static_cast<sf::Joystick::Axis>(vm["controls.hatYAxis"].as<int>());
103 sticks[Controller::stickIndicies::hat] = [=] {
104 return std::array<uint8_t, 2>{
105 convertSFML_Axis(sf::Joystick::getAxisPosition(0, hat_x_axis)),
106 convertSFML_Axis(sf::Joystick::getAxisPosition(0, hat_y_axis))};
107 };
108 return sticks;
109 }
110
111 Controller(const boost::program_options::variables_map &vm)
112 : buttons(getButtons(vm)), sticks(getSticks(vm)){};
113
114 constexpr static std::array<uint8_t, 2>
115 digtalToAnalogConversion(bool up, bool right, bool down, bool left) {
116 return {uint8_t(128 + 127 * up - 128 * down),
117 uint8_t(128 + 127 * right - 128 * left)};
118 }
119
120 constexpr static std::array<bool, 4>
121 analogToDigitalConversion(std::array<uint8_t, 2> sticks) {
122 return {sticks[1] > 128 + JOYSTICK_DEADZONE,
123 sticks[0] > 128 + JOYSTICK_DEADZONE,
124 sticks[1] < 128 - JOYSTICK_DEADZONE,
125 sticks[0] < 128 - JOYSTICK_DEADZONE};
126 }
127
128 constexpr static std::array<uint8_t, 2>
129 adjustStickValueForDeadzone(std::array<uint8_t, 2> sticks) {
130 if (sticks[0] > 128 - Controller::JOYSTICK_DEADZONE &&
131 sticks[0] < 128 + Controller::JOYSTICK_DEADZONE &&
132 sticks[1] > 128 - Controller::JOYSTICK_DEADZONE &&
133 sticks[1] < 128 + Controller::JOYSTICK_DEADZONE) {
134 return {128, 128};
135 } else {
136 return sticks;
137 }
138 }
139
140 constexpr static uint8_t convertSticksToHat(std::array<uint8_t, 2> sticks) {
141 auto [up, right, down, left] = analogToDigitalConversion(sticks);
142
143 if (right && up)
144 return 1; // up right
145 if (right && down)
146 return 3; // down right
147 if (left && down)
148 return 5; // down left
149 if (left && up)
150 return 7; // up left
151 if (up)
152 return 0; // up
153 if (right)
154 return 2; // right
155 if (down)
156 return 4; // down
157 if (left)
158 return 6; // left
159
160 return 8;
161 }
162
163 std::array<uint8_t, 8> getData() const {
164 std::array<uint8_t, 8> res;
165 res[0] = 85;
166 res[1] = 0;
167 res[2] = 0;
168 for (std::size_t i = 0; i < 8; i++) {
169 res[1] |= (buttons[i]() << i);
170 }
171 for (std::size_t i = 0; i < 6; i++) {
172 res[2] |= (buttons[i + 8]() << i);
173 }
174 auto [leftX, leftY] =
176 res[3] = leftX;
177 res[4] = leftY;
178 auto [rightX, rightY] =
180 res[5] = rightX;
181 res[6] = rightY;
182 res[7] = convertSticksToHat(sticks[stickIndicies::hat]());
183 return res;
184 }
185};
Definition: Controller.h:11
static constexpr int JOYSTICK_DEADZONE
Definition: Controller.h:27
static constexpr auto buttonMapping
Definition: Controller.h:17
static auto getButtons(const boost::program_options::variables_map &vm)
Definition: Controller.h:29
static constexpr std::array< uint8_t, 2 > adjustStickValueForDeadzone(std::array< uint8_t, 2 > sticks)
Definition: Controller.h:129
static auto getSticks(const boost::program_options::variables_map &vm)
Definition: Controller.h:73
std::array< uint8_t, 8 > getData() const
Definition: Controller.h:163
static constexpr auto convertSFML_Axis(float pos)
Definition: Controller.h:61
static constexpr std::array< bool, 4 > analogToDigitalConversion(std::array< uint8_t, 2 > sticks)
Definition: Controller.h:121
static constexpr std::array< uint8_t, 2 > digtalToAnalogConversion(bool up, bool right, bool down, bool left)
Definition: Controller.h:115
stickIndicies
Definition: Controller.h:25
@ hat
Definition: Controller.h:25
@ left
Definition: Controller.h:25
@ right
Definition: Controller.h:25
static constexpr uint8_t convertSticksToHat(std::array< uint8_t, 2 > sticks)
Definition: Controller.h:140
Controller(const boost::program_options::variables_map &vm)
Definition: Controller.h:111
Definition: EventToggle.h:35
Definition: EventToggle.h:7