Skip to content

Commit 3380ec5

Browse files
committed
WIP controller command tables.
1 parent d29c3e8 commit 3380ec5

File tree

10 files changed

+568
-93
lines changed

10 files changed

+568
-93
lines changed

Common/Cpp/Options/CheckboxDropdownOption.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,17 @@ class CheckboxDropdownCell : public CheckboxDropdownBase{
7878
return m_default;
7979
}
8080
FlagEnum current_value() const;
81+
operator FlagEnum() const{
82+
return current_value();
83+
}
8184

8285

8386
public:
8487
bool is_set(FlagEnum value) const;
88+
89+
void replace_all(FlagEnum value);
90+
void clear();
91+
8592
void set_flag(FlagEnum value);
8693
void clear_flag(FlagEnum value);
8794
void toggle_flag(FlagEnum value);

Common/Cpp/Options/CheckboxDropdownOption.tpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@ bool CheckboxDropdownCell<FlagEnum>::is_set(FlagEnum value) const{
5555
return !is_empty(value & m_current);
5656
}
5757
template <typename FlagEnum>
58+
void CheckboxDropdownCell<FlagEnum>::replace_all(FlagEnum value){
59+
{
60+
WriteSpinLock lg(m_lock);
61+
if (m_current == value){
62+
return;
63+
}
64+
m_current = value;
65+
}
66+
report_value_changed(this);
67+
}
68+
template <typename FlagEnum>
69+
void CheckboxDropdownCell<FlagEnum>::clear(){
70+
replace_all(empty_value((FlagEnum*)nullptr));
71+
}
72+
template <typename FlagEnum>
5873
void CheckboxDropdownCell<FlagEnum>::set_flag(FlagEnum value){
5974
{
6075
WriteSpinLock lg(m_lock);

Common/Cpp/Options/EditableTableOption.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,11 @@ std::vector<std::shared_ptr<EditableTableRow>> EditableTableOption::current_refs
118118
}
119119

120120
void EditableTableOption::clear(){
121-
WriteSpinLock lg(m_current_lock);
122-
m_current.clear();
121+
{
122+
WriteSpinLock lg(m_current_lock);
123+
m_current.clear();
124+
}
125+
report_value_changed(this);
123126
}
124127
void EditableTableOption::load_json(const JsonValue& json){
125128
// cout << "EditableTableOption::load_json(): " << this << endl;
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/* Controller State Table
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#include <map>
8+
#include "Common/Cpp/Exceptions.h"
9+
#include "ControllerTypeStrings.h"
10+
#include "ControllerStateTable.h"
11+
12+
namespace PokemonAutomation{
13+
14+
15+
16+
struct ControllerTypeEntry{
17+
ControllerCommandTable::RowFactory factory;
18+
std::vector<std::string> headers;
19+
};
20+
21+
std::map<ControllerClass, ControllerTypeEntry>& controller_map(){
22+
static std::map<ControllerClass, ControllerTypeEntry> map;
23+
return map;
24+
}
25+
26+
27+
28+
void ControllerCommandTable::register_controller_type(
29+
ControllerClass type,
30+
RowFactory factory,
31+
std::vector<std::string> headers
32+
){
33+
auto& map = controller_map();
34+
if (map.emplace(
35+
type, ControllerTypeEntry{factory, std::move(headers)}
36+
).second
37+
){
38+
return;
39+
}
40+
throw InternalProgramError(
41+
nullptr,
42+
PA_CURRENT_FUNCTION,
43+
"Duplicate Controller Enum: " + std::to_string((int)type)
44+
);
45+
}
46+
47+
48+
std::vector<std::string> ControllerCommandTable::make_header() const{
49+
auto& map = controller_map();
50+
auto iter = map.find(m_type);
51+
if (iter != map.end()){
52+
return iter->second.headers;
53+
}
54+
throw InternalProgramError(
55+
nullptr,
56+
PA_CURRENT_FUNCTION,
57+
"Unsupported Controller Type: " + CONTROLLER_CLASS_STRINGS().get_string(m_type)
58+
);
59+
}
60+
std::unique_ptr<EditableTableRow> ControllerCommandTable::make_row(){
61+
auto& map = controller_map();
62+
auto iter = map.find(m_type);
63+
if (iter != map.end()){
64+
return iter->second.factory(*this);
65+
}
66+
throw InternalProgramError(
67+
nullptr,
68+
PA_CURRENT_FUNCTION,
69+
"Unsupported Controller Type: " + CONTROLLER_CLASS_STRINGS().get_string(m_type)
70+
);
71+
}
72+
73+
74+
75+
76+
77+
78+
79+
ControllerCommandTables::~ControllerCommandTables(){
80+
m_type.remove_listener(*this);
81+
}
82+
ControllerCommandTables::ControllerCommandTables(const std::vector<ControllerClass>& controller_list)
83+
: BatchOption(LockMode::UNLOCK_WHILE_RUNNING)
84+
, m_type(
85+
"<b>Controller Type:</b>",
86+
make_database(controller_list),
87+
LockMode::LOCK_WHILE_RUNNING,
88+
ControllerClass::NintendoSwitch_ProController
89+
)
90+
, m_table(
91+
ControllerClass::NintendoSwitch_ProController,
92+
"",
93+
LockMode::UNLOCK_WHILE_RUNNING
94+
)
95+
{
96+
PA_ADD_OPTION(m_type);
97+
PA_ADD_OPTION(m_table);
98+
m_type.add_listener(*this);
99+
}
100+
101+
102+
void ControllerCommandTables::on_config_value_changed(void* object){
103+
m_table.clear();
104+
m_table.m_type = m_type;
105+
}
106+
107+
108+
EnumDropdownDatabase<ControllerClass> ControllerCommandTables::make_database(
109+
const std::vector<ControllerClass>& controller_list
110+
){
111+
auto& map = controller_map();
112+
EnumDropdownDatabase<ControllerClass> ret;
113+
for (ControllerClass type : controller_list){
114+
if (map.find(type) == map.end()){
115+
throw InternalProgramError(
116+
nullptr,
117+
PA_CURRENT_FUNCTION,
118+
"Unsupported Controller Type: " + CONTROLLER_CLASS_STRINGS().get_string(type)
119+
);
120+
}
121+
const std::string& str = CONTROLLER_CLASS_STRINGS().get_string(type);
122+
ret.add(type, str, str, true);
123+
}
124+
return ret;
125+
}
126+
127+
128+
129+
130+
131+
132+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* Controller State Table
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_Controllers_ControllerStateTable_H
8+
#define PokemonAutomation_Controllers_ControllerStateTable_H
9+
10+
#include "Common/Cpp/Options/BatchOption.h"
11+
#include "Common/Cpp/Options/EnumDropdownOption.h"
12+
#include "Common/Cpp/Options/EditableTableOption.h"
13+
#include "ControllerTypes.h"
14+
#include "ControllerState.h"
15+
16+
namespace PokemonAutomation{
17+
18+
19+
20+
21+
class ControllerStateRow : public EditableTableRow{
22+
public:
23+
using EditableTableRow::EditableTableRow;
24+
virtual std::unique_ptr<ControllerState> get_state(Milliseconds& duration) const = 0;
25+
};
26+
27+
28+
29+
class ControllerCommandTable : public EditableTableOption{
30+
public:
31+
using RowFactory = std::unique_ptr<ControllerStateRow> (*)(ControllerCommandTable& parent);
32+
33+
static void register_controller_type(
34+
ControllerClass type,
35+
RowFactory factory,
36+
std::vector<std::string> headers
37+
);
38+
39+
template <typename RowType>
40+
static std::unique_ptr<ControllerStateRow> make_row(ControllerCommandTable& parent){
41+
return std::unique_ptr<ControllerStateRow>(new RowType(parent));
42+
}
43+
44+
45+
public:
46+
ControllerCommandTable(
47+
ControllerClass type,
48+
std::string label,
49+
LockMode lock_while_running
50+
)
51+
: EditableTableOption(std::move(label), lock_while_running)
52+
, m_type(type)
53+
{}
54+
55+
ControllerClass type() const{
56+
return m_type;
57+
}
58+
59+
void run(
60+
CancellableScope& scope,
61+
AbstractController& controller
62+
){
63+
std::vector<std::unique_ptr<ControllerStateRow>> table = EditableTableOption::copy_snapshot<ControllerStateRow>();
64+
for (std::unique_ptr<ControllerStateRow>& command : table){
65+
Milliseconds duration;
66+
std::unique_ptr<ControllerState> state = command->get_state(duration);
67+
state->execute(scope, controller, duration);
68+
}
69+
}
70+
71+
virtual std::vector<std::string> make_header() const override;
72+
virtual std::unique_ptr<EditableTableRow> make_row() override;
73+
74+
75+
private:
76+
friend class ControllerCommandTables;
77+
ControllerClass m_type;
78+
};
79+
80+
81+
82+
83+
84+
class ControllerCommandTables : public BatchOption, public ConfigOption::Listener{
85+
public:
86+
~ControllerCommandTables();
87+
ControllerCommandTables(const std::vector<ControllerClass>& controller_list);
88+
89+
public:
90+
virtual void on_config_value_changed(void* object) override;
91+
92+
private:
93+
static EnumDropdownDatabase<ControllerClass> make_database(
94+
const std::vector<ControllerClass>& controller_list
95+
);
96+
97+
private:
98+
// There is a race condition here if multiple threads try to change this
99+
// at the same time since it clears the table. But we only ever do this
100+
// from the main Qt thread.
101+
EnumDropdownOption<ControllerClass> m_type;
102+
103+
ControllerCommandTable m_table;
104+
};
105+
106+
107+
108+
109+
110+
111+
112+
}
113+
#endif

0 commit comments

Comments
 (0)