diff --git a/src/main/java/frc/team4909/robot/operator/generic/BionicJoystick.java b/src/main/java/frc/team4909/robot/operator/generic/BionicJoystick.java index d630225..b82e524 100644 --- a/src/main/java/frc/team4909/robot/operator/generic/BionicJoystick.java +++ b/src/main/java/frc/team4909/robot/operator/generic/BionicJoystick.java @@ -134,7 +134,7 @@ public boolean get() { } } - private class BionicJoystickPOVButton extends Trigger { + private class BionicJoystickPOVButton extends BionicTrigger { private BionicJoystick inputJoystick; private int povAngle; diff --git a/src/main/java/frc/team4909/robot/operator/generic/BionicTrigger.java b/src/main/java/frc/team4909/robot/operator/generic/BionicTrigger.java new file mode 100644 index 0000000..7cff7ff --- /dev/null +++ b/src/main/java/frc/team4909/robot/operator/generic/BionicTrigger.java @@ -0,0 +1,207 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) 2008-2018 FIRST. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +package frc.team4909.robot.operator.generic; + +import edu.wpi.first.wpilibj.SendableBase; +import edu.wpi.first.wpilibj.buttons.Trigger; +import edu.wpi.first.wpilibj.command.Command; +import edu.wpi.first.wpilibj.command.Scheduler; +import edu.wpi.first.wpilibj.smartdashboard.SendableBuilder; + +/** + * This class provides an easy way to link commands to inputs. + * + *

+ * It is very easy to link a button to a command. For instance, you could link + * the trigger button of a joystick to a "score" command. + * + *

+ * It is encouraged that teams write a subclass of Trigger if they want to have + * something unusual (for instance, if they want to react to the user holding a + * button while the robot is reading a certain sensor input). For this, they + * only have to write the {@link Trigger#get()} method to get the full + * functionality of the Trigger class. + */ +public abstract class BionicTrigger extends SendableBase { + private volatile boolean m_sendablePressed; + + /** + * Returns whether or not the trigger is active. + * + *

+ * This method will be called repeatedly a command is linked to the Trigger. + * + * @return whether or not the trigger condition is active. + */ + public abstract boolean get(); + + /** + * Returns whether get() return true or the internal table for SmartDashboard + * use is pressed. + * + * @return whether get() return true or the internal table for SmartDashboard + * use is pressed. + */ + @SuppressWarnings("PMD.UselessParentheses") + private boolean grab() { + return get() || m_sendablePressed; + } + + /** + * Starts the given command whenever the trigger just becomes active. + * + * @param command the command to start + */ + public void whenActive(final Command command) { + new Trigger.ButtonScheduler() { + private boolean m_pressedLast = grab(); + + @Override + public void execute() { + boolean pressed = grab(); + + if (!m_pressedLast && pressed) { + command.start(); + } + + m_pressedLast = pressed; + } + }.start(); + } + + /** + * Constantly starts the given command while the button is held. + * + * {@link Command#start()} will be called repeatedly while the trigger is + * active, and will be canceled when the trigger becomes inactive. + * + * @param command the command to start + */ + public void whileActive(final Command command) { + new Trigger.ButtonScheduler() { + private boolean m_pressedLast = grab(); + + @Override + public void execute() { + boolean pressed = grab(); + + if (pressed) { + command.start(); + } else if (m_pressedLast && !pressed) { + command.cancel(); + } + + m_pressedLast = pressed; + } + }.start(); + } + + /** + * Starts the given command when the button is pressed, cancels when released. + * + * {@link Command#start()} will be called once when the trigger is + * active, and will be canceled when the trigger becomes inactive. + * + * @param command the command to start + */ + public void whenHeld(final Command command) { + new Trigger.ButtonScheduler() { + private boolean m_pressedLast = grab(); + + @Override + public void execute() { + boolean pressed = grab(); + + if (!m_pressedLast && pressed) { + command.start(); + } else if (m_pressedLast && !pressed) { + command.cancel(); + } + + m_pressedLast = pressed; + } + }.start(); + } + + /** + * Starts the command when the trigger becomes inactive. + * + * @param command the command to start + */ + public void whenInactive(final Command command) { + new Trigger.ButtonScheduler() { + private boolean m_pressedLast = grab(); + + @Override + public void execute() { + boolean pressed = grab(); + + if (m_pressedLast && !pressed) { + command.start(); + } + + m_pressedLast = pressed; + } + }.start(); + } + + /** + * Toggles a command when the trigger becomes active. + * + * @param command the command to toggle + */ + public void toggleWhenActive(final Command command) { + new Trigger.ButtonScheduler() { + private boolean m_pressedLast = grab(); + + @Override + public void execute() { + boolean pressed = grab(); + + if (!m_pressedLast && pressed) { + if (command.isRunning()) { + command.cancel(); + } else { + command.start(); + } + } + + m_pressedLast = pressed; + } + }.start(); + } + + /** + * Cancels a command when the trigger becomes active. + * + * @param command the command to cancel + */ + public void cancelWhenActive(final Command command) { + new Trigger.ButtonScheduler() { + private boolean m_pressedLast = grab(); + + @Override + public void execute() { + boolean pressed = grab(); + + if (!m_pressedLast && pressed) { + command.cancel(); + } + + m_pressedLast = pressed; + } + }.start(); + } + + @Override + public void initSendable(SendableBuilder builder) { + builder.setSmartDashboardType("Button"); + builder.setSafeState(() -> m_sendablePressed = false); + builder.addBooleanProperty("pressed", this::grab, value -> m_sendablePressed = value); + } +}