Skip to content

Commit 0de581d

Browse files
committed
Add support for setting controller colors.
1 parent 2b030a0 commit 0de581d

12 files changed

+337
-141
lines changed

Common/Cpp/Options/EditableTableOption.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ void EditableTableOption::clear(){
122122
m_current.clear();
123123
}
124124
void EditableTableOption::load_json(const JsonValue& json){
125+
// cout << "EditableTableOption::load_json(): " << this << endl;
126+
125127
const JsonArray* array = json.to_array();
126128
if (array == nullptr){
127129
return;
@@ -216,6 +218,9 @@ void EditableTableOption::insert_row(size_t index, std::unique_ptr<EditableTable
216218
}
217219
report_value_changed(this);
218220
}
221+
void EditableTableOption::append_row(std::unique_ptr<EditableTableRow> row){
222+
insert_row((size_t)-1, std::move(row));
223+
}
219224
void EditableTableOption::clone_row(const EditableTableRow& row){
220225
{
221226
size_t index = row.m_index;

Common/Cpp/Options/EditableTableOption.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ class EditableTableOption : public ConfigOption{
9797
// These reference are live in that they may be asynchronously changed.
9898
std::vector<std::shared_ptr<EditableTableRow>> current_refs() const;
9999

100+
// SpinLock& get_lock() const{
101+
// return m_current_lock;
102+
// }
103+
100104
// Return a copy of the entire table at the exact moment this is called.
101105
template <typename RowType>
102106
std::vector<std::unique_ptr<RowType>> copy_snapshot() const{
@@ -121,11 +125,15 @@ class EditableTableOption : public ConfigOption{
121125
}
122126
return ret;
123127
}
128+
129+
// Lambda returns a boolean. False to continue running. True to stop.
124130
template <typename RowType, typename Lambda>
125131
void run_on_all_rows(Lambda function){
126132
ReadSpinLock lg(m_current_lock);
127133
for (auto& item : m_current){
128-
function(static_cast<RowType&>(*item));
134+
if (function(static_cast<RowType&>(*item))){
135+
return;
136+
}
129137
}
130138
}
131139

@@ -144,6 +152,7 @@ class EditableTableOption : public ConfigOption{
144152

145153
// Undefined behavior to call these on rows that aren't part of the table.
146154
void insert_row(size_t index, std::unique_ptr<EditableTableRow> row);
155+
void append_row(std::unique_ptr<EditableTableRow> row);
147156
void clone_row(const EditableTableRow& row);
148157
void remove_row(EditableTableRow& row);
149158

@@ -176,6 +185,8 @@ class EditableTableOption_t : public EditableTableOption{
176185
std::vector<RowSnapshotType> snapshot() const{
177186
return EditableTableOption::snapshot<RowType, RowSnapshotType>();
178187
}
188+
189+
// Lambda returns a boolean. False to continue running. True to stop.
179190
template <typename Lambda>
180191
void run_on_all_rows(Lambda function){
181192
EditableTableOption::run_on_all_rows<RowType>(std::move(function));

SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase_Connection.cpp

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
#include "Common/Cpp/Exceptions.h"
1111
#include "Common/Cpp/PanicDump.h"
1212
#include "Common/Microcontroller/DeviceRoutines.h"
13-
#include "Common/PokemonSwSh/PokemonProgramIDs.h"
13+
//#include "Common/PokemonSwSh/PokemonProgramIDs.h"
1414
#include "ClientSource/Libraries/MessageConverter.h"
1515
#include "ClientSource/Connection/SerialConnection.h"
1616
#include "ClientSource/Connection/PABotBase.h"
1717
#include "CommonFramework/GlobalSettingsPanel.h"
1818
#include "CommonFramework/Options/Environment/ThemeSelectorOption.h"
1919
#include "Controllers/ControllerTypeStrings.h"
20+
#include "NintendoSwitch/NintendoSwitch_Settings.h"
21+
#include "NintendoSwitch/Controllers/SerialPABotBase/NintendoSwitch_SerialPABotBase_WirelessController.h"
2022
#include "SerialPABotBase.h"
2123
#include "SerialPABotBase_Connection.h"
2224

@@ -61,12 +63,12 @@ SerialPABotBase_Connection::SerialPABotBase_Connection(
6163
return;
6264
}
6365

64-
std::string name = port->systemLocation().toUtf8().data();
66+
m_device_name = port->portName().toStdString();
6567
std::string error;
6668
try{
6769
set_status_line0("Connecting...", COLOR_DARKGREEN);
6870

69-
std::unique_ptr<SerialConnection> connection(new SerialConnection(name, PABB_BAUD_RATE));
71+
std::unique_ptr<SerialConnection> connection(new SerialConnection(port->systemLocation().toStdString(), PABB_BAUD_RATE));
7072
m_botbase.reset(new PABotBase(m_logger, std::move(connection), nullptr));
7173
}catch (const ConnectionException& e){
7274
error = e.message();
@@ -211,14 +213,58 @@ ControllerModeStatus SerialPABotBase_Connection::read_device_specs(
211213

212214
if (change_controller && program_iter->second.size() > 1){
213215
ControllerType desired_controller = change_controller.value();
216+
switch (desired_controller){
217+
case ControllerType::NintendoSwitch_WiredProController:
218+
case ControllerType::NintendoSwitch_WirelessProController:
219+
case ControllerType::NintendoSwitch_LeftJoycon:
220+
case ControllerType::NintendoSwitch_RightJoycon:{
221+
NintendoSwitch::ControllerProfile profile =
222+
NintendoSwitch::ConsoleSettings::instance().CONTROLLER_SETTINGS.get_or_make_profile(
223+
m_device_name,
224+
desired_controller
225+
);
226+
227+
NintendoSwitch::ControllerColors colors;
228+
{
229+
Color color(profile.body_color);
230+
colors.body[0] = color.red();
231+
colors.body[1] = color.green();
232+
colors.body[2] = color.blue();
233+
}
234+
{
235+
Color color(profile.button_color);
236+
colors.buttons[0] = color.red();
237+
colors.buttons[1] = color.green();
238+
colors.buttons[2] = color.blue();
239+
}
240+
{
241+
Color color(profile.left_grip);
242+
colors.left_grip[0] = color.red();
243+
colors.left_grip[1] = color.green();
244+
colors.left_grip[2] = color.blue();
245+
}
246+
{
247+
Color color(profile.right_grip);
248+
colors.right_grip[0] = color.red();
249+
colors.right_grip[1] = color.green();
250+
colors.right_grip[2] = color.blue();
251+
}
252+
253+
m_botbase->issue_request_and_wait(
254+
NintendoSwitch::MessageControllerSetColors(desired_controller, colors),
255+
nullptr
256+
);
257+
}
258+
default:;
259+
}
260+
261+
214262
uint32_t native_controller_id = controller_type_to_id(desired_controller);
215263
m_botbase->issue_request_and_wait(
216264
Microcontroller::DeviceRequest_change_controller_mode(native_controller_id),
217265
nullptr
218266
);
219267

220-
221-
222268
// Re-read the controller.
223269
logger.log("Reading Controller Mode...");
224270
uint32_t type_id = Microcontroller::read_controller_mode(*m_botbase);

SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase_Connection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class SerialPABotBase_Connection : public ControllerConnection{
5454

5555
private:
5656
SerialLogger m_logger;
57+
std::string m_device_name;
5758

5859
uint32_t m_protocol = 0;
5960
uint8_t m_program_id = 0;

SerialPrograms/Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerSettings.cpp

Lines changed: 96 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,14 @@
44
*
55
*/
66

7+
#include <chrono>
8+
#include "Common/CRC32.h"
79
#include "NintendoSwitch_ControllerSettings.h"
810

11+
//#include <iostream>
12+
//using std::cout;
13+
//using std::endl;
14+
915
namespace PokemonAutomation{
1016
namespace NintendoSwitch{
1117

@@ -17,6 +23,40 @@ struct OfficialJoyconColors{
1723
uint32_t left_buttons;
1824
uint32_t right_body;
1925
uint32_t right_buttons;
26+
27+
void write_to_profile(ControllerProfile& profile, ControllerType controller) const{
28+
profile.official_name = name;
29+
switch (controller){
30+
case ControllerType::NintendoSwitch_WirelessProController:{
31+
// Set the grips to the joycon colors.
32+
profile.left_grip = left_body;
33+
profile.right_grip = right_body;
34+
35+
// Average the two button colors.
36+
uint32_t red = ((left_buttons >> 16) & 0xff) + ((right_buttons >> 16) & 0xff);
37+
uint32_t green = ((left_buttons >> 8) & 0xff) + ((right_buttons >> 8) & 0xff);
38+
uint32_t blue = ((left_buttons >> 0) & 0xff) + ((right_buttons >> 0) & 0xff);
39+
red /= 2;
40+
green /= 2;
41+
blue /= 2;
42+
profile.button_color = (red << 16) | (green << 8) | (blue << 0);
43+
44+
// Pick something for the controller body.
45+
profile.body_color = 0xd0d0d0;
46+
break;
47+
}
48+
case ControllerType::NintendoSwitch_LeftJoycon:
49+
profile.button_color = left_buttons;
50+
profile.body_color = left_body;
51+
break;
52+
case ControllerType::NintendoSwitch_RightJoycon:
53+
profile.button_color = right_buttons;
54+
profile.body_color = right_body;
55+
break;
56+
default:;
57+
}
58+
59+
}
2060
};
2161

2262
const std::vector<OfficialJoyconColors>& OFFICIAL_JOYCON_COLORS(){
@@ -192,37 +232,9 @@ void ControllerSettingsRow::value_changed(void* object){
192232
try{
193233
m_pending_official_load++;
194234

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-
}
235+
ControllerProfile profile{};
236+
OFFICIAL_JOYCON_COLORS()[index - 1].write_to_profile(profile, controller);
237+
this->set_profile(profile);
226238

227239
m_pending_official_load--;
228240
}catch (...){
@@ -255,7 +267,60 @@ std::vector<std::string> ControllerSettingsTable::make_header() const{
255267
}
256268

257269

270+
ControllerProfile ControllerSettingsTable::get_or_make_profile(
271+
const std::string& name,
272+
ControllerType controller
273+
){
274+
// cout << "ControllerSettingsTable::get_or_make_profile(): " << this << endl;
275+
276+
ControllerProfile profile{};
277+
278+
// Only relevant to Switch controllers.
279+
switch (controller){
280+
case ControllerType::NintendoSwitch_WiredProController:
281+
case ControllerType::NintendoSwitch_WirelessProController:
282+
case ControllerType::NintendoSwitch_LeftJoycon:
283+
case ControllerType::NintendoSwitch_RightJoycon:
284+
break;
285+
default:
286+
return profile;
287+
}
288+
289+
bool found = false;
290+
this->run_on_all_rows([&, controller](ControllerSettingsRow& row){
291+
if ((std::string)row.name != name){
292+
return false;
293+
}
294+
if (row.controller != controller){
295+
return false;
296+
}
297+
298+
found = true;
299+
profile = row;
300+
return true;
301+
});
302+
303+
if (found){
304+
return profile;
305+
}
306+
307+
const std::vector<OfficialJoyconColors>& DATABASE = OFFICIAL_JOYCON_COLORS();
308+
309+
uint64_t seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
310+
seed = pabb_crc32(0, &seed, sizeof(seed));
311+
seed %= DATABASE.size();
312+
313+
DATABASE[(size_t)seed].write_to_profile(profile, controller);
258314

315+
std::unique_ptr<ControllerSettingsRow> row(new ControllerSettingsRow(*this));
316+
row->name.set(name);
317+
row->controller.set(controller);
318+
row->set_profile(profile);
319+
320+
this->append_row(std::move(row));
321+
322+
return profile;
323+
}
259324

260325

261326

SerialPrograms/Source/NintendoSwitch/Controllers/NintendoSwitch_ControllerSettings.h

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
#ifndef PokemonAutomation_NintendoSwitch_ControllerSettings_H
88
#define PokemonAutomation_NintendoSwitch_ControllerSettings_H
99

10-
#include <deque>
11-
#include <mutex>
1210
#include "Common/Cpp/Options/StringOption.h"
1311
#include "Common/Cpp/Options/ColorOption.h"
1412
#include "Common/Cpp/Options/EnumDropdownOption.h"
@@ -21,7 +19,13 @@ namespace NintendoSwitch{
2119

2220

2321

24-
22+
struct ControllerProfile{
23+
uint32_t button_color;
24+
uint32_t body_color;
25+
uint32_t left_grip;
26+
uint32_t right_grip;
27+
std::string official_name;
28+
};
2529

2630
class ControllerSettingsRow : public EditableTableRow, public ConfigOption::Listener{
2731
public:
@@ -30,7 +34,24 @@ class ControllerSettingsRow : public EditableTableRow, public ConfigOption::List
3034
virtual std::unique_ptr<EditableTableRow> clone() const override;
3135
virtual void value_changed(void* object) override;
3236

33-
private:
37+
operator ControllerProfile() const{
38+
return {
39+
button_color,
40+
body_color,
41+
left_grip,
42+
right_grip,
43+
official_color.slug(),
44+
};
45+
}
46+
void set_profile(const ControllerProfile& profile){
47+
button_color.set(profile.button_color);
48+
body_color.set(profile.body_color);
49+
left_grip.set(profile.left_grip);
50+
right_grip.set(profile.right_grip);
51+
official_color.set_by_slug(profile.official_name);
52+
}
53+
54+
public:
3455
StringCell name;
3556
EnumDropdownCell<ControllerType> controller;
3657
ColorCell button_color;
@@ -49,7 +70,10 @@ class ControllerSettingsTable : public EditableTableOption_t<ControllerSettingsR
4970
ControllerSettingsTable();
5071
virtual std::vector<std::string> make_header() const override;
5172

52-
73+
ControllerProfile get_or_make_profile(
74+
const std::string& name,
75+
ControllerType controller
76+
);
5377

5478
};
5579

0 commit comments

Comments
 (0)