mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 10:43:04 +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:
parent
42a5a06b9d
commit
1beec71037
@ -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));
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -162,11 +162,11 @@ namespace osu.Game.Rulesets.UI
|
||||
KeyBindingContainer.Add(receptor);
|
||||
|
||||
keyCounter.SetReceptor(receptor);
|
||||
keyCounter.AddRange(KeyBindingContainer.DefaultKeyBindings
|
||||
keyCounter.AddTriggerRange(KeyBindingContainer.DefaultKeyBindings
|
||||
.Select(b => b.GetAction<T>())
|
||||
.Distinct()
|
||||
.OrderBy(action => action)
|
||||
.Select(action => keyCounter.CreateKeyCounter(new KeyCounterActionTrigger<T>(action))));
|
||||
.Select(action => new KeyCounterActionTrigger<T>(action)));
|
||||
}
|
||||
|
||||
private partial class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler<T>
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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--;
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user