diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/button/Trigger.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/button/Trigger.java index 46aa5e2c1d..d7b1dd0893 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/button/Trigger.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/button/Trigger.java @@ -49,6 +49,32 @@ public class Trigger implements BooleanSupplier { this(CommandScheduler.getInstance().getDefaultButtonLoop(), condition); } + /** + * Starts the command when the condition changes. + * + * @param command the command to start + * @return this trigger, so calls can be chained + */ + public Trigger onChange(Command command) { + requireNonNullParam(command, "command", "onChange"); + m_loop.bind( + new Runnable() { + private boolean m_pressedLast = m_condition.getAsBoolean(); + + @Override + public void run() { + boolean pressed = m_condition.getAsBoolean(); + + if (m_pressedLast != pressed) { + command.schedule(); + } + + m_pressedLast = pressed; + } + }); + return this; + } + /** * Starts the given command whenever the condition changes from `false` to `true`. * diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/button/Trigger.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/button/Trigger.cpp index 190a544817..78fd0b3f76 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/button/Trigger.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/button/Trigger.cpp @@ -13,6 +13,34 @@ using namespace frc2; Trigger::Trigger(const Trigger& other) = default; +Trigger Trigger::OnChange(Command* command) { + m_loop->Bind( + [condition = m_condition, previous = m_condition(), command]() mutable { + bool current = condition(); + + if (previous != current) { + command->Schedule(); + } + + previous = current; + }); + return *this; +} + +Trigger Trigger::OnChange(CommandPtr&& command) { + m_loop->Bind([condition = m_condition, previous = m_condition(), + command = std::move(command)]() mutable { + bool current = condition(); + + if (previous != current) { + command.Schedule(); + } + + previous = current; + }); + return *this; +} + Trigger Trigger::OnTrue(Command* command) { m_loop->Bind( [condition = m_condition, previous = m_condition(), command]() mutable { diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/button/Trigger.h b/wpilibNewCommands/src/main/native/include/frc2/command/button/Trigger.h index 3051a921ef..2ef93b9c1b 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/button/Trigger.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/button/Trigger.h @@ -57,6 +57,23 @@ class Trigger { Trigger(const Trigger& other); + /** + * Starts the command when the condition changes. + * + * @param command the command to start + * @return this trigger, so calls can be chained + */ + Trigger OnChange(Command* command); + + /** + * Starts the command when the condition changes. Moves command ownership to + * the button scheduler. + * + * @param command the command to start + * @return this trigger, so calls can be chained + */ + Trigger OnChange(CommandPtr&& command); + /** * Starts the given command whenever the condition changes from `false` to * `true`.