diff --git a/include/gamepad/controller.hpp b/include/gamepad/controller.hpp index 3615d3c..1e2debf 100644 --- a/include/gamepad/controller.hpp +++ b/include/gamepad/controller.hpp @@ -2,6 +2,7 @@ #include #include +#include #ifndef PROS_USE_SIMPLE_NAMES #define PROS_USE_SIMPLE_NAMES #endif @@ -30,21 +31,21 @@ class Button { uint32_t time_released = 0; uint32_t long_press_threshold = 500; - uint32_t onPress(std::function func) const; - uint32_t onLongPress(std::function func) const; - uint32_t onRelease(std::function func) const; - uint32_t addListener(EventType event, std::function func) const; - bool removeListener(uint32_t id) const; + bool onPress(std::string listenerName, std::function func) const; + bool onLongPress(std::string listenerName, std::function func) const; + bool onRelease(std::string listenerName, std::function func) const; + bool addListener(EventType event, std::string listenerName, std::function func) const; + bool removeListener(std::string listenerName) const; explicit operator bool() const { return is_pressed; } private: void update(bool is_held); uint32_t last_update_time = pros::millis(); - mutable EventHandler<> onPressEvent {}; + mutable EventHandler onPressEvent {}; uint32_t last_long_press_time = 0; - mutable EventHandler<> onLongPressEvent {}; - mutable EventHandler<> onReleaseEvent {}; + mutable EventHandler onLongPressEvent {}; + mutable EventHandler onReleaseEvent {}; }; class Controller { diff --git a/include/gamepad/event_handler.hpp b/include/gamepad/event_handler.hpp index d3be159..e8fd680 100644 --- a/include/gamepad/event_handler.hpp +++ b/include/gamepad/event_handler.hpp @@ -1,42 +1,35 @@ #pragma once #include -#include #include -#include -#include +#include +#include #include "gamepad/recursive_mutex.hpp" namespace Gamepad { -class MonotonicCounter { - template friend class EventHandler; - - static uint32_t next_value() { - static std::atomic counter = 0; - return ++counter; - } -}; - -template class EventHandler { +template class EventHandler { public: using Listener = std::function; - uint32_t add_listener(Listener func) { + bool add_listener(Key key, Listener func) { std::lock_guard lock(mutex); - uint32_t id = MonotonicCounter::next_value(); - listeners.emplace(id, std::move(func)); - return id; + if (std::find(keys.begin(), keys.end(), key) == keys.end()) return false; + keys.push_back(key); + listeners.push_back(func); + return true; } - bool remove_listener(uint32_t id) { + bool remove_listener(Key key) { std::lock_guard lock(mutex); - if (listeners.find(id) == listeners.end()) { - return false; + auto i = std::find(keys.begin(), keys.end(), key); + if (i != keys.end()) { + keys.erase(i); + listeners.erase(listeners.begin() + (i - keys.begin())); + return true; } - listeners.erase(id); - return true; + return false; } bool is_empty() { @@ -46,10 +39,11 @@ template class EventHandler { void fire(Args... args) { std::lock_guard lock(mutex); - for (auto listener : listeners) { listener.second(args...); } + for (auto listener : listeners) { listener(args...); } } private: - std::map listeners; - Gamepad::RecursiveMutex mutex; + std::vector keys {}; + std::vector listeners {}; + Gamepad::RecursiveMutex mutex {}; }; } // namespace Gamepad \ No newline at end of file diff --git a/src/gamepad/controller.cpp b/src/gamepad/controller.cpp index 2962876..22af469 100644 --- a/src/gamepad/controller.cpp +++ b/src/gamepad/controller.cpp @@ -3,33 +3,33 @@ namespace Gamepad { -uint32_t Button::onPress(std::function func) const { - return this->onPressEvent.add_listener(std::move(func)); +bool Button::onPress(std::string listenerName, std::function func) const { + return this->onPressEvent.add_listener(std::move(listenerName), std::move(func)); } -uint32_t Button::onLongPress(std::function func) const { - return this->onLongPressEvent.add_listener(std::move(func)); +bool Button::onLongPress(std::string listenerName, std::function func) const { + return this->onLongPressEvent.add_listener(std::move(listenerName), std::move(func)); } -uint32_t Button::onRelease(std::function func) const { - return this->onReleaseEvent.add_listener(std::move(func)); +bool Button::onRelease(std::string listenerName, std::function func) const { + return this->onReleaseEvent.add_listener(std::move(listenerName), std::move(func)); } -uint32_t Button::addListener(EventType event, std::function func) const { +bool Button::addListener(EventType event, std::string listenerName, std::function func) const { switch (event) { - case Gamepad::EventType::ON_PRESS: return this->onPress(std::move(func)); - case Gamepad::EventType::ON_LONG_PRESS: return this->onLongPress(std::move(func)); - case Gamepad::EventType::ON_RELEASE: return this->onRelease(std::move(func)); + case Gamepad::EventType::ON_PRESS: return this->onPress(std::move(listenerName), std::move(func)); + case Gamepad::EventType::ON_LONG_PRESS: return this->onLongPress(std::move(listenerName), std::move(func)); + case Gamepad::EventType::ON_RELEASE: return this->onRelease(std::move(listenerName), std::move(func)); default: TODO("add error logging") errno = EINVAL; - return 0; + return false; } } -bool Button::removeListener(uint32_t id) const { - return this->onPressEvent.remove_listener(id) || this->onLongPressEvent.remove_listener(id) || - this->onReleaseEvent.remove_listener(id); +bool Button::removeListener(std::string listenerName) const { + return this->onPressEvent.remove_listener(listenerName) || this->onLongPressEvent.remove_listener(listenerName) || + this->onReleaseEvent.remove_listener(listenerName); } void Button::update(const bool is_held) { diff --git a/src/main.cpp b/src/main.cpp index 60d9185..db867db 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,8 +10,7 @@ Gamepad::Controller master(CONTROLLER_MASTER); * All other competition modes are blocked by initialize; it is recommended * to keep execution time for this mode under a few seconds. */ -void initialize() { -} +void initialize() {} /** * Runs while the robot is in the disabled state of Field Management System or @@ -58,31 +57,19 @@ void autonomous() {} * task, not resume it from where it left off. */ void opcontrol() { - master.Down.onPress([](){ - printf("Down Press!\n"); - }); - master.Down.onLongPress([](){ - printf("Down longPress!\n"); - }); - master.Down.onRelease([](){ - printf("Down Release!\n"); - }); - master.Up.onPress([](){ - printf("Up Press!\n"); - }); - master.Up.onLongPress([](){ - printf("Up longPress!\n"); - }); - auto i = master.Up.onRelease([](){ - printf("Up Release!\n"); - }); - master.Up.onRelease([=](){ - master.Up.removeListener(i); - printf("Up Release 2!\n"); - }); - while (true) { - master.update(); - pros::screen::print(TEXT_MEDIUM, 3, "%f %f %f %f", master.LeftX, master.LeftY, master.RightX, master.RightY); - pros::delay(20); - } + master.Down.onPress("downPress1", []() { printf("Down Press!\n"); }); + master.Down.onLongPress("downLongPress1", []() { printf("Down longPress!\n"); }); + master.Down.onRelease("downRelease1", []() { printf("Down Release!\n"); }); + master.Up.onPress("uppress1", []() { printf("Up Press!\n"); }); + master.Up.onLongPress("upLongPress1", []() { printf("Up longPress!\n"); }); + master.Up.onRelease("upRelease1", []() { printf("Up Release!\n"); }); + master.Up.onRelease("upRelease2", [=]() { + master.Up.removeListener("upRelease1"); + printf("Up Release 2!\n"); + }); + while (true) { + master.update(); + pros::screen::print(TEXT_MEDIUM, 3, "%f %f %f %f", master.LeftX, master.LeftY, master.RightX, master.RightY); + pros::delay(20); + } } \ No newline at end of file