Skip to content

Commit e6c172f

Browse files
committed
Keyboard FCE.
1 parent 3c5b0e3 commit e6c172f

17 files changed

+385
-23
lines changed

SerialPrograms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,7 @@ file(GLOB MAIN_SOURCES
685685
Source/ComputerPrograms/Framework/ComputerProgramSession.h
686686
Source/ComputerPrograms/Framework/ComputerProgramWidget.cpp
687687
Source/ComputerPrograms/Framework/ComputerProgramWidget.h
688+
Source/Controllers/Controller.cpp
688689
Source/Controllers/Controller.h
689690
Source/Controllers/ControllerConnection.cpp
690691
Source/Controllers/ControllerConnection.h
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* Controller
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include "Common/Cpp/Exceptions.h"
8+
#include "Controller.h"
9+
10+
namespace PokemonAutomation{
11+
12+
13+
14+
void AbstractController::throw_bad_cast(const char* desired_typename){
15+
throw UserSetupError(
16+
logger(),
17+
std::string("Incompatible Controller:\n\n") +
18+
"Required:\n " + desired_typename + "\n"
19+
"Actual:\n " + name()
20+
);
21+
}
22+
23+
24+
25+
}
26+
27+

SerialPrograms/Source/Controllers/Controller.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ class AbstractController{
4242
virtual RecursiveThrottler& logging_throttler() = 0;
4343

4444

45+
public:
46+
template <typename ControllerType>
47+
ControllerType* cast(){
48+
return dynamic_cast<ControllerType*>(this);
49+
}
50+
template <typename ControllerType>
51+
ControllerType& cast_with_exception(){
52+
ControllerType* controller = dynamic_cast<ControllerType*>(this);
53+
if (!controller){
54+
throw_bad_cast(ControllerType::NAME);
55+
}
56+
return *controller;
57+
}
58+
private:
59+
void throw_bad_cast(const char* desired_typename);
60+
61+
4562
public:
4663
// Static Information
4764

@@ -210,6 +227,12 @@ class ControllerContext final : public CancellableScope{
210227
{
211228
attach(parent);
212229
}
230+
template <typename T>
231+
ControllerContext(ControllerContext<T>& context)
232+
: m_controller(context.controller().template cast_with_exception<Type>())
233+
{
234+
attach(context);
235+
}
213236
virtual ~ControllerContext(){
214237
detach();
215238
}
@@ -267,6 +290,9 @@ class ControllerContext final : public CancellableScope{
267290

268291

269292

293+
using AbstractControllerContext = ControllerContext<AbstractController>;
294+
295+
270296

271297

272298
}

SerialPrograms/Source/NintendoSwitch/NintendoSwitch_ConsoleHandle.h

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,7 @@ class ConsoleHandle : public VideoStream{
4343

4444
template <typename ControllerType = AbstractController>
4545
ControllerType& controller(){
46-
ControllerType* ret = dynamic_cast<ControllerType*>(&m_controller);
47-
if (ret){
48-
return *ret;
49-
}
50-
throw UserSetupError(
51-
logger(),
52-
std::string("Incompatible Controller:\n\n") +
53-
"Required:\n " + ControllerType::NAME + "\n"
54-
"Actual:\n " + m_controller.name()
55-
);
46+
return m_controller.cast_with_exception<ControllerType>();
5647
}
5748

5849
operator Logger&(){ return logger(); }

SerialPrograms/Source/NintendoSwitch/NintendoSwitch_Settings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ ConsoleSettings::ConsoleSettings()
151151
PA_ADD_OPTION(SWITCH1_KEYBOARD_ENTRY0);
152152
PA_ADD_OPTION(SWITCH2_DIGIT_ENTRY0);
153153
PA_ADD_OPTION(SWITCH2_KEYBOARD_ENTRY0);
154+
PA_ADD_OPTION(KEYBOARD_CONTROLLER_TIMINGS);
154155
}
155156
PA_ADD_STATIC(KEYBOARD_SECTION);
156157
PA_ADD_OPTION(KEYBOARD_MAPPINGS);

SerialPrograms/Source/NintendoSwitch/NintendoSwitch_Settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class ConsoleSettings : public BatchOption{
5959
KeyboardEntryTimingsOption SWITCH1_KEYBOARD_ENTRY0;
6060
DigitEntryTimingsOption SWITCH2_DIGIT_ENTRY0;
6161
KeyboardEntryTimingsOption SWITCH2_KEYBOARD_ENTRY0;
62+
KeyboardControllerTimingsOption KEYBOARD_CONTROLLER_TIMINGS;
6263

6364
SectionDividerOption KEYBOARD_SECTION;
6465
KeyboardMappingOption KEYBOARD_MAPPINGS;

SerialPrograms/Source/NintendoSwitch/Options/NintendoSwitch_CodeEntrySettingsOption.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,35 @@ KeyboardEntryTimingsOption::KeyboardEntryTimingsOption(bool switch2)
131131

132132

133133

134+
KeyboardControllerTimingsOption::KeyboardControllerTimingsOption()
135+
: GroupOption(
136+
"Keyboard Controller Timings",
137+
LockMode::UNLOCK_WHILE_RUNNING,
138+
GroupOption::EnableMode::ALWAYS_ENABLED, true
139+
)
140+
, TIME_UNIT(
141+
"<b>Time Unit:</b><br>Timesteps should increment in multiples of this unit.",
142+
LockMode::UNLOCK_WHILE_RUNNING,
143+
PreloadSettings::instance().DEVELOPER_MODE ? "24 ms" : "40 ms"
144+
)
145+
, HOLD(
146+
"<b>Hold:</b><br>Duration to hold each key press down.",
147+
LockMode::UNLOCK_WHILE_RUNNING,
148+
"48 ms"
149+
)
150+
, COOLDOWN(
151+
"<b>Hold:</b><br>Do not reuse a key until this long after it is reused.",
152+
LockMode::UNLOCK_WHILE_RUNNING,
153+
"24 ms"
154+
)
155+
{
156+
PA_ADD_OPTION(TIME_UNIT);
157+
PA_ADD_OPTION(HOLD);
158+
PA_ADD_OPTION(COOLDOWN);
159+
}
160+
161+
162+
134163

135164

136165

SerialPrograms/Source/NintendoSwitch/Options/NintendoSwitch_CodeEntrySettingsOption.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ class KeyboardEntryTimingsOption : public GroupOption{
5858
MillisecondsOption COOLDOWN;
5959
};
6060

61+
class KeyboardControllerTimingsOption : public GroupOption{
62+
public:
63+
KeyboardControllerTimingsOption();
64+
65+
public:
66+
MillisecondsOption TIME_UNIT;
67+
MillisecondsOption HOLD;
68+
MillisecondsOption COOLDOWN;
69+
};
70+
6171

6272

6373

SerialPrograms/Source/NintendoSwitch/Programs/FastCodeEntry/NintendoSwitch_KeyboardCodeEntry.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,118 @@ namespace NintendoSwitch{
2323
namespace FastCodeEntry{
2424

2525

26+
27+
28+
void keyboard_enter_code(
29+
ConsoleHandle& console, AbstractControllerContext& context,
30+
KeyboardLayout keyboard_layout, const std::string& code,
31+
bool include_plus
32+
){
33+
auto* keyboard = context->cast<HidControllers::Keyboard>();
34+
if (keyboard){
35+
HidControllers::KeyboardContext subcontext(context);
36+
keyboard_enter_code(console, subcontext, code, include_plus);
37+
return;
38+
}
39+
40+
auto* procon = context->cast<ProController>();
41+
if (procon){
42+
ProControllerContext subcontext(context);
43+
keyboard_enter_code(console, subcontext, keyboard_layout, code, include_plus);
44+
return;
45+
}
46+
47+
throw UserSetupError(
48+
console, "Unsupported controller type."
49+
);
50+
}
51+
52+
53+
54+
55+
56+
void keyboard_enter_code(
57+
ConsoleHandle& console, HidControllers::KeyboardContext& context,
58+
const std::string& code,
59+
bool include_plus
60+
){
61+
using namespace HidControllers;
62+
63+
Milliseconds delay = ConsoleSettings::instance().KEYBOARD_CONTROLLER_TIMINGS.TIME_UNIT;
64+
Milliseconds hold = ConsoleSettings::instance().KEYBOARD_CONTROLLER_TIMINGS.HOLD;
65+
Milliseconds cool = ConsoleSettings::instance().KEYBOARD_CONTROLLER_TIMINGS.COOLDOWN;
66+
67+
static const std::map<char, KeyboardKey> MAP{
68+
{'1', KeyboardKey::KEY_1},
69+
{'2', KeyboardKey::KEY_2},
70+
{'3', KeyboardKey::KEY_3},
71+
{'4', KeyboardKey::KEY_4},
72+
{'5', KeyboardKey::KEY_5},
73+
{'6', KeyboardKey::KEY_6},
74+
{'7', KeyboardKey::KEY_7},
75+
{'8', KeyboardKey::KEY_8},
76+
{'9', KeyboardKey::KEY_9},
77+
{'0', KeyboardKey::KEY_0},
78+
79+
{'Q', KeyboardKey::KEY_Q},
80+
{'W', KeyboardKey::KEY_W},
81+
{'E', KeyboardKey::KEY_E},
82+
{'R', KeyboardKey::KEY_R},
83+
{'T', KeyboardKey::KEY_T},
84+
{'Y', KeyboardKey::KEY_Y},
85+
{'U', KeyboardKey::KEY_U},
86+
{'P', KeyboardKey::KEY_P},
87+
88+
{'A', KeyboardKey::KEY_A},
89+
{'S', KeyboardKey::KEY_S},
90+
{'D', KeyboardKey::KEY_D},
91+
{'F', KeyboardKey::KEY_F},
92+
{'G', KeyboardKey::KEY_G},
93+
{'H', KeyboardKey::KEY_H},
94+
{'J', KeyboardKey::KEY_J},
95+
{'K', KeyboardKey::KEY_K},
96+
{'L', KeyboardKey::KEY_L},
97+
98+
{'X', KeyboardKey::KEY_X},
99+
{'C', KeyboardKey::KEY_C},
100+
{'V', KeyboardKey::KEY_V},
101+
{'B', KeyboardKey::KEY_B},
102+
{'N', KeyboardKey::KEY_N},
103+
{'M', KeyboardKey::KEY_M},
104+
};
105+
106+
for (char ch : code){
107+
auto iter = MAP.find(ch);
108+
if (iter == MAP.end()){
109+
throw_and_log<OperationFailedException>(
110+
console, ErrorReport::NO_ERROR_REPORT,
111+
"Invalid code character."
112+
);
113+
}
114+
context->issue_key(&context, delay, hold, cool, iter->second);
115+
}
116+
117+
if (include_plus){
118+
context->issue_key(&context, delay, hold, cool, KeyboardKey::KEY_ENTER);
119+
context->issue_key(&context, delay, hold, cool, KeyboardKey::KEY_ENTER);
120+
context->issue_key(&context, delay, hold, cool, KeyboardKey::KEY_ENTER);
121+
}
122+
}
123+
124+
125+
126+
127+
128+
129+
130+
131+
132+
133+
134+
135+
136+
137+
26138
struct KeyboardEntryPosition{
27139
uint8_t row;
28140
uint8_t col;

SerialPrograms/Source/NintendoSwitch/Programs/FastCodeEntry/NintendoSwitch_KeyboardCodeEntry.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define PokemonAutomation_NintendoSwitch_KeyboardCodeEntry_H
99

1010
#include <string>
11+
#include "Controllers/HidControllers/HID_Keyboard.h"
1112
#include "NintendoSwitch/Options/NintendoSwitch_CodeEntrySettingsOption.h"
1213
#include "NintendoSwitch/Controllers/NintendoSwitch_ProController.h"
1314
#include "NintendoSwitch/NintendoSwitch_ConsoleHandle.h"
@@ -18,6 +19,19 @@ namespace FastCodeEntry{
1819

1920

2021

22+
// Automatically select between keyboard or pro controller depending on the
23+
// controller type.
24+
void keyboard_enter_code(
25+
ConsoleHandle& console, AbstractControllerContext& context,
26+
KeyboardLayout keyboard_layout, const std::string& code,
27+
bool include_plus
28+
);
29+
30+
void keyboard_enter_code(
31+
ConsoleHandle& console, HidControllers::KeyboardContext& context,
32+
const std::string& code,
33+
bool include_plus
34+
);
2135
void keyboard_enter_code(
2236
ConsoleHandle& console, ProControllerContext& context,
2337
KeyboardLayout keyboard_layout, const std::string& code,

0 commit comments

Comments
 (0)