mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 14:12:56 +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));
|
AddUntilStep("key counter counted keys", () => Player.HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses.Value > 2));
|
||||||
|
|
||||||
seekTo(referenceBeatmap.Breaks[0].StartTime);
|
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);
|
AddAssert("overlay displays 100% accuracy", () => Player.BreakOverlay.ChildrenOfType<BreakInfo>().Single().AccuracyDisplay.Current.Value == 1);
|
||||||
|
|
||||||
AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000));
|
AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000));
|
||||||
|
@ -267,7 +267,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
hudOverlay = new HUDOverlay(null, Array.Empty<Mod>());
|
hudOverlay = new HUDOverlay(null, Array.Empty<Mod>());
|
||||||
|
|
||||||
// Add any key just to display the key counter visually.
|
// 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;
|
scoreProcessor.Combo.Value = 1;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddStep("Add random", () =>
|
AddStep("Add random", () =>
|
||||||
{
|
{
|
||||||
Key key = (Key)((int)Key.A + RNG.Next(26));
|
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;
|
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);
|
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 1);
|
||||||
addPressKeyStep();
|
addPressKeyStep();
|
||||||
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 2);
|
AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses.Value == 2);
|
||||||
AddStep("Disable counting", () => testCounter.IsCounting = false);
|
AddStep("Disable counting", () => testCounter.IsCounting.Value = false);
|
||||||
addPressKeyStep();
|
addPressKeyStep();
|
||||||
AddAssert($"Check {testKey} count has not changed", () => testCounter.CountPresses.Value == 2);
|
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.
|
// 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;
|
scoreProcessor.Combo.Value = 1;
|
||||||
|
|
||||||
return new Container
|
return new Container
|
||||||
|
@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
hudOverlay = new HUDOverlay(null, Array.Empty<Mod>());
|
hudOverlay = new HUDOverlay(null, Array.Empty<Mod>());
|
||||||
|
|
||||||
// Add any key just to display the key counter visually.
|
// 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);
|
action?.Invoke(hudOverlay);
|
||||||
|
|
||||||
|
@ -162,11 +162,11 @@ namespace osu.Game.Rulesets.UI
|
|||||||
KeyBindingContainer.Add(receptor);
|
KeyBindingContainer.Add(receptor);
|
||||||
|
|
||||||
keyCounter.SetReceptor(receptor);
|
keyCounter.SetReceptor(receptor);
|
||||||
keyCounter.AddRange(KeyBindingContainer.DefaultKeyBindings
|
keyCounter.AddTriggerRange(KeyBindingContainer.DefaultKeyBindings
|
||||||
.Select(b => b.GetAction<T>())
|
.Select(b => b.GetAction<T>())
|
||||||
.Distinct()
|
.Distinct()
|
||||||
.OrderBy(action => action)
|
.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>
|
private partial class ActionReceptor : KeyCounterDisplay.Receptor, IKeyBindingHandler<T>
|
||||||
|
@ -13,7 +13,9 @@ namespace osu.Game.Screens.Play
|
|||||||
private const int duration = 100;
|
private const int duration = 100;
|
||||||
private const double key_fade_time = 80;
|
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
|
public new IReadOnlyList<DefaultKeyCounter> Children
|
||||||
{
|
{
|
||||||
@ -22,12 +24,13 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DefaultKeyCounterDisplay()
|
public DefaultKeyCounterDisplay()
|
||||||
|
: base(typeof(DefaultKeyCounter))
|
||||||
{
|
{
|
||||||
KeyFlow.Direction = FillDirection.Horizontal;
|
keyFlow.Direction = FillDirection.Horizontal;
|
||||||
KeyFlow.AutoSizeAxes = Axes.Both;
|
keyFlow.AutoSizeAxes = Axes.Both;
|
||||||
KeyFlow.Alpha = 0;
|
keyFlow.Alpha = 0;
|
||||||
|
|
||||||
InternalChild = KeyFlow;
|
InternalChild = keyFlow;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
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.
|
// 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.
|
// 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)
|
public override void Add(KeyCounter key)
|
||||||
{
|
{
|
||||||
base.Add(key);
|
base.Add(key);
|
||||||
|
|
||||||
DefaultKeyCounter defaultKey = (DefaultKeyCounter)key;
|
DefaultKeyCounter defaultKey = (DefaultKeyCounter)key;
|
||||||
|
|
||||||
defaultKey.FadeTime = key_fade_time;
|
defaultKey.FadeTime = key_fade_time;
|
||||||
@ -51,7 +64,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
protected override void UpdateVisibility() =>
|
protected override void UpdateVisibility() =>
|
||||||
// Isolate changing visibility of the key counters from fading this component.
|
// 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;
|
private Color4 keyDownTextColor = Color4.DarkGray;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Screens.Play
|
|||||||
MinValue = 0
|
MinValue = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
public bool IsCounting { get; set; } = true;
|
public Bindable<bool> IsCounting { get; } = new BindableBool(true);
|
||||||
|
|
||||||
public IBindable<int> CountPresses => countPresses;
|
public IBindable<int> CountPresses => countPresses;
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
private void increment()
|
private void increment()
|
||||||
{
|
{
|
||||||
if (!IsCounting)
|
if (!IsCounting.Value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
countPresses.Value++;
|
countPresses.Value++;
|
||||||
@ -54,7 +54,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
private void decrement()
|
private void decrement()
|
||||||
{
|
{
|
||||||
if (!IsCounting)
|
if (!IsCounting.Value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
countPresses.Value--;
|
countPresses.Value--;
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
@ -15,22 +17,58 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
public abstract partial class KeyCounterDisplay : Container<KeyCounter>
|
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>
|
/// <summary>
|
||||||
/// Whether the key counter should be visible regardless of the configuration value.
|
/// Whether the key counter should be visible regardless of the configuration value.
|
||||||
/// This is true by default, but can be changed.
|
/// This is true by default, but can be changed.
|
||||||
/// </summary>
|
/// </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)
|
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);
|
base.Add(key);
|
||||||
key.IsCounting = IsCounting;
|
key.IsCounting.BindTo(IsCounting);
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -47,38 +85,10 @@ namespace osu.Game.Screens.Play
|
|||||||
ConfigVisibility.BindValueChanged(_ => UpdateVisibility(), true);
|
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 HandleNonPositionalInput => receptor == null;
|
||||||
|
|
||||||
public override bool HandlePositionalInput => 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
|
public partial class Receptor : Drawable
|
||||||
{
|
{
|
||||||
protected readonly KeyCounterDisplay Target;
|
protected readonly KeyCounterDisplay Target;
|
||||||
|
@ -440,8 +440,11 @@ namespace osu.Game.Screens.Play
|
|||||||
},
|
},
|
||||||
KeyCounter =
|
KeyCounter =
|
||||||
{
|
{
|
||||||
|
IsCounting =
|
||||||
|
{
|
||||||
|
Value = false
|
||||||
|
},
|
||||||
AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded },
|
AlwaysVisible = { BindTarget = DrawableRuleset.HasReplayLoaded },
|
||||||
IsCounting = false
|
|
||||||
},
|
},
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre
|
Origin = Anchor.Centre
|
||||||
@ -481,7 +484,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
updateGameplayState();
|
updateGameplayState();
|
||||||
updatePauseOnFocusLostState();
|
updatePauseOnFocusLostState();
|
||||||
HUDOverlay.KeyCounter.IsCounting = !isBreakTime.NewValue;
|
HUDOverlay.KeyCounter.IsCounting.Value = !isBreakTime.NewValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGameplayState()
|
private void updateGameplayState()
|
||||||
|
Loading…
Reference in New Issue
Block a user