// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Collections.Specialized; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Configuration; using osu.Game.Rulesets.UI; using osu.Game.Skinning; namespace osu.Game.Screens.Play.HUD { /// /// A flowing display of all gameplay keys. Individual keys can be added using implementations. /// public abstract partial class KeyCounterDisplay : CompositeDrawable, ISerialisableDrawable { /// /// Whether the key counter should be visible regardless of the configuration value. /// This is true by default, but can be changed. /// public Bindable AlwaysVisible { get; } = new Bindable(true); protected abstract FillFlowContainer KeyFlow { get; } protected readonly Bindable ConfigVisibility = new Bindable(); private readonly IBindableList triggers = new BindableList(); [Resolved] private InputCountController controller { get; set; } = null!; private const int duration = 100; protected void UpdateVisibility() { bool visible = AlwaysVisible.Value || ConfigVisibility.Value; // Isolate changing visibility of the key counters from fading this component. KeyFlow.FadeTo(visible ? 1 : 0, duration); // Ensure a valid size is immediately obtained even if partially off-screen // See https://github.com/ppy/osu/issues/14793. KeyFlow.AlwaysPresent = visible; } protected abstract KeyCounter CreateCounter(InputTrigger trigger); [BackgroundDependencyLoader] private void load(OsuConfigManager config, DrawableRuleset? drawableRuleset) { AutoSizeAxes = Axes.Both; config.BindWith(OsuSetting.KeyOverlay, ConfigVisibility); if (drawableRuleset != null) AlwaysVisible.BindTo(drawableRuleset.HasReplayLoaded); } protected override void LoadComplete() { base.LoadComplete(); triggers.BindTo(controller.Triggers); triggers.BindCollectionChanged(triggersChanged, true); AlwaysVisible.BindValueChanged(_ => UpdateVisibility()); ConfigVisibility.BindValueChanged(_ => UpdateVisibility(), true); } private void triggersChanged(object? sender, NotifyCollectionChangedEventArgs e) { KeyFlow.Clear(); foreach (var trigger in controller.Triggers) KeyFlow.Add(CreateCounter(trigger)); } public bool UsesFixedAnchor { get; set; } } }