Skip to content

Commit

Permalink
refactor: ♻️ Use Meyer's singleton instead of nifty counter
Browse files Browse the repository at this point in the history
  • Loading branch information
ion098 committed Aug 19, 2024
1 parent 9a6beb9 commit bfe697f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 67 deletions.
21 changes: 11 additions & 10 deletions include/gamepad/controller.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "pros/misc.h"
#include <cstdint>
#include <functional>
#ifndef PROS_USE_SIMPLE_NAMES
Expand Down Expand Up @@ -43,15 +44,7 @@ class Button {
EventHandler<> onReleaseEvent;
};

namespace _impl {
static struct ControllerInit {
ControllerInit();
~ControllerInit();
} _controllerInit;
} // namespace _impl

class Controller {
friend struct _impl::ControllerInit;
public:
/**
* Updates the state of the gamepad (all joysticks and buttons), and also runs
Expand All @@ -73,6 +66,10 @@ class Controller {
TODO("hide memebrs and expose getters/const refs")
Button L1 {}, L2 {}, R1 {}, R2 {}, Up {}, Down {}, Left {}, Right {}, X {}, B {}, Y {}, A {};
float LeftX = 0, LeftY = 0, RightX = 0, RightY = 0;
/// The master controller, same as @ref Gamepad::master
static Controller master;
/// The partner controller, same as @ref Gamepad::partner
static Controller partner;
private:
explicit Controller(pros::controller_id_e_t id)
: controller(id) {}
Expand All @@ -82,7 +79,11 @@ class Controller {
pros::Controller controller;
};

extern Controller& master;
extern Controller& partner;
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
78 changes: 21 additions & 57 deletions src/gamepad/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,7 @@
#include "gamepad/todo.hpp"
#include "pros/misc.h"

#include <new>

namespace Gamepad {

union ControllerBuf {
// this is here to allow us to control when we initialize the Controller
char c;
Controller as_controller;

// empty destructor, the Controller must be manually destroyed by ControllerInit
~ControllerBuf() {}
};

static uint32_t nifty_counter; // zero initialized at load time
ControllerBuf master_buf {};
Controller& master = master_buf.as_controller;
ControllerBuf partner_buf {};
Controller& partner = partner_buf.as_controller;

_impl::ControllerInit::ControllerInit() {
// only initialize once, if we're the first ControllerInit instance
if (nifty_counter == 0) {
new (&master_buf.as_controller) Controller(pros::E_CONTROLLER_MASTER);
new (&partner_buf.as_controller) Controller(pros::E_CONTROLLER_PARTNER);
}
++nifty_counter;
}

_impl::ControllerInit::~ControllerInit() {
--nifty_counter;
// only destroy if we're the last ControllerInit instance
if (nifty_counter == 0) {
master.~Controller();
partner.~Controller();
}
}

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) {
Expand Down Expand Up @@ -79,12 +43,12 @@ void Controller::updateButton(pros::controller_digital_e_t button_id) {
}

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 = pros::E_CONTROLLER_DIGITAL_L1; i != pros::E_CONTROLLER_DIGITAL_A; ++i) { this->updateButton(static_cast<pros::controller_digital_e_t>(i)); }

this->LeftX = this->controller.get_analog(ANALOG_LEFT_X);
this->LeftY = this->controller.get_analog(ANALOG_LEFT_Y);
this->RightX = this->controller.get_analog(ANALOG_RIGHT_X);
this->RightY = this->controller.get_analog(ANALOG_RIGHT_Y);
this->LeftX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_X);
this->LeftY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y);
this->RightX = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_X);
this->RightY = this->controller.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y);
}

const Button& Controller::operator[](pros::controller_digital_e_t button) {
Expand All @@ -93,28 +57,28 @@ const Button& Controller::operator[](pros::controller_digital_e_t button) {

float Controller::operator[](pros::controller_analog_e_t axis) {
switch (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 pros::E_CONTROLLER_ANALOG_LEFT_X: return this->LeftX;
case pros::E_CONTROLLER_ANALOG_LEFT_Y: return this->LeftY;
case pros::E_CONTROLLER_ANALOG_RIGHT_X: return this->RightX;
case pros::E_CONTROLLER_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) {
switch (button) {
case DIGITAL_L1: return &Controller::L1;
case DIGITAL_L2: return &Controller::L2;
case DIGITAL_R1: return &Controller::R1;
case DIGITAL_R2: return &Controller::R2;
case DIGITAL_UP: return &Controller::Up;
case DIGITAL_DOWN: return &Controller::Down;
case DIGITAL_LEFT: return &Controller::Left;
case DIGITAL_RIGHT: return &Controller::Right;
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 pros::E_CONTROLLER_DIGITAL_L1: return &Controller::L1;
case pros::E_CONTROLLER_DIGITAL_L2: return &Controller::L2;
case pros::E_CONTROLLER_DIGITAL_R1: return &Controller::R1;
case pros::E_CONTROLLER_DIGITAL_R2: return &Controller::R2;
case pros::E_CONTROLLER_DIGITAL_UP: return &Controller::Up;
case pros::E_CONTROLLER_DIGITAL_DOWN: return &Controller::Down;
case pros::E_CONTROLLER_DIGITAL_LEFT: return &Controller::Left;
case pros::E_CONTROLLER_DIGITAL_RIGHT: return &Controller::Right;
case pros::E_CONTROLLER_DIGITAL_X: return &Controller::X;
case pros::E_CONTROLLER_DIGITAL_B: return &Controller::B;
case pros::E_CONTROLLER_DIGITAL_Y: return &Controller::Y;
case pros::E_CONTROLLER_DIGITAL_A: return &Controller::A; TODO("change handling for default")
default: std::exit(1);
}
}
Expand Down

0 comments on commit bfe697f

Please sign in to comment.