// 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; using System.Linq; using JetBrains.Annotations; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; namespace osu.Game.Screens.Edit.Compose { /// /// Buffers events from the many s in a nested hierarchy. /// internal class HitObjectUsageEventBuffer : IDisposable { /// /// Invoked when a becomes used by a . /// /// /// If the ruleset uses pooled objects, this represents the time when the s become alive. /// public event Action HitObjectUsageBegan; /// /// Invoked when a becomes unused by a . /// /// /// If the ruleset uses pooled objects, this represents the time when the s become dead. /// public event Action HitObjectUsageFinished; /// /// Invoked when a has been transferred to another . /// public event Action HitObjectUsageTransferred; private readonly Playfield playfield; /// /// Creates a new . /// /// The most top-level . public HitObjectUsageEventBuffer([NotNull] Playfield playfield) { this.playfield = playfield; playfield.HitObjectUsageBegan += onHitObjectUsageBegan; playfield.HitObjectUsageFinished += onHitObjectUsageFinished; } private readonly List usageFinishedHitObjects = new List(); private void onHitObjectUsageBegan(HitObject hitObject) { if (usageFinishedHitObjects.Remove(hitObject)) HitObjectUsageTransferred?.Invoke(hitObject, playfield.AllHitObjects.Single(d => d.HitObject == hitObject)); else HitObjectUsageBegan?.Invoke(hitObject); } private void onHitObjectUsageFinished(HitObject hitObject) => usageFinishedHitObjects.Add(hitObject); public void Update() { foreach (var hitObject in usageFinishedHitObjects) HitObjectUsageFinished?.Invoke(hitObject); usageFinishedHitObjects.Clear(); } public void Dispose() { if (playfield != null) { playfield.HitObjectUsageBegan -= onHitObjectUsageBegan; playfield.HitObjectUsageFinished -= onHitObjectUsageFinished; } } } }