Implemented key toggle

This commit is contained in:
kalaposfos13 2024-11-14 14:21:05 +01:00
parent 6ad6079c56
commit 09b945ce8b
2 changed files with 75 additions and 36 deletions

View File

@ -47,11 +47,10 @@ Uint32 mouse_polling_id = 0;
bool mouse_enabled = false, leftjoystick_halfmode = false, rightjoystick_halfmode = false; bool mouse_enabled = false, leftjoystick_halfmode = false, rightjoystick_halfmode = false;
std::list<std::pair<u32, bool>> pressed_keys; std::list<std::pair<u32, bool>> pressed_keys;
std::list<u32> toggled_keys;
std::list<BindingConnection> connections = std::list<BindingConnection>(); std::list<BindingConnection> connections = std::list<BindingConnection>();
void toggleMouseEnabled() {
mouse_enabled ^= true;
}
ControllerOutput output_array[] = { ControllerOutput output_array[] = {
// Button mappings // Button mappings
ControllerOutput(OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TRIANGLE), ControllerOutput(OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TRIANGLE),
@ -81,11 +80,16 @@ ControllerOutput output_array[] = {
ControllerOutput(LEFTJOYSTICK_HALFMODE), ControllerOutput(LEFTJOYSTICK_HALFMODE),
ControllerOutput(RIGHTJOYSTICK_HALFMODE), ControllerOutput(RIGHTJOYSTICK_HALFMODE),
ControllerOutput(KEY_TOGGLE),
// End marker to signify the end of the array // End marker to signify the end of the array
ControllerOutput(0, Input::Axis::AxisMax) ControllerOutput(0, Input::Axis::AxisMax)
}; };
// We had to go through 3 files of indirection just to update a flag
void toggleMouseEnabled() {
mouse_enabled ^= true;
}
// parsing related functions // parsing related functions
// syntax: 'name, name,name' or 'name,name' or 'name' // syntax: 'name, name,name' or 'name,name' or 'name'
@ -161,46 +165,54 @@ void parseInputConfig(const std::string game_id = "") {
// Split the line by '=' // Split the line by '='
std::size_t equal_pos = line.find('='); std::size_t equal_pos = line.find('=');
if (equal_pos == std::string::npos) { if (equal_pos == std::string::npos) {
LOG_DEBUG(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, line); LOG_ERROR(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, line);
continue; continue;
} }
std::string before_equals = line.substr(0, equal_pos); std::string output_string = line.substr(0, equal_pos);
std::string after_equals = line.substr(equal_pos + 1); std::string input_string = line.substr(equal_pos + 1);
std::size_t comma_pos = after_equals.find(','); std::size_t comma_pos = input_string.find(',');
// special check for mouse to joystick input // special check for mouse to joystick input
if (before_equals == "mouse_to_joystick") { if (output_string == "mouse_to_joystick") {
if (after_equals == "left") { if (input_string == "left") {
mouse_joystick_binding = 1; mouse_joystick_binding = 1;
} else if (after_equals == "right") { } else if (input_string == "right") {
mouse_joystick_binding = 2; mouse_joystick_binding = 2;
} else { } else {
mouse_joystick_binding = 0; // default to 'none' or invalid mouse_joystick_binding = 0; // default to 'none' or invalid
} }
continue; continue;
} }
// mod key toggle // key toggle
if (before_equals == "modkey_toggle") { if (output_string == "key_toggle") {
if (comma_pos != std::string::npos) { if (comma_pos != std::string::npos) {
// handle key-to-key toggling (separate list?) // handle key-to-key toggling (separate list?)
LOG_DEBUG(Input, "todo: {}", line); InputBinding toggle_keys = getBindingFromString(input_string);
if(toggle_keys.keyCount() != 2) {
LOG_ERROR(Input, "Syntax error: Please provide exactly 2 keys: "
"first is the toggler, the second is the key to toggle: {}", line);
continue;
}
ControllerOutput* toggle_out = getOutputPointer(ControllerOutput(KEY_TOGGLE));
BindingConnection toggle_connection = BindingConnection(InputBinding(toggle_keys.key2), toggle_out, toggle_keys.key3);
connections.insert(connections.end(), toggle_connection);
continue; continue;
} }
LOG_DEBUG(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, line); LOG_ERROR(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, line);
continue; continue;
} }
if (before_equals == "mouse_movement_params") { if (output_string == "mouse_movement_params") {
LOG_DEBUG(Input, "todo: {}", line); LOG_DEBUG(Input, "todo: {}", line);
continue; continue;
} }
// normal cases // normal cases
InputBinding binding = getBindingFromString(after_equals); InputBinding binding = getBindingFromString(input_string);
BindingConnection connection(0, nullptr); BindingConnection connection(0, nullptr);
auto button_it = string_to_cbutton_map.find(before_equals); auto button_it = string_to_cbutton_map.find(output_string);
auto axis_it = string_to_axis_map.find(before_equals); auto axis_it = string_to_axis_map.find(output_string);
if(binding.isEmpty()) { if(binding.isEmpty()) {
LOG_DEBUG(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, line); LOG_DEBUG(Input, "Invalid format at line: {}, data: \"{}\", skipping line.", lineCount, line);
@ -262,7 +274,18 @@ void ControllerOutput::setControllerOutputController(GameController* c) {
ControllerOutput::controller = c; ControllerOutput::controller = c;
} }
void ControllerOutput::update(bool pressed, int a_value) { void toggleKeyInList(u32 key) {
auto it = std::find(toggled_keys.begin(), toggled_keys.end(), key);
if(it == toggled_keys.end()) {
toggled_keys.insert(toggled_keys.end(), key);
LOG_DEBUG(Input, "Added {} to toggled keys", key);
} else {
toggled_keys.erase(it);
LOG_DEBUG(Input, "Removed {} from toggled keys", key);
}
}
void ControllerOutput::update(bool pressed, u32 param) {
float touchpad_x = 0; float touchpad_x = 0;
if(button != 0){ if(button != 0){
switch (button) { switch (button) {
@ -279,6 +302,11 @@ void ControllerOutput::update(bool pressed, int a_value) {
case RIGHTJOYSTICK_HALFMODE: case RIGHTJOYSTICK_HALFMODE:
rightjoystick_halfmode = pressed; rightjoystick_halfmode = pressed;
break; break;
case KEY_TOGGLE:
if(pressed) {
toggleKeyInList(param);
}
break;
default: // is a normal key (hopefully) default: // is a normal key (hopefully)
controller->CheckButton(0, button, pressed); controller->CheckButton(0, button, pressed);
break; break;
@ -298,20 +326,20 @@ void ControllerOutput::update(bool pressed, int a_value) {
case Axis::TriggerRight: case Axis::TriggerRight:
// todo: verify this works (This probably works from testing, // todo: verify this works (This probably works from testing,
// but needs extra info (multiple input to the same trigger?)) // but needs extra info (multiple input to the same trigger?))
axis_value = SDL_clamp((pressed ? a_value : 0) * multiplier, 0, 127); axis_value = SDL_clamp((pressed ? (int)param : 0) * multiplier, 0, 127);
controller->Axis(0, axis, GetAxis(0, 0x80, axis_value)); controller->Axis(0, axis, GetAxis(0, 0x80, axis_value));
return; return;
default: default:
break; break;
} }
axis_value = SDL_clamp((pressed ? a_value : 0) * multiplier, -127, 127); axis_value = SDL_clamp((pressed ? (int)param : 0) * multiplier, -127, 127);
int ax = GetAxis(-0x80, 0x80, axis_value); int ax = GetAxis(-0x80, 0x80, axis_value);
controller->Axis(0, axis, ax); controller->Axis(0, axis, ax);
} else { } else {
LOG_DEBUG(Input, "Controller output with no values detected!"); LOG_DEBUG(Input, "Controller output with no values detected!");
} }
} }
void ControllerOutput::addUpdate(bool pressed, int a_value) { void ControllerOutput::addUpdate(bool pressed, u32 param) {
float touchpad_x = 0; float touchpad_x = 0;
if(button != 0){ if(button != 0){
@ -332,6 +360,11 @@ void ControllerOutput::addUpdate(bool pressed, int a_value) {
case RIGHTJOYSTICK_HALFMODE: case RIGHTJOYSTICK_HALFMODE:
rightjoystick_halfmode = pressed; rightjoystick_halfmode = pressed;
break; break;
case KEY_TOGGLE:
if(pressed) {
toggleKeyInList(param);
}
break;
default: // is a normal key (hopefully) default: // is a normal key (hopefully)
controller->CheckButton(0, button, pressed); controller->CheckButton(0, button, pressed);
break; break;
@ -350,13 +383,13 @@ void ControllerOutput::addUpdate(bool pressed, int a_value) {
case Axis::TriggerLeft: case Axis::TriggerLeft:
case Axis::TriggerRight: case Axis::TriggerRight:
// todo: verify this works // todo: verify this works
axis_value = SDL_clamp((pressed ? a_value : 0) * multiplier + axis_value, 0, 127); axis_value = SDL_clamp((pressed ? (int)param : 0) * multiplier + axis_value, 0, 127);
controller->Axis(0, axis, GetAxis(0, 0x80, axis_value)); controller->Axis(0, axis, GetAxis(0, 0x80, axis_value));
return; return;
default: default:
break; break;
} }
axis_value = SDL_clamp((pressed ? a_value : 0) * multiplier + axis_value, -127, 127); axis_value = SDL_clamp((pressed ? (int)param : 0) * multiplier + axis_value, -127, 127);
controller->Axis(0, axis, GetAxis(-0x80, 0x80, axis_value)); controller->Axis(0, axis, GetAxis(-0x80, 0x80, axis_value));
//LOG_INFO(Input, "Axis value delta: {} final value: {}", (pressed ? a_value : 0), axis_value); //LOG_INFO(Input, "Axis value delta: {} final value: {}", (pressed ? a_value : 0), axis_value);
} else { } else {
@ -390,16 +423,20 @@ bool isInputActive(const InputBinding& i) {
bool* flag2 = nullptr; bool* flag2 = nullptr;
bool* flag3 = nullptr; bool* flag3 = nullptr;
bool key1_pressed = std::find(toggled_keys.begin(), toggled_keys.end(), i.key1) != toggled_keys.end();
bool key2_pressed = std::find(toggled_keys.begin(), toggled_keys.end(), i.key2) != toggled_keys.end();
bool key3_pressed = std::find(toggled_keys.begin(), toggled_keys.end(), i.key3) != toggled_keys.end();
// First pass: locate each key and save pointers to their flags if found // First pass: locate each key and save pointers to their flags if found
for (auto& entry : pressed_keys) { for (auto& entry : pressed_keys) {
u32 key = entry.first; u32 key = entry.first;
bool& is_active = entry.second; bool& is_active = entry.second;
if (i.key1 != 0 && key == i.key1 && !flag1) { if (key1_pressed || (i.key1 != 0 && key == i.key1 && !flag1)) {
flag1 = &is_active; flag1 = &is_active;
} else if (i.key2 != 0 && key == i.key2 && !flag2) { } else if (key2_pressed || (i.key2 != 0 && key == i.key2 && !flag2)) {
flag2 = &is_active; flag2 = &is_active;
} else if (i.key3 != 0 && key == i.key3 && !flag3) { } else if (key3_pressed || (i.key3 != 0 && key == i.key3 && !flag3)) {
flag3 = &is_active; flag3 = &is_active;
break; break;
} else { } else {
@ -420,9 +457,9 @@ bool isInputActive(const InputBinding& i) {
} }
// Set flags to true only after confirming all keys are present and not overridden // Set flags to true only after confirming all keys are present and not overridden
if (flag1) *flag1 = true; if (flag1 && !key1_pressed) *flag1 = true;
if (flag2) *flag2 = true; if (flag2 && !key2_pressed) *flag2 = true;
if (flag3) *flag3 = true; if (flag3 && !key3_pressed) *flag3 = true;
LOG_DEBUG(Input, "A valid held input is found: {}, flag ptrs: {} {} {}", i.toString(), fmt::ptr(flag1), fmt::ptr(flag2), fmt::ptr(flag3)); LOG_DEBUG(Input, "A valid held input is found: {}, flag ptrs: {} {} {}", i.toString(), fmt::ptr(flag1), fmt::ptr(flag2), fmt::ptr(flag3));
return true; return true;
@ -444,7 +481,7 @@ void activateOutputsFromInputs() {
// iterates over the connections, and updates them depending on whether the corresponding input trio is found // iterates over the connections, and updates them depending on whether the corresponding input trio is found
for(auto it = connections.begin(); it != connections.end(); it++) { for(auto it = connections.begin(); it != connections.end(); it++) {
if (it->output) { if (it->output) {
it->output->addUpdate(isInputActive(it->binding), it->axis_value); it->output->addUpdate(isInputActive(it->binding), it->parameter);
} else { } else {
//LOG_DEBUG(Input, "Null output in BindingConnection at position {}", std::distance(connections.begin(), it)); //LOG_DEBUG(Input, "Null output in BindingConnection at position {}", std::distance(connections.begin(), it));
} }

View File

@ -28,6 +28,8 @@
#define LEFTJOYSTICK_HALFMODE 0x00010000 #define LEFTJOYSTICK_HALFMODE 0x00010000
#define RIGHTJOYSTICK_HALFMODE 0x00020000 #define RIGHTJOYSTICK_HALFMODE 0x00020000
#define KEY_TOGGLE 0x00200000
namespace Input { namespace Input {
using Input::Axis; using Input::Axis;
using Libraries::Pad::OrbisPadButtonDataOffset; using Libraries::Pad::OrbisPadButtonDataOffset;
@ -260,18 +262,18 @@ public:
std::string toString() const { std::string toString() const {
return fmt::format("({}, {}, {})", button, (int)axis, axis_value); return fmt::format("({}, {}, {})", button, (int)axis, axis_value);
} }
void update(bool pressed, int axis_direction = 0); void update(bool pressed, u32 param = 0);
// Off events are not counted // Off events are not counted
void addUpdate(bool pressed, int axis_direction = 0); void addUpdate(bool pressed, u32 param = 0);
}; };
class BindingConnection { class BindingConnection {
public: public:
InputBinding binding; InputBinding binding;
ControllerOutput* output; ControllerOutput* output;
int axis_value; u32 parameter;
BindingConnection(InputBinding b, ControllerOutput* out, int a_v = 0) { BindingConnection(InputBinding b, ControllerOutput* out, u32 param = 0) {
binding = b; binding = b;
axis_value = a_v; // bruh this accidentally set to be 0 no wonder it didn't do anything parameter = param; // bruh this accidentally set to be 0 no wonder it didn't do anything
// todo: check if out is in the allowed array // todo: check if out is in the allowed array
output = out; output = out;