mirror of
https://github.com/ppy/osu.git
synced 2024-11-08 13:57:29 +08:00
Merge branch 'ppy:master' into improve_retry_behaviour
This commit is contained in:
commit
0b886a79f1
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
connectionPool = new DrawablePool<FollowPointConnection>(1, 200),
|
||||
connectionPool = new DrawablePool<FollowPointConnection>(10, 200),
|
||||
pointPool = new DrawablePool<FollowPoint>(50, 1000)
|
||||
};
|
||||
}
|
||||
|
@ -11,9 +11,11 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||
using osu.Game.Rulesets.Osu.Configuration;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
@ -112,21 +114,36 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuRulesetConfigManager config)
|
||||
private void load(OsuRulesetConfigManager config, IBeatmap beatmap)
|
||||
{
|
||||
config?.BindWith(OsuRulesetSetting.PlayfieldBorderStyle, playfieldBorder.PlayfieldBorderStyle);
|
||||
|
||||
RegisterPool<HitCircle, DrawableHitCircle>(10, 100);
|
||||
var osuBeatmap = (OsuBeatmap)beatmap;
|
||||
|
||||
RegisterPool<Slider, DrawableSlider>(10, 100);
|
||||
RegisterPool<SliderHeadCircle, DrawableSliderHead>(10, 100);
|
||||
RegisterPool<SliderTailCircle, DrawableSliderTail>(10, 100);
|
||||
RegisterPool<SliderTick, DrawableSliderTick>(10, 100);
|
||||
RegisterPool<SliderRepeat, DrawableSliderRepeat>(5, 50);
|
||||
RegisterPool<HitCircle, DrawableHitCircle>(20, 100);
|
||||
|
||||
// handle edge cases where a beatmap has a slider with many repeats.
|
||||
int maxRepeatsOnOneSlider = 0;
|
||||
int maxTicksOnOneSlider = 0;
|
||||
|
||||
if (osuBeatmap != null)
|
||||
{
|
||||
foreach (var slider in osuBeatmap.HitObjects.OfType<Slider>())
|
||||
{
|
||||
maxRepeatsOnOneSlider = Math.Max(maxRepeatsOnOneSlider, slider.RepeatCount);
|
||||
maxTicksOnOneSlider = Math.Max(maxTicksOnOneSlider, slider.NestedHitObjects.OfType<SliderTick>().Count());
|
||||
}
|
||||
}
|
||||
|
||||
RegisterPool<Slider, DrawableSlider>(20, 100);
|
||||
RegisterPool<SliderHeadCircle, DrawableSliderHead>(20, 100);
|
||||
RegisterPool<SliderTailCircle, DrawableSliderTail>(20, 100);
|
||||
RegisterPool<SliderTick, DrawableSliderTick>(Math.Max(maxTicksOnOneSlider, 20), Math.Max(maxTicksOnOneSlider, 200));
|
||||
RegisterPool<SliderRepeat, DrawableSliderRepeat>(Math.Max(maxRepeatsOnOneSlider, 20), Math.Max(maxRepeatsOnOneSlider, 200));
|
||||
|
||||
RegisterPool<Spinner, DrawableSpinner>(2, 20);
|
||||
RegisterPool<SpinnerTick, DrawableSpinnerTick>(10, 100);
|
||||
RegisterPool<SpinnerBonusTick, DrawableSpinnerBonusTick>(10, 100);
|
||||
RegisterPool<SpinnerTick, DrawableSpinnerTick>(10, 200);
|
||||
RegisterPool<SpinnerBonusTick, DrawableSpinnerBonusTick>(10, 200);
|
||||
}
|
||||
|
||||
protected override HitObjectLifetimeEntry CreateLifetimeEntry(HitObject hitObject) => new OsuHitObjectLifetimeEntry(hitObject);
|
||||
@ -173,7 +190,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
private readonly Action<DrawableOsuJudgement> onLoaded;
|
||||
|
||||
public DrawableJudgementPool(HitResult result, Action<DrawableOsuJudgement> onLoaded)
|
||||
: base(10)
|
||||
: base(20)
|
||||
{
|
||||
this.result = result;
|
||||
this.onLoaded = onLoaded;
|
||||
|
@ -56,8 +56,10 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
[Test]
|
||||
public void TestCreateNewBeatmap()
|
||||
{
|
||||
AddAssert("status is none", () => EditorBeatmap.BeatmapInfo.Status == BeatmapOnlineStatus.None);
|
||||
AddStep("save beatmap", () => Editor.Save());
|
||||
AddAssert("new beatmap in database", () => beatmapManager.QueryBeatmapSet(s => s.ID == currentBeatmapSetID)?.Value.DeletePending == false);
|
||||
AddAssert("status is modified", () => EditorBeatmap.BeatmapInfo.Status == BeatmapOnlineStatus.LocallyModified);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -208,6 +210,8 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
});
|
||||
AddAssert("created difficulty has no objects", () => EditorBeatmap.HitObjects.Count == 0);
|
||||
|
||||
AddAssert("status is modified", () => EditorBeatmap.BeatmapInfo.Status == BeatmapOnlineStatus.LocallyModified);
|
||||
|
||||
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName);
|
||||
AddStep("save beatmap", () => Editor.Save());
|
||||
AddAssert("new beatmap persisted", () =>
|
||||
@ -218,7 +222,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
return beatmap != null
|
||||
&& beatmap.DifficultyName == secondDifficultyName
|
||||
&& set != null
|
||||
&& set.PerformRead(s => s.Beatmaps.Count == 2 && s.Beatmaps.Any(b => b.DifficultyName == secondDifficultyName));
|
||||
&& set.PerformRead(s => s.Beatmaps.Count == 2 && s.Beatmaps.Any(b => b.DifficultyName == secondDifficultyName) && s.Beatmaps.All(b => s.Status == BeatmapOnlineStatus.LocallyModified));
|
||||
});
|
||||
}
|
||||
|
||||
@ -294,7 +298,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
AddAssert("approach rate correctly copied", () => EditorBeatmap.Difficulty.ApproachRate == 4);
|
||||
AddAssert("combo colours correctly copied", () => EditorBeatmap.BeatmapSkin.AsNonNull().ComboColours.Count == 2);
|
||||
|
||||
AddAssert("status not copied", () => EditorBeatmap.BeatmapInfo.Status == BeatmapOnlineStatus.None);
|
||||
AddAssert("status is modified", () => EditorBeatmap.BeatmapInfo.Status == BeatmapOnlineStatus.LocallyModified);
|
||||
AddAssert("online ID not copied", () => EditorBeatmap.BeatmapInfo.OnlineID == -1);
|
||||
|
||||
AddStep("save beatmap", () => Editor.Save());
|
||||
|
@ -105,5 +105,11 @@ namespace osu.Game.Audio
|
||||
/// Retrieves the audio track.
|
||||
/// </summary>
|
||||
protected abstract Track? GetTrack();
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
Track?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +121,8 @@ namespace osu.Game.Beatmaps
|
||||
OnlineID = -1;
|
||||
LastOnlineUpdate = null;
|
||||
OnlineMD5Hash = string.Empty;
|
||||
Status = BeatmapOnlineStatus.None;
|
||||
if (Status != BeatmapOnlineStatus.LocallyModified)
|
||||
Status = BeatmapOnlineStatus.None;
|
||||
}
|
||||
|
||||
#region Properties we may not want persisted (but also maybe no harm?)
|
||||
|
@ -313,9 +313,12 @@ namespace osu.Game.Beatmaps
|
||||
beatmapInfo.MD5Hash = stream.ComputeMD5Hash();
|
||||
beatmapInfo.Hash = stream.ComputeSHA2Hash();
|
||||
|
||||
beatmapInfo.Status = BeatmapOnlineStatus.LocallyModified;
|
||||
|
||||
AddFile(setInfo, stream, createBeatmapFilenameFromMetadata(beatmapInfo));
|
||||
|
||||
setInfo.Hash = beatmapImporter.ComputeHash(setInfo);
|
||||
setInfo.Status = BeatmapOnlineStatus.LocallyModified;
|
||||
|
||||
Realm.Write(r =>
|
||||
{
|
||||
|
@ -3,13 +3,23 @@
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System.ComponentModel;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
{
|
||||
public enum BeatmapOnlineStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a special status given when local changes are made via the editor.
|
||||
/// Once in this state, online status changes should be ignored unless the beatmap is reverted or submitted.
|
||||
/// </summary>
|
||||
[Description("Local")]
|
||||
[LocalisableDescription(typeof(SongSelectStrings), nameof(SongSelectStrings.LocallyModified))]
|
||||
LocallyModified = -4,
|
||||
|
||||
None = -3,
|
||||
|
||||
[LocalisableDescription(typeof(BeatmapsetsStrings), nameof(BeatmapsetsStrings.ShowStatusGraveyard))]
|
||||
|
@ -6,6 +6,7 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using osu.Framework.Development;
|
||||
@ -51,6 +52,9 @@ namespace osu.Game.Beatmaps
|
||||
/// <summary>
|
||||
/// Queue an update for a beatmap set.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This may happen during initial import, or at a later stage in response to a user action or server event.
|
||||
/// </remarks>
|
||||
/// <param name="beatmapSet">The beatmap set to update. Updates will be applied directly (so a transaction should be started if this instance is managed).</param>
|
||||
/// <param name="preferOnlineFetch">Whether metadata from an online source should be preferred. If <c>true</c>, the local cache will be skipped to ensure the freshest data state possible.</param>
|
||||
public void Update(BeatmapSetInfo beatmapSet, bool preferOnlineFetch)
|
||||
@ -89,21 +93,26 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
if (res != null)
|
||||
{
|
||||
beatmapInfo.Status = res.Status;
|
||||
|
||||
Debug.Assert(beatmapInfo.BeatmapSet != null);
|
||||
|
||||
beatmapInfo.BeatmapSet.Status = res.BeatmapSet?.Status ?? BeatmapOnlineStatus.None;
|
||||
beatmapInfo.BeatmapSet.OnlineID = res.OnlineBeatmapSetID;
|
||||
beatmapInfo.BeatmapSet.DateRanked = res.BeatmapSet?.Ranked;
|
||||
beatmapInfo.BeatmapSet.DateSubmitted = res.BeatmapSet?.Submitted;
|
||||
|
||||
beatmapInfo.OnlineID = res.OnlineID;
|
||||
beatmapInfo.OnlineMD5Hash = res.MD5Hash;
|
||||
beatmapInfo.LastOnlineUpdate = res.LastUpdated;
|
||||
|
||||
beatmapInfo.OnlineID = res.OnlineID;
|
||||
Debug.Assert(beatmapInfo.BeatmapSet != null);
|
||||
beatmapInfo.BeatmapSet.OnlineID = res.OnlineBeatmapSetID;
|
||||
|
||||
beatmapInfo.Metadata.Author.OnlineID = res.AuthorID;
|
||||
// Some metadata should only be applied if there's no local changes.
|
||||
if (shouldSaveOnlineMetadata(beatmapInfo))
|
||||
{
|
||||
beatmapInfo.Status = res.Status;
|
||||
beatmapInfo.Metadata.Author.OnlineID = res.AuthorID;
|
||||
}
|
||||
|
||||
if (beatmapInfo.BeatmapSet.Beatmaps.All(shouldSaveOnlineMetadata))
|
||||
{
|
||||
beatmapInfo.BeatmapSet.Status = res.BeatmapSet?.Status ?? BeatmapOnlineStatus.None;
|
||||
beatmapInfo.BeatmapSet.DateRanked = res.BeatmapSet?.Ranked;
|
||||
beatmapInfo.BeatmapSet.DateSubmitted = res.BeatmapSet?.Submitted;
|
||||
}
|
||||
|
||||
logForModel(set, $"Online retrieval mapped {beatmapInfo} to {res.OnlineBeatmapSetID} / {res.OnlineID}.");
|
||||
}
|
||||
@ -202,19 +211,26 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
var status = (BeatmapOnlineStatus)reader.GetByte(2);
|
||||
|
||||
beatmapInfo.Status = status;
|
||||
// Some metadata should only be applied if there's no local changes.
|
||||
if (shouldSaveOnlineMetadata(beatmapInfo))
|
||||
{
|
||||
beatmapInfo.Status = status;
|
||||
beatmapInfo.Metadata.Author.OnlineID = reader.GetInt32(3);
|
||||
}
|
||||
|
||||
Debug.Assert(beatmapInfo.BeatmapSet != null);
|
||||
|
||||
beatmapInfo.BeatmapSet.Status = status;
|
||||
beatmapInfo.BeatmapSet.OnlineID = reader.GetInt32(0);
|
||||
// TODO: DateSubmitted and DateRanked are not provided by local cache.
|
||||
beatmapInfo.OnlineID = reader.GetInt32(1);
|
||||
beatmapInfo.Metadata.Author.OnlineID = reader.GetInt32(3);
|
||||
|
||||
beatmapInfo.OnlineMD5Hash = reader.GetString(4);
|
||||
beatmapInfo.LastOnlineUpdate = reader.GetDateTimeOffset(5);
|
||||
|
||||
Debug.Assert(beatmapInfo.BeatmapSet != null);
|
||||
beatmapInfo.BeatmapSet.OnlineID = reader.GetInt32(0);
|
||||
|
||||
if (beatmapInfo.BeatmapSet.Beatmaps.All(shouldSaveOnlineMetadata))
|
||||
{
|
||||
beatmapInfo.BeatmapSet.Status = status;
|
||||
}
|
||||
|
||||
logForModel(set, $"Cached local retrieval for {beatmapInfo}.");
|
||||
return true;
|
||||
}
|
||||
@ -233,6 +249,12 @@ namespace osu.Game.Beatmaps
|
||||
private void logForModel(BeatmapSetInfo set, string message) =>
|
||||
RealmArchiveModelImporter<BeatmapSetInfo>.LogForModel(set, $"[{nameof(BeatmapUpdaterMetadataLookup)}] {message}");
|
||||
|
||||
/// <summary>
|
||||
/// Check whether the provided beatmap is in a state where online "ranked" status metadata should be saved against it.
|
||||
/// Handles the case where a user may have locally modified a beatmap in the editor and expects the local status to stick.
|
||||
/// </summary>
|
||||
private static bool shouldSaveOnlineMetadata(BeatmapInfo beatmapInfo) => beatmapInfo.MatchesOnlineVersion || beatmapInfo.Status != BeatmapOnlineStatus.LocallyModified;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
cacheDownloadRequest?.Dispose();
|
||||
|
@ -6,15 +6,18 @@ using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.LocalisationExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
public class BeatmapSetOnlineStatusPill : CircularContainer
|
||||
public class BeatmapSetOnlineStatusPill : CircularContainer, IHasTooltip
|
||||
{
|
||||
private BeatmapOnlineStatus status;
|
||||
|
||||
@ -96,5 +99,19 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
|
||||
background.Colour = OsuColour.ForBeatmapSetOnlineStatus(Status) ?? colourProvider?.Light1 ?? colours.GreySeaFoamLighter;
|
||||
}
|
||||
|
||||
public LocalisableString TooltipText
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (Status)
|
||||
{
|
||||
case BeatmapOnlineStatus.LocallyModified:
|
||||
return SongSelectStrings.LocallyModifiedTooltip;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +118,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons
|
||||
// another async load might have completed before this one.
|
||||
// if so, do not make any changes.
|
||||
if (loadedPreview != previewTrack)
|
||||
{
|
||||
loadedPreview.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
AddInternal(loadedPreview);
|
||||
toggleLoading(false);
|
||||
|
@ -137,6 +137,9 @@ namespace osu.Game.Graphics
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case BeatmapOnlineStatus.LocallyModified:
|
||||
return Color4.OrangeRed;
|
||||
|
||||
case BeatmapOnlineStatus.Ranked:
|
||||
case BeatmapOnlineStatus.Approved:
|
||||
return Color4Extensions.FromHex(@"b3ff66");
|
||||
|
24
osu.Game/Localisation/SongSelectStrings.cs
Normal file
24
osu.Game/Localisation/SongSelectStrings.cs
Normal file
@ -0,0 +1,24 @@
|
||||
// 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 osu.Framework.Localisation;
|
||||
|
||||
namespace osu.Game.Localisation
|
||||
{
|
||||
public static class SongSelectStrings
|
||||
{
|
||||
private const string prefix = @"osu.Game.Resources.Localisation.SongSelect";
|
||||
|
||||
/// <summary>
|
||||
/// "Local"
|
||||
/// </summary>
|
||||
public static LocalisableString LocallyModified => new TranslatableString(getKey(@"locally_modified"), @"Local");
|
||||
|
||||
/// <summary>
|
||||
/// "Has been locally modified"
|
||||
/// </summary>
|
||||
public static LocalisableString LocallyModifiedTooltip => new TranslatableString(getKey(@"locally_modified_tooltip"), @"Has been locally modified");
|
||||
|
||||
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||
}
|
||||
}
|
@ -147,7 +147,10 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
||||
{
|
||||
// beatmapset may have changed.
|
||||
if (Preview != preview)
|
||||
{
|
||||
preview?.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
AddInternal(preview);
|
||||
loading = false;
|
||||
|
Loading…
Reference in New Issue
Block a user