// Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Mania.Timing.Drawables; namespace osu.Game.Rulesets.Mania.Timing { public class TimingChangeContainer : Container { /// /// The amount of time which this container spans. /// public double TimeSpan { get; set; } /// /// Adds a hit object to the most applicable timing change in this container. /// /// The hit object to add. public void Add(DrawableHitObject hitObject) { var target = timingChangeFor(hitObject); if (target == null) throw new ArgumentException("No timing change could be found that can contain the hit object.", nameof(hitObject)); target.Add(hitObject); } protected override IComparer DepthComparer => new TimingChangeReverseStartTimeComparer(); /// /// Finds the most applicable timing change that can contain a hit object. /// /// The hit object to contain. /// The last timing change which can contain . Null if no timing change can contain the hit object. private DrawableTimingChange timingChangeFor(DrawableHitObject hitObject) => Children.FirstOrDefault(c => c.CanContain(hitObject)) ?? Children.LastOrDefault(); } /// /// Compares two timing changes by their start time, falling back to creation order if their start time is equal. /// This will compare the two timing changes in reverse order. /// public class TimingChangeReverseStartTimeComparer : Drawable.ReverseCreationOrderDepthComparer { public override int Compare(Drawable x, Drawable y) { var timingChangeX = x as DrawableTimingChange; var timingChangeY = y as DrawableTimingChange; // If either of the two drawables are not hit objects, fall back to the base comparer if (timingChangeX?.TimingChange == null || timingChangeY?.TimingChange == null) return base.Compare(x, y); // Compare by start time int i = timingChangeY.TimingChange.Time.CompareTo(timingChangeX.TimingChange.Time); if (i != 0) return i; return base.Compare(x, y); } } }