Skip to content

Commit 7cb6a91

Browse files
committed
add contexts; make them mandatory where trigers are used
1 parent 0b7bcbf commit 7cb6a91

19 files changed

+404
-86
lines changed

commandsv3/src/generate/main/java/commandhid.java.jinja

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
{%- endmacro %}
99
package org.wpilib.command3.button;
1010

11+
import org.wpilib.command3.Context;
1112
import org.wpilib.command3.Scheduler;
1213
import org.wpilib.command3.Trigger;
1314
import org.wpilib.driverstation.{{ ConsoleName }}Controller;
@@ -26,10 +27,11 @@ public class Command{{ ConsoleName }}Controller extends CommandGenericHID {
2627
* Construct an instance of a controller. Commands bound to buttons on the controller will be
2728
* scheduled on the {@link Scheduler#getDefault() default scheduler} using its default event loop.
2829
*
30+
* @param context The context that must be true for trigger edges to be considered.
2931
* @param port The port index on the Driver Station that the controller is plugged into.
3032
*/
31-
public Command{{ ConsoleName }}Controller(int port) {
32-
super(port);
33+
public Command{{ ConsoleName }}Controller(Context context, int port) {
34+
super(context, port);
3335
m_hid = new {{ ConsoleName }}Controller(port);
3436
}
3537

@@ -38,10 +40,11 @@ public class Command{{ ConsoleName }}Controller extends CommandGenericHID {
3840
* scheduled on the given scheduler using its default event loop.
3941
*
4042
* @param scheduler The scheduler that should execute the triggered commands.
43+
* @param context The context that must be true for trigger edges to be considered.
4144
* @param port The port index on the Driver Station that the controller is plugged into.
4245
*/
43-
public Command{{ ConsoleName }}Controller(Scheduler scheduler, int port) {
44-
super(scheduler, port);
46+
public Command{{ ConsoleName }}Controller(Scheduler scheduler, Context context, int port) {
47+
super(scheduler, context, port);
4548
m_hid = new {{ ConsoleName }}Controller(port);
4649
}
4750

commandsv3/src/generated/main/java/org/wpilib/command3/button/CommandNiDsPS4Controller.java

Lines changed: 7 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

commandsv3/src/generated/main/java/org/wpilib/command3/button/CommandNiDsPS5Controller.java

Lines changed: 7 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

commandsv3/src/generated/main/java/org/wpilib/command3/button/CommandNiDsStadiaController.java

Lines changed: 7 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

commandsv3/src/generated/main/java/org/wpilib/command3/button/CommandNiDsXboxController.java

Lines changed: 7 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) FIRST and other WPILib contributors.
2+
// Open Source Software; you can modify and/or share it under the terms of
3+
// the WPILib BSD license file in the root directory of this project.
4+
5+
package org.wpilib.command3;
6+
7+
import java.util.function.BooleanSupplier;
8+
9+
/**
10+
* Utility class for composing BooleanSupplier conditions with logical operations.
11+
*
12+
* <p>This class provides static methods for combining multiple boolean conditions using logical
13+
* AND, OR, and NOT operations. It is commonly used for creating complex trigger conditions and
14+
* context compositions.
15+
*/
16+
public final class Conditions {
17+
private Conditions() {
18+
throw new UnsupportedOperationException("This is a utility class!");
19+
}
20+
21+
/**
22+
* Creates a BooleanSupplier that returns true when both input conditions are true.
23+
*
24+
* @param a the first condition
25+
* @param b the second condition
26+
* @return a BooleanSupplier that performs logical AND on the two conditions
27+
*/
28+
public static BooleanSupplier and(BooleanSupplier a, BooleanSupplier b) {
29+
return () -> a.getAsBoolean() && b.getAsBoolean();
30+
}
31+
32+
/**
33+
* Creates a BooleanSupplier that returns true when either input condition is true.
34+
*
35+
* @param a the first condition
36+
* @param b the second condition
37+
* @return a BooleanSupplier that performs logical OR on the two conditions
38+
*/
39+
public static BooleanSupplier or(BooleanSupplier a, BooleanSupplier b) {
40+
return () -> a.getAsBoolean() || b.getAsBoolean();
41+
}
42+
43+
/**
44+
* Creates a BooleanSupplier that returns the opposite of the input condition.
45+
*
46+
* @param a the condition to negate
47+
* @return a BooleanSupplier that performs logical NOT on the condition
48+
*/
49+
public static BooleanSupplier not(BooleanSupplier a) {
50+
return () -> !a.getAsBoolean();
51+
}
52+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright (c) FIRST and other WPILib contributors.
2+
// Open Source Software; you can modify and/or share it under the terms of
3+
// the WPILib BSD license file in the root directory of this project.
4+
5+
package org.wpilib.command3;
6+
7+
import java.util.function.BooleanSupplier;
8+
import org.wpilib.driverstation.DriverStation;
9+
import org.wpilib.event.EventLoop;
10+
11+
/**
12+
* A Context represents a condition that determines when Trigger edges should be considered.
13+
*
14+
* <p>Contexts are used to scope when triggers are active. For example, joystick button triggers
15+
* might use {@link #allTeleop} to ensure they only fire during teleop mode, preventing accidental
16+
* input during autonomous.
17+
*
18+
* <p>Contexts can be composed using logical operations to create more complex conditions:
19+
*
20+
* <pre>{@code
21+
* Context myContext = Context.allTeleop.and(() -> robot.isReady());
22+
* Trigger myTrigger = new Trigger(myContext, controller.a()::get);
23+
* }</pre>
24+
*
25+
* <p>When a trigger's context evaluates to false, edge detection is paused and will resume when the
26+
* context becomes true again.
27+
*/
28+
public class Context implements BooleanSupplier {
29+
/** A context that is always true. */
30+
public static final Context all = new Context(() -> true);
31+
32+
/** A context that is true when the robot is in autonomous mode (enabled or disabled). */
33+
public static final Context allAuto = all.and(DriverStation::isAutonomous);
34+
35+
/** A context that is true when the robot is in teleop mode (enabled or disabled). */
36+
public static final Context allTeleop = all.and(DriverStation::isTeleop);
37+
38+
/** A context that is true when the robot is in test mode (enabled or disabled). */
39+
public static final Context allTest = all.and(DriverStation::isTest);
40+
41+
private final BooleanSupplier m_condition;
42+
43+
/**
44+
* Creates a new Context with the given condition.
45+
*
46+
* <p>This constructor is protected and intended for internal use and subclassing. Use the static
47+
* factory methods or composition methods to create contexts.
48+
*
49+
* @param condition the boolean condition that determines when this context is active
50+
*/
51+
protected Context(BooleanSupplier condition) {
52+
m_condition = condition;
53+
}
54+
55+
/**
56+
* Creates a Trigger with this context and the given condition.
57+
*
58+
* <p>The resulting trigger will only fire edges when both this context and the provided condition
59+
* change, and only when this context is true.
60+
*
61+
* @param condition the trigger condition
62+
* @return a new Trigger that combines this context with the given condition
63+
*/
64+
public Trigger trigger(BooleanSupplier condition) {
65+
return new Trigger(Scheduler.getDefault(), this, Conditions.and(this, condition));
66+
}
67+
68+
/**
69+
* Creates a Trigger with this context, the given condition, and a specific event loop.
70+
*
71+
* @param loop the event loop to attach the trigger to
72+
* @param condition the trigger condition
73+
* @return a new Trigger that combines this context with the given condition
74+
*/
75+
public Trigger trigger(EventLoop loop, BooleanSupplier condition) {
76+
return new Trigger(Scheduler.getDefault(), this, loop, Conditions.and(this, condition));
77+
}
78+
79+
/**
80+
* Creates a new Context that is true when both this context and the given condition are true.
81+
*
82+
* @param condition the condition to combine with this context
83+
* @return a new Context representing the logical AND of this context and the condition
84+
*/
85+
public Context and(BooleanSupplier condition) {
86+
return new Context(Conditions.and(this, condition));
87+
}
88+
89+
/**
90+
* Creates a new Context that is true when either this context or the given context is true.
91+
*
92+
* @param condition the context to combine with this context
93+
* @return a new Context representing the logical OR of this context and the other context
94+
*/
95+
public Context or(Context condition) {
96+
return new Context(Conditions.or(this, condition));
97+
}
98+
99+
@Override
100+
public boolean getAsBoolean() {
101+
return m_condition.getAsBoolean();
102+
}
103+
}

0 commit comments

Comments
 (0)