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

[cmd] Allow specifying initial condition of Trigger bindings #7425

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,34 @@
* <p>This class is provided by the NewCommands VendorDep
*/
public class Trigger implements BooleanSupplier {
/**
* Enum specifying the initial state to use for a binding. This impacts whether or not the binding
* will be triggered immediately.
*/
public enum InitialState {
/**
* Indicates the binding should use false as the initial value. This causes a rising edge at the
* start if and only if the condition starts true.
*/
kFalse,
/**
* Indicates the binding should use true as the initial value. This causes a falling edge at the
* start if and only if the condition starts false.
*/
kTrue,
/**
* Indicates the binding should use the trigger's condition as the initial value. This never
* causes an edge at the start. This is the default behavior.
*/
kCondition,
/**
* Indicates the binding should use the negated trigger's condition as the initial value. This
* always causes an edge at the start. Rising or falling depends on if the condition starts true
* or false, respectively.
*/
kNegCondition;
}

private final BooleanSupplier m_condition;
private final EventLoop m_loop;

Expand All @@ -50,16 +78,42 @@ public Trigger(BooleanSupplier condition) {
}

/**
* Starts the command when the condition changes.
* Gets the initial state for a binding based on an initial state policy.
*
* @param initialState Initial state policy.
* @return The initial state to use.
*/
private boolean getInitialState(InitialState initialState) {
return switch (initialState) {
case kFalse -> false;
case kTrue -> true;
case kCondition -> m_condition.getAsBoolean();
case kNegCondition -> !m_condition.getAsBoolean();
};
}

/**
* Starts the command when the condition changes. The command is never started immediately.
*
* @param command the command to start
* @return this trigger, so calls can be chained
*/
public Trigger onChange(Command command) {
return onChange(command, InitialState.kCondition);
}

/**
* Starts the command when the condition changes.
*
* @param command the command to start
* @param initialState the initial state to use, kCondition (no initial edge) by default
* @return this trigger, so calls can be chained
*/
public Trigger onChange(Command command, InitialState initialState) {
requireNonNullParam(command, "command", "onChange");
m_loop.bind(
new Runnable() {
private boolean m_pressedLast = m_condition.getAsBoolean();
private boolean m_pressedLast = getInitialState(initialState);

@Override
public void run() {
Expand All @@ -76,16 +130,28 @@ public void run() {
}

/**
* Starts the given command whenever the condition changes from `false` to `true`.
* Starts the given command whenever the condition changes from `false` to `true`. The command is
* never started immediately.
*
* @param command the command to start
* @return this trigger, so calls can be chained
*/
public Trigger onTrue(Command command) {
return onTrue(command, InitialState.kCondition);
}

/**
* Starts the given command whenever the condition changes from `false` to `true`.
*
* @param command the command to start
* @param initialState the initial state to use, kCondition (no initial edge) by default
* @return this trigger, so calls can be chained
*/
public Trigger onTrue(Command command, InitialState initialState) {
requireNonNullParam(command, "command", "onTrue");
m_loop.bind(
new Runnable() {
private boolean m_pressedLast = m_condition.getAsBoolean();
private boolean m_pressedLast = getInitialState(initialState);

@Override
public void run() {
Expand All @@ -102,16 +168,28 @@ public void run() {
}

/**
* Starts the given command whenever the condition changes from `true` to `false`.
* Starts the given command whenever the condition changes from `true` to `false`. The command is
* never started immediately.
*
* @param command the command to start
* @return this trigger, so calls can be chained
*/
public Trigger onFalse(Command command) {
return onFalse(command, InitialState.kCondition);
}

/**
* Starts the given command whenever the condition changes from `true` to `false`.
*
* @param command the command to start
* @param initialState the initial state to use, kCondition (no initial edge) by default
* @return this trigger, so calls can be chained
*/
public Trigger onFalse(Command command, InitialState initialState) {
requireNonNullParam(command, "command", "onFalse");
m_loop.bind(
new Runnable() {
private boolean m_pressedLast = m_condition.getAsBoolean();
private boolean m_pressedLast = getInitialState(initialState);

@Override
public void run() {
Expand All @@ -129,7 +207,7 @@ public void run() {

/**
* Starts the given command when the condition changes to `true` and cancels it when the condition
* changes to `false`.
* changes to `false`. The command is never started immediately.
*
* <p>Doesn't re-start the command if it ends while the condition is still `true`. If the command
* should restart, see {@link edu.wpi.first.wpilibj2.command.RepeatCommand}.
Expand All @@ -138,10 +216,25 @@ public void run() {
* @return this trigger, so calls can be chained
*/
public Trigger whileTrue(Command command) {
return whileTrue(command, InitialState.kCondition);
}

/**
* Starts the given command when the condition changes to `true` and cancels it when the condition
* changes to `false`.
*
* <p>Doesn't re-start the command if it ends while the condition is still `true`. If the command
* should restart, see {@link edu.wpi.first.wpilibj2.command.RepeatCommand}.
*
* @param command the command to start
* @param initialState the initial state to use, kCondition (no initial edge) by default
* @return this trigger, so calls can be chained
*/
public Trigger whileTrue(Command command, InitialState initialState) {
requireNonNullParam(command, "command", "whileTrue");
m_loop.bind(
new Runnable() {
private boolean m_pressedLast = m_condition.getAsBoolean();
private boolean m_pressedLast = getInitialState(initialState);

@Override
public void run() {
Expand All @@ -161,7 +254,7 @@ public void run() {

/**
* Starts the given command when the condition changes to `false` and cancels it when the
* condition changes to `true`.
* condition changes to `true`. The command is never started immediately.
*
* <p>Doesn't re-start the command if it ends while the condition is still `false`. If the command
* should restart, see {@link edu.wpi.first.wpilibj2.command.RepeatCommand}.
Expand All @@ -170,10 +263,25 @@ public void run() {
* @return this trigger, so calls can be chained
*/
public Trigger whileFalse(Command command) {
return whileFalse(command, InitialState.kCondition);
}

/**
* Starts the given command when the condition changes to `false` and cancels it when the
* condition changes to `true`.
*
* <p>Doesn't re-start the command if it ends while the condition is still `false`. If the command
* should restart, see {@link edu.wpi.first.wpilibj2.command.RepeatCommand}.
*
* @param command the command to start
* @param initialState the initial state to use, kCondition (no initial edge) by default
* @return this trigger, so calls can be chained
*/
public Trigger whileFalse(Command command, InitialState initialState) {
requireNonNullParam(command, "command", "whileFalse");
m_loop.bind(
new Runnable() {
private boolean m_pressedLast = m_condition.getAsBoolean();
private boolean m_pressedLast = getInitialState(initialState);

@Override
public void run() {
Expand All @@ -192,16 +300,28 @@ public void run() {
}

/**
* Toggles a command when the condition changes from `false` to `true`.
* Toggles a command when the condition changes from `false` to `true`. The command is never
* toggled immediately.
*
* @param command the command to toggle
* @return this trigger, so calls can be chained
*/
public Trigger toggleOnTrue(Command command) {
return toggleOnTrue(command, InitialState.kCondition);
}

/**
* Toggles a command when the condition changes from `false` to `true`.
*
* @param command the command to toggle
* @param initialState the initial state to use, kCondition (no initial edge) by default
* @return this trigger, so calls can be chained
*/
public Trigger toggleOnTrue(Command command, InitialState initialState) {
requireNonNullParam(command, "command", "toggleOnTrue");
m_loop.bind(
new Runnable() {
private boolean m_pressedLast = m_condition.getAsBoolean();
private boolean m_pressedLast = getInitialState(initialState);

@Override
public void run() {
Expand All @@ -222,16 +342,28 @@ public void run() {
}

/**
* Toggles a command when the condition changes from `true` to `false`.
* Toggles a command when the condition changes from `true` to `false`. The command is never
* toggled immediately.
*
* @param command the command to toggle
* @return this trigger, so calls can be chained
*/
public Trigger toggleOnFalse(Command command) {
return toggleOnFalse(command, InitialState.kCondition);
}

/**
* Toggles a command when the condition changes from `true` to `false`.
*
* @param command the command to toggle
* @param initialState the initial state to use, kCondition (no initial edge) by default
* @return this trigger, so calls can be chained
*/
public Trigger toggleOnFalse(Command command, InitialState initialState) {
requireNonNullParam(command, "command", "toggleOnFalse");
m_loop.bind(
new Runnable() {
private boolean m_pressedLast = m_condition.getAsBoolean();
private boolean m_pressedLast = getInitialState(initialState);

@Override
public void run() {
Expand Down
Loading
Loading