mirror of
https://github.com/ppy/osu.git
synced 2025-01-30 20:32:55 +08:00
Merge branch 'master' into user-panel-status
This commit is contained in:
commit
6bbfd362b8
@ -41,6 +41,7 @@ using osu.Game.Screens.OnlinePlay.Match.Components;
|
|||||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Play.HUD;
|
using osu.Game.Screens.Play.HUD;
|
||||||
|
using osu.Game.Screens.Play.PlayerSettings;
|
||||||
using osu.Game.Screens.Ranking;
|
using osu.Game.Screens.Ranking;
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
using osu.Game.Screens.Select.Carousel;
|
using osu.Game.Screens.Select.Carousel;
|
||||||
@ -317,6 +318,92 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
AddUntilStep("wait for song select", () => songSelect.IsCurrentScreen());
|
AddUntilStep("wait for song select", () => songSelect.IsCurrentScreen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestOffsetAdjustDuringPause()
|
||||||
|
{
|
||||||
|
Player player = null;
|
||||||
|
|
||||||
|
Screens.Select.SongSelect songSelect = null;
|
||||||
|
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||||
|
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||||
|
|
||||||
|
AddStep("import beatmap", () => BeatmapImportHelper.LoadQuickOszIntoOsu(Game).WaitSafely());
|
||||||
|
|
||||||
|
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||||
|
|
||||||
|
AddStep("set mods", () => Game.SelectedMods.Value = new Mod[] { new OsuModNoFail() });
|
||||||
|
AddStep("press enter", () => InputManager.Key(Key.Enter));
|
||||||
|
|
||||||
|
AddUntilStep("wait for player", () =>
|
||||||
|
{
|
||||||
|
DismissAnyNotifications();
|
||||||
|
player = Game.ScreenStack.CurrentScreen as Player;
|
||||||
|
return player?.IsLoaded == true;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for track playing", () => Game.Beatmap.Value.Track.IsRunning);
|
||||||
|
checkOffset(0);
|
||||||
|
|
||||||
|
AddStep("adjust offset via keyboard", () => InputManager.Key(Key.Minus));
|
||||||
|
checkOffset(-1);
|
||||||
|
|
||||||
|
AddStep("pause", () => player.ChildrenOfType<GameplayClockContainer>().First().Stop());
|
||||||
|
AddUntilStep("wait for pause", () => player.ChildrenOfType<GameplayClockContainer>().First().IsPaused.Value, () => Is.True);
|
||||||
|
AddStep("attempt adjust offset via keyboard", () => InputManager.Key(Key.Minus));
|
||||||
|
checkOffset(-1);
|
||||||
|
|
||||||
|
void checkOffset(double offset)
|
||||||
|
{
|
||||||
|
AddUntilStep($"control offset is {offset}", () => this.ChildrenOfType<GameplayOffsetControl>().Single().ChildrenOfType<BeatmapOffsetControl>().Single().Current.Value,
|
||||||
|
() => Is.EqualTo(offset));
|
||||||
|
AddUntilStep($"database offset is {offset}", () => Game.BeatmapManager.QueryBeatmap(b => b.ID == Game.Beatmap.Value.BeatmapInfo.ID)!.UserSettings.Offset,
|
||||||
|
() => Is.EqualTo(offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestOffsetAdjustDuringGameplay()
|
||||||
|
{
|
||||||
|
Player player = null;
|
||||||
|
|
||||||
|
Screens.Select.SongSelect songSelect = null;
|
||||||
|
PushAndConfirm(() => songSelect = new TestPlaySongSelect());
|
||||||
|
AddUntilStep("wait for song select", () => songSelect.BeatmapSetsLoaded);
|
||||||
|
|
||||||
|
AddStep("import beatmap", () => BeatmapImportHelper.LoadOszIntoOsu(Game).WaitSafely());
|
||||||
|
|
||||||
|
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||||
|
|
||||||
|
AddStep("set mods", () => Game.SelectedMods.Value = new Mod[] { new OsuModNoFail() });
|
||||||
|
AddStep("press enter", () => InputManager.Key(Key.Enter));
|
||||||
|
|
||||||
|
AddUntilStep("wait for player", () =>
|
||||||
|
{
|
||||||
|
DismissAnyNotifications();
|
||||||
|
player = Game.ScreenStack.CurrentScreen as Player;
|
||||||
|
return player?.IsLoaded == true;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for track playing", () => Game.Beatmap.Value.Track.IsRunning);
|
||||||
|
checkOffset(0);
|
||||||
|
|
||||||
|
AddStep("adjust offset via keyboard", () => InputManager.Key(Key.Minus));
|
||||||
|
checkOffset(-1);
|
||||||
|
|
||||||
|
AddStep("seek beyond 10 seconds", () => player.ChildrenOfType<GameplayClockContainer>().First().Seek(10500));
|
||||||
|
AddUntilStep("wait for seek", () => player.ChildrenOfType<GameplayClockContainer>().First().CurrentTime, () => Is.GreaterThan(10600));
|
||||||
|
AddStep("attempt adjust offset via keyboard", () => InputManager.Key(Key.Minus));
|
||||||
|
checkOffset(-1);
|
||||||
|
|
||||||
|
void checkOffset(double offset)
|
||||||
|
{
|
||||||
|
AddUntilStep($"control offset is {offset}", () => this.ChildrenOfType<GameplayOffsetControl>().Single().ChildrenOfType<BeatmapOffsetControl>().Single().Current.Value,
|
||||||
|
() => Is.EqualTo(offset));
|
||||||
|
AddUntilStep($"database offset is {offset}", () => Game.BeatmapManager.QueryBeatmap(b => b.ID == Game.Beatmap.Value.BeatmapInfo.ID)!.UserSettings.Offset,
|
||||||
|
() => Is.EqualTo(offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestRetryCountIncrements()
|
public void TestRetryCountIncrements()
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
private OsuTextFlowContainer stats = null!;
|
private OsuTextFlowContainer stats = null!;
|
||||||
private BeatmapCarousel carousel = null!;
|
private BeatmapCarousel carousel = null!;
|
||||||
|
|
||||||
private OsuScrollContainer scroll => carousel.ChildrenOfType<OsuScrollContainer>().Single();
|
private OsuScrollContainer<Drawable> scroll => carousel.ChildrenOfType<OsuScrollContainer<Drawable>>().Single();
|
||||||
|
|
||||||
private int beatmapCount;
|
private int beatmapCount;
|
||||||
|
|
||||||
|
@ -170,8 +170,6 @@ namespace osu.Game.Configuration
|
|||||||
SetDefault(OsuSetting.ScreenshotFormat, ScreenshotFormat.Jpg);
|
SetDefault(OsuSetting.ScreenshotFormat, ScreenshotFormat.Jpg);
|
||||||
SetDefault(OsuSetting.ScreenshotCaptureMenuCursor, false);
|
SetDefault(OsuSetting.ScreenshotCaptureMenuCursor, false);
|
||||||
|
|
||||||
SetDefault(OsuSetting.SongSelectRightMouseScroll, false);
|
|
||||||
|
|
||||||
SetDefault(OsuSetting.Scaling, ScalingMode.Off);
|
SetDefault(OsuSetting.Scaling, ScalingMode.Off);
|
||||||
SetDefault(OsuSetting.SafeAreaConsiderations, true);
|
SetDefault(OsuSetting.SafeAreaConsiderations, true);
|
||||||
SetDefault(OsuSetting.ScalingBackgroundDim, 0.9f, 0.5f, 1f, 0.01f);
|
SetDefault(OsuSetting.ScalingBackgroundDim, 0.9f, 0.5f, 1f, 0.01f);
|
||||||
@ -401,7 +399,6 @@ namespace osu.Game.Configuration
|
|||||||
Skin,
|
Skin,
|
||||||
ScreenshotFormat,
|
ScreenshotFormat,
|
||||||
ScreenshotCaptureMenuCursor,
|
ScreenshotCaptureMenuCursor,
|
||||||
SongSelectRightMouseScroll,
|
|
||||||
BeatmapSkins,
|
BeatmapSkins,
|
||||||
BeatmapColours,
|
BeatmapColours,
|
||||||
BeatmapHitsounds,
|
BeatmapHitsounds,
|
||||||
|
@ -26,26 +26,12 @@ namespace osu.Game.Graphics.Containers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class OsuScrollContainer<T> : ScrollContainer<T> where T : Drawable
|
public partial class OsuScrollContainer<T> : ScrollContainer<T>
|
||||||
|
where T : Drawable
|
||||||
{
|
{
|
||||||
public const float SCROLL_BAR_WIDTH = 10;
|
public const float SCROLL_BAR_WIDTH = 10;
|
||||||
public const float SCROLL_BAR_PADDING = 3;
|
public const float SCROLL_BAR_PADDING = 3;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Allows controlling the scroll bar from any position in the container using the right mouse button.
|
|
||||||
/// Uses the value of <see cref="DistanceDecayOnRightMouseScrollbar"/> to smoothly scroll to the dragged location.
|
|
||||||
/// </summary>
|
|
||||||
public bool RightMouseScrollbar;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Controls the rate with which the target position is approached when performing a relative drag. Default is 0.02.
|
|
||||||
/// </summary>
|
|
||||||
public double DistanceDecayOnRightMouseScrollbar = 0.02;
|
|
||||||
|
|
||||||
private bool rightMouseDragging;
|
|
||||||
|
|
||||||
protected override bool IsDragging => base.IsDragging || rightMouseDragging;
|
|
||||||
|
|
||||||
public OsuScrollContainer(Direction scrollDirection = Direction.Vertical)
|
public OsuScrollContainer(Direction scrollDirection = Direction.Vertical)
|
||||||
: base(scrollDirection)
|
: base(scrollDirection)
|
||||||
{
|
{
|
||||||
@ -71,50 +57,6 @@ namespace osu.Game.Graphics.Containers
|
|||||||
ScrollTo(maxPos - DisplayableContent + extraScroll, animated);
|
ScrollTo(maxPos - DisplayableContent + extraScroll, animated);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e)
|
|
||||||
{
|
|
||||||
if (shouldPerformRightMouseScroll(e))
|
|
||||||
{
|
|
||||||
ScrollFromMouseEvent(e);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.OnMouseDown(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDrag(DragEvent e)
|
|
||||||
{
|
|
||||||
if (rightMouseDragging)
|
|
||||||
{
|
|
||||||
ScrollFromMouseEvent(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.OnDrag(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnDragStart(DragStartEvent e)
|
|
||||||
{
|
|
||||||
if (shouldPerformRightMouseScroll(e))
|
|
||||||
{
|
|
||||||
rightMouseDragging = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.OnDragStart(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDragEnd(DragEndEvent e)
|
|
||||||
{
|
|
||||||
if (rightMouseDragging)
|
|
||||||
{
|
|
||||||
rightMouseDragging = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.OnDragEnd(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnScroll(ScrollEvent e)
|
protected override bool OnScroll(ScrollEvent e)
|
||||||
{
|
{
|
||||||
// allow for controlling volume when alt is held.
|
// allow for controlling volume when alt is held.
|
||||||
@ -124,15 +66,22 @@ namespace osu.Game.Graphics.Containers
|
|||||||
return base.OnScroll(e);
|
return base.OnScroll(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void ScrollFromMouseEvent(MouseEvent e)
|
#region Absolute scrolling
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controls the rate with which the target position is approached when performing a relative drag. Default is 0.02.
|
||||||
|
/// </summary>
|
||||||
|
public double DistanceDecayOnAbsoluteScroll = 0.02;
|
||||||
|
|
||||||
|
protected virtual void ScrollToAbsolutePosition(Vector2 screenSpacePosition)
|
||||||
{
|
{
|
||||||
float fromScrollbarPosition = FromScrollbarPosition(ToLocalSpace(e.ScreenSpaceMousePosition)[ScrollDim]);
|
float fromScrollbarPosition = FromScrollbarPosition(ToLocalSpace(screenSpacePosition)[ScrollDim]);
|
||||||
float scrollbarCentreOffset = FromScrollbarPosition(Scrollbar.DrawHeight) * 0.5f;
|
float scrollbarCentreOffset = FromScrollbarPosition(Scrollbar.DrawHeight) * 0.5f;
|
||||||
|
|
||||||
ScrollTo(Clamp(fromScrollbarPosition - scrollbarCentreOffset), true, DistanceDecayOnRightMouseScrollbar);
|
ScrollTo(Clamp(fromScrollbarPosition - scrollbarCentreOffset), true, DistanceDecayOnAbsoluteScroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool shouldPerformRightMouseScroll(MouseButtonEvent e) => RightMouseScrollbar && e.Button == MouseButton.Right;
|
#endregion
|
||||||
|
|
||||||
protected override ScrollbarContainer CreateScrollbar(Direction direction) => new OsuScrollbar(direction);
|
protected override ScrollbarContainer CreateScrollbar(Direction direction) => new OsuScrollbar(direction);
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// 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 osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Input.Events;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Containers
|
namespace osu.Game.Graphics.Containers
|
||||||
{
|
{
|
||||||
@ -47,10 +47,10 @@ namespace osu.Game.Graphics.Containers
|
|||||||
base.ScrollIntoView(target, animated);
|
base.ScrollIntoView(target, animated);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ScrollFromMouseEvent(MouseEvent e)
|
protected override void ScrollToAbsolutePosition(Vector2 screenSpacePosition)
|
||||||
{
|
{
|
||||||
UserScrolling = true;
|
UserScrolling = true;
|
||||||
base.ScrollFromMouseEvent(e);
|
base.ScrollToAbsolutePosition(screenSpacePosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public new void ScrollTo(double value, bool animated = true, double? distanceDecay = null)
|
public new void ScrollTo(double value, bool animated = true, double? distanceDecay = null)
|
||||||
|
@ -204,6 +204,7 @@ namespace osu.Game.Input.Bindings
|
|||||||
new KeyBinding(InputKey.BackSpace, GlobalAction.DeselectAllMods),
|
new KeyBinding(InputKey.BackSpace, GlobalAction.DeselectAllMods),
|
||||||
new KeyBinding(new[] { InputKey.Control, InputKey.Up }, GlobalAction.IncreaseModSpeed),
|
new KeyBinding(new[] { InputKey.Control, InputKey.Up }, GlobalAction.IncreaseModSpeed),
|
||||||
new KeyBinding(new[] { InputKey.Control, InputKey.Down }, GlobalAction.DecreaseModSpeed),
|
new KeyBinding(new[] { InputKey.Control, InputKey.Down }, GlobalAction.DecreaseModSpeed),
|
||||||
|
new KeyBinding(new[] { InputKey.MouseRight }, GlobalAction.AbsoluteScrollSongList),
|
||||||
};
|
};
|
||||||
|
|
||||||
private static IEnumerable<KeyBinding> audioControlKeyBindings => new[]
|
private static IEnumerable<KeyBinding> audioControlKeyBindings => new[]
|
||||||
@ -490,6 +491,9 @@ namespace osu.Game.Input.Bindings
|
|||||||
|
|
||||||
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorSeekToNextBookmark))]
|
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorSeekToNextBookmark))]
|
||||||
EditorSeekToNextBookmark,
|
EditorSeekToNextBookmark,
|
||||||
|
|
||||||
|
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.AbsoluteScrollSongList))]
|
||||||
|
AbsoluteScrollSongList
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum GlobalActionCategory
|
public enum GlobalActionCategory
|
||||||
|
@ -449,6 +449,11 @@ namespace osu.Game.Localisation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString EditorSeekToNextBookmark => new TranslatableString(getKey(@"editor_seek_to_next_bookmark"), @"Seek to next bookmark");
|
public static LocalisableString EditorSeekToNextBookmark => new TranslatableString(getKey(@"editor_seek_to_next_bookmark"), @"Seek to next bookmark");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Absolute scroll song list"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString AbsoluteScrollSongList => new TranslatableString(getKey(@"absolute_scroll_song_list"), @"Absolute scroll song list");
|
||||||
|
|
||||||
private static string getKey(string key) => $@"{prefix}:{key}";
|
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,6 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
|
|||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new SettingsCheckbox
|
|
||||||
{
|
|
||||||
ClassicDefault = true,
|
|
||||||
LabelText = UserInterfaceStrings.RightMouseScroll,
|
|
||||||
Current = config.GetBindable<bool>(OsuSetting.SongSelectRightMouseScroll),
|
|
||||||
},
|
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
{
|
{
|
||||||
LabelText = UserInterfaceStrings.ShowConvertedBeatmaps,
|
LabelText = UserInterfaceStrings.ShowConvertedBeatmaps,
|
||||||
|
@ -322,6 +322,7 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies.CacheAs(DrawableRuleset.FrameStableClock);
|
dependencies.CacheAs(DrawableRuleset.FrameStableClock);
|
||||||
|
dependencies.CacheAs<IGameplayClock>(DrawableRuleset.FrameStableClock);
|
||||||
|
|
||||||
// add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components.
|
// add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components.
|
||||||
// also give the overlays the ruleset skin provider to allow rulesets to potentially override HUD elements (used to disable combo counters etc.)
|
// also give the overlays the ruleset skin provider to allow rulesets to potentially override HUD elements (used to disable combo counters etc.)
|
||||||
|
@ -274,20 +274,36 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
|||||||
beatmapOffsetSubscription?.Dispose();
|
beatmapOffsetSubscription?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
Current.Disabled = !allowOffsetAdjust;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool allowOffsetAdjust
|
||||||
|
{
|
||||||
|
get
|
||||||
{
|
{
|
||||||
// General limitations to ensure players don't do anything too weird.
|
// General limitations to ensure players don't do anything too weird.
|
||||||
// These match stable for now.
|
// These match stable for now.
|
||||||
if (player is SubmittingPlayer)
|
if (player is SubmittingPlayer)
|
||||||
{
|
{
|
||||||
|
Debug.Assert(gameplayClock != null);
|
||||||
|
|
||||||
// TODO: the blocking conditions should probably display a message.
|
// TODO: the blocking conditions should probably display a message.
|
||||||
if (player?.IsBreakTime.Value == false && gameplayClock?.CurrentTime - gameplayClock?.StartTime > 10000)
|
if (!player.IsBreakTime.Value && gameplayClock.CurrentTime - gameplayClock.StartTime > 10000)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (gameplayClock?.IsPaused.Value == true)
|
if (gameplayClock.IsPaused.Value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
|
{
|
||||||
// To match stable, this should adjust by 5 ms, or 1 ms when holding alt.
|
// To match stable, this should adjust by 5 ms, or 1 ms when holding alt.
|
||||||
// But that is hard to make work with global actions due to the operating mode.
|
// But that is hard to make work with global actions due to the operating mode.
|
||||||
// Let's use the more precise as a default for now.
|
// Let's use the more precise as a default for now.
|
||||||
@ -296,10 +312,12 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
|||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
case GlobalAction.IncreaseOffset:
|
case GlobalAction.IncreaseOffset:
|
||||||
|
if (!Current.Disabled)
|
||||||
Current.Value += amount;
|
Current.Value += amount;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case GlobalAction.DecreaseOffset:
|
case GlobalAction.DecreaseOffset:
|
||||||
|
if (!Current.Disabled)
|
||||||
Current.Value -= amount;
|
Current.Value -= amount;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Caching;
|
using osu.Framework.Caching;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
@ -184,8 +185,6 @@ namespace osu.Game.Screens.Select
|
|||||||
private readonly Cached itemsCache = new Cached();
|
private readonly Cached itemsCache = new Cached();
|
||||||
private PendingScrollOperation pendingScrollOperation = PendingScrollOperation.None;
|
private PendingScrollOperation pendingScrollOperation = PendingScrollOperation.None;
|
||||||
|
|
||||||
public Bindable<bool> RightClickScrollingEnabled = new Bindable<bool>();
|
|
||||||
|
|
||||||
public Bindable<RandomSelectAlgorithm> RandomAlgorithm = new Bindable<RandomSelectAlgorithm>();
|
public Bindable<RandomSelectAlgorithm> RandomAlgorithm = new Bindable<RandomSelectAlgorithm>();
|
||||||
private readonly List<CarouselBeatmapSet> previouslyVisitedRandomSets = new List<CarouselBeatmapSet>();
|
private readonly List<CarouselBeatmapSet> previouslyVisitedRandomSets = new List<CarouselBeatmapSet>();
|
||||||
private readonly List<CarouselBeatmap> randomSelectedBeatmaps = new List<CarouselBeatmap>();
|
private readonly List<CarouselBeatmap> randomSelectedBeatmaps = new List<CarouselBeatmap>();
|
||||||
@ -226,9 +225,6 @@ namespace osu.Game.Screens.Select
|
|||||||
randomSelectSample = audio.Samples.Get(@"SongSelect/select-random");
|
randomSelectSample = audio.Samples.Get(@"SongSelect/select-random");
|
||||||
|
|
||||||
config.BindWith(OsuSetting.RandomSelectAlgorithm, RandomAlgorithm);
|
config.BindWith(OsuSetting.RandomSelectAlgorithm, RandomAlgorithm);
|
||||||
config.BindWith(OsuSetting.SongSelectRightMouseScroll, RightClickScrollingEnabled);
|
|
||||||
|
|
||||||
RightClickScrollingEnabled.BindValueChanged(enabled => Scroll.RightMouseScrollbar = enabled.NewValue, true);
|
|
||||||
|
|
||||||
detachedBeatmapSets = beatmaps.GetBeatmapSets(cancellationToken);
|
detachedBeatmapSets = beatmaps.GetBeatmapSets(cancellationToken);
|
||||||
detachedBeatmapSets.BindCollectionChanged(beatmapSetsChanged);
|
detachedBeatmapSets.BindCollectionChanged(beatmapSetsChanged);
|
||||||
@ -1161,10 +1157,8 @@ namespace osu.Game.Screens.Select
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class CarouselScrollContainer : UserTrackingScrollContainer<DrawableCarouselItem>
|
public partial class CarouselScrollContainer : UserTrackingScrollContainer<DrawableCarouselItem>, IKeyBindingHandler<GlobalAction>
|
||||||
{
|
{
|
||||||
private bool rightMouseScrollBlocked;
|
|
||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => true;
|
||||||
|
|
||||||
public CarouselScrollContainer()
|
public CarouselScrollContainer()
|
||||||
@ -1176,31 +1170,54 @@ namespace osu.Game.Screens.Select
|
|||||||
Masking = false;
|
Masking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e)
|
#region Absolute scrolling
|
||||||
{
|
|
||||||
if (e.Button == MouseButton.Right)
|
|
||||||
{
|
|
||||||
// we need to block right click absolute scrolling when hovering a carousel item so context menus can display.
|
|
||||||
// this can be reconsidered when we have an alternative to right click scrolling.
|
|
||||||
if (GetContainingInputManager()!.HoveredDrawables.OfType<DrawableCarouselItem>().Any())
|
|
||||||
{
|
|
||||||
rightMouseScrollBlocked = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rightMouseScrollBlocked = false;
|
private bool absoluteScrolling;
|
||||||
return base.OnMouseDown(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnDragStart(DragStartEvent e)
|
protected override bool IsDragging => base.IsDragging || absoluteScrolling;
|
||||||
|
|
||||||
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
if (rightMouseScrollBlocked)
|
switch (e.Action)
|
||||||
|
{
|
||||||
|
case GlobalAction.AbsoluteScrollSongList:
|
||||||
|
// The default binding for absolute scroll is right mouse button.
|
||||||
|
// To avoid conflicts with context menus, disallow absolute scroll completely if it looks like things will fall over.
|
||||||
|
if (e.CurrentState.Mouse.Buttons.Contains(MouseButton.Right)
|
||||||
|
&& GetContainingInputManager()!.HoveredDrawables.OfType<IHasContextMenu>().Any())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return base.OnDragStart(e);
|
ScrollToAbsolutePosition(e.CurrentState.Mouse.Position);
|
||||||
|
absoluteScrolling = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||||
|
{
|
||||||
|
switch (e.Action)
|
||||||
|
{
|
||||||
|
case GlobalAction.AbsoluteScrollSongList:
|
||||||
|
absoluteScrolling = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||||
|
{
|
||||||
|
if (absoluteScrolling)
|
||||||
|
{
|
||||||
|
ScrollToAbsolutePosition(e.CurrentState.Mouse.Position);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.OnMouseMove(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
protected override ScrollbarContainer CreateScrollbar(Direction direction)
|
protected override ScrollbarContainer CreateScrollbar(Direction direction)
|
||||||
{
|
{
|
||||||
return new PaddedScrollbar();
|
return new PaddedScrollbar();
|
||||||
|
@ -11,13 +11,18 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Extensions.TypeExtensions;
|
using osu.Framework.Extensions.TypeExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Input.Bindings;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Input.Bindings;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Screens.SelectV2
|
namespace osu.Game.Screens.SelectV2
|
||||||
{
|
{
|
||||||
@ -390,7 +395,7 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
/// Implementation of scroll container which handles very large vertical lists by internally using <c>double</c> precision
|
/// Implementation of scroll container which handles very large vertical lists by internally using <c>double</c> precision
|
||||||
/// for pre-display Y values.
|
/// for pre-display Y values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private partial class CarouselScrollContainer : OsuScrollContainer
|
private partial class CarouselScrollContainer : UserTrackingScrollContainer, IKeyBindingHandler<GlobalAction>
|
||||||
{
|
{
|
||||||
public readonly Container Panels;
|
public readonly Container Panels;
|
||||||
|
|
||||||
@ -465,6 +470,55 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
foreach (var d in Panels)
|
foreach (var d in Panels)
|
||||||
d.Y = (float)(((ICarouselPanel)d).DrawYPosition + scrollableExtent);
|
d.Y = (float)(((ICarouselPanel)d).DrawYPosition + scrollableExtent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Absolute scrolling
|
||||||
|
|
||||||
|
private bool absoluteScrolling;
|
||||||
|
|
||||||
|
protected override bool IsDragging => base.IsDragging || absoluteScrolling;
|
||||||
|
|
||||||
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
|
{
|
||||||
|
switch (e.Action)
|
||||||
|
{
|
||||||
|
case GlobalAction.AbsoluteScrollSongList:
|
||||||
|
|
||||||
|
// The default binding for absolute scroll is right mouse button.
|
||||||
|
// To avoid conflicts with context menus, disallow absolute scroll completely if it looks like things will fall over.
|
||||||
|
if (e.CurrentState.Mouse.Buttons.Contains(MouseButton.Right)
|
||||||
|
&& GetContainingInputManager()!.HoveredDrawables.OfType<IHasContextMenu>().Any())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ScrollToAbsolutePosition(e.CurrentState.Mouse.Position);
|
||||||
|
absoluteScrolling = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||||
|
{
|
||||||
|
switch (e.Action)
|
||||||
|
{
|
||||||
|
case GlobalAction.AbsoluteScrollSongList:
|
||||||
|
absoluteScrolling = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||||
|
{
|
||||||
|
if (absoluteScrolling)
|
||||||
|
{
|
||||||
|
ScrollToAbsolutePosition(e.CurrentState.Mouse.Position);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.OnMouseMove(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BoundsCarouselItem : CarouselItem
|
private class BoundsCarouselItem : CarouselItem
|
||||||
|
Loading…
Reference in New Issue
Block a user