diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs new file mode 100644 index 0000000000..66e21fbf67 --- /dev/null +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -0,0 +1,72 @@ +using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using OpenTK.Input; + +namespace osu.Game.Graphics.Containers +{ + class OsuScrollContainer : ScrollContainer + { + /// + /// Add the ability to seek to an absolute scroll position when the right mouse button is pressed or dragged. + /// Uses the value of to smoothly scroll to the dragged location. + /// + public bool RightMouseScrollbar = false; + + /// + /// Controls the rate with which the target position is approached when performing a relative drag. Default is 0.02. + /// + public double DistanceDecayOnRightMouseScrollbar = 0.02; + + private bool shouldPerformRelativeDrag(InputState state) => RightMouseScrollbar && state.Mouse.IsPressed(MouseButton.Right); + + private void scrollToRelative(float value) => ScrollTo(Clamp((value - Scrollbar.DrawSize[ScrollDim] / 2) / Scrollbar.Size[ScrollDim]), true, DistanceDecayOnRightMouseScrollbar); + + private bool mouseScrollBarDragging; + + protected override bool IsDragging => base.IsDragging || mouseScrollBarDragging; + + protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) + { + if (shouldPerformRelativeDrag(state)) + { + scrollToRelative(state.Mouse.Position[ScrollDim]); + return true; + } + + return base.OnMouseDown(state, args); + } + + protected override bool OnDrag(InputState state) + { + if (mouseScrollBarDragging) + { + scrollToRelative(state.Mouse.Position[ScrollDim]); + return true; + } + + return base.OnDrag(state); + } + + protected override bool OnDragStart(InputState state) + { + if (shouldPerformRelativeDrag(state)) + { + mouseScrollBarDragging = true; + return true; + } + + return base.OnDragStart(state); + } + + protected override bool OnDragEnd(InputState state) + { + if (mouseScrollBarDragging) + { + mouseScrollBarDragging = false; + return true; + } + + return base.OnDragEnd(state); + } + } +} diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 1d792f1b78..37c3804543 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -114,7 +114,7 @@ namespace osu.Game.Graphics.Containers public SectionsContainer() { - Add(ScrollContainer = new ScrollContainer() + Add(ScrollContainer = new OsuScrollContainer() { RelativeSizeAxes = Axes.Both, Masking = false, diff --git a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs index 9f61d13813..135f8f43b9 100644 --- a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs @@ -81,7 +81,7 @@ namespace osu.Game.Overlays.Chat Padding = new MarginPadding { Top = 85, Right = WIDTH_PADDING }, Children = new[] { - new ScrollContainer + new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Children = new[] diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index f8b7c7e581..e51f931959 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; using osu.Game.Online.Chat; namespace osu.Game.Overlays.Chat @@ -25,7 +26,7 @@ namespace osu.Game.Overlays.Chat Children = new Drawable[] { - scroll = new ScrollContainer + scroll = new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index eeb072fb00..ca46bdea95 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Database; +using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Music { @@ -49,7 +50,7 @@ namespace osu.Game.Overlays.Music { Children = new Drawable[] { - new ScrollContainer + new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Children = new Drawable[] diff --git a/osu.Game/Overlays/NotificationManager.cs b/osu.Game/Overlays/NotificationManager.cs index 382683cbcc..18cb49f335 100644 --- a/osu.Game/Overlays/NotificationManager.cs +++ b/osu.Game/Overlays/NotificationManager.cs @@ -36,7 +36,7 @@ namespace osu.Game.Overlays Colour = Color4.Black, Alpha = 0.6f, }, - scrollContainer = new ScrollContainer + scrollContainer = new OsuScrollContainer { RelativeSizeAxes = Axes.Both, Margin = new MarginPadding { Top = Toolbar.Toolbar.HEIGHT }, diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs index 25f6b4f60b..c5b8b0cf85 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Game.Graphics.Backgrounds; +using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.SearchableList { @@ -60,7 +61,7 @@ namespace osu.Game.Overlays.SearchableList RelativeSizeAxes = Axes.Both, Children = new[] { - new ScrollContainer + new OsuScrollContainer { RelativeSizeAxes = Axes.Both, ScrollbarVisible = false, diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs index 3a822be791..761204dda4 100644 --- a/osu.Game/Screens/Multiplayer/RoomInspector.cs +++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs @@ -17,6 +17,7 @@ using osu.Framework.Localisation; using osu.Game.Beatmaps.Drawables; using osu.Game.Database; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; using osu.Game.Users; @@ -341,7 +342,7 @@ namespace osu.Game.Screens.Multiplayer }, }, }, - participantsScroll = new ScrollContainer + participantsScroll = new OsuScrollContainer { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index e560cfe413..2a8e4ca5fb 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -12,6 +12,7 @@ using System; using osu.Framework.Allocation; using osu.Framework.Threading; using osu.Game.Database; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Scoring; using osu.Game.Online.API; @@ -74,7 +75,7 @@ namespace osu.Game.Screens.Select.Leaderboards { Children = new Drawable[] { - scrollContainer = new ScrollContainer + scrollContainer = new OsuScrollContainer { RelativeSizeAxes = Axes.Both, ScrollbarVisible = false, diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3d84f287f0..691df1d2d1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -78,6 +78,7 @@ +