diff --git a/osu.Android.props b/osu.Android.props
index 215a9a8090..0f6e32d664 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -61,6 +61,6 @@
-
+
diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs
index 33f93cdb4a..406c0af28d 100644
--- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs
+++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs
@@ -15,6 +15,7 @@ using osu.Framework.Graphics.Sprites;
using osuTK.Graphics;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics.Textures;
+using osu.Game.Audio;
namespace osu.Game.Rulesets.Catch.Tests
{
@@ -92,7 +93,7 @@ namespace osu.Game.Rulesets.Catch.Tests
return null;
}
- public SampleChannel GetSample(string sampleName) =>
+ public SampleChannel GetSample(ISampleInfo sampleInfo) =>
throw new NotImplementedException();
public Texture GetTexture(string componentName) =>
diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs
index 971518909d..953763c95d 100644
--- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs
+++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs
@@ -58,7 +58,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
int spriteCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardSprite));
int animationCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardAnimation));
- int sampleCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardSample));
+ int sampleCount = background.Elements.Count(x => x.GetType() == typeof(StoryboardSampleInfo));
Assert.AreEqual(15, spriteCount);
Assert.AreEqual(1, animationCount);
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs
index 0b5978e3eb..6c003e62ec 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinnableDrawable.cs
@@ -10,6 +10,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Textures;
+using osu.Game.Audio;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Skinning;
@@ -253,7 +254,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public Texture GetTexture(string componentName) => throw new NotImplementedException();
- public SampleChannel GetSample(string sampleName) => throw new NotImplementedException();
+ public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException();
public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException();
}
@@ -264,7 +265,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public Texture GetTexture(string componentName) => throw new NotImplementedException();
- public SampleChannel GetSample(string sampleName) => throw new NotImplementedException();
+ public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException();
public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException();
}
@@ -275,7 +276,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public Texture GetTexture(string componentName) => throw new NotImplementedException();
- public SampleChannel GetSample(string sampleName) => throw new NotImplementedException();
+ public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException();
public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => throw new NotImplementedException();
}
diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs
index 17df9ccc7e..14c6ea5c8e 100644
--- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs
+++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs
@@ -121,7 +121,7 @@ namespace osu.Game.Beatmaps.Formats
var layer = parseLayer(split[2]);
var path = cleanFilename(split[3]);
var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100;
- storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume));
+ storyboard.GetLayer(layer).Add(new StoryboardSampleInfo(path, time, (int)volume));
break;
}
}
diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs
index 524a4742c0..f532302de2 100644
--- a/osu.Game/Graphics/ScreenshotManager.cs
+++ b/osu.Game/Graphics/ScreenshotManager.cs
@@ -22,7 +22,7 @@ using SixLabors.ImageSharp;
namespace osu.Game.Graphics
{
- public class ScreenshotManager : Container, IKeyBindingHandler, IHandleGlobalInput
+ public class ScreenshotManager : Container, IKeyBindingHandler, IHandleGlobalKeyboardInput
{
private readonly BindableBool cursorVisibility = new BindableBool(true);
diff --git a/osu.Game/Input/Bindings/GlobalActionContainer.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs
index b70072a222..bf758e21d9 100644
--- a/osu.Game/Input/Bindings/GlobalActionContainer.cs
+++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs
@@ -10,7 +10,7 @@ using osu.Framework.Input.Bindings;
namespace osu.Game.Input.Bindings
{
- public class GlobalActionContainer : DatabasedKeyBindingContainer, IHandleGlobalInput
+ public class GlobalActionContainer : DatabasedKeyBindingContainer, IHandleGlobalKeyboardInput
{
private readonly Drawable handler;
diff --git a/osu.Game/Input/IdleTracker.cs b/osu.Game/Input/IdleTracker.cs
index cbc446a126..39ccf9fe1c 100644
--- a/osu.Game/Input/IdleTracker.cs
+++ b/osu.Game/Input/IdleTracker.cs
@@ -12,7 +12,7 @@ namespace osu.Game.Input
///
/// Track whether the end-user is in an idle state, based on their last interaction with the game.
///
- public class IdleTracker : Component, IKeyBindingHandler, IHandleGlobalInput
+ public class IdleTracker : Component, IKeyBindingHandler, IHandleGlobalKeyboardInput
{
private readonly double timeToIdle;
diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs
index 8a6b52b7ee..919f8a2fa0 100644
--- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs
@@ -1,21 +1,22 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System.Linq;
+using System.Collections.Generic;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
+using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
+using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays.Direct;
using osu.Game.Users;
using osuTK;
namespace osu.Game.Overlays.Profile.Sections.Beatmaps
{
- public class PaginatedBeatmapContainer : PaginatedContainer
+ public class PaginatedBeatmapContainer : PaginatedContainer
{
private const float panel_padding = 10f;
private readonly BeatmapSetType type;
- private GetUserBeatmapsRequest request;
public PaginatedBeatmapContainer(BeatmapSetType type, Bindable user, string header, string missing = "None... yet.")
: base(user, header, missing)
@@ -27,40 +28,15 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
ItemsContainer.Spacing = new Vector2(panel_padding);
}
- protected override void ShowMore()
- {
- request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
- request.Success += sets => Schedule(() =>
+ protected override APIRequest> CreateRequest() =>
+ new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
+
+ protected override Drawable CreateDrawableItem(APIBeatmapSet model) => !model.OnlineBeatmapSetID.HasValue
+ ? null
+ : new DirectGridPanel(model.ToBeatmapSet(Rulesets))
{
- MoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0);
- MoreButton.IsLoading = false;
-
- if (!sets.Any() && VisiblePages == 1)
- {
- MissingText.Show();
- return;
- }
-
- foreach (var s in sets)
- {
- if (!s.OnlineBeatmapSetID.HasValue)
- continue;
-
- ItemsContainer.Add(new DirectGridPanel(s.ToBeatmapSet(Rulesets))
- {
- Anchor = Anchor.TopCentre,
- Origin = Anchor.TopCentre,
- });
- }
- });
-
- Api.Queue(request);
- }
-
- protected override void Dispose(bool isDisposing)
- {
- base.Dispose(isDisposing);
- request?.Cancel();
- }
+ Anchor = Anchor.TopCentre,
+ Origin = Anchor.TopCentre,
+ };
}
}
diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
index 23072f8d90..6e6d6272c7 100644
--- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
@@ -1,19 +1,19 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System.Linq;
+using System.Collections.Generic;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
+using osu.Game.Online.API.Requests.Responses;
using osu.Game.Users;
namespace osu.Game.Overlays.Profile.Sections.Historical
{
- public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer
+ public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer
{
- private GetUserMostPlayedBeatmapsRequest request;
-
public PaginatedMostPlayedBeatmapContainer(Bindable user)
: base(user, "Most Played Beatmaps", "No records. :(")
{
@@ -22,35 +22,10 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
ItemsContainer.Direction = FillDirection.Vertical;
}
- protected override void ShowMore()
- {
- request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage);
- request.Success += beatmaps => Schedule(() =>
- {
- MoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0);
- MoreButton.IsLoading = false;
+ protected override APIRequest> CreateRequest() =>
+ new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage);
- if (!beatmaps.Any() && VisiblePages == 1)
- {
- MissingText.Show();
- return;
- }
-
- MissingText.Hide();
-
- foreach (var beatmap in beatmaps)
- {
- ItemsContainer.Add(new DrawableMostPlayedBeatmap(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount));
- }
- });
-
- Api.Queue(request);
- }
-
- protected override void Dispose(bool isDisposing)
- {
- base.Dispose(isDisposing);
- request?.Cancel();
- }
+ protected override Drawable CreateDrawableItem(APIUserMostPlayedBeatmap model) =>
+ new DrawableMostPlayedBeatmap(model.GetBeatmapInfo(Rulesets), model.PlayCount);
}
}
diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs
index b459afcb49..bb221bd43a 100644
--- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs
@@ -11,22 +11,27 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Online.API;
using osu.Game.Rulesets;
using osu.Game.Users;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
namespace osu.Game.Overlays.Profile.Sections
{
- public abstract class PaginatedContainer : FillFlowContainer
+ public abstract class PaginatedContainer : FillFlowContainer
{
- protected readonly FillFlowContainer ItemsContainer;
- protected readonly ShowMoreButton MoreButton;
- protected readonly OsuSpriteText MissingText;
+ private readonly ShowMoreButton moreButton;
+ private readonly OsuSpriteText missingText;
+ private APIRequest> retrievalRequest;
+ private CancellationTokenSource loadCancellation;
+
+ [Resolved]
+ private IAPIProvider api { get; set; }
protected int VisiblePages;
protected int ItemsPerPage;
protected readonly Bindable User = new Bindable();
-
- protected IAPIProvider Api;
- protected APIRequest RetrievalRequest;
+ protected readonly FillFlowContainer ItemsContainer;
protected RulesetStore Rulesets;
protected PaginatedContainer(Bindable user, string header, string missing)
@@ -51,15 +56,15 @@ namespace osu.Game.Overlays.Profile.Sections
RelativeSizeAxes = Axes.X,
Spacing = new Vector2(0, 2),
},
- MoreButton = new ShowMoreButton
+ moreButton = new ShowMoreButton
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Alpha = 0,
Margin = new MarginPadding { Top = 10 },
- Action = ShowMore,
+ Action = showMore,
},
- MissingText = new OsuSpriteText
+ missingText = new OsuSpriteText
{
Font = OsuFont.GetFont(size: 15),
Text = missing,
@@ -69,9 +74,8 @@ namespace osu.Game.Overlays.Profile.Sections
}
[BackgroundDependencyLoader]
- private void load(IAPIProvider api, RulesetStore rulesets)
+ private void load(RulesetStore rulesets)
{
- Api = api;
Rulesets = rulesets;
User.ValueChanged += onUserChanged;
@@ -80,13 +84,54 @@ namespace osu.Game.Overlays.Profile.Sections
private void onUserChanged(ValueChangedEvent e)
{
+ loadCancellation?.Cancel();
+ retrievalRequest?.Cancel();
+
VisiblePages = 0;
ItemsContainer.Clear();
if (e.NewValue != null)
- ShowMore();
+ showMore();
}
- protected abstract void ShowMore();
+ private void showMore()
+ {
+ loadCancellation = new CancellationTokenSource();
+
+ retrievalRequest = CreateRequest();
+ retrievalRequest.Success += UpdateItems;
+
+ api.Queue(retrievalRequest);
+ }
+
+ protected virtual void UpdateItems(List items) => Schedule(() =>
+ {
+ if (!items.Any() && VisiblePages == 1)
+ {
+ moreButton.Hide();
+ moreButton.IsLoading = false;
+ missingText.Show();
+ return;
+ }
+
+ LoadComponentsAsync(items.Select(CreateDrawableItem).Where(d => d != null), drawables =>
+ {
+ missingText.Hide();
+ moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0);
+ moreButton.IsLoading = false;
+
+ ItemsContainer.AddRange(drawables);
+ }, loadCancellation.Token);
+ });
+
+ protected abstract APIRequest> CreateRequest();
+
+ protected abstract Drawable CreateDrawableItem(TModel model);
+
+ protected override void Dispose(bool isDisposing)
+ {
+ base.Dispose(isDisposing);
+ retrievalRequest?.Cancel();
+ }
}
}
diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
index 4a9ac6e5c7..853b9db0a7 100644
--- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
@@ -5,18 +5,18 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Online.API.Requests;
using osu.Game.Users;
using System;
-using System.Collections.Generic;
-using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
+using osu.Game.Online.API.Requests.Responses;
+using System.Collections.Generic;
+using osu.Game.Online.API;
namespace osu.Game.Overlays.Profile.Sections.Ranks
{
- public class PaginatedScoreContainer : PaginatedContainer
+ public class PaginatedScoreContainer : PaginatedContainer
{
private readonly bool includeWeight;
private readonly ScoreType type;
- private GetUserScoresRequest request;
public PaginatedScoreContainer(ScoreType type, Bindable user, string header, string missing, bool includeWeight = false)
: base(user, header, missing)
@@ -29,52 +29,27 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
ItemsContainer.Direction = FillDirection.Vertical;
}
- protected override void ShowMore()
+ protected override void UpdateItems(List items)
{
- request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
- request.Success += scores => Schedule(() =>
- {
- foreach (var s in scores)
- s.Ruleset = Rulesets.GetRuleset(s.RulesetID);
+ foreach (var item in items)
+ item.Ruleset = Rulesets.GetRuleset(item.RulesetID);
- if (!scores.Any() && VisiblePages == 1)
- {
- MoreButton.Hide();
- MoreButton.IsLoading = false;
- MissingText.Show();
- return;
- }
-
- IEnumerable drawableScores;
-
- switch (type)
- {
- default:
- drawableScores = scores.Select(score => new DrawablePerformanceScore(score, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null));
- break;
-
- case ScoreType.Recent:
- drawableScores = scores.Select(score => new DrawableTotalScore(score));
- break;
- }
-
- LoadComponentsAsync(drawableScores, s =>
- {
- MissingText.Hide();
- MoreButton.FadeTo(scores.Count == ItemsPerPage ? 1 : 0);
- MoreButton.IsLoading = false;
-
- ItemsContainer.AddRange(s);
- });
- });
-
- Api.Queue(request);
+ base.UpdateItems(items);
}
- protected override void Dispose(bool isDisposing)
+ protected override APIRequest> CreateRequest() =>
+ new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
+
+ protected override Drawable CreateDrawableItem(APILegacyScoreInfo model)
{
- base.Dispose(isDisposing);
- request?.Cancel();
+ switch (type)
+ {
+ default:
+ return new DrawablePerformanceScore(model, includeWeight ? Math.Pow(0.95, ItemsContainer.Count) : (double?)null);
+
+ case ScoreType.Recent:
+ return new DrawableTotalScore(model);
+ }
}
}
}
diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs
index f2a778a874..3f9d4dc93e 100644
--- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs
@@ -4,51 +4,24 @@
using osu.Framework.Graphics;
using osu.Game.Online.API.Requests;
using osu.Game.Users;
-using System.Linq;
using osu.Framework.Bindables;
using osu.Game.Online.API.Requests.Responses;
+using osu.Game.Online.API;
+using System.Collections.Generic;
namespace osu.Game.Overlays.Profile.Sections.Recent
{
- public class PaginatedRecentActivityContainer : PaginatedContainer
+ public class PaginatedRecentActivityContainer : PaginatedContainer
{
- private GetUserRecentActivitiesRequest request;
-
public PaginatedRecentActivityContainer(Bindable user, string header, string missing)
: base(user, header, missing)
{
ItemsPerPage = 5;
}
- protected override void ShowMore()
- {
- request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage);
- request.Success += activities => Schedule(() =>
- {
- MoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0);
- MoreButton.IsLoading = false;
+ protected override APIRequest> CreateRequest() =>
+ new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage);
- if (!activities.Any() && VisiblePages == 1)
- {
- MissingText.Show();
- return;
- }
-
- MissingText.Hide();
-
- foreach (APIRecentActivity activity in activities)
- {
- ItemsContainer.Add(new DrawableRecentActivity(activity));
- }
- });
-
- Api.Queue(request);
- }
-
- protected override void Dispose(bool isDisposing)
- {
- base.Dispose(isDisposing);
- request?.Cancel();
- }
+ protected override Drawable CreateDrawableItem(APIRecentActivity model) => new DrawableRecentActivity(model);
}
}
diff --git a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs
index 26235fa280..9cd3aac2cb 100644
--- a/osu.Game/Overlays/Volume/VolumeControlReceptor.cs
+++ b/osu.Game/Overlays/Volume/VolumeControlReceptor.cs
@@ -9,7 +9,7 @@ using osu.Game.Input.Bindings;
namespace osu.Game.Overlays.Volume
{
- public class VolumeControlReceptor : Container, IScrollBindingHandler, IHandleGlobalInput
+ public class VolumeControlReceptor : Container, IScrollBindingHandler, IHandleGlobalKeyboardInput
{
public Func ActionRequested;
public Func ScrollActionRequested;
diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs
index c7556dddd5..6072bb64ed 100644
--- a/osu.Game/Skinning/DefaultSkin.cs
+++ b/osu.Game/Skinning/DefaultSkin.cs
@@ -4,6 +4,7 @@
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures;
+using osu.Game.Audio;
namespace osu.Game.Skinning
{
@@ -19,6 +20,6 @@ namespace osu.Game.Skinning
public override Texture GetTexture(string componentName) => null;
- public override SampleChannel GetSample(string sampleName) => null;
+ public override SampleChannel GetSample(ISampleInfo sampleInfo) => null;
}
}
diff --git a/osu.Game/Skinning/ISkin.cs b/osu.Game/Skinning/ISkin.cs
index 0e67a1897c..4867aba0a9 100644
--- a/osu.Game/Skinning/ISkin.cs
+++ b/osu.Game/Skinning/ISkin.cs
@@ -5,6 +5,7 @@ using System;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures;
+using osu.Game.Audio;
namespace osu.Game.Skinning
{
@@ -17,7 +18,7 @@ namespace osu.Game.Skinning
Texture GetTexture(string componentName);
- SampleChannel GetSample(string sampleName);
+ SampleChannel GetSample(ISampleInfo sampleInfo);
TValue GetValue(Func query) where TConfiguration : SkinConfiguration;
}
diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs
index 37a3059160..570ba1ced7 100644
--- a/osu.Game/Skinning/LegacySkin.cs
+++ b/osu.Game/Skinning/LegacySkin.cs
@@ -17,6 +17,7 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.IO.Stores;
using osu.Framework.Text;
+using osu.Game.Audio;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
@@ -179,7 +180,22 @@ namespace osu.Game.Skinning
return texture;
}
- public override SampleChannel GetSample(string sampleName) => Samples.Get(getFallbackName(sampleName));
+ public override SampleChannel GetSample(ISampleInfo sampleInfo)
+ {
+ foreach (var lookup in sampleInfo.LookupNames)
+ {
+ var sample = Samples.Get(getFallbackName(lookup));
+
+ if (sample != null)
+ return sample;
+ }
+
+ if (sampleInfo is HitSampleInfo hsi)
+ // Try fallback to non-bank samples.
+ return Samples.Get(hsi.Name);
+
+ return null;
+ }
private bool hasFont(string fontName) => GetTexture($"{fontName}-0") != null;
diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs
index 7882e0f31b..fc36d1c8da 100644
--- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs
+++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs
@@ -8,6 +8,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Textures;
+using osu.Game.Audio;
using osu.Game.Configuration;
namespace osu.Game.Skinning
@@ -49,13 +50,13 @@ namespace osu.Game.Skinning
return fallbackSource.GetTexture(componentName);
}
- public SampleChannel GetSample(string sampleName)
+ public SampleChannel GetSample(ISampleInfo sampleInfo)
{
SampleChannel sourceChannel;
- if (beatmapHitsounds.Value && (sourceChannel = skin?.GetSample(sampleName)) != null)
+ if (beatmapHitsounds.Value && (sourceChannel = skin?.GetSample(sampleInfo)) != null)
return sourceChannel;
- return fallbackSource?.GetSample(sampleName);
+ return fallbackSource?.GetSample(sampleInfo);
}
public TValue GetValue(Func query) where TConfiguration : SkinConfiguration
diff --git a/osu.Game/Skinning/Skin.cs b/osu.Game/Skinning/Skin.cs
index 09c0d3d0bc..027d9df8b8 100644
--- a/osu.Game/Skinning/Skin.cs
+++ b/osu.Game/Skinning/Skin.cs
@@ -5,6 +5,7 @@ using System;
using osu.Framework.Audio.Sample;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures;
+using osu.Game.Audio;
namespace osu.Game.Skinning
{
@@ -16,7 +17,7 @@ namespace osu.Game.Skinning
public abstract Drawable GetDrawableComponent(string componentName);
- public abstract SampleChannel GetSample(string sampleName);
+ public abstract SampleChannel GetSample(ISampleInfo sampleInfo);
public abstract Texture GetTexture(string componentName);
diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs
index 19997e8844..e747a8b1ce 100644
--- a/osu.Game/Skinning/SkinManager.cs
+++ b/osu.Game/Skinning/SkinManager.cs
@@ -15,6 +15,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures;
using osu.Framework.Platform;
+using osu.Game.Audio;
using osu.Game.Database;
using osu.Game.IO.Archives;
@@ -120,7 +121,7 @@ namespace osu.Game.Skinning
public Texture GetTexture(string componentName) => CurrentSkin.Value.GetTexture(componentName);
- public SampleChannel GetSample(string sampleName) => CurrentSkin.Value.GetSample(sampleName);
+ public SampleChannel GetSample(ISampleInfo sampleInfo) => CurrentSkin.Value.GetSample(sampleInfo);
public TValue GetValue(Func query) where TConfiguration : SkinConfiguration => CurrentSkin.Value.GetValue(query);
}
diff --git a/osu.Game/Skinning/SkinnableSound.cs b/osu.Game/Skinning/SkinnableSound.cs
index 8e2b5cec98..dcb14b4412 100644
--- a/osu.Game/Skinning/SkinnableSound.cs
+++ b/osu.Game/Skinning/SkinnableSound.cs
@@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
@@ -37,34 +36,26 @@ namespace osu.Game.Skinning
public void Play() => channels?.ForEach(c => c.Play());
- public override bool IsPresent => false; // We don't need to receive updates.
+ public override bool IsPresent => Scheduler.HasPendingTasks;
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
channels = hitSamples.Select(s =>
{
- var ch = loadChannel(s, skin.GetSample);
+ var ch = skin.GetSample(s);
+
if (ch == null && allowFallback)
- ch = loadChannel(s, audio.Samples.Get);
+ foreach (var lookup in s.LookupNames)
+ if ((ch = audio.Samples.Get($"Gameplay/{lookup}")) != null)
+ break;
+
+ if (ch != null)
+ ch.Volume.Value = s.Volume / 100.0;
+
return ch;
}).Where(c => c != null).ToArray();
}
- private SampleChannel loadChannel(ISampleInfo info, Func getSampleFunction)
- {
- foreach (var lookup in info.LookupNames)
- {
- var ch = getSampleFunction($"Gameplay/{lookup}");
- if (ch == null)
- continue;
-
- ch.Volume.Value = info.Volume / 100.0;
- return ch;
- }
-
- return null;
- }
-
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs
index ffd238d4e1..b04f1d4518 100644
--- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs
+++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSample.cs
@@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System.IO;
using osu.Framework.Allocation;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
@@ -17,25 +16,24 @@ namespace osu.Game.Storyboards.Drawables
///
private const double allowable_late_start = 100;
- private readonly StoryboardSample sample;
+ private readonly StoryboardSampleInfo sampleInfo;
private SampleChannel channel;
public override bool RemoveWhenNotAlive => false;
- public DrawableStoryboardSample(StoryboardSample sample)
+ public DrawableStoryboardSample(StoryboardSampleInfo sampleInfo)
{
- this.sample = sample;
- LifetimeStart = sample.StartTime;
+ this.sampleInfo = sampleInfo;
+ LifetimeStart = sampleInfo.StartTime;
}
[BackgroundDependencyLoader]
private void load(IBindable beatmap)
{
- // Try first with the full name, then attempt with no path
- channel = beatmap.Value.Skin.GetSample(sample.Path) ?? beatmap.Value.Skin.GetSample(Path.ChangeExtension(sample.Path, null));
+ channel = beatmap.Value.Skin.GetSample(sampleInfo);
if (channel != null)
- channel.Volume.Value = sample.Volume / 100;
+ channel.Volume.Value = sampleInfo.Volume / 100.0;
}
protected override void Update()
@@ -43,27 +41,27 @@ namespace osu.Game.Storyboards.Drawables
base.Update();
// TODO: this logic will need to be consolidated with other game samples like hit sounds.
- if (Time.Current < sample.StartTime)
+ if (Time.Current < sampleInfo.StartTime)
{
// We've rewound before the start time of the sample
channel?.Stop();
// In the case that the user fast-forwards to a point far beyond the start time of the sample,
// we want to be able to fall into the if-conditional below (therefore we must not have a life time end)
- LifetimeStart = sample.StartTime;
+ LifetimeStart = sampleInfo.StartTime;
LifetimeEnd = double.MaxValue;
}
- else if (Time.Current - Time.Elapsed < sample.StartTime)
+ else if (Time.Current - Time.Elapsed < sampleInfo.StartTime)
{
// We've passed the start time of the sample. We only play the sample if we're within an allowable range
// from the sample's start, to reduce layering if we've been fast-forwarded far into the future
- if (Time.Current - sample.StartTime < allowable_late_start)
+ if (Time.Current - sampleInfo.StartTime < allowable_late_start)
channel?.Play();
// In the case that the user rewinds to a point far behind the start time of the sample,
// we want to be able to fall into the if-conditional above (therefore we must not have a life time start)
LifetimeStart = double.MinValue;
- LifetimeEnd = sample.StartTime;
+ LifetimeEnd = sampleInfo.StartTime;
}
}
}
diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs
index 24231cdca6..5d6ce215f5 100644
--- a/osu.Game/Storyboards/StoryboardSample.cs
+++ b/osu.Game/Storyboards/StoryboardSample.cs
@@ -1,21 +1,30 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System.Collections.Generic;
using osu.Framework.Graphics;
+using osu.Game.Audio;
using osu.Game.Storyboards.Drawables;
namespace osu.Game.Storyboards
{
- public class StoryboardSample : IStoryboardElement
+ public class StoryboardSampleInfo : IStoryboardElement, ISampleInfo
{
- public string Path { get; set; }
+ public string Path { get; }
public bool IsDrawable => true;
public double StartTime { get; }
- public float Volume;
+ public int Volume { get; }
- public StoryboardSample(string path, double time, float volume)
+ public IEnumerable LookupNames => new[]
+ {
+ // Try first with the full name, then attempt with no path
+ Path,
+ System.IO.Path.ChangeExtension(Path, null),
+ };
+
+ public StoryboardSampleInfo(string path, double time, int volume)
{
Path = path;
StartTime = time;
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 4fe9119cef..d791909372 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index 82301549d7..9fc472bf40 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -118,8 +118,8 @@
-
-
+
+