Skip to content

Commit 6e09d45

Browse files
committed
Switch infra to use floating-point joysticks.
1 parent 6c6e5a7 commit 6e09d45

34 files changed

+505
-279
lines changed

SerialPrograms/Source/Controllers/ControllerState.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ JsonObject ControllerState::to_json() const{
2727
}
2828
void ControllerState::execute(
2929
Cancellable* scope,
30+
bool enable_logging,
3031
AbstractController& controller,
3132
Milliseconds duration
3233
) const{

SerialPrograms/Source/Controllers/ControllerState.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class ControllerState{
4040
// Execution
4141
virtual void execute(
4242
Cancellable* scope,
43+
bool enable_logging,
4344
AbstractController& controller,
4445
Milliseconds duration
4546
) const;

SerialPrograms/Source/Controllers/ControllerStateTable.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -368,24 +368,24 @@ EnumDropdownDatabase<ControllerClass> ControllerCommandTables::make_database(
368368

369369

370370

371-
std::string get_joystick_direction(uint8_t x, uint8_t y){
371+
std::string get_joystick_direction(const JoystickPosition& position){
372372
std::string direction = "";
373-
if (x > NintendoSwitch::STICK_CENTER){
374-
if (y > NintendoSwitch::STICK_CENTER){
373+
if (position.x > 0){
374+
if (position.y < 0){
375375
// right-down
376376
direction = "\u2198";
377-
}else if (y == NintendoSwitch::STICK_CENTER){
377+
}else if (position.y == 0){
378378
// right
379379
direction = "\u2192";
380380
}else{ // y < STICK_CENTER
381381
// right-up
382382
direction = "\u2197";
383383
}
384-
}else if (x == NintendoSwitch::STICK_CENTER){
385-
if (y > NintendoSwitch::STICK_CENTER){
384+
}else if (position.x == 0){
385+
if (position.y < 0){
386386
// down
387387
direction = "\u2193";
388-
}else if (y == NintendoSwitch::STICK_CENTER){
388+
}else if (position.y == 0){
389389
// neutral
390390
direction = "neutral";
391391
}else{ // y < STICK_CENTER
@@ -394,10 +394,10 @@ std::string get_joystick_direction(uint8_t x, uint8_t y){
394394
}
395395

396396
}else { // x < STICK_CENTER
397-
if (y > NintendoSwitch::STICK_CENTER){
397+
if (position.y < 0){
398398
// left-down
399399
direction = "\u2199";
400-
}else if (y == NintendoSwitch::STICK_CENTER){
400+
}else if (position.y == 0){
401401
// left
402402
direction = "\u2190";
403403
}else{ // y < STICK_CENTER

SerialPrograms/Source/Controllers/ControllerStateTable.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "Common/Cpp/Options/GroupOption.h"
1212
#include "Common/Cpp/Options/EnumDropdownOption.h"
1313
#include "Common/Cpp/Options/EditableTableOption.h"
14+
#include "Controllers/Joystick.h"
1415
#include "ControllerTypes.h"
1516
#include "ControllerState.h"
1617

@@ -65,7 +66,7 @@ class ControllerCommandTable : public EditableTableOption{
6566
for (std::unique_ptr<ControllerStateRow>& command : table){
6667
Milliseconds duration;
6768
std::unique_ptr<ControllerState> state = command->get_state(duration);
68-
state->execute(&scope, controller, duration);
69+
state->execute(&scope, true, controller, duration);
6970
}
7071
}
7172

@@ -123,7 +124,7 @@ class ControllerCommandTables : public GroupOption, public ConfigOption::Listene
123124
};
124125

125126

126-
std::string get_joystick_direction(uint8_t x, uint8_t y);
127+
std::string get_joystick_direction(const JoystickPosition& position);
127128

128129

129130

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* Joystick
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include <cmath>
8+
#include "Joystick.h"
9+
10+
namespace PokemonAutomation{
11+
12+
13+
JoystickCardinal::operator JoystickPosition() const{
14+
double radians = angle * (3.1415926535897932385 / 180);
15+
return JoystickPosition(
16+
magnitude * std::sin(radians),
17+
magnitude * std::cos(radians)
18+
);
19+
}
20+
21+
22+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* Joystick
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_Controllers_Joystick_H
8+
#define PokemonAutomation_Controllers_Joystick_H
9+
10+
namespace PokemonAutomation{
11+
12+
13+
struct JoystickPosition{
14+
double x = 0.0;
15+
double y = 0.0;
16+
17+
JoystickPosition() = default;
18+
JoystickPosition(double x, double y)
19+
: x(x), y(y)
20+
{}
21+
22+
bool is_neutral() const{
23+
return x == 0 && y == 0;
24+
}
25+
26+
friend bool operator==(const JoystickPosition& lhs, const JoystickPosition& rhs){
27+
return lhs.x == rhs.x && lhs.y == rhs.y;
28+
}
29+
friend bool operator!=(const JoystickPosition& lhs, const JoystickPosition& rhs){
30+
return lhs.x != rhs.x || lhs.y != rhs.y;
31+
}
32+
};
33+
34+
35+
struct JoystickCardinal{
36+
double magnitude = 0.0;
37+
double angle = 0.0;
38+
39+
JoystickCardinal(double magnitude, double angle)
40+
: magnitude(magnitude), angle(angle)
41+
{}
42+
43+
operator JoystickPosition() const;
44+
};
45+
46+
47+
48+
}
49+
#endif

SerialPrograms/Source/NintendoSwitch/Controllers/Joycon/NintendoSwitch_Joycon.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "CommonTools/Async/SuperControlSession.tpp"
1010
#include "ControllerInput/ControllerInput.h"
1111
#include "ControllerInput/Keyboard/KeyboardInput_State.h"
12+
#include "Controllers/JoystickTools.h"
1213
#include "Controllers/ControllerTypes.h"
1314
#include "NintendoSwitch/NintendoSwitch_Settings.h"
1415
#include "NintendoSwitch/Controllers/NintendoSwitch_VirtualControllerState.h"
@@ -59,6 +60,42 @@ JoyconController::JoyconController(Logger& logger, ControllerClass controller_cl
5960
JoyconController::~JoyconController(){
6061
}
6162

63+
64+
65+
void JoyconController::issue_joystick(
66+
Cancellable* cancellable,
67+
Milliseconds delay, Milliseconds hold, Milliseconds cooldown,
68+
uint8_t x, uint8_t y
69+
){
70+
issue_joystick(
71+
cancellable,
72+
delay, hold, cooldown,
73+
JoystickPosition(
74+
JoystickTools::linear_u8_to_float(x),
75+
-JoystickTools::linear_u8_to_float(y)
76+
)
77+
);
78+
}
79+
void JoyconController::issue_full_controller_state(
80+
Cancellable* cancellable,
81+
bool enable_logging,
82+
Milliseconds duration,
83+
Button button,
84+
uint8_t joystick_x, uint8_t joystick_y
85+
){
86+
issue_full_controller_state(
87+
cancellable,
88+
enable_logging,
89+
duration,
90+
button,
91+
JoystickPosition(
92+
JoystickTools::linear_u8_to_float(joystick_x),
93+
-JoystickTools::linear_u8_to_float(joystick_y)
94+
)
95+
);
96+
}
97+
98+
6299
void JoyconController::run_controller_input(const ControllerInputState& state){
63100

64101
if (state.type() != ControllerInputType::HID_Keyboard){
@@ -85,7 +122,7 @@ void JoyconController::run_controller_input(const ControllerInputState& state){
85122
deltas.to_state(controller_state);
86123

87124
WallClock timestamp = current_time();
88-
controller_state.execute(nullptr, *this, 2000ms);
125+
controller_state.execute(nullptr, false, *this, 2000ms);
89126

90127
on_command_input(timestamp, controller_state);
91128
}

SerialPrograms/Source/NintendoSwitch/Controllers/Joycon/NintendoSwitch_Joycon.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define PokemonAutomation_NintendoSwitch_Joycon_H
99

1010
#include "Common/Cpp/Containers/Pimpl.h"
11+
#include "Controllers/Joystick.h"
1112
#include "NintendoSwitch/Controllers/NintendoSwitch_ControllerButtons.h"
1213
#include "Controllers/ControllerTypes.h"
1314
#include "Controllers/Controller.h"
@@ -77,10 +78,15 @@ class JoyconController : public AbstractController{
7778
Button button
7879
) = 0;
7980

80-
virtual void issue_joystick(
81+
void issue_joystick(
8182
Cancellable* cancellable,
8283
Milliseconds delay, Milliseconds hold, Milliseconds cooldown,
8384
uint8_t x, uint8_t y
85+
);
86+
virtual void issue_joystick(
87+
Cancellable* cancellable,
88+
Milliseconds delay, Milliseconds hold, Milliseconds cooldown,
89+
const JoystickPosition& position
8490
) = 0;
8591

8692
// Gyro: Accelerometer (experimental - API subject to change)
@@ -134,12 +140,19 @@ class JoyconController : public AbstractController{
134140
// (such as Joycon gyro or new stuff in Switch 2), we can simply add
135141
// overloads to this and gate them behind features.
136142
//
137-
virtual void issue_full_controller_state(
143+
void issue_full_controller_state(
138144
Cancellable* cancellable,
139145
bool enable_logging,
140146
Milliseconds duration,
141147
Button button,
142148
uint8_t joystick_x, uint8_t joystick_y
149+
);
150+
virtual void issue_full_controller_state(
151+
Cancellable* cancellable,
152+
bool enable_logging,
153+
Milliseconds duration,
154+
Button button,
155+
const JoystickPosition& joystick
143156
) = 0;
144157

145158

SerialPrograms/Source/NintendoSwitch/Controllers/Joycon/NintendoSwitch_JoyconState.cpp

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
*
55
*/
66

7+
#include "Common/Cpp/PrettyPrint.h"
78
#include "Common/Cpp/Json/JsonObject.h"
9+
#include "Controllers/JoystickTools.h"
810
#include "NintendoSwitch_Joycon.h"
911
#include "NintendoSwitch_JoyconState.h"
1012

@@ -17,8 +19,7 @@ namespace NintendoSwitch{
1719

1820
void JoyconState::clear(){
1921
buttons = BUTTON_NONE;
20-
joystick_x = 128;
21-
joystick_y = 128;
22+
joystick = JoystickPosition();
2223
}
2324
bool JoyconState::operator==(const ControllerState& x) const{
2425
if (typeid(*this) != typeid(x)){
@@ -30,18 +31,13 @@ bool JoyconState::operator==(const ControllerState& x) const{
3031
if (buttons != r.buttons){
3132
return false;
3233
}
33-
if (joystick_x != r.joystick_x){
34-
return false;
35-
}
36-
if (joystick_y != r.joystick_y){
34+
if (joystick != r.joystick){
3735
return false;
3836
}
3937
return true;
4038
}
4139
bool JoyconState::is_neutral() const{
42-
return buttons == 0
43-
&& joystick_x == 128
44-
&& joystick_y == 128;
40+
return buttons == 0 && joystick.is_neutral();
4541
}
4642

4743
void JoyconState::load_json(const JsonObject& json){
@@ -58,35 +54,48 @@ void JoyconState::load_json(const JsonObject& json){
5854
buttons = string_to_button(buttons_string);
5955
}
6056

57+
6158
// Backwards compatibility.
62-
json.read_integer(joystick_x, "joystick_x", 0, 255);
63-
json.read_integer(joystick_y, "joystick_y", 0, 255);
59+
{
60+
uint8_t joystick_x = 128;
61+
uint8_t joystick_y = 128;
62+
63+
json.read_integer(joystick_x, "joystick_x", 0, 255);
64+
json.read_integer(joystick_y, "joystick_y", 0, 255);
65+
66+
json.read_integer(joystick_x, "jx", 0, 255);
67+
json.read_integer(joystick_y, "jy", 0, 255);
68+
69+
joystick.x = JoystickTools::linear_u8_to_float(joystick_x);
70+
joystick.y = -JoystickTools::linear_u8_to_float(joystick_y);
71+
}
6472

65-
json.read_integer(joystick_x, "jx", 0, 255);
66-
json.read_integer(joystick_y, "jy", 0, 255);
73+
json.read_float(joystick.x, "jxf");
74+
json.read_float(joystick.y, "jyf");
6775
}
6876
JsonObject JoyconState::to_json() const{
6977
JsonObject obj;
7078
if (buttons != BUTTON_NONE){
7179
obj["buttons"] = button_to_string(buttons);
7280
}
73-
if (joystick_x != STICK_CENTER || joystick_y != STICK_CENTER){
74-
obj["jx"] = joystick_x;
75-
obj["jy"] = joystick_y;
81+
if (!joystick.is_neutral()){
82+
obj["jxf"] = joystick.x;
83+
obj["jyf"] = joystick.y;
7684
}
7785
return obj;
7886
}
7987
void JoyconState::execute(
8088
Cancellable* scope,
89+
bool enable_logging,
8190
AbstractController& controller,
8291
Milliseconds duration
8392
) const{
8493
controller.cast_with_exception<JoyconController>().issue_full_controller_state(
8594
scope,
86-
true,
95+
enable_logging,
8796
duration,
8897
buttons,
89-
joystick_x, joystick_y
98+
joystick
9099
);
91100
}
92101
std::string JoyconState::to_cpp(Milliseconds hold, Milliseconds release) const{
@@ -97,7 +106,7 @@ std::string JoyconState::to_cpp(Milliseconds hold, Milliseconds release) const{
97106
non_neutral_field = 0;
98107
non_neutral_fields++;
99108
}
100-
if (joystick_x != STICK_CENTER || joystick_y != STICK_CENTER){
109+
if (!joystick.is_neutral()){
101110
non_neutral_field = 1;
102111
non_neutral_fields++;
103112
}
@@ -114,7 +123,7 @@ std::string JoyconState::to_cpp(Milliseconds hold, Milliseconds release) const{
114123
std::string ret;
115124
ret += "pbf_controller_state(context, "
116125
+ button_to_code_string(buttons) + ", "
117-
+ std::to_string(joystick_x) + ", " + std::to_string(joystick_y) + ", "
126+
+ tostr_fixed(joystick.x, 3) + ", " + tostr_fixed(joystick.y, 3) + ", "
118127
+ hold_str +");\n";
119128
if (release != Milliseconds(0)){
120129
ret += "pbf_wait(context, " + release_str + ");\n";
@@ -128,7 +137,7 @@ std::string JoyconState::to_cpp(Milliseconds hold, Milliseconds release) const{
128137
+ hold_str + ", " + release_str + ");\n";
129138
case 1:
130139
return "pbf_move_joystick(context, "
131-
+ std::to_string(joystick_x) + ", " + std::to_string(joystick_y) + ", "
140+
+ tostr_fixed(joystick.x, 3) + ", " + tostr_fixed(joystick.y, 3) + ", "
132141
+ hold_str + ", " + release_str + ");\n";
133142
}
134143
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Impossible state.");

0 commit comments

Comments
 (0)