Skip to content

Commit

Permalink
feat: ✨ Add joystick curves to controller
Browse files Browse the repository at this point in the history
Allow users to assign a DriveCurve per axis to be used by the controller when updating joystick values.
  • Loading branch information
ion098 committed Jun 17, 2024
1 parent 749edf4 commit 1ca81b0
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 44 deletions.
57 changes: 32 additions & 25 deletions include/gamepad/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

#include <cstdint>
#include <functional>
#include <memory>
#ifndef PROS_USE_SIMPLE_NAMES
#define PROS_USE_SIMPLE_NAMES
#endif

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

Expand All @@ -19,34 +21,35 @@ enum EventType {
};

class Button {
friend class Controller;
friend class Controller;
public:
bool rising_edge = false;
bool falling_edge = false;
bool is_pressed = false;
uint32_t last_press_time = pros::millis();
uint32_t last_release_time = last_press_time;
uint32_t time_held = 0;
uint32_t time_released = 0;
uint32_t long_press_threshold = 500;
bool rising_edge = false;
bool falling_edge = false;
bool is_pressed = false;
uint32_t last_press_time = pros::millis();
uint32_t last_release_time = last_press_time;
uint32_t time_held = 0;
uint32_t time_released = 0;
uint32_t long_press_threshold = 500;

uint32_t onPress(std::function<void(void)> func);
uint32_t onLongPress(std::function<void(void)> func);
uint32_t onRelease(std::function<void(void)> func);
uint32_t addListener(EventType event, std::function<void(void)> func);
bool removeListener(uint32_t id);
uint32_t onPress(std::function<void(void)> func);
uint32_t onLongPress(std::function<void(void)> func);
uint32_t onRelease(std::function<void(void)> func);
uint32_t addListener(EventType event, std::function<void(void)> func);
bool removeListener(uint32_t id);
private:
void update(bool is_held);

void update(bool is_held);

EventHandler<> onPressEvent;
EventHandler<> onLongPressEvent;
EventHandler<> onReleaseEvent;
EventHandler<> onPressEvent;
EventHandler<> onLongPressEvent;
EventHandler<> onReleaseEvent;
};

class Controller {
public:
explicit Controller(pros::controller_id_e_t id): controller(id) {}
explicit Controller(pros::controller_id_e_t id)
: controller(id) {}

/**
* Updates the state of the gamepad (all joysticks and buttons), and also runs
* any registered handlers.
Expand All @@ -64,14 +67,18 @@ class Controller {
* @param joystick Which joystick axis's value to return
*/
float operator[](pros::controller_analog_e_t joystick);
void setCurve(pros::controller_analog_e_t joystick, std::shared_ptr<DriveCurve> curve);
void setCurve(pros::controller_analog_e_t joystick, DriveCurve& curve);
TODO("hide memebrs and expose getters/const refs")
Button L1{}, L2{}, R1{}, R2{},
Up{}, Down{}, Left{}, Right{},
X{}, B{}, Y{}, A{};
Button L1 {}, L2 {}, R1 {}, R2 {}, Up {}, Down {}, Left {}, Right {}, X {}, B {}, Y {}, A {};
float LeftX = 0, LeftY = 0, RightX = 0, RightY = 0;
private:
static Button Controller::* button_to_ptr(pros::controller_digital_e_t button);
std::shared_ptr<DriveCurve> CurveLeftX {nullptr};
std::shared_ptr<DriveCurve> CurveLeftY {nullptr};
std::shared_ptr<DriveCurve> CurveRightX {nullptr};
std::shared_ptr<DriveCurve> CurveRightY {nullptr};
static Button Controller::*button_to_ptr(pros::controller_digital_e_t button);
void updateButton(pros::controller_digital_e_t button_id);
pros::Controller controller;
}; // namespace Gamepad
}
} // namespace Gamepad
46 changes: 27 additions & 19 deletions src/gamepad/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@

namespace Gamepad {

uint32_t Button::onPress(std::function<void(void)> func) {
return this->onPressEvent.add_listener(std::move(func));
}
uint32_t Button::onPress(std::function<void(void)> func) { return this->onPressEvent.add_listener(std::move(func)); }

uint32_t Button::onLongPress(std::function<void(void)> func) {
return this->onLongPressEvent.add_listener(std::move(func));
Expand All @@ -26,12 +24,8 @@ void Button::update(const bool is_held) {
} else {
this->time_released += pros::millis() - last_update_time;
}
if (this->rising_edge) {
this->time_held = 0;
}
if (this->falling_edge) {
this->time_released = 0;
}
if (this->rising_edge) { this->time_held = 0; }
if (this->falling_edge) { this->time_released = 0; }

if (this->rising_edge) {
onPressEvent.fire();
Expand All @@ -43,20 +37,22 @@ void Button::update(const bool is_held) {
}

void Controller::updateButton(pros::controller_digital_e_t button_id) {
Button Controller::* button = Controller::button_to_ptr(button_id);
Button Controller::*button = Controller::button_to_ptr(button_id);
bool is_held = this->controller.get_digital(button_id);
(this->*button).update(is_held);
}

void Controller::update() {
for(int i = DIGITAL_L1; i != DIGITAL_A; ++i) {
this->updateButton(static_cast<pros::controller_digital_e_t>(i));
}
for (int i = DIGITAL_L1; i != DIGITAL_A; ++i) { this->updateButton(static_cast<pros::controller_digital_e_t>(i)); }

this->LeftX = this->controller.get_analog(ANALOG_LEFT_X);
if (this->CurveLeftX) this->LeftX = this->CurveLeftX->curve(this->LeftX);
this->LeftY = this->controller.get_analog(ANALOG_LEFT_Y);
if (this->CurveLeftY) this->LeftY = this->CurveLeftY->curve(this->LeftY);
this->RightX = this->controller.get_analog(ANALOG_RIGHT_X);
if (this->CurveRightX) this->RightX = this->CurveRightX->curve(this->RightX);
this->RightY = this->controller.get_analog(ANALOG_RIGHT_Y);
if (this->CurveRightY) this->RightY = this->CurveRightY->curve(this->RightY);
}

const Button& Controller::operator[](pros::controller_digital_e_t button) {
Expand All @@ -68,13 +64,26 @@ float Controller::operator[](pros::controller_analog_e_t axis) {
case ANALOG_LEFT_X: return this->LeftX;
case ANALOG_LEFT_Y: return this->LeftY;
case ANALOG_RIGHT_X: return this->RightX;
case ANALOG_RIGHT_Y: return this->RightY;
TODO("change handling for default")
case ANALOG_RIGHT_Y: return this->RightY; TODO("change handling for default")
default: std::exit(1);
}
}

Button Controller::* Controller::button_to_ptr(pros::controller_digital_e_t button) {
void Controller::setCurve(pros::controller_analog_e_t joystick, std::shared_ptr<DriveCurve> curve) {
switch (axis) {
case ANALOG_LEFT_X: this->CurveLeftX = curve;
case ANALOG_LEFT_Y: this->CurveLeftY = curve;
case ANALOG_RIGHT_X: this->CurveRightX = curve;
case ANALOG_RIGHT_Y: this->CurveRightY = curve; TODO("add error logging")
default: errno = EINVAL;
}
}

void Controller::setCurve(pros::controller_analog_e_t joystick, DriveCurve& curve) {
this->setCurve(joystick, std::shared_ptr<DriveCurve>(&curve, [](void*) {}));
}

Button Controller::*Controller::button_to_ptr(pros::controller_digital_e_t button) {
switch (button) {
case DIGITAL_L1: return &Controller::L1;
case DIGITAL_L2: return &Controller::L2;
Expand All @@ -87,9 +96,8 @@ Button Controller::* Controller::button_to_ptr(pros::controller_digital_e_t butt
case DIGITAL_X: return &Controller::X;
case DIGITAL_B: return &Controller::B;
case DIGITAL_Y: return &Controller::Y;
case DIGITAL_A: return &Controller::A;
TODO("change handling for default")
case DIGITAL_A: return &Controller::A; TODO("change handling for default")
default: std::exit(1);
}
}
}
} // namespace Gamepad

0 comments on commit 1ca81b0

Please sign in to comment.