From 510b15161cc82dafe32f31fc8d7cf16714e5e26a Mon Sep 17 00:00:00 2001 From: lufimio <67525443+PA055@users.noreply.github.com> Date: Sun, 6 Oct 2024 19:08:29 -0400 Subject: [PATCH] fix: :bug: made it possible to change `long_press_threshold` and `repeat_cooldown` --- include/gamepad/button.hpp | 65 ++++++++++++++++++++++++++++++-------- src/gamepad/button.cpp | 15 +++++++-- src/main.cpp | 26 ++++++++++++++- 3 files changed, 89 insertions(+), 17 deletions(-) diff --git a/include/gamepad/button.hpp b/include/gamepad/button.hpp index fee1471..b867da7 100644 --- a/include/gamepad/button.hpp +++ b/include/gamepad/button.hpp @@ -31,10 +31,43 @@ class Button { uint32_t time_released = 0; /// How many times the button has been repeat-pressed uint32_t repeat_iterations = 0; - /// How long the threshold should be for the longPress and shortRelease events - uint32_t long_press_threshold = 500; - /// How often repeatPress is called - uint32_t repeat_cooldown = 50; + /** + * @brief Set the time for a press to be considered a long press for the button + * + * @note this is likely to be used with the onLongPress(), onShortRelease(), onLongRelease(), or onRepeatPress() + * events + * + * @param threshold the time in ms that would be considered a long press + * + * @b Example: + * @code {.cpp} + * // change the threshold + * gamepad::master.Left.set_long_press_threshold(5000); + * // then call the function + * gamepad::master.Left.onLongPress("longPress1", []() { + * std::cout << "I was held for 5000ms instead of the 500ms default!" << std::endl; + * }); + * @endcode + */ + void set_long_press_threshold(uint32_t threshold) const; + /** + * @brief Set the interval for the repeatPress event to repeat + * + * @note this is likely to be used with the onRepeatPress() event + * + * @param cooldown the interval in ms + * + * @b Example: + * @code {.cpp} + * // change the threshold + * gamepad::master.Up.set_repeat_cooldown(100); + * // then call the function + * gamepad::master.Up.onRepeatPress("repeatPress1", []() { + * std::cout << "I'm being repeated every 100ms instead of the 50ms default!" << std::endl; + * }); + * @endcode + */ + void set_repeat_cooldown(uint32_t cooldown) const; /** * @brief Register a function to run when the button is pressed. * @@ -56,7 +89,7 @@ class Button { * @brief Register a function to run when the button is long pressed. * * By default, onLongPress will fire when the button has been held down for - * 500ms or more, this threshold can be adjusted by changing long_press_threshold. + * 500ms or more, this threshold can be adjusted via the set_long_press_threshold() method. * * @warning When using this event along with onPress, both the onPress * and onlongPress listeners may fire together. @@ -97,7 +130,7 @@ class Button { * @brief Register a function to run when the button is short released. * * By default, shortRelease will fire when the button has been released before 500ms, this threshold can be - * adjusted by changing long_press_threshold. + * adjusted via the set_long_press_threshold() method. * * @note This event will most likely be used along with the longPress event. * @@ -119,7 +152,7 @@ class Button { * @brief Register a function to run when the button is long released. * * By default, longRelease will fire when the button has been released after 500ms, this threshold can be - * adjusted by changing long_press_threshold. + * adjusted via the set_long_press_threshold() method. * * @param listenerName The name of the listener, this must be a unique name * @param func The function to run when the button is long released, the function MUST NOT block @@ -129,9 +162,9 @@ class Button { * @b Example: * @code {.cpp} * // Use a function... - * gamepad::master.A.onLongRelease("moveLiftToGround", moveLiftToGround); + * gamepad::master.Up.onLongRelease("moveLiftToGround", moveLiftToGround); * // ...or a lambda - * gamepad::master.B.onLongRelease("spinIntake", []() { intake.move(127); }); + * gamepad::master.Left.onLongRelease("spinIntake", []() { intake.move(127); }); * @endcode * */ @@ -139,8 +172,8 @@ class Button { /** * @brief Register a function to run periodically after its been held * - * By default repeatPress will start repeating after 500ms and repeat every 50ms, this can be changed by - * adjusting long_press_threshold and repeat_cooldown respectively + * By default repeatPress will start repeating after 500ms and repeat every 50ms, this can be adjusted via the + * set_long_press_threshold() and set_repeat_cooldown() methods respectively * * @param listenerName The name of the listener, this must be a unique name * @param func the function to run periodically when the button is held, the function MUST NOT block @@ -150,9 +183,9 @@ class Button { * @b Example: * @code {.cpp} * // Use a function... - * gamepad::master.A.onRepeatPress("shootDisk", shootOneDisk); + * gamepad::master.X.onRepeatPress("shootDisk", shootOneDisk); * // ...or a lambda - * gamepad::master.B.onRepeatPress("scoreOneRing", []() { intake.move_relative(200, 100); }); + * gamepad::master.A.onRepeatPress("scoreOneRing", []() { intake.move_relative(200, 100); }); * @endcode * */ @@ -207,11 +240,15 @@ class Button { * @param is_held Whether or not the button is currently held down */ void update(bool is_held); + /// How long the threshold should be for the longPress and shortRelease events + mutable uint32_t long_press_threshold = 500; + /// How often repeatPress is called + mutable uint32_t repeat_cooldown = 50; /// The last time the update function was called uint32_t last_update_time = pros::millis(); /// The last time the long press event was fired uint32_t last_long_press_time = 0; - // The last time the repeat event was called + /// The last time the repeat event was called uint32_t last_repeat_time = 0; mutable _impl::EventHandler onPressEvent {}; mutable _impl::EventHandler onLongPressEvent {}; diff --git a/src/gamepad/button.cpp b/src/gamepad/button.cpp index 7cd7eb3..127aaca 100644 --- a/src/gamepad/button.cpp +++ b/src/gamepad/button.cpp @@ -1,8 +1,18 @@ #include "gamepad/button.hpp" #include "gamepad/todo.hpp" #include "pros/rtos.hpp" +#include +#include namespace gamepad { +void Button::set_long_press_threshold(uint32_t threshold) const { + this->long_press_threshold = threshold; +} + +void Button::set_repeat_cooldown(uint32_t cooldown) const { + this->repeat_cooldown = cooldown; +} + bool Button::onPress(std::string listenerName, std::function func) const { return this->onPressEvent.add_listener(std::move(listenerName) + "_user", std::move(func)); } @@ -65,10 +75,10 @@ void Button::update(const bool is_held) { this->last_long_press_time <= pros::millis() - this->time_held) { this->onLongPressEvent.fire(); this->last_long_press_time = pros::millis(); - this->last_repeat_time = pros::millis(); + this->last_repeat_time = pros::millis() - this->repeat_cooldown; this->repeat_iterations = 0; } else if (this->is_pressed && this->time_held >= this->long_press_threshold && - pros::millis() - this->last_repeat_time > this->repeat_cooldown) { + pros::millis() - this->last_repeat_time >= this->repeat_cooldown) { this->repeat_iterations++; this->onRepeatPressEvent.fire(); this->last_repeat_time = pros::millis(); @@ -77,6 +87,7 @@ void Button::update(const bool is_held) { if (this->time_held < this->long_press_threshold) this->onShortReleaseEvent.fire(); else this->onLongReleaseEvent.fire(); } + if (this->rising_edge) this->time_held = 0; if (this->falling_edge) this->time_released = 0; this->last_update_time = pros::millis(); diff --git a/src/main.cpp b/src/main.cpp index e3da78e..b0bef76 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,9 @@ #include "main.h" #include "gamepad/api.hpp" +#include "gamepad/controller.hpp" +#include "pros/rtos.hpp" +#include +#include /** * Runs initialization code. This occurs as soon as the program is started. @@ -8,6 +12,8 @@ * to keep execution time for this mode under a few seconds. */ +uint32_t last_repeat_press_time = pros::millis(); + void downPress1() { printf("Down Press!\n"); } void upRelease1() { printf("Up Release!\n"); } @@ -16,6 +22,18 @@ void leftLongPress1() { printf("Left Long Press!\n"); } void leftShortRelease1() { printf("Left Short Release!\n"); } +void leftLongRelease1() { printf("Left Long Release!\n"); } + +void aPress1() { + last_repeat_press_time = pros::millis(); + printf("A Pressed!\n"); +} + +void aRepeatPress1() { + printf("A Repeat Pressed %ims after last\n", pros::millis() - last_repeat_press_time); + last_repeat_press_time = pros::millis(); +} + void initialize() { // We can register functions to run when buttons are pressed gamepad::master.Down.onPress("downPress1", downPress1); @@ -23,9 +41,15 @@ void initialize() { gamepad::master.Up.onRelease("downRelease1", upRelease1); // There's also the longPress event gamepad::master.Left.onLongPress("leftLongPress1", leftLongPress1); - // We can have two functions on one button, + // We can have two or even more functions on one button, // just remember to give them different names gamepad::master.Left.onShortRelease("leftShortRelease", leftShortRelease1); + gamepad::master.Left.onLongRelease("leftLongRelease", leftLongRelease1); + // We also have the repeat press event, where we can adjust the timing + gamepad::master.A.set_long_press_threshold(1000); // in ms + gamepad::master.A.set_repeat_cooldown(100); // in ms + gamepad::master.A.onPress("aStartPress", aPress1); + gamepad::master.A.onRepeatPress("aRepeatPress", aRepeatPress1); // And we can use lambda's too gamepad::master.X.onShortRelease("xShortRelease1", []() { printf("X Short Release!\n"); }); }