Skip to content

Commit ca28232

Browse files
committed
More cleanup of the controller interface. Remove a lot of hard-coded Serial PABotBase stuff.
1 parent 69d3a61 commit ca28232

File tree

11 files changed

+238
-70
lines changed

11 files changed

+238
-70
lines changed

SerialPrograms/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,8 @@ file(GLOB MAIN_SOURCES
609609
Source/Controllers/ControllerSession.h
610610
Source/Controllers/ControllerSelectorWidget.cpp
611611
Source/Controllers/ControllerSelectorWidget.h
612+
Source/Controllers/NullController.cpp
613+
Source/Controllers/NullController.h
612614
Source/Controllers/SerialPABotBase/SerialPABotBase.cpp
613615
Source/Controllers/SerialPABotBase/SerialPABotBase.h
614616
Source/Controllers/SerialPABotBase/SerialPABotBase_Handle.cpp

SerialPrograms/SerialPrograms.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ SOURCES += \
309309
Source/Controllers/ControllerSelectorWidget.cpp \
310310
Source/Controllers/ControllerSession.cpp \
311311
Source/Controllers/ControllerDescriptor.cpp \
312+
Source/Controllers/NullController.cpp \
312313
Source/Controllers/SerialPABotBase/SerialPABotBase.cpp \
313314
Source/Controllers/SerialPABotBase/SerialPABotBase_Handle.cpp \
314315
Source/Integrations/DiscordIntegrationSettings.cpp \
@@ -1424,6 +1425,7 @@ HEADERS += \
14241425
Source/Controllers/ControllerSelectorWidget.h \
14251426
Source/Controllers/ControllerSession.h \
14261427
Source/Controllers/ControllerDescriptor.h \
1428+
Source/Controllers/NullController.h \
14271429
Source/Controllers/SerialPABotBase/SerialPABotBase.h \
14281430
Source/Controllers/SerialPABotBase/SerialPABotBase_Handle.h \
14291431
Source/Integrations/DiscordIntegrationSettings.h \

SerialPrograms/Source/Controllers/ControllerCapability.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ class ControllerRequirements{
5959
return m_map.find(device) != m_map.end();
6060
}
6161

62-
// Check compatibility. If compatible, returns empty string. Otherwise
63-
// returns one of the missing features.
62+
// Check compatibility. If compatible, returns empty string.
63+
// Otherwise returns one of the missing features.
6464
std::string check_compatibility(const std::string& device, const std::set<std::string>& features) const{
6565
auto scope_check = m_sanitizer.check_scope();
6666

SerialPrograms/Source/Controllers/ControllerDescriptor.cpp

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,63 @@
44
*
55
*/
66

7+
#include <iterator>
8+
#include "Common/Cpp/Exceptions.h"
79
#include "Common/Cpp/Json/JsonValue.h"
810
#include "Common/Cpp/Json/JsonObject.h"
11+
#include "ControllerCapability.h"
912
#include "ControllerDescriptor.h"
10-
#include "Controllers/SerialPABotBase/SerialPABotBase.h"
11-
#include "NintendoSwitch/Controllers/NintendoSwitch_SerialPABotBase.h"
12-
#include "ControllerConnection.h"
13+
#include "NullController.h"
14+
15+
//#include <iostream>
16+
//using std::cout;
17+
//using std::endl;
1318

1419
namespace PokemonAutomation{
1520

1621

17-
bool NullControllerDescriptor::operator==(const ControllerDescriptor& x) const{
18-
return typeid(*this) == typeid(x);
19-
}
20-
const char* NullControllerDescriptor::type_name() const{
21-
return "None";
22-
}
23-
std::string NullControllerDescriptor::display_name() const{
24-
return "(none)";
25-
}
26-
void NullControllerDescriptor::load_json(const JsonValue& json){
22+
//
23+
// Here we store a map of all controller types in the program.
24+
//
25+
std::map<std::string, std::unique_ptr<ControllerType>> CONTROLLER_TYPES;
2726

27+
28+
void ControllerType::register_factory(
29+
const std::string& name,
30+
std::unique_ptr<ControllerType> factory
31+
){
32+
auto ret = CONTROLLER_TYPES.emplace(name, std::move(factory));
33+
if (!ret.second){
34+
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Duplicate Factory Name: " + name);
35+
}
2836
}
29-
JsonValue NullControllerDescriptor::to_json() const{
30-
return JsonValue();
31-
}
32-
std::unique_ptr<ControllerConnection> NullControllerDescriptor::open(
33-
Logger& logger,
34-
const ControllerRequirements& requirements
35-
) const{
36-
return nullptr;
37+
38+
39+
40+
std::vector<std::shared_ptr<const ControllerDescriptor>>
41+
get_compatible_descriptors(const ControllerRequirements& requirements){
42+
std::vector<std::shared_ptr<const ControllerDescriptor>> ret;
43+
44+
// Find all the devices in common between the supported list and the
45+
// required list. For each of those, enumerate all the descriptors and
46+
// combine them into a single list.
47+
for (const auto& device : requirements.map()){
48+
auto iter = CONTROLLER_TYPES.find(device.first);
49+
if (iter != CONTROLLER_TYPES.end()){
50+
std::vector<std::shared_ptr<const ControllerDescriptor>> list = iter->second->list();
51+
std::move(list.begin(), list.end(), std::back_inserter(ret));
52+
}
53+
}
54+
55+
return ret;
3756
}
3857

3958

4059

4160

61+
62+
63+
4264
ControllerOption::ControllerOption()
4365
: m_current(new NullControllerDescriptor())
4466
{}
@@ -51,19 +73,13 @@ void ControllerOption::load_json(const JsonValue& json){
5173
const std::string& type = obj.get_string_throw("DeviceType");
5274
const JsonValue& params = obj.get_value_throw("Parameters");
5375

54-
if (type == "None"){
55-
auto descriptor = std::make_unique<NullControllerDescriptor>();
56-
m_current = std::move(descriptor);
57-
return;
58-
}
59-
if (type == SerialPABotBase::NintendoSwitch_Basic){
60-
auto descriptor = std::make_unique<NintendoSwitch::SwitchController_SerialPABotBase_Descriptor>();
61-
descriptor->load_json(params);
62-
m_current = std::move(descriptor);
76+
auto iter = CONTROLLER_TYPES.find(type);
77+
if (iter == CONTROLLER_TYPES.end()){
78+
m_current.reset(new NullControllerDescriptor());
6379
return;
6480
}
6581

66-
m_current.reset(new NullControllerDescriptor());
82+
m_current = iter->second->make(params);
6783
}
6884
JsonValue ControllerOption::to_json() const{
6985
if (!m_current){

SerialPrograms/Source/Controllers/ControllerDescriptor.h

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,76 @@ namespace PokemonAutomation{
1515

1616
class JsonValue;
1717
class ControllerRequirements;
18+
class ControllerType;
19+
class ControllerDescriptor;
1820
class ControllerConnection;
1921

2022

23+
//
24+
// Represents an entire type of controller.
25+
//
26+
// For example:
27+
// - "Nintendo Switch via Serial PABotBase" is a type of controller.
28+
// - "Nintendo Switch via Joycon Emulatiion" is a type of controller. (hypothetical)
29+
// - "Xbox One via whatever..." ...
30+
//
31+
// One instance of this class exists for each type of controller.
32+
//
33+
class ControllerType{
34+
public:
35+
virtual ~ControllerType() = default;
36+
37+
// Returns a list of all available instances for this controller type.
38+
virtual std::vector<std::shared_ptr<const ControllerDescriptor>> list() const = 0;
39+
40+
// Construct a descriptor from a JSON config. (reloading saved controller settings)
41+
virtual std::unique_ptr<ControllerDescriptor> make(const JsonValue& json) const = 0;
42+
43+
protected:
44+
static void register_factory(
45+
const std::string& name,
46+
std::unique_ptr<ControllerType> factory
47+
);
48+
};
49+
50+
51+
//
52+
// Subclass helper for ControllerType.
53+
//
54+
template <typename DescriptorType>
55+
class ControllerType_t : public ControllerType{
56+
public:
57+
// Subclasses must implement this function.
58+
virtual std::vector<std::shared_ptr<const ControllerDescriptor>> list() const override;
59+
60+
// This function is provided for you.
61+
virtual std::unique_ptr<ControllerDescriptor> make(const JsonValue& json) const override{
62+
std::unique_ptr<DescriptorType> ptr(new DescriptorType());
63+
ptr->load_json(json);
64+
return ptr;
65+
}
66+
67+
private:
68+
static int register_class(){
69+
ControllerType::register_factory(
70+
DescriptorType::TYPENAME,
71+
std::make_unique<ControllerType_t<DescriptorType>>()
72+
);
73+
return 0;
74+
}
75+
static int initializer;
76+
};
77+
template <typename DescriptorType>
78+
int ControllerType_t<DescriptorType>::initializer = register_class();
2179

80+
81+
82+
83+
//
84+
// Represents a user-selectable controller. When the user clicks on the
85+
// "Controller" dropdown, every item in that list corresponds to an instance
86+
// of this class.
87+
//
2288
class ControllerDescriptor{
2389
public:
2490
virtual ~ControllerDescriptor() = default;
@@ -36,22 +102,20 @@ class ControllerDescriptor{
36102
) const = 0;
37103
};
38104

39-
class NullControllerDescriptor : public ControllerDescriptor{
40-
public:
41-
virtual bool operator==(const ControllerDescriptor& x) const override;
42-
virtual const char* type_name() const override;
43-
virtual std::string display_name() const override;
44-
virtual void load_json(const JsonValue& json) override;
45-
virtual JsonValue to_json() const override;
46-
virtual std::unique_ptr<ControllerConnection> open(
47-
Logger& logger,
48-
const ControllerRequirements& requirements
49-
) const override;
50-
};
105+
106+
107+
108+
std::vector<std::shared_ptr<const ControllerDescriptor>>
109+
get_compatible_descriptors(const ControllerRequirements& requirements);
110+
111+
51112

52113

53114

54115

116+
//
117+
// A configurable option type for the descriptor.
118+
//
55119
class ControllerOption{
56120
public:
57121
ControllerOption();

SerialPrograms/Source/Controllers/ControllerSelectorWidget.cpp

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

77
#include <QHBoxLayout>
88
#include "Common/Qt/NoWheelComboBox.h"
9-
#include "Controllers/ControllerCapability.h"
9+
#include "Controllers/NullController.h"
1010
#include "ControllerSelectorWidget.h"
11-
#include "SerialPABotBase/SerialPABotBase.h"
12-
#include "NintendoSwitch/Controllers/NintendoSwitch_SerialPABotBase.h"
1311

1412
//#include <iostream>
1513
//using std::cout;
@@ -82,20 +80,9 @@ void ControllerSelectorWidget::refresh(){
8280
m_device_list.clear();
8381
m_devices_dropdown->clear();
8482

85-
86-
// Add the "no selection" option.
87-
m_device_list.emplace_back(new NullControllerDescriptor());
88-
89-
// If SerialPABotBase is supported, add them to the list.
90-
if (m_session.requirements().contains_device(SerialPABotBase::NintendoSwitch_Basic)){ // REMOVE
91-
std::vector<std::unique_ptr<const ControllerDescriptor>> serial =
92-
NintendoSwitch::SwitchController_SerialPABotBase_Descriptor::get_all_devices();
93-
std::move(serial.begin(), serial.end(), std::back_inserter(m_device_list));
94-
}
95-
96-
// If we add new interfaces, add them here.
97-
98-
83+
// Rebuild the device list.
84+
m_device_list = get_compatible_descriptors(m_session.requirements());
85+
m_device_list.insert(m_device_list.begin(), std::make_unique<NullControllerDescriptor>());
9986

10087
std::shared_ptr<const ControllerDescriptor> current = m_session.descriptor();
10188

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* Null Controller
2+
*
3+
* From: https://github.com/PokemonAutomation/Arduino-Source
4+
*
5+
*/
6+
7+
#include "Common/Cpp/Json/JsonValue.h"
8+
#include "ControllerConnection.h"
9+
#include "NullController.h"
10+
11+
namespace PokemonAutomation{
12+
13+
template <>
14+
std::vector<std::shared_ptr<const ControllerDescriptor>> ControllerType_t<NullControllerDescriptor>::list() const{
15+
std::vector<std::shared_ptr<const ControllerDescriptor>> ret;
16+
ret.emplace_back(new NullControllerDescriptor());
17+
return ret;
18+
}
19+
20+
21+
template class ControllerType_t<NullControllerDescriptor>;
22+
const char NullControllerDescriptor::TYPENAME[] = "None";
23+
24+
25+
bool NullControllerDescriptor::operator==(const ControllerDescriptor& x) const{
26+
return typeid(*this) == typeid(x);
27+
}
28+
const char* NullControllerDescriptor::type_name() const{
29+
return TYPENAME;
30+
}
31+
std::string NullControllerDescriptor::display_name() const{
32+
return "(none)";
33+
}
34+
void NullControllerDescriptor::load_json(const JsonValue& json){
35+
36+
}
37+
JsonValue NullControllerDescriptor::to_json() const{
38+
return JsonValue();
39+
}
40+
std::unique_ptr<ControllerConnection> NullControllerDescriptor::open(
41+
Logger& logger,
42+
const ControllerRequirements& requirements
43+
) const{
44+
return nullptr;
45+
}
46+
47+
48+
49+
50+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* Null Controller
2+
*
3+
* From: https://github.com/PokemonAutomation/Arduino-Source
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_Controllers_Null_H
8+
#define PokemonAutomation_Controllers_Null_H
9+
10+
#include "ControllerDescriptor.h"
11+
12+
namespace PokemonAutomation{
13+
14+
15+
16+
class NullControllerDescriptor : public ControllerDescriptor{
17+
public:
18+
static const char TYPENAME[];
19+
20+
public:
21+
virtual bool operator==(const ControllerDescriptor& x) const override;
22+
virtual const char* type_name() const override;
23+
virtual std::string display_name() const override;
24+
virtual void load_json(const JsonValue& json) override;
25+
virtual JsonValue to_json() const override;
26+
virtual std::unique_ptr<ControllerConnection> open(
27+
Logger& logger,
28+
const ControllerRequirements& requirements
29+
) const override;
30+
};
31+
32+
33+
34+
}
35+
#endif

SerialPrograms/Source/NintendoSwitch/Controllers/NintendoSwitch_Controller.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include "ClientSource/Connection/BotBaseMessage.h"
1414

1515
namespace PokemonAutomation{
16-
class Cancellable;
1716
namespace NintendoSwitch{
1817

1918

0 commit comments

Comments
 (0)