mirror of
https://github.com/ppy/osu.git
synced 2024-11-12 14:07:52 +08:00
Merge remote-tracking branch 'upstream/master' into tournament-tools
This commit is contained in:
commit
1682a8ce0d
@ -23,6 +23,7 @@ namespace osu.Game.Tests.Visual
|
||||
public class TestCaseChatLink : OsuTestCase
|
||||
{
|
||||
private readonly TestChatLineContainer textContainer;
|
||||
private readonly DialogOverlay dialogOverlay;
|
||||
private Color4 linkColour;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
@ -37,6 +38,7 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
public TestCaseChatLink()
|
||||
{
|
||||
Add(dialogOverlay = new DialogOverlay { Depth = float.MinValue });
|
||||
Add(textContainer = new TestChatLineContainer
|
||||
{
|
||||
Padding = new MarginPadding { Left = 20, Right = 20 },
|
||||
@ -57,6 +59,7 @@ namespace osu.Game.Tests.Visual
|
||||
Dependencies.Cache(chatManager);
|
||||
|
||||
Dependencies.Cache(new ChatOverlay());
|
||||
Dependencies.Cache(dialogOverlay);
|
||||
|
||||
testLinksGeneral();
|
||||
testEcho();
|
||||
|
@ -42,6 +42,8 @@ namespace osu.Game.Configuration
|
||||
if (!val) Set(OsuSetting.SavePassword, false);
|
||||
};
|
||||
|
||||
Set(OsuSetting.ExternalLinkWarning, true);
|
||||
|
||||
// Audio
|
||||
Set(OsuSetting.VolumeInactive, 0.25, 0, 1, 0.01);
|
||||
|
||||
@ -148,6 +150,7 @@ namespace osu.Game.Configuration
|
||||
BeatmapSkins,
|
||||
BeatmapHitsounds,
|
||||
IncreaseFirstObjectVisibility,
|
||||
ScoreDisplayMode
|
||||
ScoreDisplayMode,
|
||||
ExternalLinkWarning
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
|
||||
@ -24,14 +23,12 @@ namespace osu.Game.Graphics.Containers
|
||||
private OsuGame game;
|
||||
private ChannelManager channelManager;
|
||||
private Action showNotImplementedError;
|
||||
private GameHost host;
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuGame game, NotificationOverlay notifications, GameHost host, ChannelManager channelManager)
|
||||
private void load(OsuGame game, NotificationOverlay notifications, ChannelManager channelManager)
|
||||
{
|
||||
// will be null in tests
|
||||
this.game = game;
|
||||
this.host = host;
|
||||
this.channelManager = channelManager;
|
||||
|
||||
showNotImplementedError = () => notifications?.Post(new SimpleNotification
|
||||
@ -98,7 +95,7 @@ namespace osu.Game.Graphics.Containers
|
||||
showNotImplementedError?.Invoke();
|
||||
break;
|
||||
case LinkAction.External:
|
||||
host.OpenUrlExternally(url);
|
||||
game?.OpenUrlExternally(url);
|
||||
break;
|
||||
case LinkAction.OpenUserProfile:
|
||||
if (long.TryParse(linkArgument, out long userId))
|
||||
|
@ -77,7 +77,7 @@ namespace osu.Game.Online.Chat
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
|
||||
CurrentChannel.Value = JoinedChannels.FirstOrDefault(c => c.Type == ChannelType.PM && c.Users.Count == 1 && c.Users.Any(u => u.Id == user.Id))
|
||||
?? new Channel { Name = user.Username, Users = { user } };
|
||||
?? new Channel { Name = user.Username, Users = { user }, Type = ChannelType.PM };
|
||||
}
|
||||
|
||||
private void currentChannelChanged(Channel channel) => JoinChannel(channel);
|
||||
@ -223,13 +223,11 @@ namespace osu.Game.Online.Chat
|
||||
{
|
||||
foreach (var channel in channels)
|
||||
{
|
||||
// add as available if not already
|
||||
if (AvailableChannels.All(c => c.Id != channel.Id))
|
||||
AvailableChannels.Add(channel);
|
||||
var ch = getChannel(channel, addToAvailable: true);
|
||||
|
||||
// join any channels classified as "defaults"
|
||||
if (joinDefaults && defaultChannels.Any(c => c.Equals(channel.Name, StringComparison.OrdinalIgnoreCase)))
|
||||
JoinChannel(channel);
|
||||
JoinChannel(ch);
|
||||
}
|
||||
};
|
||||
req.Failure += error =>
|
||||
@ -262,37 +260,73 @@ namespace osu.Game.Online.Chat
|
||||
api.Queue(fetchInitialMsgReq);
|
||||
}
|
||||
|
||||
public void JoinChannel(Channel channel)
|
||||
/// <summary>
|
||||
/// Find an existing channel instance for the provided channel. Lookup is performed basd on ID.
|
||||
/// The provided channel may be used if an existing instance is not found.
|
||||
/// </summary>
|
||||
/// <param name="lookup">A candidate channel to be used for lookup or permanently on lookup failure.</param>
|
||||
/// <param name="addToAvailable">Whether the channel should be added to <see cref="AvailableChannels"/> if not already.</param>
|
||||
/// <param name="addToJoined">Whether the channel should be added to <see cref="JoinedChannels"/> if not already.</param>
|
||||
/// <returns>The found channel.</returns>
|
||||
private Channel getChannel(Channel lookup, bool addToAvailable = false, bool addToJoined = false)
|
||||
{
|
||||
if (channel == null) return;
|
||||
Channel found = null;
|
||||
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
var existing = JoinedChannels.FirstOrDefault(c => c.Id == channel.Id);
|
||||
bool lookupCondition(Channel ch) => lookup.Id > 0 ? ch.Id == lookup.Id : lookup.Name == ch.Name;
|
||||
|
||||
if (existing != null)
|
||||
var available = AvailableChannels.FirstOrDefault(lookupCondition);
|
||||
if (available != null)
|
||||
found = available;
|
||||
|
||||
var joined = JoinedChannels.FirstOrDefault(lookupCondition);
|
||||
if (found == null && joined != null)
|
||||
found = joined;
|
||||
|
||||
if (found == null)
|
||||
{
|
||||
// if we already have this channel loaded, we don't want to make a second one.
|
||||
channel = existing;
|
||||
found = lookup;
|
||||
|
||||
// if we're using a channel object from the server, we want to remove ourselves from the users list.
|
||||
// this is because we check the first user in the channel to display a name/icon on tabs for now.
|
||||
var foundSelf = found.Users.FirstOrDefault(u => u.Id == api.LocalUser.Value.Id);
|
||||
if (foundSelf != null)
|
||||
found.Users.Remove(foundSelf);
|
||||
}
|
||||
|
||||
if (joined == null && addToJoined) JoinedChannels.Add(found);
|
||||
if (available == null && addToAvailable) AvailableChannels.Add(found);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Joins a channel if it has not already been joined.
|
||||
/// </summary>
|
||||
/// <param name="channel">The channel to join.</param>
|
||||
/// <param name="alreadyJoined">Whether the channel has already been joined server-side. Will skip a join request.</param>
|
||||
/// <returns>The joined channel. Note that this may not match the parameter channel as it is a backed object.</returns>
|
||||
public Channel JoinChannel(Channel channel, bool alreadyJoined = false)
|
||||
{
|
||||
if (channel == null) return null;
|
||||
|
||||
channel = getChannel(channel, addToJoined: true);
|
||||
|
||||
// ensure we are joined to the channel
|
||||
if (!channel.Joined.Value)
|
||||
{
|
||||
if (alreadyJoined)
|
||||
channel.Joined.Value = true;
|
||||
else
|
||||
{
|
||||
var foundSelf = channel.Users.FirstOrDefault(u => u.Id == api.LocalUser.Value.Id);
|
||||
if (foundSelf != null)
|
||||
channel.Users.Remove(foundSelf);
|
||||
|
||||
JoinedChannels.Add(channel);
|
||||
|
||||
if (channel.Type == ChannelType.Public && !channel.Joined)
|
||||
switch (channel.Type)
|
||||
{
|
||||
case ChannelType.Public:
|
||||
var req = new JoinChannelRequest(channel, api.LocalUser);
|
||||
req.Success += () =>
|
||||
{
|
||||
channel.Joined.Value = true;
|
||||
JoinChannel(channel);
|
||||
};
|
||||
req.Success += () => JoinChannel(channel, true);
|
||||
req.Failure += ex => LeaveChannel(channel);
|
||||
api.Queue(req);
|
||||
return;
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,6 +338,8 @@ namespace osu.Game.Online.Chat
|
||||
// let's fetch a small number of messages to bring us up-to-date with the backlog.
|
||||
fetchInitalMessages(channel);
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
public void LeaveChannel(Channel channel)
|
||||
@ -352,21 +388,9 @@ namespace osu.Game.Online.Chat
|
||||
if (updates?.Presence != null)
|
||||
{
|
||||
foreach (var channel in updates.Presence)
|
||||
{
|
||||
if (!channel.Joined.Value)
|
||||
{
|
||||
// we received this from the server so should mark the channel already joined.
|
||||
channel.Joined.Value = true;
|
||||
|
||||
JoinChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
if (!channelsInitialised)
|
||||
{
|
||||
channelsInitialised = true;
|
||||
// we want this to run after the first presence so we can see if the user is in any channels already.
|
||||
initializeChannels();
|
||||
JoinChannel(channel, true);
|
||||
}
|
||||
|
||||
//todo: handle left channels
|
||||
@ -379,6 +403,13 @@ namespace osu.Game.Online.Chat
|
||||
lastMessageId = updates.Messages.LastOrDefault()?.Id ?? lastMessageId;
|
||||
}
|
||||
|
||||
if (!channelsInitialised)
|
||||
{
|
||||
channelsInitialised = true;
|
||||
// we want this to run after the first presence so we can see if the user is in any channels already.
|
||||
initializeChannels();
|
||||
}
|
||||
|
||||
fetchUpdates();
|
||||
};
|
||||
|
||||
|
36
osu.Game/Online/Chat/ExternalLinkOpener.cs
Normal file
36
osu.Game/Online/Chat/ExternalLinkOpener.cs
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Chat;
|
||||
|
||||
namespace osu.Game.Online.Chat
|
||||
{
|
||||
public class ExternalLinkOpener : Component
|
||||
{
|
||||
private GameHost host;
|
||||
private DialogOverlay dialogOverlay;
|
||||
private Bindable<bool> externalLinkWarning;
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(GameHost host, DialogOverlay dialogOverlay, OsuConfigManager config)
|
||||
{
|
||||
this.host = host;
|
||||
this.dialogOverlay = dialogOverlay;
|
||||
externalLinkWarning = config.GetBindable<bool>(OsuSetting.ExternalLinkWarning);
|
||||
}
|
||||
|
||||
public void OpenUrlExternally(string url)
|
||||
{
|
||||
if (externalLinkWarning)
|
||||
dialogOverlay.Push(new ExternalLinkDialog(url, () => host.OpenUrlExternally(url)));
|
||||
else
|
||||
host.OpenUrlExternally(url);
|
||||
}
|
||||
}
|
||||
}
|
@ -50,7 +50,9 @@ namespace osu.Game
|
||||
{
|
||||
public Toolbar Toolbar;
|
||||
|
||||
private ChatOverlay chat;
|
||||
private ChatOverlay chatOverlay;
|
||||
|
||||
private ChannelManager channelManager;
|
||||
|
||||
private MusicController musicController;
|
||||
|
||||
@ -179,6 +181,9 @@ namespace osu.Game
|
||||
LocalConfig.BindWith(OsuSetting.VolumeInactive, inactiveVolumeAdjust);
|
||||
}
|
||||
|
||||
private ExternalLinkOpener externalLinkOpener;
|
||||
public void OpenUrlExternally(string url) => externalLinkOpener.OpenUrlExternally(url);
|
||||
|
||||
private ScheduledDelegate scoreLoad;
|
||||
|
||||
/// <summary>
|
||||
@ -338,12 +343,8 @@ namespace osu.Game
|
||||
//overlay elements
|
||||
loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add);
|
||||
loadComponentSingleFile(social = new SocialOverlay { Depth = -1 }, mainContent.Add);
|
||||
loadComponentSingleFile(new ChannelManager(), channelManager =>
|
||||
{
|
||||
dependencies.Cache(channelManager);
|
||||
AddInternal(channelManager);
|
||||
});
|
||||
loadComponentSingleFile(chat = new ChatOverlay { Depth = -1 }, mainContent.Add);
|
||||
loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal);
|
||||
loadComponentSingleFile(chatOverlay = new ChatOverlay { Depth = -1 }, mainContent.Add);
|
||||
loadComponentSingleFile(settings = new MainSettings
|
||||
{
|
||||
GetToolbarHeight = () => ToolbarOffset,
|
||||
@ -376,13 +377,16 @@ namespace osu.Game
|
||||
dependencies.Cache(onscreenDisplay);
|
||||
dependencies.Cache(social);
|
||||
dependencies.Cache(direct);
|
||||
dependencies.Cache(chat);
|
||||
dependencies.Cache(chatOverlay);
|
||||
dependencies.Cache(channelManager);
|
||||
dependencies.Cache(userProfile);
|
||||
dependencies.Cache(musicController);
|
||||
dependencies.Cache(beatmapSetOverlay);
|
||||
dependencies.Cache(notifications);
|
||||
dependencies.Cache(dialogOverlay);
|
||||
|
||||
Add(externalLinkOpener = new ExternalLinkOpener());
|
||||
|
||||
var singleDisplaySideOverlays = new OverlayContainer[] { settings, notifications };
|
||||
overlays.AddRange(singleDisplaySideOverlays);
|
||||
|
||||
@ -409,7 +413,7 @@ namespace osu.Game
|
||||
}
|
||||
|
||||
// ensure only one of these overlays are open at once.
|
||||
var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct };
|
||||
var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, social, direct };
|
||||
overlays.AddRange(singleDisplayOverlays);
|
||||
|
||||
foreach (var overlay in singleDisplayOverlays)
|
||||
@ -534,7 +538,7 @@ namespace osu.Game
|
||||
switch (action)
|
||||
{
|
||||
case GlobalAction.ToggleChat:
|
||||
chat.ToggleVisibility();
|
||||
chatOverlay.ToggleVisibility();
|
||||
return true;
|
||||
case GlobalAction.ToggleSocial:
|
||||
social.ToggleVisibility();
|
||||
|
33
osu.Game/Overlays/Chat/ExternalLinkDialog.cs
Normal file
33
osu.Game/Overlays/Chat/ExternalLinkDialog.cs
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Overlays.Dialog;
|
||||
|
||||
namespace osu.Game.Overlays.Chat
|
||||
{
|
||||
public class ExternalLinkDialog : PopupDialog
|
||||
{
|
||||
public ExternalLinkDialog(string url, Action openExternalLinkAction)
|
||||
{
|
||||
HeaderText = "Just checking...";
|
||||
BodyText = $"You are about to leave osu! and open the following link in a web browser:\n\n{url}";
|
||||
|
||||
Icon = FontAwesome.fa_warning;
|
||||
|
||||
Buttons = new PopupDialogButton[]
|
||||
{
|
||||
new PopupDialogOkButton
|
||||
{
|
||||
Text = @"Yes. Go for it.",
|
||||
Action = openExternalLinkAction
|
||||
},
|
||||
new PopupDialogCancelButton
|
||||
{
|
||||
Text = @"No! Abort mission!"
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -209,7 +209,6 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
textbox.Current.Disabled = true;
|
||||
currentChannelContainer.Clear(false);
|
||||
channelTabControl.Current.Value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -7,12 +7,10 @@ using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -35,7 +33,7 @@ namespace osu.Game.Overlays.Dialog
|
||||
private readonly Container ring;
|
||||
private readonly FillFlowContainer<PopupDialogButton> buttonsContainer;
|
||||
private readonly SpriteIcon icon;
|
||||
private readonly SpriteText header;
|
||||
private readonly TextFlowContainer header;
|
||||
private readonly TextFlowContainer body;
|
||||
|
||||
private bool actionInvoked;
|
||||
@ -46,10 +44,19 @@ namespace osu.Game.Overlays.Dialog
|
||||
set => icon.Icon = value;
|
||||
}
|
||||
|
||||
private string text;
|
||||
|
||||
public string HeaderText
|
||||
{
|
||||
get => header.Text;
|
||||
set => header.Text = value;
|
||||
get => text;
|
||||
set
|
||||
{
|
||||
if (text == value)
|
||||
return;
|
||||
text = value;
|
||||
|
||||
header.Text = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string BodyText
|
||||
@ -164,18 +171,20 @@ namespace osu.Game.Overlays.Dialog
|
||||
},
|
||||
},
|
||||
},
|
||||
header = new OsuSpriteText
|
||||
header = new OsuTextFlowContainer(t => t.TextSize = 25)
|
||||
{
|
||||
Origin = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
TextSize = 25,
|
||||
Shadow = true,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding(15),
|
||||
TextAnchor = Anchor.TopCentre,
|
||||
},
|
||||
body = new OsuTextFlowContainer(t => t.TextSize = 18)
|
||||
{
|
||||
Padding = new MarginPadding(15),
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding(15),
|
||||
TextAnchor = Anchor.TopCentre,
|
||||
},
|
||||
},
|
||||
|
@ -406,6 +406,10 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
base.PopOut();
|
||||
|
||||
// This is here mostly as a performance fix.
|
||||
// If the playlist is not hidden it will update children even when the music controller is hidden (due to AlwaysPresent).
|
||||
playlist.State = Visibility.Hidden;
|
||||
|
||||
this.FadeOut(transition_length, Easing.OutQuint);
|
||||
dragContainer.ScaleTo(0.9f, transition_length, Easing.OutQuint);
|
||||
}
|
||||
|
27
osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs
Normal file
27
osu.Game/Overlays/Settings/Sections/Online/WebSettings.cs
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Configuration;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Online
|
||||
{
|
||||
public class WebSettings : SettingsSubsection
|
||||
{
|
||||
protected override string Header => "Web";
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Warn about opening external links",
|
||||
Bindable = config.GetBindable<bool>(OsuSetting.ExternalLinkWarning)
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Overlays.Settings.Sections.Online;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
@ -15,6 +16,7 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new WebSettings()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -228,15 +228,19 @@ namespace osu.Game.Overlays.Volume
|
||||
public void Decrease(double amount = 1, bool isPrecise = false) => adjust(-amount, isPrecise);
|
||||
|
||||
// because volume precision is set to 0.01, this local is required to keep track of more precise adjustments and only apply when possible.
|
||||
private double adjustAccumulator;
|
||||
private double scrollAccumulation;
|
||||
|
||||
private void adjust(double delta, bool isPrecise)
|
||||
{
|
||||
adjustAccumulator += delta * adjust_step * (isPrecise ? 0.1 : 1);
|
||||
if (Math.Abs(adjustAccumulator) < Bindable.Precision)
|
||||
return;
|
||||
Volume += adjustAccumulator;
|
||||
adjustAccumulator = 0;
|
||||
scrollAccumulation += delta * adjust_step * (isPrecise ? 0.1 : 1);
|
||||
|
||||
var precision = Bindable.Precision;
|
||||
|
||||
while (Math.Abs(scrollAccumulation) > precision)
|
||||
{
|
||||
Volume += Math.Sign(scrollAccumulation) * precision;
|
||||
scrollAccumulation = scrollAccumulation < 0 ? Math.Min(0, scrollAccumulation + precision) : Math.Max(0, scrollAccumulation - precision);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnScroll(ScrollEvent e)
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Screens.Backgrounds;
|
||||
@ -181,12 +182,24 @@ namespace osu.Game.Screens.Edit
|
||||
LoadComponentAsync(currentScreen, screenContainer.Add);
|
||||
}
|
||||
|
||||
private double scrollAccumulation;
|
||||
|
||||
protected override bool OnScroll(ScrollEvent e)
|
||||
{
|
||||
if (e.ScrollDelta.X + e.ScrollDelta.Y > 0)
|
||||
scrollAccumulation += (e.ScrollDelta.X + e.ScrollDelta.Y) * (e.IsPrecise ? 0.1 : 1);
|
||||
|
||||
const int precision = 1;
|
||||
|
||||
while (Math.Abs(scrollAccumulation) > precision)
|
||||
{
|
||||
if (scrollAccumulation > 0)
|
||||
clock.SeekBackward(!clock.IsRunning);
|
||||
else
|
||||
clock.SeekForward(!clock.IsRunning);
|
||||
|
||||
scrollAccumulation = scrollAccumulation < 0 ? Math.Min(0, scrollAccumulation + precision) : Math.Max(0, scrollAccumulation - precision);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -310,9 +310,9 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
currentPlaceholder = placeholder;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.Update();
|
||||
base.UpdateAfterChildren();
|
||||
|
||||
var fadeStart = scrollContainer.Current + scrollContainer.DrawHeight;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user