// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; using osu.Framework.Graphics.Performance; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Objects { /// /// A that stores the lifetime for a . /// public class HitObjectLifetimeEntry : LifetimeEntry { /// /// The . /// public readonly HitObject HitObject; /// /// The result that was judged with. /// This is set by the accompanying , and reused when required for rewinding. /// internal JudgementResult Result; private readonly IBindable startTimeBindable = new BindableDouble(); /// /// Creates a new . /// /// The to store the lifetime of. public HitObjectLifetimeEntry(HitObject hitObject) { HitObject = hitObject; startTimeBindable.BindTo(HitObject.StartTimeBindable); startTimeBindable.BindValueChanged(onStartTimeChanged, true); } // The lifetime start, as set by the hitobject. private double realLifetimeStart = double.MinValue; /// /// The time at which the should become alive. /// public new double LifetimeStart { get => realLifetimeStart; set => setLifetime(realLifetimeStart = value, LifetimeEnd); } // The lifetime end, as set by the hitobject. private double realLifetimeEnd = double.MaxValue; /// /// The time at which the should become dead. /// public new double LifetimeEnd { get => realLifetimeEnd; set => setLifetime(LifetimeStart, realLifetimeEnd = value); } private void setLifetime(double start, double end) { if (keepAlive) { start = double.MinValue; end = double.MaxValue; } base.LifetimeStart = start; base.LifetimeEnd = end; } private bool keepAlive; /// /// Whether the should be kept always alive. /// internal bool KeepAlive { set { if (keepAlive == value) return; keepAlive = value; setLifetime(realLifetimeStart, realLifetimeEnd); } } /// /// A safe offset prior to the start time of at which it may begin displaying contents. /// By default, s are assumed to display their contents within 10 seconds prior to their start time. /// /// /// This is only used as an optimisation to delay the initial update of the and may be tuned more aggressively if required. /// It is indirectly used to decide the automatic transform offset provided to . /// A more accurate should be set for further optimisation (in , for example). /// protected virtual double InitialLifetimeOffset => 10000; /// /// Resets according to the change in start time of the . /// private void onStartTimeChanged(ValueChangedEvent startTime) => LifetimeStart = HitObject.StartTime - InitialLifetimeOffset; } }