// Copyright (c) FIRST and other WPILib contributors. // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. package org.wpilib.command2; import java.util.ArrayList; import java.util.List; import org.wpilib.util.sendable.SendableBuilder; /** * A command composition that runs a list of commands in sequence. * *

The rules for command compositions apply: command instances that are passed to it cannot be * added to any other composition or scheduled individually, and the composition requires all * subsystems its components require. * *

This class is provided by the NewCommands VendorDep */ public class SequentialCommandGroup extends Command { private final List m_commands = new ArrayList<>(); private int m_currentCommandIndex = -1; private boolean m_runWhenDisabled = true; private InterruptionBehavior m_interruptBehavior = InterruptionBehavior.kCancelIncoming; /** * Creates a new SequentialCommandGroup. The given commands will be run sequentially, with the * composition finishing when the last command finishes. * * @param commands the commands to include in this composition. */ @SuppressWarnings("this-escape") public SequentialCommandGroup(Command... commands) { addCommands(commands); } /** * Adds the given commands to the group. * * @param commands Commands to add, in order of execution. */ @SuppressWarnings("PMD.UseArraysAsList") public final void addCommands(Command... commands) { if (m_currentCommandIndex != -1) { throw new IllegalStateException( "Commands cannot be added to a composition while it's running"); } CommandScheduler.getInstance().registerComposedCommands(commands); for (Command command : commands) { m_commands.add(command); addRequirements(command.getRequirements()); m_runWhenDisabled &= command.runsWhenDisabled(); if (command.getInterruptionBehavior() == InterruptionBehavior.kCancelSelf) { m_interruptBehavior = InterruptionBehavior.kCancelSelf; } } } @Override public final void initialize() { m_currentCommandIndex = 0; if (!m_commands.isEmpty()) { m_commands.get(0).initialize(); } } @Override public final void execute() { if (m_commands.isEmpty()) { return; } Command currentCommand = m_commands.get(m_currentCommandIndex); currentCommand.execute(); if (currentCommand.isFinished()) { currentCommand.end(false); m_currentCommandIndex++; if (m_currentCommandIndex < m_commands.size()) { m_commands.get(m_currentCommandIndex).initialize(); } } } @Override public final void end(boolean interrupted) { if (interrupted && !m_commands.isEmpty() && m_currentCommandIndex > -1 && m_currentCommandIndex < m_commands.size()) { m_commands.get(m_currentCommandIndex).end(true); } m_currentCommandIndex = -1; } @Override public final boolean isFinished() { return m_currentCommandIndex == m_commands.size(); } @Override public boolean runsWhenDisabled() { return m_runWhenDisabled; } @Override public InterruptionBehavior getInterruptionBehavior() { return m_interruptBehavior; } @Override public void initSendable(SendableBuilder builder) { super.initSendable(builder); builder.addIntegerProperty("index", () -> m_currentCommandIndex, null); } }