// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; namespace osu.Game.Storyboards { public class CommandLoop : CommandTimelineGroup { public double LoopStartTime; /// /// The total number of times this loop is played back. Always greater than zero. /// public readonly int TotalIterations; public override double StartTime => LoopStartTime + CommandsStartTime; public override double EndTime => // In an ideal world, we would multiply the command duration by TotalIterations here. // Unfortunately this would clash with how stable handled end times, and results in some storyboards playing outro // sequences for minutes or hours. StartTime + CommandsDuration; /// /// Construct a new command loop. /// /// The start time of the loop. /// The number of times the loop should repeat. Should be greater than zero. Zero means a single playback. public CommandLoop(double startTime, int repeatCount) { if (repeatCount < 0) throw new ArgumentException("Repeat count must be zero or above.", nameof(repeatCount)); LoopStartTime = startTime; TotalIterations = repeatCount + 1; } public override IEnumerable.TypedCommand> GetCommands(CommandTimelineSelector timelineSelector, double offset = 0) { for (int loop = 0; loop < TotalIterations; loop++) { double loopOffset = LoopStartTime + loop * CommandsDuration; foreach (var command in base.GetCommands(timelineSelector, offset + loopOffset)) yield return command; } } public override string ToString() => $"{LoopStartTime} x{TotalIterations}"; } }