Skip to content

Commit d4c4391

Browse files
committed
Add controller dropdown for dev mode.
1 parent f793474 commit d4c4391

File tree

8 files changed

+200
-50
lines changed

8 files changed

+200
-50
lines changed

SerialPrograms/Source/Controllers/ControllerCapability.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ const EnumStringMap<ControllerInterface> CONTROLLER_INTERFACE_STRINGS{
1717

1818
const EnumStringMap<ControllerType> CONTROLLER_TYPE_STRINGS{
1919
{ControllerType::None, "None"},
20-
{ControllerType::NintendoSwitch_WiredProController, "NintendoSwitch_WiredProController"},
21-
{ControllerType::NintendoSwitch_WirelessProController, "NintendoSwitch_WirelessProController"},
22-
{ControllerType::NintendoSwitch_LeftJoycon, "NintendoSwitch_LeftJoycon"},
23-
{ControllerType::NintendoSwitch_RightJoycon, "NintendoSwitch_RightJoycon"},
20+
{ControllerType::NintendoSwitch_WiredProController, "Switch: Wired Pro Controller"},
21+
{ControllerType::NintendoSwitch_WirelessProController, "Switch: Wireless Pro Controller"},
22+
{ControllerType::NintendoSwitch_LeftJoycon, "Switch: Left Joycon"},
23+
{ControllerType::NintendoSwitch_RightJoycon, "Switch: Right Joycon"},
2424
};
2525

2626
const EnumStringMap<ControllerFeature> CONTROLLER_FEATURE_STRINGS{

SerialPrograms/Source/Controllers/ControllerDescriptor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void ControllerOption::load_json(const JsonValue& json){
101101
}
102102
const std::string* controller = obj->get_string("Controller");
103103
if (controller != nullptr){
104-
controller_type = CONTROLLER_TYPE_STRINGS.get_enum(*controller);
104+
controller_type = CONTROLLER_TYPE_STRINGS.get_enum(*controller, ControllerType::None);
105105
}
106106
const JsonValue* params = obj->get_value("Parameters");
107107
if (params == nullptr){

SerialPrograms/Source/Controllers/ControllerSelectorWidget.cpp

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <QHBoxLayout>
88
#include "Common/Qt/NoWheelComboBox.h"
9+
#include "CommonFramework/GlobalSettingsPanel.h"
910
#include "ControllerSelectorWidget.h"
1011

1112
//#include <iostream>
@@ -29,11 +30,20 @@ ControllerSelectorWidget::ControllerSelectorWidget(QWidget& parent, ControllerSe
2930
serial_row->addWidget(new QLabel("<b>Controller:</b>", this), 1);
3031
serial_row->addSpacing(5);
3132

32-
m_devices_dropdown = new NoWheelComboBox(this);
33-
serial_row->addWidget(m_devices_dropdown, 5);
34-
refresh();
33+
QHBoxLayout* dropdowns = new QHBoxLayout();
34+
serial_row->addLayout(dropdowns, 5);
3535
serial_row->addSpacing(5);
3636

37+
m_devices_dropdown = new NoWheelComboBox(this);
38+
dropdowns->addWidget(m_devices_dropdown, 3);
39+
refresh_devices();
40+
41+
if (PreloadSettings::instance().DEVELOPER_MODE){
42+
dropdowns->addSpacing(5);
43+
m_controllers_dropdown = new NoWheelComboBox(this);
44+
dropdowns->addWidget(m_controllers_dropdown, 2);
45+
}
46+
3747
m_status_text = new QLabel(this);
3848
serial_row->addWidget(m_status_text, 3);
3949
serial_row->addSpacing(5);
@@ -60,9 +70,25 @@ ControllerSelectorWidget::ControllerSelectorWidget(QWidget& parent, ControllerSe
6070
}
6171

6272
m_session.set_device(selected);
63-
refresh();
73+
refresh_devices();
6474
}
6575
);
76+
if (PreloadSettings::instance().DEVELOPER_MODE){
77+
connect(
78+
m_controllers_dropdown, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
79+
this, [this](int index){
80+
index = std::max(index, 0);
81+
ControllerType new_value = CONTROLLER_TYPE_STRINGS.get_enum(
82+
m_controllers_dropdown->itemText(index).toStdString(),
83+
ControllerType::None
84+
);
85+
if (new_value == m_session.controller_type()){
86+
return;
87+
}
88+
m_session.set_controller(new_value);
89+
}
90+
);
91+
}
6692
connect(
6793
m_reset_button, &QPushButton::clicked,
6894
this, [this](bool){
@@ -75,7 +101,7 @@ ControllerSelectorWidget::ControllerSelectorWidget(QWidget& parent, ControllerSe
75101

76102

77103

78-
void ControllerSelectorWidget::refresh(){
104+
void ControllerSelectorWidget::refresh_devices(){
79105
m_device_list.clear();
80106
m_devices_dropdown->clear();
81107

@@ -100,13 +126,45 @@ void ControllerSelectorWidget::refresh(){
100126
// cout << "items = " << m_devices_dropdown->count() << endl;
101127
m_devices_dropdown->setCurrentIndex((int)index);
102128
}
129+
void ControllerSelectorWidget::refresh_controllers(
130+
ControllerType controller_type,
131+
const std::vector<ControllerType>& available_controllers
132+
){
133+
if (m_controllers_dropdown == nullptr){
134+
return;
135+
}
136+
// cout << "refresh_controllers()" << endl;
103137

138+
m_controllers_dropdown->clear();
104139

140+
size_t index = 0;
141+
for (size_t c = 0; c < available_controllers.size(); c++){
142+
const std::string& name = CONTROLLER_TYPE_STRINGS.get_string(available_controllers[c]);
143+
m_controllers_dropdown->addItem(QString::fromStdString(name));
144+
if (controller_type == available_controllers[c]){
145+
index = c;
146+
}
147+
}
148+
m_controllers_dropdown->setCurrentIndex((int)index);
149+
}
105150

106-
void ControllerSelectorWidget::controller_changed(const std::shared_ptr<const ControllerDescriptor>& descriptor){
151+
152+
153+
void ControllerSelectorWidget::descriptor_changed(
154+
const std::shared_ptr<const ControllerDescriptor>& descriptor
155+
){
107156
QMetaObject::invokeMethod(this, [this]{
108-
refresh();
109-
});
157+
refresh_devices();
158+
}, Qt::QueuedConnection);
159+
}
160+
void ControllerSelectorWidget::controller_changed(
161+
ControllerType controller_type,
162+
const std::vector<ControllerType>& available_controllers
163+
){
164+
// cout << "ControllerSelectorWidget::controller_changed()" << endl;
165+
QMetaObject::invokeMethod(this, [=, this]{
166+
refresh_controllers(controller_type, available_controllers);
167+
}, Qt::QueuedConnection);
110168
}
111169
void ControllerSelectorWidget::post_status_text_changed(const std::string& text){
112170
// cout << "ControllerSelectorWidget::status_text_changed(): " << text << endl;

SerialPrograms/Source/Controllers/ControllerSelectorWidget.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,30 @@ class ControllerSelectorWidget : public QWidget, private ControllerSession::List
2424
ControllerSelectorWidget(QWidget& parent, ControllerSession& session);
2525

2626
public:
27-
virtual void controller_changed(const std::shared_ptr<const ControllerDescriptor>& descriptor) override;
27+
virtual void descriptor_changed(
28+
const std::shared_ptr<const ControllerDescriptor>& descriptor
29+
) override;
30+
virtual void controller_changed(
31+
ControllerType controller_type,
32+
const std::vector<ControllerType>& available_controllers
33+
) override;
2834
virtual void post_status_text_changed(const std::string& text) override;
2935
virtual void options_locked(bool locked) override;
3036

3137
private:
32-
void refresh();
38+
void refresh_devices();
39+
void refresh_controllers(
40+
ControllerType controller_type,
41+
const std::vector<ControllerType>& available_controllers
42+
);
3343

3444
private:
3545
ControllerSession& m_session;
3646

37-
QComboBox* m_devices_dropdown;
38-
QLabel* m_status_text;
39-
QPushButton* m_reset_button;
47+
QComboBox* m_devices_dropdown = nullptr;
48+
QComboBox* m_controllers_dropdown = nullptr;
49+
QLabel* m_status_text = nullptr;
50+
QPushButton* m_reset_button = nullptr;
4051

4152
std::vector<std::shared_ptr<const ControllerDescriptor>> m_device_list;
4253
};

SerialPrograms/Source/Controllers/ControllerSession.cpp

Lines changed: 88 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@ namespace PokemonAutomation{
1515

1616

1717
void ControllerSession::add_listener(Listener& listener){
18-
std::lock_guard<std::mutex> lg0(m_state_lock);
18+
std::lock_guard<std::mutex> lg(m_state_lock);
1919
m_listeners.add(listener);
20+
// if (m_connection && m_connection->is_ready()){
21+
signal_controller_changed(m_option.m_controller_type, m_available_controllers);
22+
// }
2023
}
2124
void ControllerSession::remove_listener(Listener& listener){
22-
std::lock_guard<std::mutex> lg0(m_state_lock);
25+
std::lock_guard<std::mutex> lg(m_state_lock);
2326
m_listeners.remove(listener);
2427
}
2528

@@ -73,6 +76,10 @@ std::shared_ptr<const ControllerDescriptor> ControllerSession::descriptor() cons
7376
std::lock_guard<std::mutex> lg(m_state_lock);
7477
return m_descriptor;
7578
}
79+
ControllerType ControllerSession::controller_type() const{
80+
std::lock_guard<std::mutex> lg(m_state_lock);
81+
return m_option.m_controller_type;
82+
}
7683
std::string ControllerSession::status_text() const{
7784
std::lock_guard<std::mutex> lg(m_state_lock);
7885
if (!m_connection){
@@ -157,7 +164,29 @@ bool ControllerSession::set_device(const std::shared_ptr<const ControllerDescrip
157164
m_option.m_descriptor = device;
158165
m_descriptor = device;
159166
}
160-
signal_controller_changed(device);
167+
signal_descriptor_changed(device);
168+
signal_status_text_changed(status_text());
169+
return true;
170+
}
171+
bool ControllerSession::set_controller(ControllerType controller_type){
172+
// cout << "set_controller()" << endl;
173+
{
174+
std::lock_guard<std::mutex> lg(m_state_lock);
175+
if (m_option.m_controller_type == controller_type){
176+
return true;
177+
}
178+
if (m_options_locked){
179+
return false;
180+
}
181+
m_option.m_controller_type = controller_type;
182+
183+
m_controller.reset();
184+
m_connection.reset();
185+
m_connection = m_descriptor->open_connection(m_logger);
186+
if (m_connection){
187+
m_connection->add_status_listener(*this);
188+
}
189+
}
161190
signal_status_text_changed(status_text());
162191
return true;
163192
}
@@ -190,34 +219,58 @@ void ControllerSession::pre_not_ready(){
190219
m_listeners.run_method_unique(&Listener::pre_not_ready);
191220
}
192221
void ControllerSession::post_ready(const std::map<ControllerType, std::set<ControllerFeature>>& controllers){
193-
if (controllers.empty()){
194-
return;
195-
}
196-
197-
auto iter = controllers.begin();
198-
199-
if (controllers.size() == 1){
200-
// Only one controller available. Force the option to it.
201-
m_option.m_controller_type = iter->first;
202-
}else{
203-
// Otherwise, try to use the option setting. If it's not valid,
204-
// clear it.
205-
iter = controllers.find(m_option.m_controller_type);
206-
if (iter == controllers.end()){
207-
m_option.m_controller_type = ControllerType::None;
208-
m_controller.reset();
222+
std::vector<ControllerType> available_controllers;
223+
224+
if (controllers.size() > 1){
225+
available_controllers.emplace_back(ControllerType::None);
226+
}
227+
228+
ControllerType selected_controller = ControllerType::None;
229+
bool ready = false;
230+
{
231+
std::lock_guard<std::mutex> lg(m_state_lock);
232+
233+
for (const auto& item : controllers){
234+
available_controllers.emplace_back(item.first);
235+
}
236+
m_available_controllers = available_controllers;
237+
m_controller.reset();
238+
239+
if (controllers.empty()){
209240
return;
210241
}
211-
}
212242

213-
// cout << "post_ready()" << endl;
243+
auto iter = controllers.begin();
244+
245+
if (controllers.size() == 1){
246+
// Only one controller available. Force the option to it.
247+
selected_controller = iter->first;
248+
}else{
249+
// Keep the current controller only if it exists.
250+
iter = controllers.find(m_option.m_controller_type);
251+
if (iter != controllers.end()){
252+
selected_controller = m_option.m_controller_type;
253+
}
254+
}
255+
256+
// cout << "post_ready()" << endl;
257+
258+
if (selected_controller != ControllerType::None){
259+
m_controller = m_descriptor->make_controller(m_logger, *m_connection, selected_controller, m_requirements);
260+
}
261+
m_option.m_controller_type = selected_controller;
214262

215-
m_controller.reset();
216-
m_controller = m_descriptor->make_controller(m_logger, *m_connection, iter->first, m_requirements);
217-
m_listeners.run_method_unique(&Listener::post_ready, controllers);
218-
signal_ready_changed(m_controller->is_ready());
263+
ready = m_controller && m_controller->is_ready();
264+
signal_controller_changed(selected_controller, available_controllers);
265+
}
266+
if (ready){
267+
m_listeners.run_method_unique(&Listener::post_ready, controllers);
268+
signal_ready_changed(m_controller->is_ready());
269+
}
219270
}
220271
void ControllerSession::post_status_text_changed(const std::string& text){
272+
std::lock_guard<std::mutex> lg(m_state_lock);
273+
221274
do{
222275
if (m_controller == nullptr){
223276
break;
@@ -239,8 +292,16 @@ void ControllerSession::post_status_text_changed(const std::string& text){
239292
void ControllerSession::signal_ready_changed(bool ready){
240293
m_listeners.run_method_unique(&Listener::ready_changed, ready);
241294
}
242-
void ControllerSession::signal_controller_changed(const std::shared_ptr<const ControllerDescriptor>& descriptor){
243-
m_listeners.run_method_unique(&Listener::controller_changed, descriptor);
295+
void ControllerSession::signal_descriptor_changed(
296+
const std::shared_ptr<const ControllerDescriptor>& descriptor
297+
){
298+
m_listeners.run_method_unique(&Listener::descriptor_changed, descriptor);
299+
}
300+
void ControllerSession::signal_controller_changed(
301+
ControllerType controller_type,
302+
const std::vector<ControllerType>& available_controllers
303+
){
304+
m_listeners.run_method_unique(&Listener::controller_changed, controller_type, available_controllers);
244305
}
245306
void ControllerSession::signal_status_text_changed(const std::string& text){
246307
m_listeners.run_method_unique(&Listener::post_status_text_changed, text);

SerialPrograms/Source/Controllers/ControllerSession.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@ class ControllerSession : private ControllerConnection::StatusListener{
2424
public:
2525
struct Listener : ControllerConnection::StatusListener{
2626
virtual void ready_changed(bool ready){}
27-
virtual void controller_changed(const std::shared_ptr<const ControllerDescriptor>& descriptor){}
27+
virtual void descriptor_changed(
28+
const std::shared_ptr<const ControllerDescriptor>& descriptor
29+
){}
30+
virtual void controller_changed(
31+
ControllerType controller_type,
32+
const std::vector<ControllerType>& available_controllers
33+
){}
2834
virtual void post_status_text_changed(const std::string& text){}
2935
virtual void options_locked(bool locked){}
3036
};
@@ -53,6 +59,7 @@ class ControllerSession : private ControllerConnection::StatusListener{
5359

5460
bool ready() const;
5561
std::shared_ptr<const ControllerDescriptor> descriptor() const;
62+
ControllerType controller_type() const;
5663
std::string status_text() const;
5764

5865
const ControllerOption& option() const{
@@ -73,6 +80,7 @@ class ControllerSession : private ControllerConnection::StatusListener{
7380

7481
public:
7582
bool set_device(const std::shared_ptr<const ControllerDescriptor>& device);
83+
bool set_controller(ControllerType controller_type);
7684

7785

7886
public:
@@ -113,7 +121,13 @@ class ControllerSession : private ControllerConnection::StatusListener{
113121
virtual void post_status_text_changed(const std::string& text) override;
114122

115123
void signal_ready_changed(bool ready);
116-
void signal_controller_changed(const std::shared_ptr<const ControllerDescriptor>& descriptor);
124+
void signal_descriptor_changed(
125+
const std::shared_ptr<const ControllerDescriptor>& descriptor
126+
);
127+
void signal_controller_changed(
128+
ControllerType controller_type,
129+
const std::vector<ControllerType>& available_controllers
130+
);
117131
void signal_status_text_changed(const std::string& text);
118132
void signal_options_locked(bool locked);
119133

@@ -130,6 +144,8 @@ class ControllerSession : private ControllerConnection::StatusListener{
130144
std::unique_ptr<ControllerConnection> m_connection;
131145
std::unique_ptr<AbstractController> m_controller;
132146

147+
std::vector<ControllerType> m_available_controllers;
148+
133149
ListenerSet<Listener> m_listeners;
134150
};
135151

0 commit comments

Comments
 (0)