1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 07:22:54 +08:00

refactor(KeyCounterDisplay): apply suggestions

I also took the freedom to add type checking, as we can't limit the
usage of `Add()` since it's a Container. The exception thrown also
advises of using the suggested `AddTrigger()` instead.
This commit is contained in:
tsrk 2023-02-22 14:58:27 +00:00
parent 42a5a06b9d
commit 1beec71037
No known key found for this signature in database
GPG Key ID: EBD46BB3049B56D6
10 changed files with 86 additions and 60 deletions

View File

@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses.Value > 2));
seekTo(referenceBeatmap.Breaks[0].StartTime);
AddAssert("keys not counting", () => !Player.HUDOverlay.KeyCounter.IsCounting);
AddAssert("keys not counting", () => !Player.HUDOverlay.KeyCounter.IsCounting.Value);
AddAssert("overlay displays 100% accuracy", () => Player.BreakOverlay.ChildrenOfType<BreakInfo>().Single().AccuracyDisplay.Current.Value == 1);
AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000));

View File

@ -267,7 +267,7 @@ namespace osu.Game.Tests.Visual.Gameplay
hudOverlay = new HUDOverlay(null, Array.Empty<Mod>());
// Add any key just to display the key counter visually.
hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboardTrigger(Key.Space)));
hudOverlay.KeyCounter.AddTrigger(new KeyCounterKeyboardTrigger(Key.Space));
scoreProcessor.Combo.Value = 1;

View File

@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddStep("Add random", () =>
{
Key key = (Key)((int)Key.A + RNG.Next(26));
kc.Add(kc.CreateKeyCounter(new KeyCounterKeyboardTrigger(key)));
kc.AddTrigger(new KeyCounterKeyboardTrigger(key));
});
Key testKey = ((KeyCounterKeyboardTrigger)kc.Children.First().Trigger).Key;
@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 1);
addPressKeyStep();
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 2);
AddStep("Disable counting", () => testCounter.IsCounting = false);
AddStep("Disable counting", () => testCounter.IsCounting.Value = false);
addPressKeyStep();
AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses.Value == 2);

View File

@ -53,7 +53,7 @@ namespace osu.Game.Tests.Visual.Gameplay
};
// Add any key just to display the key counter visually.
hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboardTrigger(Key.Space)));
hudOverlay.KeyCounter.AddTrigger(new KeyCounterKeyboardTrigger(Key.Space));
scoreProcessor.Combo.Value = 1;
return new Container

View File

@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.Gameplay
hudOverlay = new HUDOverlay(null, Array.Empty<Mod>());
// Add any key just to display the key counter visually.
hudOverlay.KeyCounter.Add(hudOverlay.KeyCounter.CreateKeyCounter(new KeyCounterKeyboardTrigger(Key.Space)));
hudOverlay.KeyCounter.AddTrigger(new KeyCounterKeyboardTrigger(Key.Space));
action?.Invoke(hudOverlay);

View File

@ -162,11 +162,11 @@ namespace osu.Game.Rulesets.UI
KeyBindingContainer.Add(receptor);
keyCounter.SetReceptor(receptor);
keyCounter.AddRange(KeyBindingContainer.DefaultKeyBindings
.Select(b => b.GetAction<T>())
.Distinct()
.OrderBy(action => action)
.Select(action => keyCounter.CreateKeyCounter(new KeyCounterActionTrigger<T>(action))));
keyCounter.AddTriggerRange(KeyBindingContainer.DefaultKeyBindings
.Select(b => b.GetAction<T>())
.Distinct()
.OrderBy(action => action)
.Select(action => new KeyCounterActionTrigger<T>(action)));
}
private partial class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler<T>

View File

@ -13,7 +13,9 @@ namespace osu.Game.Screens.Play
private const int duration = 100;
private const double key_fade_time = 80;
protected override Container<KeyCounter> Content => KeyFlow;
private readonly FillFlowContainer<KeyCounter> keyFlow = new FillFlowContainer<KeyCounter>();
protected override Container<KeyCounter> Content => keyFlow;
public new IReadOnlyList<DefaultKeyCounter> Children
{
@ -22,12 +24,13 @@ namespace osu.Game.Screens.Play
}
public DefaultKeyCounterDisplay()
: base(typeof(DefaultKeyCounter))
{
KeyFlow.Direction = FillDirection.Horizontal;
KeyFlow.AutoSizeAxes = Axes.Both;
KeyFlow.Alpha = 0;
keyFlow.Direction = FillDirection.Horizontal;
keyFlow.AutoSizeAxes = Axes.Both;
keyFlow.Alpha = 0;
InternalChild = KeyFlow;
InternalChild = keyFlow;
}
protected override void Update()
@ -36,12 +39,22 @@ namespace osu.Game.Screens.Play
// Don't use autosize as it will shrink to zero when KeyFlow is hidden.
// In turn this can cause the display to be masked off screen and never become visible again.
Size = KeyFlow.Size;
Size = keyFlow.Size;
}
public override void AddTrigger(KeyCounter.InputTrigger trigger)
{
DefaultKeyCounter key = new DefaultKeyCounter(trigger);
Add(key);
key.FadeTime = key_fade_time;
key.KeyDownTextColor = KeyDownTextColor;
key.KeyUpTextColor = KeyUpTextColor;
}
public override void Add(KeyCounter key)
{
base.Add(key);
DefaultKeyCounter defaultKey = (DefaultKeyCounter)key;
defaultKey.FadeTime = key_fade_time;
@ -51,7 +64,7 @@ namespace osu.Game.Screens.Play
protected override void UpdateVisibility() =>
// Isolate changing visibility of the key counters from fading this component.
KeyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration);
keyFlow.FadeTo(AlwaysVisible.Value || ConfigVisibility.Value ? 1 : 0, duration);
private Color4 keyDownTextColor = Color4.DarkGray;

View File

@ -21,7 +21,7 @@ namespace osu.Game.Screens.Play
MinValue = 0
};
public bool IsCounting { get; set; } = true;
public Bindable<bool> IsCounting { get; } = new BindableBool(true);
public IBindable<int> CountPresses => countPresses;
@ -46,7 +46,7 @@ namespace osu.Game.Screens.Play
private void increment()
{
if (!IsCounting)
if (!IsCounting.Value)
return;
countPresses.Value++;
@ -54,7 +54,7 @@ namespace osu.Game.Screens.Play
private void decrement()
{
if (!IsCounting)
if (!IsCounting.Value)
return;
countPresses.Value--;

View File

@ -2,9 +2,11 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
@ -15,22 +17,58 @@ namespace osu.Game.Screens.Play
{
public abstract partial class KeyCounterDisplay : Container<KeyCounter>
{
protected readonly Bindable<bool> ConfigVisibility = new Bindable<bool>();
protected readonly FillFlowContainer<KeyCounter> KeyFlow = new FillFlowContainer<KeyCounter>();
protected override Container<KeyCounter> Content => KeyFlow;
/// <summary>
/// Whether the key counter should be visible regardless of the configuration value.
/// This is true by default, but can be changed.
/// </summary>
public readonly Bindable<bool> AlwaysVisible = new Bindable<bool>(true);
public Bindable<bool> AlwaysVisible { get; } = new Bindable<bool>(true);
public Bindable<bool> IsCounting { get; } = new BindableBool(true);
public IReadOnlyList<KeyCounter.InputTrigger> Triggers
{
get => Children.Select(c => c.Trigger).ToArray();
set
{
Clear();
value.ForEach(AddTrigger);
}
}
protected readonly Bindable<bool> ConfigVisibility = new Bindable<bool>();
protected abstract void UpdateVisibility();
private Receptor? receptor;
private readonly Type[] acceptedTypes;
protected KeyCounterDisplay(params Type[] acceptedTypes)
{
this.acceptedTypes = acceptedTypes;
}
public void SetReceptor(Receptor receptor)
{
if (this.receptor != null)
throw new InvalidOperationException("Cannot set a new receptor when one is already active");
this.receptor = receptor;
}
public abstract void AddTrigger(KeyCounter.InputTrigger trigger);
public void AddTriggerRange(IEnumerable<KeyCounter.InputTrigger> triggers) => triggers.ForEach(AddTrigger);
private bool checkType(KeyCounter key) => acceptedTypes.Length == 0 || acceptedTypes.Any(t => t.IsInstanceOfType(key));
public override void Add(KeyCounter key)
{
if (!checkType(key))
throw new InvalidOperationException($"{key.GetType()} is not a supported counter type. (hint: you may want to use {nameof(AddTrigger)} instead.)");
base.Add(key);
key.IsCounting = IsCounting;
key.IsCounting.BindTo(IsCounting);
}
[BackgroundDependencyLoader]
@ -47,38 +85,10 @@ namespace osu.Game.Screens.Play
ConfigVisibility.BindValueChanged(_ => UpdateVisibility(), true);
}
private bool isCounting = true;
public bool IsCounting
{
get => isCounting;
set
{
if (value == isCounting) return;
isCounting = value;
foreach (var child in Children)
child.IsCounting = value;
}
}
protected abstract void UpdateVisibility();
public override bool HandleNonPositionalInput => receptor == null;
public override bool HandlePositionalInput => receptor == null;
private Receptor? receptor;
public void SetReceptor(Receptor receptor)
{
if (this.receptor != null)
throw new InvalidOperationException("Cannot set a new receptor when one is already active");
this.receptor = receptor;
}
public virtual KeyCounter CreateKeyCounter(KeyCounter.InputTrigger trigger) => new DefaultKeyCounter(trigger);
public partial class Receptor : Drawable
{
protected readonly KeyCounterDisplay Target;

View File

@ -440,8 +440,11 @@ namespace osu.Game.Screens.Play
},
KeyCounter =
{
IsCounting =
{
Value = false
},
AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded },
IsCounting = false
},
Anchor = Anchor.Centre,
Origin = Anchor.Centre
@ -481,7 +484,7 @@ namespace osu.Game.Screens.Play
{
updateGameplayState();
updatePauseOnFocusLostState();
HUDOverlay.KeyCounter.IsCounting = !isBreakTime.NewValue;
HUDOverlay.KeyCounter.IsCounting.Value = !isBreakTime.NewValue;
}
private void updateGameplayState()