Merge branch 'master' into non-concurrent-sample-playback

This commit is contained in:
smoogipoo
2021-02-12 17:22:15 +09:00
295 changed files with 7478 additions and 2398 deletions

View File

@ -918,15 +918,10 @@ namespace osu.Game.Screens.Select
}
}
protected class CarouselScrollContainer : OsuScrollContainer<DrawableCarouselItem>
protected class CarouselScrollContainer : UserTrackingScrollContainer<DrawableCarouselItem>
{
private bool rightMouseScrollBlocked;
/// <summary>
/// Whether the last scroll event was user triggered, directly on the scroll container.
/// </summary>
public bool UserScrolling { get; private set; }
public CarouselScrollContainer()
{
// size is determined by the carousel itself, due to not all content necessarily being loaded.
@ -936,18 +931,6 @@ namespace osu.Game.Screens.Select
Masking = false;
}
protected override void OnUserScroll(float value, bool animated = true, double? distanceDecay = default)
{
UserScrolling = true;
base.OnUserScroll(value, animated, distanceDecay);
}
public new void ScrollTo(float value, bool animated = true, double? distanceDecay = null)
{
UserScrolling = false;
base.ScrollTo(value, animated, distanceDecay);
}
protected override bool OnMouseDown(MouseDownEvent e)
{
if (e.Button == MouseButton.Right)

View File

@ -391,7 +391,7 @@ namespace osu.Game.Screens.Select
if (Precision.AlmostEquals(bpmMin, bpmMax))
return $"{bpmMin:0}";
return $"{bpmMin:0}-{bpmMax:0} (mostly {beatmap.ControlPointInfo.BPMMode:0})";
return $"{bpmMin:0}-{bpmMax:0} (mostly {60000 / beatmap.GetMostCommonBeatLength():0})";
}
private OsuSpriteText[] getMapper(BeatmapMetadata metadata)

View File

@ -13,6 +13,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
using osu.Framework.Utils;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osuTK;
using osuTK.Graphics;
@ -20,10 +21,6 @@ namespace osu.Game.Screens.Select.Carousel
{
public class CarouselHeader : Container
{
private Sample sampleHover;
private readonly Box hoverLayer;
public Container BorderContainer;
public readonly Bindable<CarouselItemState> State = new Bindable<CarouselItemState>(CarouselItemState.NotSelected);
@ -44,23 +41,11 @@ namespace osu.Game.Screens.Select.Carousel
Children = new Drawable[]
{
Content,
hoverLayer = new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
Blending = BlendingParameters.Additive,
},
new HoverLayer()
}
};
}
[BackgroundDependencyLoader]
private void load(AudioManager audio, OsuColour colours)
{
sampleHover = audio.Samples.Get($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}");
hoverLayer.Colour = colours.Blue.Opacity(0.1f);
}
protected override void LoadComplete()
{
base.LoadComplete();
@ -97,18 +82,50 @@ namespace osu.Game.Screens.Select.Carousel
}
}
protected override bool OnHover(HoverEvent e)
public class HoverLayer : HoverSampleDebounceComponent
{
sampleHover?.Play();
private Sample sampleHover;
hoverLayer.FadeIn(100, Easing.OutQuint);
return base.OnHover(e);
}
private Box box;
protected override void OnHoverLost(HoverLostEvent e)
{
hoverLayer.FadeOut(1000, Easing.OutQuint);
base.OnHoverLost(e);
public HoverLayer()
{
RelativeSizeAxes = Axes.Both;
}
[BackgroundDependencyLoader]
private void load(AudioManager audio, OsuColour colours)
{
InternalChild = box = new Box
{
Colour = colours.Blue.Opacity(0.1f),
Alpha = 0,
Blending = BlendingParameters.Additive,
RelativeSizeAxes = Axes.Both,
};
sampleHover = audio.Samples.Get("SongSelect/song-ping");
}
protected override bool OnHover(HoverEvent e)
{
box.FadeIn(100, Easing.OutQuint);
return base.OnHover(e);
}
protected override void OnHoverLost(HoverLostEvent e)
{
box.FadeOut(1000, Easing.OutQuint);
base.OnHoverLost(e);
}
public override void PlayHoverSample()
{
if (sampleHover == null) return;
sampleHover.Frequency.Value = 0.90 + RNG.NextDouble(0.2);
sampleHover.Play();
}
}
}
}

View File

@ -18,7 +18,6 @@ using System.Threading;
using osu.Framework.Threading;
using osu.Framework.Utils;
using osu.Game.Configuration;
using osu.Game.Overlays.Settings;
using osu.Game.Rulesets;
namespace osu.Game.Screens.Select.Details
@ -83,32 +82,22 @@ namespace osu.Game.Screens.Select.Details
mods.BindValueChanged(modsChanged, true);
}
private readonly List<ISettingsItem> references = new List<ISettingsItem>();
private ModSettingChangeTracker modSettingChangeTracker;
private ScheduledDelegate debouncedStatisticsUpdate;
private void modsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
{
// TODO: find a more permanent solution for this if/when it is needed in other components.
// this is generating drawables for the only purpose of storing bindable references.
foreach (var r in references)
r.Dispose();
modSettingChangeTracker?.Dispose();
references.Clear();
ScheduledDelegate debounce = null;
foreach (var mod in mods.NewValue.OfType<IApplicableToDifficulty>())
modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue);
modSettingChangeTracker.SettingChanged += m =>
{
foreach (var setting in mod.CreateSettingsControls().OfType<ISettingsItem>())
{
setting.SettingChanged += () =>
{
debounce?.Cancel();
debounce = Scheduler.AddDelayed(updateStatistics, 100);
};
if (!(m is IApplicableToDifficulty))
return;
references.Add(setting);
}
}
debouncedStatisticsUpdate?.Cancel();
debouncedStatisticsUpdate = Scheduler.AddDelayed(updateStatistics, 100);
};
updateStatistics();
}
@ -173,6 +162,7 @@ namespace osu.Game.Screens.Select.Details
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
modSettingChangeTracker?.Dispose();
starDifficultyCancellationSource?.Cancel();
}

View File

@ -28,19 +28,16 @@ namespace osu.Game.Screens.Select
private readonly List<OverlayContainer> overlays = new List<OverlayContainer>();
/// <param name="button">THe button to be added.</param>
/// <param name="button">The button to be added.</param>
/// <param name="overlay">The <see cref="OverlayContainer"/> to be toggled by this button.</param>
public void AddButton(FooterButton button, OverlayContainer overlay)
{
overlays.Add(overlay);
button.Action = () => showOverlay(overlay);
if (overlay != null)
{
overlays.Add(overlay);
button.Action = () => showOverlay(overlay);
}
AddButton(button);
}
/// <param name="button">Button to be added.</param>
public void AddButton(FooterButton button)
{
button.Hovered = updateModeLight;
button.HoverLost = updateModeLight;

View File

@ -1,82 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using Humanizer;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.OnlinePlay.Components;
namespace osu.Game.Screens.Select
{
public class MatchSongSelect : SongSelect, IOnlinePlaySubScreen
{
public Action<PlaylistItem> Selected;
public string ShortTitle => "song selection";
public override string Title => ShortTitle.Humanize();
public override bool AllowEditing => false;
[Resolved(typeof(Room), nameof(Room.Playlist))]
protected BindableList<PlaylistItem> Playlist { get; private set; }
[Resolved]
private BeatmapManager beatmaps { get; set; }
public MatchSongSelect()
{
Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING };
}
protected override BeatmapDetailArea CreateBeatmapDetailArea() => new MatchBeatmapDetailArea
{
CreateNewItem = createNewItem
};
protected override bool OnStart()
{
switch (Playlist.Count)
{
case 0:
createNewItem();
break;
case 1:
populateItemFromCurrent(Playlist.Single());
break;
}
this.Exit();
return true;
}
private void createNewItem()
{
PlaylistItem item = new PlaylistItem
{
ID = Playlist.Count == 0 ? 0 : Playlist.Max(p => p.ID) + 1
};
populateItemFromCurrent(item);
Playlist.Add(item);
}
private void populateItemFromCurrent(PlaylistItem item)
{
item.Beatmap.Value = Beatmap.Value.BeatmapInfo;
item.Ruleset.Value = Ruleset.Value;
item.RequiredMods.Clear();
item.RequiredMods.AddRange(Mods.Value.Select(m => m.CreateCopy()));
}
}
}

View File

@ -251,11 +251,7 @@ namespace osu.Game.Screens.Select
Children = new Drawable[]
{
BeatmapOptions = new BeatmapOptionsOverlay(),
ModSelect = new ModSelectOverlay
{
Origin = Anchor.BottomCentre,
Anchor = Anchor.BottomCentre,
}
ModSelect = CreateModSelectOverlay()
}
}
}
@ -267,9 +263,8 @@ namespace osu.Game.Screens.Select
if (Footer != null)
{
Footer.AddButton(new FooterButtonMods { Current = Mods }, ModSelect);
Footer.AddButton(new FooterButtonRandom { Action = triggerRandom });
Footer.AddButton(new FooterButtonOptions(), BeatmapOptions);
foreach (var (button, overlay) in CreateFooterButtons())
Footer.AddButton(button, overlay);
BeatmapOptions.AddButton(@"Manage", @"collections", FontAwesome.Solid.Book, colours.Green, () => manageCollectionsDialog?.Show());
BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.Solid.Trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo));
@ -305,6 +300,19 @@ namespace osu.Game.Screens.Select
}
}
/// <summary>
/// Creates the buttons to be displayed in the footer.
/// </summary>
/// <returns>A set of <see cref="FooterButton"/> and an optional <see cref="OverlayContainer"/> which the button opens when pressed.</returns>
protected virtual IEnumerable<(FooterButton, OverlayContainer)> CreateFooterButtons() => new (FooterButton, OverlayContainer)[]
{
(new FooterButtonMods { Current = Mods }, ModSelect),
(new FooterButtonRandom { Action = triggerRandom }, null),
(new FooterButtonOptions(), BeatmapOptions)
};
protected virtual ModSelectOverlay CreateModSelectOverlay() => new LocalPlayerModSelectOverlay();
protected virtual void ApplyFilterToCarousel(FilterCriteria criteria)
{
// if not the current screen, we want to get carousel in a good presentation state before displaying (resume or enter).