Skip to content

Commit 91b6a6d

Browse files
committed
Initial work on color table.
1 parent 719abff commit 91b6a6d

File tree

7 files changed

+387
-5
lines changed

7 files changed

+387
-5
lines changed
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
/* Nintendo Switch Controller Settings
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include "NintendoSwitch_ControllerSettings.h"
8+
9+
namespace PokemonAutomation{
10+
namespace NintendoSwitch{
11+
12+
13+
14+
struct OfficialJoyconColors{
15+
std::string name;
16+
uint32_t left_body;
17+
uint32_t left_buttons;
18+
uint32_t right_body;
19+
uint32_t right_buttons;
20+
};
21+
22+
const std::vector<OfficialJoyconColors>& OFFICIAL_JOYCON_COLORS(){
23+
// From: https://switchbrew.org/wiki/Joy-Con#Colors
24+
const static std::vector<OfficialJoyconColors> database{
25+
{"Developer Black", 0x313131, 0x0F0F0F, 0x313131, 0x0F0F0F},
26+
27+
{"Stock: Grey / Grey", 0x828282, 0x0F0F0F, 0x828282, 0x0F0F0F},
28+
{"Stock: Neon Blue / Neon Red", 0x0AB9E6, 0x001E1E, 0xFF3C28, 0x1E0A0A},
29+
{"Stock: OLED White", 0xE6E6E6, 0x323232, 0xE6E6E6, 0x323232},
30+
31+
{"Neon Red / Neon Blue", 0xFF3C28, 0x1E0A0A, 0x0AB9E6, 0x001E1E},
32+
{"Blue / Neon Yellow", 0x4655F5, 0x00000A, 0xE6FF00, 0x142800},
33+
{"Neon Green / Neon Pink", 0x1EDC00, 0x002800, 0xFF3278, 0x28001E},
34+
{"Neon Purple / Neon Orange", 0xB400E6, 0x140014, 0xFAA005, 0x0F0A00},
35+
{"Pastel Pink / Pastel Pink", 0xFFAFAF, 0x372D2D, 0xFFAFAF, 0x372D2D},
36+
{"Pastel Pink / Pastel Yellow", 0xFFAFAF, 0x372D2D, 0xF5FF82, 0x32332D},
37+
{"Pastel Purple / Pastel Green", 0xF0CBEB, 0x373037, 0xBCFFC8, 0x2D322D},
38+
39+
{"Super Mario Odyssey Edition Red", 0xE10F00, 0x280A0A, 0xE10F00, 0x280A0A},
40+
{"Let's Go! Pikachu and Eevee", 0xC88C32, 0x281900, 0xFFDC00, 0x322800},
41+
{"Nintendo Labo Creators Contest Edition", 0xD7AA73, 0x1E1914, 0xD7AA73, 0x1E1914},
42+
{"Dragon Quest XI S Lotto Edition", 0x1473FA, 0x00000F, 0x1473FA, 0x00000F},
43+
// {"Disney Tsum Tsum Festival Edition", 0xB400E6, 0x140014, 0xFF3278, 0x28001E},
44+
{"Animal Crossing: New Horizons Edition", 0x82FF96, 0x0A1E0A, 0x96F5F5, 0x0A1E28},
45+
{"Fortnite Wildcat Edition", 0xFFCC00, 0x1A1100, 0x0084FF, 0x000F1E},
46+
{"Mario Red x Blue Edition", 0xF04614, 0x1E1914, 0xF04614, 0x1E1914},
47+
{"Fortnite Fleet Force Edition", 0x0084FF, 0x000F1E, 0xFFCC00, 0x1A1100},
48+
{"Legend of Zelda: Skyward Sword Edition", 0x2D50F0, 0x1E0F46, 0x500FC8, 0x00051E},
49+
{"Splatoon 3 OLED Edition", 0x6455F5, 0x28282D, 0xC3FA05, 0x1E1E28},
50+
{"Pokémon: Scarlet x Violet OLED Edition", 0xF07341, 0x322D1E, 0x9650AA, 0x32322D},
51+
{"Legend of Zelda: Tears of the Kingdom Edition", 0xD2BE69, 0x32322D, 0xD2BE69, 0x32322D},
52+
};
53+
return database;
54+
}
55+
56+
57+
StringSelectDatabase make_JOYCON_DATABASE(){
58+
StringSelectDatabase database;
59+
database.add_entry(StringSelectEntry("Custom", "Custom"));
60+
for (const OfficialJoyconColors& item : OFFICIAL_JOYCON_COLORS()){
61+
database.add_entry(
62+
StringSelectEntry(item.name, item.name)
63+
);
64+
}
65+
return database;
66+
}
67+
const StringSelectDatabase& JOYCON_DATABASE(){
68+
static const StringSelectDatabase database = make_JOYCON_DATABASE();
69+
return database;
70+
}
71+
72+
73+
74+
75+
76+
const EnumDropdownDatabase<ControllerType>& ControllerSettingsType_Database(){
77+
static const EnumDropdownDatabase<ControllerType> database({
78+
{ControllerType::NintendoSwitch_WirelessProController, "pro-controller", "Pro Controller"},
79+
{ControllerType::NintendoSwitch_LeftJoycon, "left-joycon", "Left Joycon"},
80+
{ControllerType::NintendoSwitch_RightJoycon, "right-joycon", "Right Joycon"},
81+
});
82+
return database;
83+
}
84+
85+
86+
87+
ControllerSettingsRow::~ControllerSettingsRow(){
88+
official_color.remove_listener(*this);
89+
#if 1
90+
right_grip.remove_listener(*this);
91+
left_grip.remove_listener(*this);
92+
// body_color.remove_listener(*this);
93+
button_color.remove_listener(*this);
94+
#endif
95+
controller.remove_listener(*this);
96+
}
97+
ControllerSettingsRow::ControllerSettingsRow(EditableTableOption& parent_table)
98+
: EditableTableRow(parent_table)
99+
, name(false, LockMode::UNLOCK_WHILE_RUNNING, "", "COM3")
100+
, controller(
101+
ControllerSettingsType_Database(),
102+
LockMode::UNLOCK_WHILE_RUNNING,
103+
ControllerType::NintendoSwitch_WirelessProController
104+
)
105+
, button_color(
106+
LockMode::UNLOCK_WHILE_RUNNING,
107+
false,
108+
0x0A1E19, 0x0A1E19
109+
)
110+
, body_color(
111+
LockMode::UNLOCK_WHILE_RUNNING,
112+
false,
113+
0xd0d0d0, 0xd0d0d0
114+
)
115+
, left_grip(
116+
LockMode::UNLOCK_WHILE_RUNNING,
117+
false,
118+
0x82FF96, 0x82FF96
119+
)
120+
, right_grip(
121+
LockMode::UNLOCK_WHILE_RUNNING,
122+
false,
123+
0x96F5F5, 0x96F5F5
124+
)
125+
, official_color(
126+
JOYCON_DATABASE(),
127+
LockMode::UNLOCK_WHILE_RUNNING,
128+
0
129+
)
130+
, m_pending_official_load(0)
131+
{
132+
add_option(name, "Name");
133+
add_option(controller, "Controller");
134+
add_option(button_color, "Button");
135+
add_option(body_color, "Body");
136+
add_option(left_grip, "Left Grip");
137+
add_option(right_grip, "Right Grip");
138+
add_option(official_color, "Official Color");
139+
140+
controller.add_listener(*this);
141+
#if 1
142+
button_color.add_listener(*this);
143+
// body_color.add_listener(*this);
144+
left_grip.add_listener(*this);
145+
right_grip.add_listener(*this);
146+
#endif
147+
official_color.add_listener(*this);
148+
}
149+
std::unique_ptr<EditableTableRow> ControllerSettingsRow::clone() const{
150+
std::unique_ptr<ControllerSettingsRow> ret(new ControllerSettingsRow(parent()));
151+
ret->name.set((std::string)name);
152+
ret->controller.set(controller);
153+
ret->button_color.set(button_color);
154+
ret->body_color.set(body_color);
155+
ret->left_grip.set(left_grip);
156+
ret->right_grip.set(right_grip);
157+
ret->official_color.set_by_index(official_color.index());
158+
return ret;
159+
}
160+
void ControllerSettingsRow::value_changed(void* object){
161+
if (object == &button_color ||
162+
// object == &body_color ||
163+
object == &left_grip ||
164+
object == &right_grip
165+
){
166+
if (m_pending_official_load.load(std::memory_order_relaxed) == 0){
167+
official_color.set_by_index(0);
168+
}
169+
return;
170+
}
171+
172+
if (object == &controller){
173+
ConfigOptionState state = controller == ControllerType::NintendoSwitch_WirelessProController
174+
? ConfigOptionState::ENABLED
175+
: ConfigOptionState::HIDDEN;
176+
left_grip.set_visibility(state);
177+
right_grip.set_visibility(state);
178+
179+
// Force an update on the chosen theme.
180+
object = &official_color;
181+
}
182+
183+
if (object != &official_color){
184+
return;
185+
}
186+
187+
size_t index = official_color.index();
188+
if (index == 0){
189+
return;
190+
}
191+
192+
try{
193+
m_pending_official_load++;
194+
195+
const OfficialJoyconColors& entry = OFFICIAL_JOYCON_COLORS()[index - 1];
196+
switch (controller){
197+
case ControllerType::NintendoSwitch_WirelessProController:{
198+
// Set the grips to the joycon colors.
199+
left_grip.set(entry.left_body);
200+
right_grip.set(entry.right_body);
201+
202+
// Average the two button colors.
203+
uint32_t red = ((entry.left_buttons >> 16) & 0xff) + ((entry.right_buttons >> 16) & 0xff);
204+
uint32_t green = ((entry.left_buttons >> 8) & 0xff) + ((entry.right_buttons >> 8) & 0xff);
205+
uint32_t blue = ((entry.left_buttons >> 0) & 0xff) + ((entry.right_buttons >> 0) & 0xff);
206+
red /= 2;
207+
green /= 2;
208+
blue /= 2;
209+
button_color.set((red << 16) | (green << 8) | (blue << 0));
210+
211+
// Pick something for the controller body.
212+
body_color.set(0xd0d0d0);
213+
214+
break;
215+
}
216+
case ControllerType::NintendoSwitch_LeftJoycon:
217+
button_color.set(entry.left_buttons);
218+
body_color.set(entry.left_body);
219+
break;
220+
case ControllerType::NintendoSwitch_RightJoycon:
221+
button_color.set(entry.right_buttons);
222+
body_color.set(entry.right_body);
223+
break;
224+
default:;
225+
}
226+
227+
m_pending_official_load--;
228+
}catch (...){
229+
m_pending_official_load--;
230+
throw;
231+
}
232+
233+
}
234+
235+
236+
237+
238+
ControllerSettingsTable::ControllerSettingsTable()
239+
: EditableTableOption_t<ControllerSettingsRow>(
240+
"<b>Controller Settings:</b>",
241+
LockMode::UNLOCK_WHILE_RUNNING,
242+
true
243+
)
244+
{}
245+
std::vector<std::string> ControllerSettingsTable::make_header() const{
246+
return std::vector<std::string>{
247+
"Name",
248+
"Controller",
249+
"Button",
250+
"Body",
251+
"Left Grip",
252+
"Right Grip",
253+
"Quick Select",
254+
};
255+
}
256+
257+
258+
259+
260+
261+
262+
263+
264+
265+
266+
267+
268+
269+
270+
271+
272+
}
273+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* Nintendo Switch Controller Settings
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_NintendoSwitch_ControllerSettings_H
8+
#define PokemonAutomation_NintendoSwitch_ControllerSettings_H
9+
10+
#include <deque>
11+
#include <mutex>
12+
#include "Common/Cpp/Options/StringOption.h"
13+
#include "Common/Cpp/Options/ColorOption.h"
14+
#include "Common/Cpp/Options/EnumDropdownOption.h"
15+
#include "Common/Cpp/Options/EditableTableOption.h"
16+
#include "CommonTools/Options/StringSelectOption.h"
17+
#include "Controllers/ControllerTypes.h"
18+
19+
namespace PokemonAutomation{
20+
namespace NintendoSwitch{
21+
22+
23+
24+
25+
26+
class ControllerSettingsRow : public EditableTableRow, public ConfigOption::Listener{
27+
public:
28+
~ControllerSettingsRow();
29+
ControllerSettingsRow(EditableTableOption& parent_table);
30+
virtual std::unique_ptr<EditableTableRow> clone() const override;
31+
virtual void value_changed(void* object) override;
32+
33+
private:
34+
StringCell name;
35+
EnumDropdownCell<ControllerType> controller;
36+
ColorCell button_color;
37+
ColorCell body_color;
38+
ColorCell left_grip;
39+
ColorCell right_grip;
40+
StringSelectCell official_color;
41+
42+
private:
43+
std::atomic<size_t> m_pending_official_load;
44+
};
45+
46+
47+
class ControllerSettingsTable : public EditableTableOption_t<ControllerSettingsRow>{
48+
public:
49+
ControllerSettingsTable();
50+
virtual std::vector<std::string> make_header() const override;
51+
52+
53+
54+
};
55+
56+
57+
}
58+
}
59+
#endif

SerialPrograms/Source/NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessController.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ class SerialPABotBase_WirelessController : public SerialPABotBase_Controller{
4545

4646
protected:
4747
void encode_joystick(uint8_t data[3], uint8_t x, uint8_t y){
48+
// 2048 is the neutral position.
49+
//
50+
// 1897 is the point where the joystick calibrator will register it as
51+
// off-center.
52+
//
53+
// ~320 is where it reaches the maximum value.
54+
//
55+
// It we linearly interpolate between 1897 and 320, we seem to match
56+
// the wired controller's behavior.
57+
//
58+
// I suspect the need to offset by 151 from 2048 -> 1897 is Nintendo's
59+
// way to alleviate the joycon drift problem.
4860
const uint16_t min = 1897;
4961
const uint16_t max = 320;
5062

@@ -68,7 +80,7 @@ class SerialPABotBase_WirelessController : public SerialPABotBase_Controller{
6880
uint16_t wy = (uint16_t)(2048 - dy + 0.5);
6981

7082
// wx = 320;
71-
// cout << "wx = " << wx << endl;
83+
// cout << "wx = " << wx << ", wy = " << wy << endl;
7284

7385
data[0] = (uint8_t)wx;
7486
data[1] = (uint8_t)(wx >> 8 | wy << 4);

0 commit comments

Comments
 (0)