1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-07 06:23:39 +08:00

Merge branch 'master' into base-s-v

This commit is contained in:
Dean Herbert
2023-05-09 20:52:11 +09:00
Unverified
30 changed files with 87 additions and 73 deletions
@@ -1,8 +1,6 @@
// 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.
#nullable disable
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
@@ -40,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Tests
private const double time_tail = 4000;
private const double time_after_tail = 5250;
private List<JudgementResult> judgementResults;
private List<JudgementResult> judgementResults = new List<JudgementResult>();
/// <summary>
/// -----[ ]-----
@@ -61,6 +59,44 @@ namespace osu.Game.Rulesets.Mania.Tests
assertNoteJudgement(HitResult.IgnoreMiss);
}
/// <summary>
/// -----[ ]-----
/// x o
/// </summary>
[Test]
public void TestCorrectInput()
{
performTest(new List<ReplayFrame>
{
new ManiaReplayFrame(time_head, ManiaAction.Key1),
new ManiaReplayFrame(time_tail),
});
assertHeadJudgement(HitResult.Perfect);
assertTickJudgement(HitResult.LargeTickHit);
assertTailJudgement(HitResult.Perfect);
assertNoteJudgement(HitResult.IgnoreHit);
}
/// <summary>
/// -----[ ]-----
/// x o
/// </summary>
[Test]
public void TestLateRelease()
{
performTest(new List<ReplayFrame>
{
new ManiaReplayFrame(time_head, ManiaAction.Key1),
new ManiaReplayFrame(time_after_tail),
});
assertHeadJudgement(HitResult.Perfect);
assertTickJudgement(HitResult.LargeTickHit);
assertTailJudgement(HitResult.Miss);
assertNoteJudgement(HitResult.IgnoreMiss);
}
/// <summary>
/// -----[ ]-----
/// x o
@@ -521,9 +557,9 @@ namespace osu.Game.Rulesets.Mania.Tests
private void assertLastTickJudgement(HitResult result)
=> AddAssert($"last tick judged as {result}", () => judgementResults.Last(j => j.HitObject is HoldNoteTick).Type, () => Is.EqualTo(result));
private ScoreAccessibleReplayPlayer currentPlayer;
private ScoreAccessibleReplayPlayer currentPlayer = null!;
private void performTest(List<ReplayFrame> frames, Beatmap<ManiaHitObject> beatmap = null)
private void performTest(List<ReplayFrame> frames, Beatmap<ManiaHitObject>? beatmap = null)
{
if (beatmap == null)
{
@@ -569,15 +605,13 @@ namespace osu.Game.Rulesets.Mania.Tests
AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0);
AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen());
AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor?.HasCompleted.Value == true);
AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value);
}
private partial class ScoreAccessibleReplayPlayer : ReplayPlayer
{
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
protected override bool PauseOnFocusLost => false;
public ScoreAccessibleReplayPlayer(Score score)
@@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Setup
specialStyle = new LabelledSwitchButton
{
Label = "Use special (N+1) style",
Description = "Changes one column to act as a classic \"scratch\" or \"special\" column, which can be moved around by the user's skin (to the left/right/centre). Generally used in 5k (4+1) or 8key (7+1) configurations.",
Description = "Changes one column to act as a classic \"scratch\" or \"special\" column, which can be moved around by the user's skin (to the left/right/centre). Generally used in 6K (5+1) or 8K (7+1) configurations.",
Current = { Value = Beatmap.BeatmapInfo.SpecialStyle }
}
};
@@ -3,7 +3,6 @@
#nullable disable
using System;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -219,6 +218,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
if (Time.Current < releaseTime)
releaseTime = null;
if (Time.Current < HoldStartTime)
endHold();
// Pad the full size container so its contents (i.e. the masking container) reach under the tail.
// This is required for the tail to not be masked away, since it lies outside the bounds of the hold note.
sizingContainer.Padding = new MarginPadding
@@ -245,9 +247,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
// 2. The head note will move along with the new "head position" in the container.
if (Head.IsHit && releaseTime == null && DrawHeight > 0)
{
// How far past the hit target this hold note is. Always a positive value.
float yOffset = Math.Max(0, Direction.Value == ScrollingDirection.Up ? -Y : Y);
sizingContainer.Height = Math.Clamp(1 - yOffset / DrawHeight, 0, 1);
// How far past the hit target this hold note is.
float yOffset = Direction.Value == ScrollingDirection.Up ? -Y : Y;
sizingContainer.Height = 1 - yOffset / DrawHeight;
}
}
@@ -322,14 +324,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
if (e.Action != Action.Value)
return;
// do not run any of this logic when rewinding, as it inverts order of presses/releases.
if (Time.Elapsed < 0)
return;
// Make sure a hold was started
if (HoldStartTime == null)
return;
// do not run any of this logic when rewinding, as it inverts order of presses/releases.
if (Time.Elapsed < 0)
return;
Tail.UpdateResult();
endHold();
@@ -1,8 +1,6 @@
// 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.
#nullable disable
using System;
using System.Linq;
using System.Net;
@@ -20,7 +18,7 @@ namespace osu.Game.Tests.Visual.Online
{
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
private WikiOverlay wiki;
private WikiOverlay wiki = null!;
[SetUp]
public void SetUp() => Schedule(() => Child = wiki = new WikiOverlay());
@@ -29,13 +27,13 @@ namespace osu.Game.Tests.Visual.Online
public void TestMainPage()
{
setUpWikiResponse(responseMainPage);
AddStep("Show main page", () => wiki.Show());
AddStep("Show main page", () => wiki.ShowPage());
}
[Test]
public void TestCancellationDoesntShowError()
{
AddStep("Show main page", () => wiki.Show());
AddStep("Show main page", () => wiki.ShowPage());
AddStep("Show another page", () => wiki.ShowPage("Article_styling_criteria/Formatting"));
AddUntilStep("Current path is not error", () => wiki.CurrentPath != "error");
@@ -73,7 +71,23 @@ namespace osu.Game.Tests.Visual.Online
AddUntilStep("Error message correct", () => wiki.ChildrenOfType<SpriteText>().Any(text => text.Text == "\"This_page_will_error_out\"."));
}
private void setUpWikiResponse(APIWikiPage r, string redirectionPath = null)
[Test]
public void TestReturnAfterErrorPage()
{
setUpWikiResponse(responseArticlePage);
AddStep("Show article page", () => wiki.ShowPage("Article_styling_criteria/Formatting"));
AddUntilStep("Wait for non-error page", () => wiki.CurrentPath == "Article_styling_criteria/Formatting");
AddStep("Show nonexistent page", () => wiki.ShowPage("This_page_will_error_out"));
AddUntilStep("Wait for error page", () => wiki.CurrentPath == "error");
AddStep("Show article page", () => wiki.ShowPage("Article_styling_criteria/Formatting"));
AddUntilStep("Wait for non-error page", () => wiki.CurrentPath == "Article_styling_criteria/Formatting");
AddUntilStep("Error message not displayed", () => wiki.ChildrenOfType<SpriteText>().All(text => text.Text != "\"This_page_will_error_out\"."));
}
private void setUpWikiResponse(APIWikiPage r, string? redirectionPath = null)
=> AddStep("set up response", () =>
{
dummyAPI.HandleRequest = request =>
+4 -1
View File
@@ -107,9 +107,12 @@ namespace osu.Game.Beatmaps
// Aggregate durations into a set of (beatLength, duration) tuples for each beat length
.GroupBy(t => Math.Round(t.beatLength * 1000) / 1000)
.Select(g => (beatLength: g.Key, duration: g.Sum(t => t.duration)))
// Get the most common one, or 0 as a suitable default
// Get the most common one, or 0 as a suitable default (see handling below)
.OrderByDescending(i => i.duration).FirstOrDefault();
if (mostCommon.beatLength == 0)
return TimingControlPoint.DEFAULT_BEAT_LENGTH;
return mostCommon.beatLength;
}
-2
View File
@@ -1,12 +1,10 @@
// 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.Testing;
using Realms;
namespace osu.Game.Beatmaps
{
[ExcludeFromDynamicCompile]
[MapTo("BeatmapDifficulty")]
public class BeatmapDifficulty : EmbeddedObject, IBeatmapDifficultyInfo
{
-2
View File
@@ -12,7 +12,6 @@ using osu.Framework.Extensions;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Game.Beatmaps.Formats;
using osu.Game.Collections;
using osu.Game.Database;
@@ -28,7 +27,6 @@ namespace osu.Game.Beatmaps
/// <summary>
/// Handles the storage and retrieval of Beatmaps/WorkingBeatmaps.
/// </summary>
[ExcludeFromDynamicCompile]
public class BeatmapImporter : RealmArchiveModelImporter<BeatmapSetInfo>
{
public override IEnumerable<string> HandledExtensions => new[] { ".osz" };
-2
View File
@@ -6,7 +6,6 @@ using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
using osu.Framework.Testing;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Collections;
using osu.Game.Database;
@@ -27,7 +26,6 @@ namespace osu.Game.Beatmaps
/// <remarks>
/// There are some legacy fields in this model which are not persisted to realm. These are isolated in a code region within the class and should eventually be migrated to `Beatmap`.
/// </remarks>
[ExcludeFromDynamicCompile]
[Serializable]
[MapTo("Beatmap")]
public class BeatmapInfo : RealmObject, IHasGuidPrimaryKey, IBeatmapInfo, IEquatable<BeatmapInfo>
-2
View File
@@ -15,7 +15,6 @@ using osu.Framework.Audio.Track;
using osu.Framework.Extensions;
using osu.Framework.IO.Stores;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Game.Beatmaps.Formats;
using osu.Game.Database;
using osu.Game.Extensions;
@@ -33,7 +32,6 @@ namespace osu.Game.Beatmaps
/// <summary>
/// Handles general operations related to global beatmap management.
/// </summary>
[ExcludeFromDynamicCompile]
public class BeatmapManager : ModelManager<BeatmapSetInfo>, IModelImporter<BeatmapSetInfo>, IWorkingBeatmapCache
{
public ITrackStore BeatmapTrackStore { get; }
-2
View File
@@ -4,7 +4,6 @@
using System;
using JetBrains.Annotations;
using Newtonsoft.Json;
using osu.Framework.Testing;
using osu.Game.Models;
using osu.Game.Users;
using osu.Game.Utils;
@@ -23,7 +22,6 @@ namespace osu.Game.Beatmaps
///
/// Note that difficulty name is not stored in this metadata but in <see cref="BeatmapInfo"/>.
/// </remarks>
[ExcludeFromDynamicCompile]
[Serializable]
[MapTo("BeatmapMetadata")]
public class BeatmapMetadata : RealmObject, IBeatmapMetadataInfo, IDeepCloneable<BeatmapMetadata>
-2
View File
@@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.Models;
@@ -17,7 +16,6 @@ namespace osu.Game.Beatmaps
/// <summary>
/// A realm model containing metadata for a beatmap set (containing multiple <see cref="BeatmapInfo"/>s).
/// </summary>
[ExcludeFromDynamicCompile]
[MapTo("BeatmapSet")]
public class BeatmapSetInfo : RealmObject, IHasGuidPrimaryKey, IHasRealmFiles, ISoftDelete, IEquatable<BeatmapSetInfo>, IBeatmapSetInfo
{
@@ -13,7 +13,6 @@ using osu.Framework.Development;
using osu.Framework.IO.Network;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
@@ -30,7 +29,6 @@ namespace osu.Game.Beatmaps
/// On creating the component, a copy of a database containing metadata for a large subset of beatmaps (stored to <see cref="cache_database_name"/>) will be downloaded if not already present locally.
/// This will always be checked before doing a second online query to get required metadata.
/// </remarks>
[ExcludeFromDynamicCompile]
public class BeatmapUpdaterMetadataLookup : IDisposable
{
private readonly IAPIProvider api;
-2
View File
@@ -16,7 +16,6 @@ using osu.Framework.Audio.Track;
using osu.Framework.Extensions;
using osu.Framework.Graphics.Textures;
using osu.Framework.Logging;
using osu.Framework.Testing;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI;
@@ -25,7 +24,6 @@ using osu.Game.Storyboards;
namespace osu.Game.Beatmaps
{
[ExcludeFromDynamicCompile]
public abstract class WorkingBeatmap : IWorkingBeatmap
{
public readonly BeatmapInfo BeatmapInfo;
-2
View File
@@ -17,7 +17,6 @@ using osu.Framework.Lists;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Framework.Statistics;
using osu.Framework.Testing;
using osu.Game.Beatmaps.Formats;
using osu.Game.Database;
using osu.Game.IO;
@@ -121,7 +120,6 @@ namespace osu.Game.Beatmaps
#endregion
[ExcludeFromDynamicCompile]
private class BeatmapManagerWorkingBeatmap : WorkingBeatmap
{
[NotNull]
@@ -4,11 +4,9 @@
#nullable disable
using osu.Framework.Platform;
using osu.Framework.Testing;
namespace osu.Game.Configuration
{
[ExcludeFromDynamicCompile]
public class DevelopmentOsuConfigManager : OsuConfigManager
{
protected override string Filename => base.Filename.Replace(".ini", ".dev.ini");
@@ -12,7 +12,6 @@ using osu.Framework.Extensions;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Localisation;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Game.Beatmaps.Drawables.Cards;
using osu.Game.Input;
using osu.Game.Input.Bindings;
@@ -26,7 +25,6 @@ using osu.Game.Skinning;
namespace osu.Game.Configuration
{
[ExcludeFromDynamicCompile]
public class OsuConfigManager : IniConfigManager<OsuSetting>, IGameplaySettings
{
public OsuConfigManager(Storage storage)
-2
View File
@@ -8,7 +8,6 @@ using osu.Framework.Extensions;
using osu.Framework.IO.Stores;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Game.Extensions;
using osu.Game.IO;
using osu.Game.Models;
@@ -19,7 +18,6 @@ namespace osu.Game.Database
/// <summary>
/// Handles the storing of files to the file system (and database) backing.
/// </summary>
[ExcludeFromDynamicCompile]
public class RealmFileStore
{
private readonly RealmAccess realm;
-2
View File
@@ -1,13 +1,11 @@
// 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.Testing;
using osu.Game.IO;
using Realms;
namespace osu.Game.Models
{
[ExcludeFromDynamicCompile]
[MapTo("File")]
public class RealmFile : RealmObject, IFileInfo
{
-2
View File
@@ -3,14 +3,12 @@
using System;
using JetBrains.Annotations;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.IO;
using Realms;
namespace osu.Game.Models
{
[ExcludeFromDynamicCompile]
public class RealmNamedFileUsage : EmbeddedObject, INamedFile, INamedFileUsage
{
public RealmFile File { get; set; } = null!;
@@ -10,12 +10,10 @@ using osu.Game.Graphics.Sprites;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Localisation;
using osu.Framework.Testing;
using osu.Game.Graphics;
namespace osu.Game.Overlays.Settings
{
[ExcludeFromDynamicCompile]
public abstract partial class SettingsSubsection : FillFlowContainer, IFilterable
{
protected override Container<Drawable> Content => FlowContent;
+2
View File
@@ -157,7 +157,9 @@ namespace osu.Game.Overlays
private void onFail(string originalPath)
{
wikiData.Value = null;
path.Value = "error";
LoadDisplay(articlePage = new WikiArticlePage($@"{api.WebsiteRootUrl}/wiki/",
$"Something went wrong when trying to fetch page \"{originalPath}\".\n\n[Return to the main page](Main_Page)."));
}
-2
View File
@@ -10,7 +10,6 @@ using osu.Framework.Bindables;
using osu.Framework.Extensions.TypeExtensions;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Framework.Testing;
using osu.Game.Configuration;
using osu.Game.Extensions;
using osu.Game.Rulesets.UI;
@@ -21,7 +20,6 @@ namespace osu.Game.Rulesets.Mods
/// <summary>
/// The base class for gameplay modifiers.
/// </summary>
[ExcludeFromDynamicCompile]
public abstract class Mod : IMod, IEquatable<Mod>, IDeepCloneable<Mod>
{
[JsonIgnore]
@@ -30,7 +30,7 @@ using osuTK.Graphics;
namespace osu.Game.Rulesets.Objects.Drawables
{
[Cached(typeof(DrawableHitObject))]
public abstract partial class DrawableHitObject : PoolableDrawableWithLifetime<HitObjectLifetimeEntry>
public abstract partial class DrawableHitObject : PoolableDrawableWithLifetime<HitObjectLifetimeEntry>, IAnimationTimeReference
{
/// <summary>
/// Invoked after this <see cref="DrawableHitObject"/>'s applied <see cref="HitObject"/> has had its defaults applied.
@@ -425,11 +425,13 @@ namespace osu.Game.Rulesets.Objects.Drawables
LifetimeEnd = double.MaxValue;
double transformTime = HitObject.StartTime - InitialLifetimeOffset;
clearExistingStateTransforms();
using (BeginAbsoluteSequence(transformTime))
double initialTransformsTime = HitObject.StartTime - InitialLifetimeOffset;
AnimationStartTime.Value = initialTransformsTime;
using (BeginAbsoluteSequence(initialTransformsTime))
UpdateInitialTransforms();
using (BeginAbsoluteSequence(StateUpdateTime))
@@ -721,6 +723,8 @@ namespace osu.Game.Rulesets.Objects.Drawables
if (CurrentSkin != null)
CurrentSkin.SourceChanged -= skinSourceChanged;
}
public Bindable<double> AnimationStartTime { get; } = new BindableDouble();
}
public abstract partial class DrawableHitObject<TObject> : DrawableHitObject
-2
View File
@@ -12,7 +12,6 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Bindings;
using osu.Framework.IO.Stores;
using osu.Framework.Localisation;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Legacy;
using osu.Game.Configuration;
@@ -34,7 +33,6 @@ using osu.Game.Users;
namespace osu.Game.Rulesets
{
[ExcludeFromDynamicCompile]
public abstract class Ruleset
{
public RulesetInfo RulesetInfo { get; }
-2
View File
@@ -3,13 +3,11 @@
using System;
using JetBrains.Annotations;
using osu.Framework.Testing;
using osu.Game.Rulesets.Difficulty;
using Realms;
namespace osu.Game.Rulesets
{
[ExcludeFromDynamicCompile]
[MapTo("Ruleset")]
public class RulesetInfo : RealmObject, IEquatable<RulesetInfo>, IComparable<RulesetInfo>, IRulesetInfo
{
@@ -1,8 +1,6 @@
// 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.
#nullable disable
namespace osu.Game.Rulesets.UI.Scrolling.Algorithms
{
public interface IScrollAlgorithm
-2
View File
@@ -7,7 +7,6 @@ using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
using osu.Framework.Localisation;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Models;
@@ -25,7 +24,6 @@ namespace osu.Game.Scoring
/// <summary>
/// A realm model containing metadata for a single score.
/// </summary>
[ExcludeFromDynamicCompile]
[MapTo("Score")]
public class ScoreInfo : RealmObject, IHasGuidPrimaryKey, IHasRealmFiles, ISoftDelete, IEquatable<ScoreInfo>, IScoreInfo
{
-2
View File
@@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Newtonsoft.Json;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.IO;
using osu.Game.Models;
@@ -13,7 +12,6 @@ using Realms;
namespace osu.Game.Skinning
{
[ExcludeFromDynamicCompile]
[MapTo("Skin")]
[JsonObject(MemberSerialization.OptIn)]
public class SkinInfo : RealmObject, IHasRealmFiles, IEquatable<SkinInfo>, IHasGuidPrimaryKey, ISoftDelete, IHasNamedFiles
-2
View File
@@ -18,7 +18,6 @@ using osu.Framework.Graphics.Rendering;
using osu.Framework.Graphics.Textures;
using osu.Framework.IO.Stores;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Framework.Threading;
using osu.Framework.Utils;
using osu.Game.Audio;
@@ -36,7 +35,6 @@ namespace osu.Game.Skinning
/// This is also exposed and cached as <see cref="ISkinSource"/> to allow for any component to potentially have skinning support.
/// For gameplay components, see <see cref="RulesetSkinProvidingContainer"/> which adds extra legacy and toggle logic that may affect the lookup process.
/// </remarks>
[ExcludeFromDynamicCompile]
public class SkinManager : ModelManager<SkinInfo>, ISkinSource, IStorageResourceProvider, IModelImporter<SkinInfo>
{
/// <summary>
-1
View File
@@ -36,7 +36,6 @@ using osu.Game.Tests.Rulesets;
namespace osu.Game.Tests.Visual
{
[ExcludeFromDynamicCompile]
public abstract partial class OsuTestScene : TestScene
{
[Cached]