Skip to content

Commit 05cc31f

Browse files
authored
Merge pull request #21 from LemLib/main
🔖 v0.2.0 Release
2 parents e44a8e7 + a1a8ae1 commit 05cc31f

File tree

8 files changed

+432
-285
lines changed

8 files changed

+432
-285
lines changed

Diff for: Makefile

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ EXCLUDE_COLD_LIBRARIES:=
2525

2626
# Set this to 1 to add additional rules to compile your project as a PROS library template
2727
IS_LIBRARY:=1
28-
# TODO: CHANGE THIS!
2928
LIBNAME:=gamepad
30-
VERSION:=0.1.0
29+
VERSION:=0.2.0
3130
# EXCLUDE_SRC_FROM_LIB= $(SRCDIR)/unpublishedfile.c
3231
# this line excludes opcontrol.c and similar files
3332
EXCLUDE_SRC_FROM_LIB+=$(foreach file, $(SRCDIR)/main,$(foreach cext,$(CEXTS),$(file).$(cext)) $(foreach cxxext,$(CXXEXTS),$(file).$(cxxext)))

Diff for: include/gamepad/button.hpp

+260
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <functional>
5+
#include <string>
6+
7+
#include "event_handler.hpp"
8+
9+
namespace gamepad {
10+
enum EventType {
11+
ON_PRESS,
12+
ON_LONG_PRESS,
13+
ON_RELEASE,
14+
ON_SHORT_RELEASE,
15+
ON_LONG_RELEASE,
16+
ON_REPEAT_PRESS,
17+
};
18+
19+
class Button {
20+
friend class Gamepad;
21+
public:
22+
/// Whether the button has just been pressed
23+
bool rising_edge = false;
24+
/// Whether the button has just been released
25+
bool falling_edge = false;
26+
/// Whether the button is currently held down
27+
bool is_pressed = false;
28+
/// How long the button has been held down
29+
uint32_t time_held = 0;
30+
/// How long the button has been released
31+
uint32_t time_released = 0;
32+
/// How many times the button has been repeat-pressed
33+
uint32_t repeat_iterations = 0;
34+
/**
35+
* @brief Set the time for a press to be considered a long press for the button
36+
*
37+
* @note this is likely to be used with the onLongPress(), onShortRelease(), onLongRelease(), or onRepeatPress()
38+
* events
39+
*
40+
* @param threshold the time in ms that would be considered a long press
41+
*
42+
* @b Example:
43+
* @code {.cpp}
44+
* // change the threshold
45+
* gamepad::master.Left.set_long_press_threshold(5000);
46+
* // then call the function
47+
* gamepad::master.Left.onLongPress("longPress1", []() {
48+
* std::cout << "I was held for 5000ms instead of the 500ms default!" << std::endl;
49+
* });
50+
* @endcode
51+
*/
52+
void set_long_press_threshold(uint32_t threshold) const;
53+
/**
54+
* @brief Set the interval for the repeatPress event to repeat
55+
*
56+
* @note this is likely to be used with the onRepeatPress() event
57+
*
58+
* @param cooldown the interval in ms
59+
*
60+
* @b Example:
61+
* @code {.cpp}
62+
* // change the threshold
63+
* gamepad::master.Up.set_repeat_cooldown(100);
64+
* // then call the function
65+
* gamepad::master.Up.onRepeatPress("repeatPress1", []() {
66+
* std::cout << "I'm being repeated every 100ms instead of the 50ms default!" << std::endl;
67+
* });
68+
* @endcode
69+
*/
70+
void set_repeat_cooldown(uint32_t cooldown) const;
71+
/**
72+
* @brief Register a function to run when the button is pressed.
73+
*
74+
* @param listenerName The name of the listener, this must be a unique name
75+
* @param func The function to run when the button is pressed, the function MUST NOT block
76+
* @return true The listener was successfully registered
77+
* @return false The listener was not successfully registered (there is already a listener with this name)
78+
*
79+
* @b Example:
80+
* @code {.cpp}
81+
* // Use a function...
82+
* gamepad::master.Down.onPress("downPress1", downPress1);
83+
* // ...or a lambda
84+
* gamepad::master.Up.onPress("upPress1", []() { std::cout << "I was pressed!" << std::endl; });
85+
* @endcode
86+
*/
87+
bool onPress(std::string listenerName, std::function<void(void)> func) const;
88+
/**
89+
* @brief Register a function to run when the button is long pressed.
90+
*
91+
* By default, onLongPress will fire when the button has been held down for
92+
* 500ms or more, this threshold can be adjusted via the set_long_press_threshold() method.
93+
*
94+
* @warning When using this event along with onPress, both the onPress
95+
* and onlongPress listeners may fire together.
96+
*
97+
* @param listenerName The name of the listener, this must be a unique name
98+
* @param func The function to run when the button is long pressed, the function MUST NOT block
99+
* @return true The listener was successfully registered
100+
* @return false The listener was not successfully registered (there is already a listener with this name)
101+
*
102+
* @b Example:
103+
* @code {.cpp}
104+
* // Use a function...
105+
* gamepad::master.Left.onLongPress("fireCatapult", fireCatapult);
106+
* // ...or a lambda
107+
* gamepad::master.Right.onLongPress("print_right", []() { std::cout << "Right button was long pressed!" <<
108+
* std::endl; });
109+
* @endcode
110+
*/
111+
bool onLongPress(std::string listenerName, std::function<void(void)> func) const;
112+
/**
113+
* @brief Register a function to run when the button is released.
114+
*
115+
* @param listenerName The name of the listener, this must be a unique name
116+
* @param func The function to run when the button is released, the function MUST NOT block
117+
* @return true The listener was successfully registered
118+
* @return false The listener was not successfully registered (there is already a listener with this name)
119+
*
120+
* @b Example:
121+
* @code {.cpp}
122+
* // Use a function...
123+
* gamepad::master.X.onRelease("stopFlywheel", stopFlywheel);
124+
* // ...or a lambda
125+
* gamepad::master.Y.onRelease("stopIntake", []() { intake.move(0); });
126+
* @endcode
127+
*/
128+
bool onRelease(std::string listenerName, std::function<void(void)> func) const;
129+
/**
130+
* @brief Register a function to run when the button is short released.
131+
*
132+
* By default, shortRelease will fire when the button has been released before 500ms, this threshold can be
133+
* adjusted via the set_long_press_threshold() method.
134+
*
135+
* @note This event will most likely be used along with the longPress event.
136+
*
137+
* @param listenerName The name of the listener, this must be a unique name
138+
* @param func The function to run when the button is short released, the function MUST NOT block
139+
* @return true The listener was successfully registered
140+
* @return false The listener was not successfully registered (there is already a listener with this name)
141+
*
142+
* @b Example:
143+
* @code {.cpp}
144+
* // Use a function...
145+
* gamepad::master.A.onShortRelease("raiseLiftOneLevel", raiseLiftOneLevel);
146+
* // ...or a lambda
147+
* gamepad::master.B.onShortRelease("intakeOnePiece", []() { intake.move_relative(600, 100); });
148+
* @endcode
149+
*/
150+
bool onShortRelease(std::string listenerName, std::function<void(void)> func) const;
151+
/**
152+
* @brief Register a function to run when the button is long released.
153+
*
154+
* By default, longRelease will fire when the button has been released after 500ms, this threshold can be
155+
* adjusted via the set_long_press_threshold() method.
156+
*
157+
* @param listenerName The name of the listener, this must be a unique name
158+
* @param func The function to run when the button is long released, the function MUST NOT block
159+
* @return true The listener was successfully registered
160+
* @return false The listener was not successfully registered (there is already a listener with this name)
161+
*
162+
* @b Example:
163+
* @code {.cpp}
164+
* // Use a function...
165+
* gamepad::master.Up.onLongRelease("moveLiftToGround", moveLiftToGround);
166+
* // ...or a lambda
167+
* gamepad::master.Left.onLongRelease("spinIntake", []() { intake.move(127); });
168+
* @endcode
169+
*
170+
*/
171+
bool onLongRelease(std::string listenerName, std::function<void(void)> func) const;
172+
/**
173+
* @brief Register a function to run periodically after its been held
174+
*
175+
* By default repeatPress will start repeating after 500ms and repeat every 50ms, this can be adjusted via the
176+
* set_long_press_threshold() and set_repeat_cooldown() methods respectively
177+
*
178+
* @param listenerName The name of the listener, this must be a unique name
179+
* @param func the function to run periodically when the button is held, the function MUST NOT block
180+
* @return true The listener was successfully registered
181+
* @return false The listener was not successfully registered (there is already a listener with this name)
182+
*
183+
* @b Example:
184+
* @code {.cpp}
185+
* // Use a function...
186+
* gamepad::master.X.onRepeatPress("shootDisk", shootOneDisk);
187+
* // ...or a lambda
188+
* gamepad::master.A.onRepeatPress("scoreOneRing", []() { intake.move_relative(200, 100); });
189+
* @endcode
190+
*
191+
*/
192+
bool onRepeatPress(std::string listenerName, std::function<void(void)> func) const;
193+
/**
194+
* @brief Register a function to run for a given event.
195+
*
196+
* @param event Which event to register the listener on.
197+
* @param listenerName The name of the listener, this must be a unique name
198+
* @param func The function to run for the given event, the function MUST NOT block
199+
* @return true The listener was successfully registered
200+
* @return false The listener was not successfully registered (there is already a listener with this name)
201+
*
202+
* @b Example:
203+
* @code {.cpp}
204+
* // Use a function...
205+
* gamepad::master.L1.addListener(gamepad::ON_PRESS, "start_spin", startSpin);
206+
* // ...or a lambda
207+
* gamepad::master.L1.addListener(gamepad::ON_RELEASE, "stop_spin", []() { motor1.brake(); });
208+
* @endcode
209+
*/
210+
bool addListener(EventType event, std::string listenerName, std::function<void(void)> func) const;
211+
/**
212+
* @brief Removes a listener from the button
213+
* @warning Usage of this function is discouraged.
214+
*
215+
* @param listenerName The name of the listener to remove
216+
* @return true The specified listener was successfully removed
217+
* @return false The specified listener could not be removed
218+
*
219+
* @b Example:
220+
* @code {.cpp}
221+
* // Add an event listener...
222+
* gamepad::master.L1.addListener(gamepad::ON_PRESS, "do_something", doSomething);
223+
* // ...and now get rid of it
224+
* gamepad::master.L1.removeListener("do_something");
225+
* @endcode
226+
*/
227+
bool removeListener(std::string listenerName) const;
228+
229+
/**
230+
* @brief Returns a value indicating whether the button is currently being held.
231+
*
232+
* @return true The button is currently pressed
233+
* @return false The button is not currently pressed
234+
*/
235+
explicit operator bool() const { return is_pressed; }
236+
private:
237+
/**
238+
* @brief Updates the button and runs any event handlers, if necessary
239+
*
240+
* @param is_held Whether or not the button is currently held down
241+
*/
242+
void update(bool is_held);
243+
/// How long the threshold should be for the longPress and shortRelease events
244+
mutable uint32_t long_press_threshold = 500;
245+
/// How often repeatPress is called
246+
mutable uint32_t repeat_cooldown = 50;
247+
/// The last time the update function was called
248+
uint32_t last_update_time = pros::millis();
249+
/// The last time the long press event was fired
250+
uint32_t last_long_press_time = 0;
251+
/// The last time the repeat event was called
252+
uint32_t last_repeat_time = 0;
253+
mutable _impl::EventHandler<std::string> onPressEvent {};
254+
mutable _impl::EventHandler<std::string> onLongPressEvent {};
255+
mutable _impl::EventHandler<std::string> onReleaseEvent {};
256+
mutable _impl::EventHandler<std::string> onShortReleaseEvent {};
257+
mutable _impl::EventHandler<std::string> onLongReleaseEvent {};
258+
mutable _impl::EventHandler<std::string> onRepeatPressEvent {};
259+
};
260+
} // namespace gamepad

0 commit comments

Comments
 (0)