mirror of
https://github.com/ppy/osu.git
synced 2025-01-29 23:22:55 +08:00
Move absolute scroll support local to carousel and allow custom bindings
This commit is contained in:
parent
1c2621d88e
commit
a6057a9f54
@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
private OsuTextFlowContainer stats = null!;
|
||||
private BeatmapCarousel carousel = null!;
|
||||
|
||||
private OsuScrollContainer scroll => carousel.ChildrenOfType<OsuScrollContainer>().Single();
|
||||
private OsuScrollContainer<Drawable> scroll => carousel.ChildrenOfType<OsuScrollContainer<Drawable>>().Single();
|
||||
|
||||
private int beatmapCount;
|
||||
|
||||
|
@ -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_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)
|
||||
: base(scrollDirection)
|
||||
{
|
||||
@ -71,50 +57,6 @@ namespace osu.Game.Graphics.Containers
|
||||
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)
|
||||
{
|
||||
// allow for controlling volume when alt is held.
|
||||
@ -124,15 +66,22 @@ namespace osu.Game.Graphics.Containers
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Events;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Graphics.Containers
|
||||
{
|
||||
@ -47,10 +47,10 @@ namespace osu.Game.Graphics.Containers
|
||||
base.ScrollIntoView(target, animated);
|
||||
}
|
||||
|
||||
protected override void ScrollFromMouseEvent(MouseEvent e)
|
||||
protected override void ScrollToAbsolutePosition(Vector2 screenSpacePosition)
|
||||
{
|
||||
UserScrolling = true;
|
||||
base.ScrollFromMouseEvent(e);
|
||||
base.ScrollToAbsolutePosition(screenSpacePosition);
|
||||
}
|
||||
|
||||
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(new[] { InputKey.Control, InputKey.Up }, GlobalAction.IncreaseModSpeed),
|
||||
new KeyBinding(new[] { InputKey.Control, InputKey.Down }, GlobalAction.DecreaseModSpeed),
|
||||
new KeyBinding(new[] { InputKey.MouseRight }, GlobalAction.AbsoluteScrollSongList),
|
||||
};
|
||||
|
||||
private static IEnumerable<KeyBinding> audioControlKeyBindings => new[]
|
||||
@ -490,6 +491,9 @@ namespace osu.Game.Input.Bindings
|
||||
|
||||
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorSeekToNextBookmark))]
|
||||
EditorSeekToNextBookmark,
|
||||
|
||||
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.AbsoluteScrollSongList))]
|
||||
AbsoluteScrollSongList
|
||||
}
|
||||
|
||||
public enum GlobalActionCategory
|
||||
|
@ -449,6 +449,11 @@ namespace osu.Game.Localisation
|
||||
/// </summary>
|
||||
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}";
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Caching;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
@ -208,7 +209,6 @@ namespace osu.Game.Screens.Select
|
||||
setPool,
|
||||
Scroll = new CarouselScrollContainer
|
||||
{
|
||||
RightMouseScrollbar = true,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
noResultsPlaceholder = new NoResultsPlaceholder()
|
||||
@ -1157,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 CarouselScrollContainer()
|
||||
@ -1172,31 +1170,54 @@ namespace osu.Game.Screens.Select
|
||||
Masking = false;
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
#region Absolute scrolling
|
||||
|
||||
private bool absoluteScrolling;
|
||||
|
||||
protected override bool IsDragging => base.IsDragging || absoluteScrolling;
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||
{
|
||||
if (e.Button == MouseButton.Right)
|
||||
switch (e.Action)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
rightMouseScrollBlocked = false;
|
||||
return base.OnMouseDown(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override bool OnDragStart(DragStartEvent e)
|
||||
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||
{
|
||||
if (rightMouseScrollBlocked)
|
||||
return false;
|
||||
|
||||
return base.OnDragStart(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)
|
||||
{
|
||||
return new PaddedScrollbar();
|
||||
|
@ -11,13 +11,18 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.TypeExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
@ -121,7 +126,6 @@ namespace osu.Game.Screens.SelectV2
|
||||
},
|
||||
scroll = new CarouselScrollContainer
|
||||
{
|
||||
RightMouseScrollbar = true,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = false,
|
||||
}
|
||||
@ -391,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
|
||||
/// for pre-display Y values.
|
||||
/// </summary>
|
||||
private partial class CarouselScrollContainer : UserTrackingScrollContainer
|
||||
private partial class CarouselScrollContainer : UserTrackingScrollContainer, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
public readonly Container Panels;
|
||||
|
||||
@ -466,6 +470,55 @@ namespace osu.Game.Screens.SelectV2
|
||||
foreach (var d in Panels)
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user