mirror of
https://github.com/ppy/osu
synced 2025-01-09 15:49:32 +00:00
Merge branch 'master' into async-beatmap-load
This commit is contained in:
commit
2fafe9a651
@ -13,6 +13,7 @@ using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Lists;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Threading;
|
||||
@ -159,6 +160,8 @@ namespace osu.Game.Beatmaps
|
||||
/// <param name="beatmap">The beatmap difficulty to restore.</param>
|
||||
public void Restore(BeatmapInfo beatmap) => beatmaps.Restore(beatmap);
|
||||
|
||||
private readonly WeakList<WorkingBeatmap> workingCache = new WeakList<WorkingBeatmap>();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a <see cref="WorkingBeatmap"/> instance for the provided <see cref="BeatmapInfo"/>
|
||||
/// </summary>
|
||||
@ -173,12 +176,18 @@ namespace osu.Game.Beatmaps
|
||||
if (beatmapInfo?.BeatmapSet == null || beatmapInfo == DefaultBeatmap?.BeatmapInfo)
|
||||
return DefaultBeatmap;
|
||||
|
||||
var cached = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == beatmapInfo.ID);
|
||||
|
||||
if (cached != null)
|
||||
return cached;
|
||||
|
||||
if (beatmapInfo.Metadata == null)
|
||||
beatmapInfo.Metadata = beatmapInfo.BeatmapSet.Metadata;
|
||||
|
||||
WorkingBeatmap working = new BeatmapManagerWorkingBeatmap(Files.Store, new LargeTextureStore(host?.CreateTextureLoaderStore(Files.Store)), beatmapInfo, audioManager);
|
||||
|
||||
previous?.TransferTo(working);
|
||||
workingCache.Add(working);
|
||||
|
||||
return working;
|
||||
}
|
||||
|
@ -51,6 +51,11 @@ namespace osu.Game.Beatmaps
|
||||
total_count.Value++;
|
||||
}
|
||||
|
||||
~WorkingBeatmap()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
protected virtual Track GetVirtualTrack()
|
||||
{
|
||||
const double excess_length = 1000;
|
||||
@ -248,7 +253,6 @@ namespace osu.Game.Beatmaps
|
||||
// cancelling the beatmap load is safe for now since the retrieval is a synchronous
|
||||
// operation. if we add an async retrieval method this may need to be reconsidered.
|
||||
beatmapCancellation.Cancel();
|
||||
|
||||
total_count.Value--;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Statistics;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
@ -31,11 +32,20 @@ namespace osu.Game.Database
|
||||
recycleThreadContexts();
|
||||
}
|
||||
|
||||
private static readonly GlobalStatistic<int> reads = GlobalStatistics.Get<int>("Database", "Get (Read)");
|
||||
private static readonly GlobalStatistic<int> writes = GlobalStatistics.Get<int>("Database", "Get (Write)");
|
||||
private static readonly GlobalStatistic<int> commits = GlobalStatistics.Get<int>("Database", "Commits");
|
||||
private static readonly GlobalStatistic<int> rollbacks = GlobalStatistics.Get<int>("Database", "Rollbacks");
|
||||
|
||||
/// <summary>
|
||||
/// Get a context for the current thread for read-only usage.
|
||||
/// If a <see cref="DatabaseWriteUsage"/> is in progress, the existing write-safe context will be returned.
|
||||
/// </summary>
|
||||
public OsuDbContext Get() => threadContexts.Value;
|
||||
public OsuDbContext Get()
|
||||
{
|
||||
reads.Value++;
|
||||
return threadContexts.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request a context for write usage. Can be consumed in a nested fashion (and will return the same underlying context).
|
||||
@ -45,6 +55,7 @@ namespace osu.Game.Database
|
||||
/// <returns>A usage containing a usable context.</returns>
|
||||
public DatabaseWriteUsage GetForWrite(bool withTransaction = true)
|
||||
{
|
||||
writes.Value++;
|
||||
Monitor.Enter(writeLock);
|
||||
OsuDbContext context;
|
||||
|
||||
@ -90,9 +101,15 @@ namespace osu.Game.Database
|
||||
if (usages == 0)
|
||||
{
|
||||
if (currentWriteDidError)
|
||||
{
|
||||
rollbacks.Value++;
|
||||
currentWriteTransaction?.Rollback();
|
||||
}
|
||||
else
|
||||
{
|
||||
commits.Value++;
|
||||
currentWriteTransaction?.Commit();
|
||||
}
|
||||
|
||||
if (currentWriteDidWrite || currentWriteDidError)
|
||||
{
|
||||
|
@ -6,6 +6,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Statistics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.IO;
|
||||
@ -34,6 +35,8 @@ namespace osu.Game.Database
|
||||
|
||||
private static readonly Lazy<OsuDbLoggerFactory> logger = new Lazy<OsuDbLoggerFactory>(() => new OsuDbLoggerFactory());
|
||||
|
||||
private static readonly GlobalStatistic<int> contexts = GlobalStatistics.Get<int>("Database", "Contexts");
|
||||
|
||||
static OsuDbContext()
|
||||
{
|
||||
// required to initialise native SQLite libraries on some platforms.
|
||||
@ -76,6 +79,8 @@ namespace osu.Game.Database
|
||||
connection.Close();
|
||||
throw;
|
||||
}
|
||||
|
||||
contexts.Value++;
|
||||
}
|
||||
|
||||
~OsuDbContext()
|
||||
@ -85,6 +90,20 @@ namespace osu.Game.Database
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private bool isDisposed;
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (isDisposed) return;
|
||||
|
||||
isDisposed = true;
|
||||
|
||||
base.Dispose();
|
||||
|
||||
contexts.Value--;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
|
@ -6,23 +6,28 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Graphics.Backgrounds
|
||||
{
|
||||
public class Background : BufferedContainer
|
||||
/// <summary>
|
||||
/// A background which offers blurring via a <see cref="BufferedContainer"/> on demand.
|
||||
/// </summary>
|
||||
public class Background : CompositeDrawable
|
||||
{
|
||||
public Sprite Sprite;
|
||||
|
||||
private readonly string textureName;
|
||||
|
||||
private BufferedContainer bufferedContainer;
|
||||
|
||||
public Background(string textureName = @"")
|
||||
{
|
||||
CacheDrawnFrameBuffer = true;
|
||||
|
||||
this.textureName = textureName;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
Add(Sprite = new Sprite
|
||||
AddInternal(Sprite = new Sprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
@ -37,5 +42,28 @@ namespace osu.Game.Graphics.Backgrounds
|
||||
if (!string.IsNullOrEmpty(textureName))
|
||||
Sprite.Texture = textures.Get(textureName);
|
||||
}
|
||||
|
||||
public Vector2 BlurSigma => bufferedContainer?.BlurSigma ?? Vector2.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// Smoothly adjusts <see cref="IBufferedContainer.BlurSigma"/> over time.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
|
||||
public void BlurTo(Vector2 newBlurSigma, double duration = 0, Easing easing = Easing.None)
|
||||
{
|
||||
if (bufferedContainer == null)
|
||||
{
|
||||
RemoveInternal(Sprite);
|
||||
|
||||
AddInternal(bufferedContainer = new BufferedContainer
|
||||
{
|
||||
CacheDrawnFrameBuffer = true,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = Sprite
|
||||
});
|
||||
}
|
||||
|
||||
bufferedContainer.BlurTo(newBlurSigma, duration, easing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,24 +66,64 @@ namespace osu.Game.Overlays
|
||||
}
|
||||
};
|
||||
|
||||
Header.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch);
|
||||
Header.Tabs.Current.ValueChanged += _ => queueUpdate();
|
||||
|
||||
Filter.Tabs.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch);
|
||||
Filter.Tabs.Current.ValueChanged += _ => queueUpdate();
|
||||
|
||||
Filter.DisplayStyleControl.DisplayStyle.ValueChanged += style => recreatePanels(style.NewValue);
|
||||
Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => Scheduler.AddOnce(updateSearch);
|
||||
Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += _ => queueUpdate();
|
||||
|
||||
currentQuery.BindTo(Filter.Search.Current);
|
||||
currentQuery.ValueChanged += query =>
|
||||
{
|
||||
queryChangedDebounce?.Cancel();
|
||||
|
||||
if (string.IsNullOrEmpty(query.NewValue))
|
||||
Scheduler.AddOnce(updateSearch);
|
||||
queueUpdate();
|
||||
else
|
||||
queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500);
|
||||
};
|
||||
}
|
||||
|
||||
currentQuery.BindTo(Filter.Search.Current);
|
||||
private APIRequest getUsersRequest;
|
||||
|
||||
private readonly Bindable<string> currentQuery = new Bindable<string>();
|
||||
|
||||
private ScheduledDelegate queryChangedDebounce;
|
||||
|
||||
private void queueUpdate() => Scheduler.AddOnce(updateSearch);
|
||||
|
||||
private void updateSearch()
|
||||
{
|
||||
queryChangedDebounce?.Cancel();
|
||||
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
Users = null;
|
||||
clearPanels();
|
||||
loading.Hide();
|
||||
getUsersRequest?.Cancel();
|
||||
|
||||
if (API?.IsLoggedIn != true)
|
||||
return;
|
||||
|
||||
switch (Header.Tabs.Current.Value)
|
||||
{
|
||||
case SocialTab.Friends:
|
||||
var friendRequest = new GetFriendsRequest(); // TODO filter arguments?
|
||||
friendRequest.Success += updateUsers;
|
||||
API.Queue(getUsersRequest = friendRequest);
|
||||
break;
|
||||
|
||||
default:
|
||||
var userRequest = new GetUsersRequest(); // TODO filter arguments!
|
||||
userRequest.Success += response => updateUsers(response.Select(r => r.User));
|
||||
API.Queue(getUsersRequest = userRequest);
|
||||
break;
|
||||
}
|
||||
|
||||
loading.Show();
|
||||
}
|
||||
|
||||
private void recreatePanels(PanelDisplayStyle displayStyle)
|
||||
@ -133,45 +173,6 @@ namespace osu.Game.Overlays
|
||||
});
|
||||
}
|
||||
|
||||
private APIRequest getUsersRequest;
|
||||
|
||||
private readonly Bindable<string> currentQuery = new Bindable<string>();
|
||||
|
||||
private ScheduledDelegate queryChangedDebounce;
|
||||
|
||||
private void updateSearch()
|
||||
{
|
||||
queryChangedDebounce?.Cancel();
|
||||
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
Users = null;
|
||||
clearPanels();
|
||||
loading.Hide();
|
||||
getUsersRequest?.Cancel();
|
||||
|
||||
if (API?.IsLoggedIn != true)
|
||||
return;
|
||||
|
||||
switch (Header.Tabs.Current.Value)
|
||||
{
|
||||
case SocialTab.Friends:
|
||||
var friendRequest = new GetFriendsRequest(); // TODO filter arguments?
|
||||
friendRequest.Success += updateUsers;
|
||||
API.Queue(getUsersRequest = friendRequest);
|
||||
break;
|
||||
|
||||
default:
|
||||
var userRequest = new GetUsersRequest(); // TODO filter arguments!
|
||||
userRequest.Success += response => updateUsers(response.Select(r => r.User));
|
||||
API.Queue(getUsersRequest = userRequest);
|
||||
break;
|
||||
}
|
||||
|
||||
loading.Show();
|
||||
}
|
||||
|
||||
private void updateUsers(IEnumerable<User> newUsers)
|
||||
{
|
||||
Users = newUsers;
|
||||
@ -193,7 +194,7 @@ namespace osu.Game.Overlays
|
||||
switch (state)
|
||||
{
|
||||
case APIState.Online:
|
||||
Scheduler.AddOnce(updateSearch);
|
||||
queueUpdate();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Screens.Backgrounds
|
||||
private Background background;
|
||||
|
||||
private int currentDisplay;
|
||||
private const int background_count = 5;
|
||||
private const int background_count = 7;
|
||||
|
||||
private string backgroundName => $@"Menu/menu-background-{currentDisplay % background_count + 1}";
|
||||
|
||||
|
@ -86,6 +86,7 @@ namespace osu.Game.Screens.Menu
|
||||
if (!resuming)
|
||||
{
|
||||
Beatmap.Value = introBeatmap;
|
||||
introBeatmap = null;
|
||||
|
||||
if (menuVoice.Value)
|
||||
welcome.Play();
|
||||
@ -94,7 +95,10 @@ namespace osu.Game.Screens.Menu
|
||||
{
|
||||
// Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu.
|
||||
if (menuMusic.Value)
|
||||
{
|
||||
track.Start();
|
||||
track = null;
|
||||
}
|
||||
|
||||
LoadComponentAsync(mainMenu = new MainMenu());
|
||||
|
||||
|
@ -96,13 +96,13 @@ namespace osu.Game.Screens.Menu
|
||||
var track = beatmap.Value.TrackLoaded ? beatmap.Value.Track : null;
|
||||
var effect = beatmap.Value.BeatmapLoaded ? beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? Time.Current) : null;
|
||||
|
||||
float[] temporalAmplitudes = track?.CurrentAmplitudes.FrequencyAmplitudes ?? new float[256];
|
||||
float[] temporalAmplitudes = track?.CurrentAmplitudes.FrequencyAmplitudes;
|
||||
|
||||
for (int i = 0; i < bars_per_visualiser; i++)
|
||||
{
|
||||
if (track?.IsRunning ?? false)
|
||||
{
|
||||
float targetAmplitude = temporalAmplitudes[(i + indexOffset) % bars_per_visualiser] * (effect?.KiaiMode == true ? 1 : 0.5f);
|
||||
float targetAmplitude = (temporalAmplitudes?[(i + indexOffset) % bars_per_visualiser] ?? 0) * (effect?.KiaiMode == true ? 1 : 0.5f);
|
||||
if (targetAmplitude > frequencyAmplitudes[i])
|
||||
frequencyAmplitudes[i] = targetAmplitude;
|
||||
}
|
||||
@ -115,7 +115,6 @@ namespace osu.Game.Screens.Menu
|
||||
}
|
||||
|
||||
indexOffset = (indexOffset + index_change) % bars_per_visualiser;
|
||||
Scheduler.AddDelayed(updateAmplitudes, time_between_updates);
|
||||
}
|
||||
|
||||
private void updateColour()
|
||||
@ -131,7 +130,8 @@ namespace osu.Game.Screens.Menu
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateAmplitudes();
|
||||
|
||||
Scheduler.AddDelayed(updateAmplitudes, time_between_updates, true);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
|
@ -14,7 +14,7 @@
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.4" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.701.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2019.702.0" />
|
||||
<PackageReference Include="SharpCompress" Version="0.23.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
|
@ -104,7 +104,7 @@
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.701.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2019.702.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.702.0" />
|
||||
<PackageReference Include="SharpCompress" Version="0.22.0" />
|
||||
|
Loading…
Reference in New Issue
Block a user