mirror of
https://github.com/ppy/osu
synced 2025-01-19 12:30:50 +00:00
Merge pull request #9370 from peppy/song-select-key-repeat
This commit is contained in:
commit
a4254802c1
@ -17,11 +17,12 @@ using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Screens.Select.Carousel;
|
||||
using osu.Game.Screens.Select.Filter;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.SongSelect
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneBeatmapCarousel : OsuTestScene
|
||||
public class TestSceneBeatmapCarousel : OsuManualInputManagerTestScene
|
||||
{
|
||||
private TestBeatmapCarousel carousel;
|
||||
private RulesetStore rulesets;
|
||||
@ -39,6 +40,43 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
this.rulesets = rulesets;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestKeyRepeat()
|
||||
{
|
||||
loadBeatmaps();
|
||||
advanceSelection(false);
|
||||
|
||||
AddStep("press down arrow", () => InputManager.PressKey(Key.Down));
|
||||
|
||||
BeatmapInfo selection = null;
|
||||
|
||||
checkSelectionIterating(true);
|
||||
|
||||
AddStep("press up arrow", () => InputManager.PressKey(Key.Up));
|
||||
|
||||
checkSelectionIterating(true);
|
||||
|
||||
AddStep("release down arrow", () => InputManager.ReleaseKey(Key.Down));
|
||||
|
||||
checkSelectionIterating(true);
|
||||
|
||||
AddStep("release up arrow", () => InputManager.ReleaseKey(Key.Up));
|
||||
|
||||
checkSelectionIterating(false);
|
||||
|
||||
void checkSelectionIterating(bool isIterating)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
AddStep("store selection", () => selection = carousel.SelectedBeatmap);
|
||||
if (isIterating)
|
||||
AddUntilStep("selection changed", () => carousel.SelectedBeatmap != selection);
|
||||
else
|
||||
AddUntilStep("selection not changed", () => carousel.SelectedBeatmap == selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRecommendedSelection()
|
||||
{
|
||||
|
@ -19,6 +19,7 @@ using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Input.Bindings;
|
||||
@ -301,6 +302,9 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
private void selectNextDifficulty(int direction)
|
||||
{
|
||||
if (selectedBeatmap == null)
|
||||
return;
|
||||
|
||||
var unfilteredDifficulties = selectedBeatmapSet.Children.Where(s => !s.Filtered.Value).ToList();
|
||||
|
||||
int index = unfilteredDifficulties.IndexOf(selectedBeatmap);
|
||||
@ -452,32 +456,49 @@ namespace osu.Game.Screens.Select
|
||||
/// </summary>
|
||||
public void ScrollToSelected() => scrollPositionCache.Invalidate();
|
||||
|
||||
#region Key / button selection logic
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Left:
|
||||
SelectNext(-1, true);
|
||||
if (!e.Repeat)
|
||||
beginRepeatSelection(() => SelectNext(-1, true), e.Key);
|
||||
return true;
|
||||
|
||||
case Key.Right:
|
||||
SelectNext(1, true);
|
||||
if (!e.Repeat)
|
||||
beginRepeatSelection(() => SelectNext(1, true), e.Key);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyUpEvent e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Left:
|
||||
case Key.Right:
|
||||
endRepeatSelection(e.Key);
|
||||
break;
|
||||
}
|
||||
|
||||
base.OnKeyUp(e);
|
||||
}
|
||||
|
||||
public bool OnPressed(GlobalAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case GlobalAction.SelectNext:
|
||||
SelectNext(1, false);
|
||||
beginRepeatSelection(() => SelectNext(1, false), action);
|
||||
return true;
|
||||
|
||||
case GlobalAction.SelectPrevious:
|
||||
SelectNext(-1, false);
|
||||
beginRepeatSelection(() => SelectNext(-1, false), action);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -486,8 +507,44 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
public void OnReleased(GlobalAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case GlobalAction.SelectNext:
|
||||
case GlobalAction.SelectPrevious:
|
||||
endRepeatSelection(action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private ScheduledDelegate repeatDelegate;
|
||||
private object lastRepeatSource;
|
||||
|
||||
/// <summary>
|
||||
/// Begin repeating the specified selection action.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to perform.</param>
|
||||
/// <param name="source">The source of the action. Used in conjunction with <see cref="endRepeatSelection"/> to only cancel the correct action (most recently pressed key).</param>
|
||||
private void beginRepeatSelection(Action action, object source)
|
||||
{
|
||||
endRepeatSelection();
|
||||
|
||||
lastRepeatSource = source;
|
||||
repeatDelegate = this.BeginKeyRepeat(Scheduler, action);
|
||||
}
|
||||
|
||||
private void endRepeatSelection(object source = null)
|
||||
{
|
||||
// only the most recent source should be able to cancel the current action.
|
||||
if (source != null && !EqualityComparer<object>.Default.Equals(lastRepeatSource, source))
|
||||
return;
|
||||
|
||||
repeatDelegate?.Cancel();
|
||||
repeatDelegate = null;
|
||||
lastRepeatSource = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
Loading…
Reference in New Issue
Block a user