Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔖 v0.1.0 Release! #15

Merged
merged 77 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
09148af
Update devcontainer.json
ion098 May 23, 2024
eabc919
Update postCreateCommand.bash
ion098 May 23, 2024
86af24a
Merge pull request #3 from LemLib/feature/codespace-support
Aang099 May 23, 2024
c8e0880
fix: :bug: Malformed URL on PR open event
meisZWFLZ May 23, 2024
a0f62b8
:green_heart: That should be a SHA..
meisZWFLZ May 23, 2024
75eb85e
Merge pull request #4 from LemLib/ci/fix/malformed-url-on-pr-open-event
Aang099 May 23, 2024
6f8b5fd
Merge pull request #5 from LemLib/main
ion098 May 24, 2024
7c5ac05
add more event handling methods
ion098 May 24, 2024
c3fa979
add operator bool to Button
ion098 May 24, 2024
565ade4
Format all files
ion098 May 24, 2024
9ad720f
change handling of default cases
ion098 May 27, 2024
f4d01f3
added missing return and default case to Button::addListener
ion098 May 27, 2024
8466e2c
fix switch formatting
ion098 May 27, 2024
0d221e6
remove unnecessary todo
ion098 May 27, 2024
c397474
hide buttons / joystick values and expose const refs to users instead
ion098 May 27, 2024
af8e66d
implement nifty counter for Controller
ion098 May 28, 2024
3dc4a67
use Gamepad in main.cpp
ion098 May 28, 2024
4ce0057
use union instead of array for Controller buffer
ion098 May 29, 2024
3ded296
hide controllerInit in _impl namespace
ion098 May 29, 2024
6321e53
fix compile error, move ControllerInit ctor and dtor to _impl namespace
ion098 May 29, 2024
fd24a3f
fixed more compile issues, fixed all declarations to be in correct na…
ion098 May 29, 2024
8613f8f
fix onLongPress so it does not repeatedly fire
ion098 Jun 2, 2024
7d22c8b
fix long press so it actually fires
ion098 Jun 5, 2024
2b4d5ab
update example code in main.cpp
ion098 Jun 5, 2024
6e152b8
Add RecursiveMutex class and fix deadlock in remove_listener
ion098 Jun 5, 2024
490620b
add removeListener test to main.cpp
ion098 Jun 5, 2024
b4742e5
Fix capitalization error in #include file path
ion098 Jun 5, 2024
1832d76
remove unnecessary todos and includes
ion098 Jun 7, 2024
fb93b84
feat: :sparkles: Add names to button listeners
ion098 Jul 5, 2024
e14160d
feat: :sparkles: Add shortRelease button event
ion098 Jul 5, 2024
54b5302
feat: :sparkles: Allow internal code to add listeners that don't conf…
ion098 Jul 8, 2024
55c6782
fix: :bug: Allow handlers to actually be registered
ion098 Jul 13, 2024
e02fedf
test: :white_check_mark: Add shortRelease test in main.cpp
ion098 Jul 13, 2024
907cbf5
docs: :memo: Add documentation to Button, Controller, and EventHandle…
ion098 Jul 13, 2024
10f33ce
refactor: :recycle: Move EventHandler and RecursiveMutex to Gamepad::…
ion098 Jul 19, 2024
a829c7d
ci: :construction_worker: Add clang-format workflow
ion098 Jul 20, 2024
646a77d
ci: :green_heart: Fix pr-comment so it works with empty pr bodies
ion098 Jul 20, 2024
3f0f5ff
ci: :green_heart: Fix copy-paste error in clang-format workflow
ion098 Jul 20, 2024
be072f0
ci: :green_heart: Fix pr-comment for real this time
ion098 Jul 20, 2024
e5b0c43
Merge pull request #9 from LemLib/ci/clang-format-check
ion098 Jul 20, 2024
1997092
Merge branch 'main' into feature/global-instances
ion098 Jul 20, 2024
b320148
Merge branch 'main' into feature/event-handler
ion098 Jul 20, 2024
d138ee0
style: :art: Fix formatting
ion098 Jul 27, 2024
219b2c9
Merge pull request #10 from LemLib/style/fix-formatting
Aang099 Jul 28, 2024
9f1b114
ci: :arrow_up: update pros-build to v2.0.2
meisZWFLZ Aug 9, 2024
da5d41c
Merge pull request #11 from LemLib/meisZWFLZ-patch-1
Aang099 Aug 9, 2024
e9226df
Bump clang-format version
Aang099 Aug 9, 2024
18d8680
Merge pull request #12 from LemLib/clang-format-18
Aang099 Aug 9, 2024
df0eccd
style: :art: Format everything
ion098 Aug 11, 2024
da35fc8
Merge branch 'feature/event-handler' of https://github.com/LemLib/Gam…
ion098 Aug 11, 2024
cbb3bef
Merge branch 'main' of https://github.com/LemLib/Gamepad into feature…
ion098 Aug 11, 2024
de2e8e9
docs: :bulb: Remove obsolete todo in Button::update
ion098 Aug 11, 2024
f34e6d7
fix: :adhesive_bandage: Never throw in RecursiveMutex::lock
ion098 Aug 11, 2024
402a090
docs: :memo: Remove @brief from member vars in Button class
ion098 Aug 12, 2024
8f26067
style: :art: Fix formatting
ion098 Aug 13, 2024
9a6beb9
Merge branch 'main' into feature/global-instances
ion098 Aug 13, 2024
fbf8e84
fix: :adhesive_bandage: Fix memory leak in RecursiveMutex class
ion098 Aug 19, 2024
4eb21f3
refactor: :fire: Remove unnecessary include in recursive_mutex.hpp
ion098 Aug 19, 2024
020af19
docs: :memo: Document RecursiveMutex class
ion098 Aug 19, 2024
1b5c5f8
refactor: :recycle: Use inline variable instead of nifty counter
ion098 Aug 19, 2024
641917b
style: :art: Format controller.cpp
ion098 Aug 19, 2024
8a70ae0
style: :art: Fix formatting in main.cpp
ion098 Aug 21, 2024
9c1e994
Merge pull request #7 from LemLib/feature/global-instances
SizzinSeal Aug 21, 2024
fae16ac
Merge branch 'main' into feature/event-handler
ion098 Aug 21, 2024
40468c4
fix: :bug: Fix compiler errors from merging
ion098 Aug 21, 2024
0597d84
refactor: :recycle: Rearrange main.cpp, improve docs in main.cpp
ion098 Aug 21, 2024
b2bfc25
style: :art: Reformat files
ion098 Aug 21, 2024
da27ae1
docs: :memo: Add example code to Button class methods
ion098 Aug 21, 2024
2831ee2
style: :art: Fix formatting
ion098 Aug 21, 2024
7f210fc
docs: :memo: Improve docs formatting/grammar
ion098 Aug 22, 2024
6b75be8
docs: :memo: Fix formatting of docs for Controller
ion098 Aug 23, 2024
da5a563
style: :art: Remove braces on single line ifs in controller.cpp
ion098 Aug 23, 2024
6f1d792
fix: :bug: Fix A button not working
ion098 Sep 5, 2024
8280f2f
Merge pull request #6 from LemLib/feature/event-handler
ion098 Sep 6, 2024
766136a
fix: :bug: Make A button actually work
ion098 Sep 6, 2024
c3e795e
Merge pull request #13 from LemLib/fix/a-button
Aang099 Sep 6, 2024
99897dc
Merge remote-tracking branch 'origin/stable' into chore/fix-merge-con…
ion098 Sep 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"postCreateCommand": "chmod 777 .devcontainer/postCreateCommand.bash && .devcontainer/postCreateCommand.bash"
}
"postCreateCommand": "chmod 777 .devcontainer/postCreateCommand.bash && .devcontainer/postCreateCommand.bash && source ~/.bashrc"
}
1 change: 0 additions & 1 deletion .devcontainer/postCreateCommand.bash
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ curl https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/10.3
tar -xjvf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2
echo "PATH=$PATH:/home/codespace/gcc-arm-none-eabi-10.3-2021.10/bin" >> ~/.bashrc
popd
source ~/.bashrc
21 changes: 21 additions & 0 deletions .github/workflows/clang-format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: test-clang-format

on:
push:
branches:
- '*'
pull_request:
workflow_dispatch:


jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: DoozyX/[email protected]
with:
source: './src/gamepad ./include/gamepad'
extensions: 'hpp,cpp'
clangFormatVersion: 18
2 changes: 1 addition & 1 deletion .github/workflows/pr-comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:

const old_marker = new RegExp(marker.replace("\r\n", "\r?\n")).exec(old_body)?.[0] ?? marker;

body = old_body.split(old_marker)[0] + marker + body;
body = (old_body ?? "").split(old_marker)[0] + marker + body;
await github.request('PATCH /repos/{owner}/{repo}/pulls/{pull_number}', {
owner: owner,
repo: repo,
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pros-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ jobs:

steps:
- uses: actions/checkout@v4
- uses: LemLib/pros-build@v1.0.0
- uses: LemLib/pros-build@v2.0.2
with:
library-path: gamepad
4 changes: 4 additions & 0 deletions include/gamepad/api.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once

#include "gamepad/event_handler.hpp" // IWYU pragma: export
#include "gamepad/controller.hpp" // IWYU pragma: export
274 changes: 274 additions & 0 deletions include/gamepad/controller.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
#pragma once

#include "pros/misc.h"
#include <cstdint>
#include <functional>
#include <string>
#ifndef PROS_USE_SIMPLE_NAMES
#define PROS_USE_SIMPLE_NAMES
#endif

#include "event_handler.hpp"
#include "pros/misc.hpp"
#include "pros/rtos.hpp"

namespace Gamepad {

enum EventType {
ON_PRESS,
ON_LONG_PRESS,
ON_RELEASE,
ON_SHORT_RELEASE,
};

class Button {
friend class Controller;
public:
/// Whether the button has just been pressed
bool rising_edge = false;
/// Whether the button has just been released
bool falling_edge = false;
/// Whether the button is currently held down
bool is_pressed = false;
/// How long the button has been held down
uint32_t time_held = 0;
/// How long the button has been released
uint32_t time_released = 0;
/// How long the threshold should be for the longPress and shortRelease events
uint32_t long_press_threshold = 500;
/**
* @brief Register a function to run when the button is pressed.
*
* @param listenerName The name of the listener, this must be a unique name
* @param func The function to run when the button is pressed, the function MUST NOT block
* @return true The listener was successfully registered
* @return false The listener was not successfully registered (there is already a listener with this name)
*
* @b Example:
* @code {.cpp}
* // Use a function...
* Gamepad::master.Down.onPress("downPress1", downPress1);
* // ...or a lambda
* Gamepad::master.Up.onPress("upPress1", []() { std::cout << "I was pressed!" << std::endl; });
* @endcode
*/
bool onPress(std::string listenerName, std::function<void(void)> func) const;
/**
* @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.
*
* @warning When using this event along with onPress, both the onPress
* and onlongPress listeners may fire together.
*
* @param listenerName The name of the listener, this must be a unique name
* @param func The function to run when the button is long pressed, the function MUST NOT block
* @return true The listener was successfully registered
* @return false The listener was not successfully registered (there is already a listener with this name)
*
* @b Example:
* @code {.cpp}
* // Use a function...
* Gamepad::master.Left.onLongPress("fireCatapult", fireCatapult);
* // ...or a lambda
* Gamepad::master.Right.onLongPress("print_right", []() { std::cout << "Right button was long pressed!" <<
* std::endl; });
* @endcode
*/
bool onLongPress(std::string listenerName, std::function<void(void)> func) const;
/**
* @brief Register a function to run when the button is released.
*
* @param listenerName The name of the listener, this must be a unique name
* @param func The function to run when the button is released, the function MUST NOT block
* @return true The listener was successfully registered
* @return false The listener was not successfully registered (there is already a listener with this name)
*
* @b Example:
* @code {.cpp}
* // Use a function...
* Gamepad::master.X.onRelease("stopFlywheel", stopFlywheel);
* // ...or a lambda
* Gamepad::master.Y.onRelease("stopIntake", []() { intake.move(0); });
* @endcode
*/
bool onRelease(std::string listenerName, std::function<void(void)> func) const;
/**
* @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.
*
* @note This event will most likely be used along with the longPress event.
*
* @param listenerName The name of the listener, this must be a unique name
* @param func The function to run when the button is short released, the function MUST NOT block
* @return true The listener was successfully registered
* @return false The listener was not successfully registered (there is already a listener with this name)
*
* @b Example:
* @code {.cpp}
* // Use a function...
* Gamepad::master.A.onShortRelease("raiseLiftOneLevel", raiseLiftOneLevel);
* // ...or a lambda
* Gamepad::master.B.onShortRelease("intakeOnePicce", []() { intake.move_relative(600, 100); });
* @endcode
*/
bool onShortRelease(std::string listenerName, std::function<void(void)> func) const;
/**
* @brief Register a function to run for a given event.
*
* @param event Which event to register the listener on.
* @param listenerName The name of the listener, this must be a unique name
* @param func The function to run for the given event, the function MUST NOT block
* @return true The listener was successfully registered
* @return false The listener was not successfully registered (there is already a listener with this name)
*
* @b Example:
* @code {.cpp}
* // Use a function...
* Gamepad::master.L1.addListener(Gamepad::ON_PRESS, "start_spin", startSpin);
* // ...or a lambda
* Gamepad::master.L1.addListener(Gamepad::ON_RELEASE, "stop_spin", []() { motor1.brake(); });
* @endcode
*/
bool addListener(EventType event, std::string listenerName, std::function<void(void)> func) const;
/**
* @brief Removes a listener from the button
* @warning Usage of this function is discouraged.
*
* @param listenerName The name of the listener to remove
* @return true The specified listener was successfully removed
* @return false The specified listener could not be removed
*
* @b Example:
* @code {.cpp}
* // Add an event listener...
* Gamepad::master.L1.addListener(Gamepad::ON_PRESS, "do_something", doSomething);
* // ...and now get rid of it
* Gamepad::master.L1.removeListener("do_something");
* @endcode
*/
bool removeListener(std::string listenerName) const;

/**
* @brief Returns a value indicating whether the button is currently being held.
*
* @return true The button is currently pressed
* @return false The button is not currently pressed
*/
explicit operator bool() const { return is_pressed; }
private:
/**
* @brief Updates the button and runs any event handlers, if necessary
*
* @param is_held Whether or not the button is currently held down
*/
void update(bool is_held);
/// he 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;
mutable _impl::EventHandler<std::string> onPressEvent {};
mutable _impl::EventHandler<std::string> onLongPressEvent {};
mutable _impl::EventHandler<std::string> onReleaseEvent {};
mutable _impl::EventHandler<std::string> onShortReleaseEvent {};
};

class Controller {
public:
/**
* @brief Updates the state of the gamepad (all joysticks and buttons), and also runs
* any registered listeners.
*
* @note This function should be called at the beginning of every loop iteration.
*
* @b Example:
* @code {.cpp}
* while (true) {
* Gamepad::master.update();
* // do robot control stuff here...
* pros::delay(25);
* }
* @endcode
*
*/
void update();
/**
* @brief Get the state of a button on the controller.
*
* @param button Which button to return
*
* @b Example:
* @code {.cpp}
* if(Gamepad::master[DIGITAL_L1]) {
* // do something here...
* }
* @endcode
*
*/
const Button& operator[](pros::controller_digital_e_t button);
/**
* @brief Get the value of a joystick axis on the controller.
*
* @param joystick Which joystick axis to return
*
* @b Example:
* @code {.cpp}
* // control a motor with a joystick
* intake.move(Gamepad::master[ANALOG_RIGHT_Y]);
* @endcode
*
*/
float operator[](pros::controller_analog_e_t joystick);
const Button& L1 {m_L1};
const Button& L2 {m_L2};
const Button& R1 {m_R1};
const Button& R2 {m_R2};
const Button& Up {m_Up};
const Button& Down {m_Down};
const Button& Left {m_Left};
const Button& Right {m_Right};
const Button& X {m_X};
const Button& B {m_B};
const Button& Y {m_Y};
const Button& A {m_A};
const float& LeftX = m_LeftX;
const float& LeftY = m_LeftY;
const float& RightX = m_RightX;
const float& RightY = m_RightY;
/// The master controller, same as @ref Gamepad::master
static Controller master;
/// The partner controller, same as @ref Gamepad::partner
static Controller partner;
private:
Controller(pros::controller_id_e_t id)
: controller(id) {}

Button m_L1 {}, m_L2 {}, m_R1 {}, m_R2 {}, m_Up {}, m_Down {}, m_Left {}, m_Right {}, m_X {}, m_B {}, m_Y {},
m_A {};
float m_LeftX = 0, m_LeftY = 0, m_RightX = 0, m_RightY = 0;
Button Fake {};
/**
* @brief Gets a unique name for a listener that will not conflict with user listener names.
*
* @important: when using the function, you must register the listener by
* directly calling add_listener on the EventHandler, do NOT use onPress/addListener,etc.
*
* @return std::string A unique listener name
*/
static std::string unique_name();
static Button Controller::*button_to_ptr(pros::controller_digital_e_t button);
void updateButton(pros::controller_digital_e_t button_id);
pros::Controller controller;
};

inline Controller Controller::master {pros::E_CONTROLLER_MASTER};
inline Controller Controller::partner {pros::E_CONTROLLER_PARTNER};
/// The master controller
inline Controller& master = Controller::master;
/// The partner controller
inline Controller& partner = Controller::partner;

} // namespace Gamepad
Loading
Loading