// 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 osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; namespace osu.Game.Graphics.Containers { public abstract class HoldToConfirmContainer : Container { public const double DANGEROUS_HOLD_ACTIVATION_DELAY = 500; private const int fadeout_delay = 200; /// /// Whether the associated action is considered dangerous, warranting a longer hold. /// public bool IsDangerousAction { get; } /// /// The action to perform when a hold successfully completes. /// public Action Action; /// /// Whether currently in a fired state (and the confirm has been sent). /// public bool Fired { get; private set; } private bool confirming; /// /// The current activation delay for this control. /// public IBindable HoldActivationDelay => holdActivationDelay; /// /// The progress of any ongoing hold operation. 0 means no hold has started; 1 means a hold has been completed. /// public IBindable Progress => progress; /// /// Whether the overlay should be allowed to return from a fired state. /// protected virtual bool AllowMultipleFires => false; private readonly Bindable progress = new BindableDouble(); private readonly Bindable holdActivationDelay = new Bindable(); [Resolved] private OsuConfigManager config { get; set; } protected HoldToConfirmContainer(bool isDangerousAction = false) { IsDangerousAction = isDangerousAction; } protected override void LoadComplete() { base.LoadComplete(); if (IsDangerousAction) holdActivationDelay.Value = DANGEROUS_HOLD_ACTIVATION_DELAY; else config.BindWith(OsuSetting.UIHoldActivationDelay, holdActivationDelay); } protected void BeginConfirm() { if (confirming || (!AllowMultipleFires && Fired)) return; confirming = true; this.TransformBindableTo(progress, 1, holdActivationDelay.Value * (1 - progress.Value), Easing.Out).OnComplete(_ => Confirm()); } protected virtual void Confirm() { Action?.Invoke(); Fired = true; } protected void AbortConfirm() { if (!AllowMultipleFires && Fired) return; confirming = false; Fired = false; this .TransformBindableTo(progress, progress.Value) .Delay(200) .TransformBindableTo(progress, 0, fadeout_delay, Easing.InSine); } } }