mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 13:32:54 +08:00
Merge branch 'master' into skillsrework
This commit is contained in:
commit
cefef81cdf
1
.github/workflows/diffcalc.yml
vendored
1
.github/workflows/diffcalc.yml
vendored
@ -53,6 +53,7 @@ jobs:
|
|||||||
diffcalc:
|
diffcalc:
|
||||||
name: Run
|
name: Run
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
|
timeout-minutes: 1440
|
||||||
if: needs.metadata.outputs.continue == 'yes'
|
if: needs.metadata.outputs.continue == 'yes'
|
||||||
needs: metadata
|
needs: metadata
|
||||||
strategy:
|
strategy:
|
||||||
|
@ -51,11 +51,11 @@
|
|||||||
<Reference Include="Java.Interop" />
|
<Reference Include="Java.Interop" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.918.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.1004.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.924.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.1004.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Transitive Dependencies">
|
<ItemGroup Label="Transitive Dependencies">
|
||||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
||||||
<PackageReference Include="Realm" Version="10.5.0" />
|
<PackageReference Include="Realm" Version="10.6.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -140,10 +140,10 @@ namespace osu.Desktop
|
|||||||
switch (activity)
|
switch (activity)
|
||||||
{
|
{
|
||||||
case UserActivity.InGame game:
|
case UserActivity.InGame game:
|
||||||
return game.Beatmap.ToString();
|
return game.BeatmapInfo.ToString();
|
||||||
|
|
||||||
case UserActivity.Editing edit:
|
case UserActivity.Editing edit:
|
||||||
return edit.Beatmap.ToString();
|
return edit.BeatmapInfo.ToString();
|
||||||
|
|
||||||
case UserActivity.InLobby lobby:
|
case UserActivity.InLobby lobby:
|
||||||
return privacyMode.Value == DiscordRichPresenceMode.Limited ? string.Empty : lobby.Room.Name.Value;
|
return privacyMode.Value == DiscordRichPresenceMode.Limited ? string.Empty : lobby.Room.Name.Value;
|
||||||
|
@ -74,7 +74,10 @@ namespace osu.Desktop
|
|||||||
|
|
||||||
// we want to allow multiple instances to be started when in debug.
|
// we want to allow multiple instances to be started when in debug.
|
||||||
if (!DebugUtils.IsDebugBuild)
|
if (!DebugUtils.IsDebugBuild)
|
||||||
|
{
|
||||||
|
Logger.Log(@"osu! does not support multiple running instances.", LoggingTarget.Runtime, LogLevel.Error);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tournamentClient)
|
if (tournamentClient)
|
||||||
|
@ -29,8 +29,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor
|
|||||||
|
|
||||||
protected CatchSelectionBlueprintTestScene()
|
protected CatchSelectionBlueprintTestScene()
|
||||||
{
|
{
|
||||||
EditorBeatmap = new EditorBeatmap(new CatchBeatmap());
|
EditorBeatmap = new EditorBeatmap(new CatchBeatmap()) { Difficulty = { CircleSize = 0 } };
|
||||||
EditorBeatmap.BeatmapInfo.BaseDifficulty.CircleSize = 0;
|
|
||||||
EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint
|
EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint
|
||||||
{
|
{
|
||||||
BeatLength = 100
|
BeatLength = 100
|
||||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Catch.Edit.Blueprints;
|
using osu.Game.Rulesets.Catch.Edit.Blueprints;
|
||||||
using osu.Game.Rulesets.Catch.Edit.Blueprints.Components;
|
using osu.Game.Rulesets.Catch.Edit.Blueprints.Components;
|
||||||
@ -26,7 +27,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor
|
|||||||
protected override void AddHitObject(DrawableHitObject hitObject)
|
protected override void AddHitObject(DrawableHitObject hitObject)
|
||||||
{
|
{
|
||||||
// Create nested bananas (but positions are not randomized because beatmap processing is not done).
|
// Create nested bananas (but positions are not randomized because beatmap processing is not done).
|
||||||
hitObject.HitObject.ApplyDefaults(new ControlPointInfo(), Beatmap.Value.BeatmapInfo.BaseDifficulty);
|
hitObject.HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||||
|
|
||||||
base.AddHitObject(hitObject);
|
base.AddHitObject(hitObject);
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Extensions.ObjectExtensions;
|
using osu.Framework.Extensions.ObjectExtensions;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.Edit.Blueprints;
|
using osu.Game.Rulesets.Catch.Edit.Blueprints;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||||
@ -23,11 +23,12 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor
|
|||||||
|
|
||||||
private JuiceStream lastObject => LastObject?.HitObject as JuiceStream;
|
private JuiceStream lastObject => LastObject?.HitObject as JuiceStream;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
protected override IBeatmap GetPlayableBeatmap()
|
||||||
private void load()
|
|
||||||
{
|
{
|
||||||
Beatmap.Value.BeatmapInfo.BaseDifficulty.SliderTickRate = 5;
|
var playable = base.GetPlayableBeatmap();
|
||||||
Beatmap.Value.BeatmapInfo.BaseDifficulty.SliderMultiplier = velocity * 10;
|
playable.Difficulty.SliderTickRate = 5;
|
||||||
|
playable.Difficulty.SliderMultiplier = velocity * 10;
|
||||||
|
return playable;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -223,7 +223,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Editor
|
|||||||
X = x,
|
X = x,
|
||||||
Path = sliderPath,
|
Path = sliderPath,
|
||||||
};
|
};
|
||||||
EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = velocity;
|
EditorBeatmap.Difficulty.SliderMultiplier = velocity;
|
||||||
EditorBeatmap.Add(hitObject);
|
EditorBeatmap.Add(hitObject);
|
||||||
EditorBeatmap.Update(hitObject);
|
EditorBeatmap.Update(hitObject);
|
||||||
Assert.That(hitObject.Velocity, Is.EqualTo(velocity));
|
Assert.That(hitObject.Velocity, Is.EqualTo(velocity));
|
||||||
|
@ -290,7 +290,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
{
|
{
|
||||||
public IEnumerable<CaughtObject> CaughtObjects => this.ChildrenOfType<CaughtObject>();
|
public IEnumerable<CaughtObject> CaughtObjects => this.ChildrenOfType<CaughtObject>();
|
||||||
|
|
||||||
public TestCatcher(DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty)
|
public TestCatcher(DroppedObjectContainer droppedObjectTarget, IBeatmapDifficultyInfo difficulty)
|
||||||
: base(droppedObjectTarget, difficulty)
|
: base(droppedObjectTarget, difficulty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -298,7 +298,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
public class TestKiaiFruit : Fruit
|
public class TestKiaiFruit : Fruit
|
||||||
{
|
{
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
controlPointInfo.Add(0, new EffectControlPoint { KiaiMode = true });
|
controlPointInfo.Add(0, new EffectControlPoint { KiaiMode = true });
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
private ScheduledDelegate addManyFruit;
|
private ScheduledDelegate addManyFruit;
|
||||||
|
|
||||||
private BeatmapDifficulty beatmapDifficulty;
|
private IBeatmapDifficultyInfo beatmapDifficulty;
|
||||||
|
|
||||||
public TestSceneCatcherArea()
|
public TestSceneCatcherArea()
|
||||||
{
|
{
|
||||||
@ -120,7 +120,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
|
|
||||||
private class TestCatcherArea : CatcherArea
|
private class TestCatcherArea : CatcherArea
|
||||||
{
|
{
|
||||||
public TestCatcherArea(BeatmapDifficulty beatmapDifficulty)
|
public TestCatcherArea(IBeatmapDifficultyInfo beatmapDifficulty)
|
||||||
{
|
{
|
||||||
var droppedObjectContainer = new DroppedObjectContainer();
|
var droppedObjectContainer = new DroppedObjectContainer();
|
||||||
Add(droppedObjectContainer);
|
Add(droppedObjectContainer);
|
||||||
|
@ -211,7 +211,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
|
|
||||||
palpableObjects.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
|
palpableObjects.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
|
||||||
|
|
||||||
double halfCatcherWidth = Catcher.CalculateCatchWidth(beatmap.BeatmapInfo.BaseDifficulty) / 2;
|
double halfCatcherWidth = Catcher.CalculateCatchWidth(beatmap.Difficulty) / 2;
|
||||||
|
|
||||||
// Todo: This is wrong. osu!stable calculated hyperdashes using the full catcher size, excluding the margins.
|
// Todo: This is wrong. osu!stable calculated hyperdashes using the full catcher size, excluding the margins.
|
||||||
// This should theoretically cause impossible scenarios, but practically, likely due to the size of the playfield, it doesn't seem possible.
|
// This should theoretically cause impossible scenarios, but practically, likely due to the size of the playfield, it doesn't seem possible.
|
||||||
|
@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
return new CatchDifficultyAttributes { Mods = mods, Skills = skills };
|
return new CatchDifficultyAttributes { Mods = mods, Skills = skills };
|
||||||
|
|
||||||
// this is the same as osu!, so there's potential to share the implementation... maybe
|
// this is the same as osu!, so there's potential to share the implementation... maybe
|
||||||
double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
double preempt = IBeatmapDifficultyInfo.DifficultyRange(beatmap.Difficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
||||||
|
|
||||||
return new CatchDifficultyAttributes
|
return new CatchDifficultyAttributes
|
||||||
{
|
{
|
||||||
@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
|
|
||||||
// In 2B beatmaps, it is possible that a normal Fruit is placed in the middle of a JuiceStream.
|
// In 2B beatmaps, it is possible that a normal Fruit is placed in the middle of a JuiceStream.
|
||||||
foreach (var hitObject in beatmap.HitObjects
|
foreach (var hitObject in beatmap.HitObjects
|
||||||
.SelectMany(obj => obj is JuiceStream stream ? stream.NestedHitObjects : new[] { obj })
|
.SelectMany(obj => obj is JuiceStream stream ? stream.NestedHitObjects.AsEnumerable() : new[] { obj })
|
||||||
.Cast<CatchHitObject>()
|
.Cast<CatchHitObject>()
|
||||||
.OrderBy(x => x.StartTime))
|
.OrderBy(x => x.StartTime))
|
||||||
{
|
{
|
||||||
@ -69,10 +69,10 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
|
|
||||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
|
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
|
||||||
{
|
{
|
||||||
halfCatcherWidth = Catcher.CalculateCatchWidth(beatmap.BeatmapInfo.BaseDifficulty) * 0.5f;
|
halfCatcherWidth = Catcher.CalculateCatchWidth(beatmap.Difficulty) * 0.5f;
|
||||||
|
|
||||||
// For circle sizes above 5.5, reduce the catcher width further to simulate imperfect gameplay.
|
// For circle sizes above 5.5, reduce the catcher width further to simulate imperfect gameplay.
|
||||||
halfCatcherWidth *= 1 - (Math.Max(0, beatmap.BeatmapInfo.BaseDifficulty.CircleSize - 5.5f) * 0.0625f);
|
halfCatcherWidth *= 1 - (Math.Max(0, beatmap.Difficulty.CircleSize - 5.5f) * 0.0625f);
|
||||||
|
|
||||||
return new Skill[]
|
return new Skill[]
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
public class CatchEditorPlayfield : CatchPlayfield
|
public class CatchEditorPlayfield : CatchPlayfield
|
||||||
{
|
{
|
||||||
// TODO fixme: the size of the catcher is not changed when circle size is changed in setup screen.
|
// TODO fixme: the size of the catcher is not changed when circle size is changed in setup screen.
|
||||||
public CatchEditorPlayfield(BeatmapDifficulty difficulty)
|
public CatchEditorPlayfield(IBeatmapDifficultyInfo difficulty)
|
||||||
: base(difficulty)
|
: base(difficulty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Playfield CreatePlayfield() => new CatchEditorPlayfield(Beatmap.BeatmapInfo.BaseDifficulty);
|
protected override Playfield CreatePlayfield() => new CatchEditorPlayfield(Beatmap.Difficulty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,11 +128,11 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int RandomSeed => (int)StartTime;
|
public int RandomSeed => (int)StartTime;
|
||||||
|
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450);
|
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450);
|
||||||
|
|
||||||
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
|
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double SpanDuration => Duration / this.SpanCount();
|
public double SpanDuration => Duration / this.SpanCount();
|
||||||
|
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
|
@ -34,9 +34,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
internal CatcherArea CatcherArea { get; private set; }
|
internal CatcherArea CatcherArea { get; private set; }
|
||||||
|
|
||||||
private readonly BeatmapDifficulty difficulty;
|
private readonly IBeatmapDifficultyInfo difficulty;
|
||||||
|
|
||||||
public CatchPlayfield(BeatmapDifficulty difficulty)
|
public CatchPlayfield(IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
this.difficulty = difficulty;
|
this.difficulty = difficulty;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
private readonly DrawablePool<CaughtBanana> caughtBananaPool;
|
private readonly DrawablePool<CaughtBanana> caughtBananaPool;
|
||||||
private readonly DrawablePool<CaughtDroplet> caughtDropletPool;
|
private readonly DrawablePool<CaughtDroplet> caughtDropletPool;
|
||||||
|
|
||||||
public Catcher([NotNull] DroppedObjectContainer droppedObjectTarget, BeatmapDifficulty difficulty = null)
|
public Catcher([NotNull] DroppedObjectContainer droppedObjectTarget, IBeatmapDifficultyInfo difficulty = null)
|
||||||
{
|
{
|
||||||
this.droppedObjectTarget = droppedObjectTarget;
|
this.droppedObjectTarget = droppedObjectTarget;
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the scale of the catcher based off the provided beatmap difficulty.
|
/// Calculates the scale of the catcher based off the provided beatmap difficulty.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static Vector2 calculateScale(BeatmapDifficulty difficulty) => new Vector2(1.0f - 0.7f * (difficulty.CircleSize - 5) / 5);
|
private static Vector2 calculateScale(IBeatmapDifficultyInfo difficulty) => new Vector2(1.0f - 0.7f * (difficulty.CircleSize - 5) / 5);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the width of the area used for attempting catches in gameplay.
|
/// Calculates the width of the area used for attempting catches in gameplay.
|
||||||
@ -184,7 +184,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
/// Calculates the width of the area used for attempting catches in gameplay.
|
/// Calculates the width of the area used for attempting catches in gameplay.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="difficulty">The beatmap difficulty.</param>
|
/// <param name="difficulty">The beatmap difficulty.</param>
|
||||||
public static float CalculateCatchWidth(BeatmapDifficulty difficulty) => CalculateCatchWidth(calculateScale(difficulty));
|
public static float CalculateCatchWidth(IBeatmapDifficultyInfo difficulty) => CalculateCatchWidth(calculateScale(difficulty));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determine if this catcher can catch a <see cref="CatchHitObject"/> in the current position.
|
/// Determine if this catcher can catch a <see cref="CatchHitObject"/> in the current position.
|
||||||
|
@ -27,14 +27,14 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
: base(ruleset, beatmap, mods)
|
: base(ruleset, beatmap, mods)
|
||||||
{
|
{
|
||||||
Direction.Value = ScrollingDirection.Down;
|
Direction.Value = ScrollingDirection.Down;
|
||||||
TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450);
|
TimeRange.Value = IBeatmapDifficultyInfo.DifficultyRange(beatmap.Difficulty.ApproachRate, 1800, 1200, 450);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
|
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
|
||||||
|
|
||||||
protected override ReplayRecorder CreateReplayRecorder(Score score) => new CatchReplayRecorder(score, (CatchPlayfield)Playfield);
|
protected override ReplayRecorder CreateReplayRecorder(Score score) => new CatchReplayRecorder(score, (CatchPlayfield)Playfield);
|
||||||
|
|
||||||
protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty);
|
protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.Difficulty);
|
||||||
|
|
||||||
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new CatchPlayfieldAdjustmentContainer();
|
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new CatchPlayfieldAdjustmentContainer();
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
{
|
{
|
||||||
IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo);
|
IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo);
|
||||||
|
|
||||||
var roundedCircleSize = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.CircleSize);
|
var roundedCircleSize = Math.Round(beatmap.Difficulty.CircleSize);
|
||||||
var roundedOverallDifficulty = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
var roundedOverallDifficulty = Math.Round(beatmap.Difficulty.OverallDifficulty);
|
||||||
|
|
||||||
if (IsForCurrentRuleset)
|
if (IsForCurrentRuleset)
|
||||||
{
|
{
|
||||||
@ -71,9 +71,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
originalTargetColumns = TargetColumns;
|
originalTargetColumns = TargetColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetColumnCountForNonConvert(BeatmapInfo beatmap)
|
public static int GetColumnCountForNonConvert(BeatmapInfo beatmapInfo)
|
||||||
{
|
{
|
||||||
var roundedCircleSize = Math.Round(beatmap.BaseDifficulty.CircleSize);
|
var roundedCircleSize = Math.Round(beatmapInfo.BaseDifficulty.CircleSize);
|
||||||
return (int)Math.Max(1, roundedCircleSize);
|
return (int)Math.Max(1, roundedCircleSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
|||||||
|
|
||||||
protected override Beatmap<ManiaHitObject> ConvertBeatmap(IBeatmap original, CancellationToken cancellationToken)
|
protected override Beatmap<ManiaHitObject> ConvertBeatmap(IBeatmap original, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty;
|
IBeatmapDifficultyInfo difficulty = original.Difficulty;
|
||||||
|
|
||||||
int seed = (int)MathF.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)MathF.Round(difficulty.ApproachRate);
|
int seed = (int)MathF.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)MathF.Round(difficulty.ApproachRate);
|
||||||
Random = new FastRandom(seed);
|
Random = new FastRandom(seed);
|
||||||
|
@ -61,7 +61,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
StartTime = (int)Math.Round(hitObject.StartTime);
|
StartTime = (int)Math.Round(hitObject.StartTime);
|
||||||
|
|
||||||
// This matches stable's calculation.
|
// This matches stable's calculation.
|
||||||
EndTime = (int)Math.Floor(StartTime + distanceData.Distance * beatLength * SpanCount * 0.01 / beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier);
|
EndTime = (int)Math.Floor(StartTime + distanceData.Distance * beatLength * SpanCount * 0.01 / beatmap.Difficulty.SliderMultiplier);
|
||||||
|
|
||||||
SegmentDuration = (EndTime - StartTime) / SpanCount;
|
SegmentDuration = (EndTime - StartTime) / SpanCount;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
if (drainTime == 0)
|
if (drainTime == 0)
|
||||||
drainTime = 10000;
|
drainTime = 10000;
|
||||||
|
|
||||||
BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty;
|
IBeatmapDifficultyInfo difficulty = OriginalBeatmap.Difficulty;
|
||||||
conversionDifficulty = ((difficulty.DrainRate + Math.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15;
|
conversionDifficulty = ((difficulty.DrainRate + Math.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + (double)OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15;
|
||||||
conversionDifficulty = Math.Min(conversionDifficulty.Value, 12);
|
conversionDifficulty = Math.Min(conversionDifficulty.Value, 12);
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
{
|
{
|
||||||
lowerBound ??= RandomStart;
|
lowerBound ??= RandomStart;
|
||||||
upperBound ??= TotalColumns;
|
upperBound ??= TotalColumns;
|
||||||
nextColumn ??= (_ => GetRandomColumn(lowerBound, upperBound));
|
nextColumn ??= _ => GetRandomColumn(lowerBound, upperBound);
|
||||||
|
|
||||||
// Check for the initial column
|
// Check for the initial column
|
||||||
if (isValid(initialColumn))
|
if (isValid(initialColumn))
|
||||||
@ -176,7 +176,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
|
|
||||||
return initialColumn;
|
return initialColumn;
|
||||||
|
|
||||||
bool isValid(int column) => validation?.Invoke(column) != false && !patterns.Any(p => p.ColumnHasObject(column));
|
bool isValid(int column)
|
||||||
|
{
|
||||||
|
if (validation?.Invoke(column) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var p in patterns)
|
||||||
|
{
|
||||||
|
if (p.ColumnHasObject(column))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -12,46 +12,68 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class Pattern
|
internal class Pattern
|
||||||
{
|
{
|
||||||
private readonly List<ManiaHitObject> hitObjects = new List<ManiaHitObject>();
|
private List<ManiaHitObject> hitObjects;
|
||||||
|
private HashSet<int> containedColumns;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// All the hit objects contained in this pattern.
|
/// All the hit objects contained in this pattern.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<ManiaHitObject> HitObjects => hitObjects;
|
public IEnumerable<ManiaHitObject> HitObjects => hitObjects ?? Enumerable.Empty<ManiaHitObject>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check whether a column of this patterns contains a hit object.
|
/// Check whether a column of this patterns contains a hit object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="column">The column index.</param>
|
/// <param name="column">The column index.</param>
|
||||||
/// <returns>Whether the column with index <paramref name="column"/> contains a hit object.</returns>
|
/// <returns>Whether the column with index <paramref name="column"/> contains a hit object.</returns>
|
||||||
public bool ColumnHasObject(int column) => hitObjects.Exists(h => h.Column == column);
|
public bool ColumnHasObject(int column) => containedColumns?.Contains(column) == true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Amount of columns taken up by hit objects in this pattern.
|
/// Amount of columns taken up by hit objects in this pattern.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int ColumnWithObjects => HitObjects.GroupBy(h => h.Column).Count();
|
public int ColumnWithObjects => containedColumns?.Count ?? 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a hit object to this pattern.
|
/// Adds a hit object to this pattern.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hitObject">The hit object to add.</param>
|
/// <param name="hitObject">The hit object to add.</param>
|
||||||
public void Add(ManiaHitObject hitObject) => hitObjects.Add(hitObject);
|
public void Add(ManiaHitObject hitObject)
|
||||||
|
{
|
||||||
|
prepareStorage();
|
||||||
|
|
||||||
|
hitObjects.Add(hitObject);
|
||||||
|
containedColumns.Add(hitObject.Column);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copies hit object from another pattern to this one.
|
/// Copies hit object from another pattern to this one.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="other">The other pattern.</param>
|
/// <param name="other">The other pattern.</param>
|
||||||
public void Add(Pattern other) => hitObjects.AddRange(other.HitObjects);
|
public void Add(Pattern other)
|
||||||
|
{
|
||||||
|
prepareStorage();
|
||||||
|
|
||||||
|
if (other.hitObjects != null)
|
||||||
|
{
|
||||||
|
hitObjects.AddRange(other.hitObjects);
|
||||||
|
|
||||||
|
foreach (var h in other.hitObjects)
|
||||||
|
containedColumns.Add(h.Column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clears this pattern, removing all hit objects.
|
/// Clears this pattern, removing all hit objects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Clear() => hitObjects.Clear();
|
public void Clear()
|
||||||
|
{
|
||||||
|
hitObjects?.Clear();
|
||||||
|
containedColumns?.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
private void prepareStorage()
|
||||||
/// Removes a hit object from this pattern.
|
{
|
||||||
/// </summary>
|
hitObjects ??= new List<ManiaHitObject>();
|
||||||
/// <param name="hitObject">The hit object to remove.</param>
|
containedColumns ??= new HashSet<int>();
|
||||||
public bool Remove(ManiaHitObject hitObject) => hitObjects.Remove(hitObject);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
return new ManiaDifficultyAttributes { Mods = mods, Skills = skills };
|
return new ManiaDifficultyAttributes { Mods = mods, Skills = skills };
|
||||||
|
|
||||||
HitWindows hitWindows = new ManiaHitWindows();
|
HitWindows hitWindows = new ManiaHitWindows();
|
||||||
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty);
|
||||||
|
|
||||||
return new ManiaDifficultyAttributes
|
return new ManiaDifficultyAttributes
|
||||||
{
|
{
|
||||||
@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
Mods = mods,
|
Mods = mods,
|
||||||
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
|
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
|
||||||
GreatHitWindow = (int)Math.Ceiling(getHitWindow300(mods) / clockRate),
|
GreatHitWindow = (int)Math.Ceiling(getHitWindow300(mods) / clockRate),
|
||||||
ScoreMultiplier = getScoreMultiplier(beatmap, mods),
|
ScoreMultiplier = getScoreMultiplier(mods),
|
||||||
MaxCombo = beatmap.HitObjects.Sum(h => h is HoldNote ? 2 : 1),
|
MaxCombo = beatmap.HitObjects.Sum(h => h is HoldNote ? 2 : 1),
|
||||||
Skills = skills
|
Skills = skills
|
||||||
};
|
};
|
||||||
@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
|
|
||||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[]
|
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[]
|
||||||
{
|
{
|
||||||
new Strain(mods, ((ManiaBeatmap)beatmap).TotalColumns)
|
new Strain(mods, ((ManiaBeatmap)Beatmap).TotalColumns)
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override Mod[] DifficultyAdjustmentMods
|
protected override Mod[] DifficultyAdjustmentMods
|
||||||
@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getScoreMultiplier(IBeatmap beatmap, Mod[] mods)
|
private double getScoreMultiplier(Mod[] mods)
|
||||||
{
|
{
|
||||||
double scoreMultiplier = 1;
|
double scoreMultiplier = 1;
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var maniaBeatmap = (ManiaBeatmap)beatmap;
|
var maniaBeatmap = (ManiaBeatmap)Beatmap;
|
||||||
int diff = maniaBeatmap.TotalColumns - maniaBeatmap.OriginalTotalColumns;
|
int diff = maniaBeatmap.TotalColumns - maniaBeatmap.OriginalTotalColumns;
|
||||||
|
|
||||||
if (diff > 0)
|
if (diff > 0)
|
||||||
|
@ -13,9 +13,9 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
{
|
{
|
||||||
private FilterCriteria.OptionalRange<float> keys;
|
private FilterCriteria.OptionalRange<float> keys;
|
||||||
|
|
||||||
public bool Matches(BeatmapInfo beatmap)
|
public bool Matches(BeatmapInfo beatmapInfo)
|
||||||
{
|
{
|
||||||
return !keys.HasFilter || (beatmap.RulesetID == new ManiaRuleset().LegacyID && keys.IsInRange(ManiaBeatmapConverter.GetColumnCountForNonConvert(beatmap)));
|
return !keys.HasFilter || (beatmapInfo.RulesetID == new ManiaRuleset().LegacyID && keys.IsInRange(ManiaBeatmapConverter.GetColumnCountForNonConvert(beatmapInfo)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryParseCustomKeywordCriteria(string key, Operator op, string value)
|
public bool TryParseCustomKeywordCriteria(string key, Operator op, string value)
|
||||||
|
@ -84,7 +84,7 @@ namespace osu.Game.Rulesets.Mania.Objects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private double tickSpacing = 50;
|
private double tickSpacing = 50;
|
||||||
|
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
{
|
{
|
||||||
// Mania doesn't care about global velocity
|
// Mania doesn't care about global velocity
|
||||||
p.Velocity = 1;
|
p.Velocity = 1;
|
||||||
p.BaseBeatLength *= Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier;
|
p.BaseBeatLength *= Beatmap.Difficulty.SliderMultiplier;
|
||||||
|
|
||||||
// For non-mania beatmap, speed changes should only happen through timing points
|
// For non-mania beatmap, speed changes should only happen through timing points
|
||||||
if (!isForCurrentRuleset)
|
if (!isForCurrentRuleset)
|
||||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks
|
|||||||
public class CheckTooShortSpinnersTest
|
public class CheckTooShortSpinnersTest
|
||||||
{
|
{
|
||||||
private CheckTooShortSpinners check;
|
private CheckTooShortSpinners check;
|
||||||
private BeatmapDifficulty difficulty;
|
private IBeatmapDifficultyInfo difficulty;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
@ -81,12 +81,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks
|
|||||||
assertTooShort(new List<HitObject> { spinnerHighOd }, difficultyHighOd);
|
assertTooShort(new List<HitObject> { spinnerHighOd }, difficultyHighOd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertOk(List<HitObject> hitObjects, BeatmapDifficulty beatmapDifficulty)
|
private void assertOk(List<HitObject> hitObjects, IBeatmapDifficultyInfo beatmapDifficulty)
|
||||||
{
|
{
|
||||||
Assert.That(check.Run(getContext(hitObjects, beatmapDifficulty)), Is.Empty);
|
Assert.That(check.Run(getContext(hitObjects, beatmapDifficulty)), Is.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertVeryShort(List<HitObject> hitObjects, BeatmapDifficulty beatmapDifficulty)
|
private void assertVeryShort(List<HitObject> hitObjects, IBeatmapDifficultyInfo beatmapDifficulty)
|
||||||
{
|
{
|
||||||
var issues = check.Run(getContext(hitObjects, beatmapDifficulty)).ToList();
|
var issues = check.Run(getContext(hitObjects, beatmapDifficulty)).ToList();
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks
|
|||||||
Assert.That(issues.First().Template is CheckTooShortSpinners.IssueTemplateVeryShort);
|
Assert.That(issues.First().Template is CheckTooShortSpinners.IssueTemplateVeryShort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertTooShort(List<HitObject> hitObjects, BeatmapDifficulty beatmapDifficulty)
|
private void assertTooShort(List<HitObject> hitObjects, IBeatmapDifficultyInfo beatmapDifficulty)
|
||||||
{
|
{
|
||||||
var issues = check.Run(getContext(hitObjects, beatmapDifficulty)).ToList();
|
var issues = check.Run(getContext(hitObjects, beatmapDifficulty)).ToList();
|
||||||
|
|
||||||
@ -102,12 +102,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor.Checks
|
|||||||
Assert.That(issues.First().Template is CheckTooShortSpinners.IssueTemplateTooShort);
|
Assert.That(issues.First().Template is CheckTooShortSpinners.IssueTemplateTooShort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BeatmapVerifierContext getContext(List<HitObject> hitObjects, BeatmapDifficulty beatmapDifficulty)
|
private BeatmapVerifierContext getContext(List<HitObject> hitObjects, IBeatmapDifficultyInfo beatmapDifficulty)
|
||||||
{
|
{
|
||||||
var beatmap = new Beatmap<HitObject>
|
var beatmap = new Beatmap<HitObject>
|
||||||
{
|
{
|
||||||
HitObjects = hitObjects,
|
HitObjects = hitObjects,
|
||||||
BeatmapInfo = new BeatmapInfo { BaseDifficulty = beatmapDifficulty }
|
BeatmapInfo = new BeatmapInfo { BaseDifficulty = new BeatmapDifficulty(beatmapDifficulty) }
|
||||||
};
|
};
|
||||||
|
|
||||||
return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
||||||
|
@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup() => Schedule(() =>
|
public void Setup() => Schedule(() =>
|
||||||
{
|
{
|
||||||
editorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1;
|
editorBeatmap.Difficulty.SliderMultiplier = 1;
|
||||||
editorBeatmap.ControlPointInfo.Clear();
|
editorBeatmap.ControlPointInfo.Clear();
|
||||||
editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length });
|
editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length });
|
||||||
|
|
||||||
|
@ -4,13 +4,11 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Testing;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
@ -122,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
|||||||
private bool checkSomeHit() => Player.ScoreProcessor.JudgedHits >= 4;
|
private bool checkSomeHit() => Player.ScoreProcessor.JudgedHits >= 4;
|
||||||
|
|
||||||
private bool objectWithIncreasedVisibilityHasIndex(int index)
|
private bool objectWithIncreasedVisibilityHasIndex(int index)
|
||||||
=> Player.Mods.Value.OfType<TestOsuModHidden>().Single().FirstObject == Player.ChildrenOfType<GameplayBeatmap>().Single().HitObjects[index];
|
=> Player.GameplayState.Mods.OfType<TestOsuModHidden>().Single().FirstObject == Player.GameplayState.Beatmap.HitObjects[index];
|
||||||
|
|
||||||
private class TestOsuModHidden : OsuModHidden
|
private class TestOsuModHidden : OsuModHidden
|
||||||
{
|
{
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,3 @@
|
|||||||
|
[General]
|
||||||
|
Version: latest
|
||||||
|
HitCircleOverlayAboveNumber: 0
|
@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
{
|
{
|
||||||
Position = new Vector2(100, 300),
|
Position = new Vector2(100, 300),
|
||||||
},
|
},
|
||||||
accuracyHeatmap = new TestAccuracyHeatmap(new ScoreInfo { Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo })
|
accuracyHeatmap = new TestAccuracyHeatmap(new ScoreInfo { BeatmapInfo = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo })
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
@ -17,6 +17,7 @@ using osu.Framework.Testing.Input;
|
|||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Skinning;
|
using osu.Game.Rulesets.Osu.Skinning;
|
||||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
@ -29,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
public class TestSceneGameplayCursor : OsuSkinnableTestScene
|
public class TestSceneGameplayCursor : OsuSkinnableTestScene
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
private GameplayBeatmap gameplayBeatmap;
|
private GameplayState gameplayState;
|
||||||
|
|
||||||
private OsuCursorContainer lastContainer;
|
private OsuCursorContainer lastContainer;
|
||||||
|
|
||||||
@ -40,7 +41,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
public TestSceneGameplayCursor()
|
public TestSceneGameplayCursor()
|
||||||
{
|
{
|
||||||
gameplayBeatmap = new GameplayBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo));
|
var ruleset = new OsuRuleset();
|
||||||
|
gameplayState = new GameplayState(CreateBeatmap(ruleset.RulesetInfo), ruleset, Array.Empty<Mod>());
|
||||||
|
|
||||||
AddStep("change background colour", () =>
|
AddStep("change background colour", () =>
|
||||||
{
|
{
|
||||||
@ -57,7 +59,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
AddSliderStep("circle size", 0f, 10f, 0f, val =>
|
AddSliderStep("circle size", 0f, 10f, 0f, val =>
|
||||||
{
|
{
|
||||||
config.SetValue(OsuSetting.AutoCursorSize, true);
|
config.SetValue(OsuSetting.AutoCursorSize, true);
|
||||||
gameplayBeatmap.BeatmapInfo.BaseDifficulty.CircleSize = val;
|
gameplayState.Beatmap.Difficulty.CircleSize = val;
|
||||||
Scheduler.AddOnce(() => loadContent(false));
|
Scheduler.AddOnce(() => loadContent(false));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,7 +75,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
public void TestSizing(int circleSize, float userScale)
|
public void TestSizing(int circleSize, float userScale)
|
||||||
{
|
{
|
||||||
AddStep($"set user scale to {userScale}", () => config.SetValue(OsuSetting.GameplayCursorSize, userScale));
|
AddStep($"set user scale to {userScale}", () => config.SetValue(OsuSetting.GameplayCursorSize, userScale));
|
||||||
AddStep($"adjust cs to {circleSize}", () => gameplayBeatmap.BeatmapInfo.BaseDifficulty.CircleSize = circleSize);
|
AddStep($"adjust cs to {circleSize}", () => gameplayState.Beatmap.Difficulty.CircleSize = circleSize);
|
||||||
AddStep("turn on autosizing", () => config.SetValue(OsuSetting.AutoCursorSize, true));
|
AddStep("turn on autosizing", () => config.SetValue(OsuSetting.AutoCursorSize, true));
|
||||||
|
|
||||||
AddStep("load content", () => loadContent());
|
AddStep("load content", () => loadContent());
|
||||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
};
|
};
|
||||||
|
|
||||||
var hitWindows = new OsuHitWindows();
|
var hitWindows = new OsuHitWindows();
|
||||||
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty);
|
||||||
|
|
||||||
CreateModTest(new ModTestData
|
CreateModTest(new ModTestData
|
||||||
{
|
{
|
||||||
@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
};
|
};
|
||||||
|
|
||||||
var hitWindows = new OsuHitWindows();
|
var hitWindows = new OsuHitWindows();
|
||||||
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty);
|
||||||
|
|
||||||
CreateModTest(new ModTestData
|
CreateModTest(new ModTestData
|
||||||
{
|
{
|
||||||
|
@ -400,9 +400,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
Beatmap.Value = CreateWorkingBeatmap(new Beatmap<OsuHitObject>
|
Beatmap.Value = CreateWorkingBeatmap(new Beatmap<OsuHitObject>
|
||||||
{
|
{
|
||||||
HitObjects = hitObjects,
|
HitObjects = hitObjects,
|
||||||
|
Difficulty = new BeatmapDifficulty { SliderTickRate = 3 },
|
||||||
BeatmapInfo =
|
BeatmapInfo =
|
||||||
{
|
{
|
||||||
BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 },
|
|
||||||
Ruleset = new OsuRuleset().RulesetInfo
|
Ruleset = new OsuRuleset().RulesetInfo
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -452,7 +452,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
private class TestSpinner : Spinner
|
private class TestSpinner : Spinner
|
||||||
{
|
{
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
SpinsRequired = 1;
|
SpinsRequired = 1;
|
||||||
|
@ -412,7 +412,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
private class TestSpinner : Spinner
|
private class TestSpinner : Spinner
|
||||||
{
|
{
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
SpinsRequired = 1;
|
SpinsRequired = 1;
|
||||||
|
@ -37,6 +37,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier;
|
double speedRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier;
|
||||||
double flashlightRating = Math.Sqrt(skills[2].DifficultyValue()) * difficulty_multiplier;
|
double flashlightRating = Math.Sqrt(skills[2].DifficultyValue()) * difficulty_multiplier;
|
||||||
|
|
||||||
|
if (mods.Any(h => h is OsuModRelax))
|
||||||
|
speedRating = 0.0;
|
||||||
|
|
||||||
double baseAimPerformance = Math.Pow(5 * Math.Max(1, aimRating / 0.0675) - 4, 3) / 100000;
|
double baseAimPerformance = Math.Pow(5 * Math.Max(1, aimRating / 0.0675) - 4, 3) / 100000;
|
||||||
double baseSpeedPerformance = Math.Pow(5 * Math.Max(1, speedRating / 0.0675) - 4, 3) / 100000;
|
double baseSpeedPerformance = Math.Pow(5 * Math.Max(1, speedRating / 0.0675) - 4, 3) / 100000;
|
||||||
double baseFlashlightPerformance = 0.0;
|
double baseFlashlightPerformance = 0.0;
|
||||||
@ -53,7 +56,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
|
|
||||||
double starRating = basePerformance > 0.00001 ? Math.Cbrt(1.12) * 0.027 * (Math.Cbrt(100000 / Math.Pow(2, 1 / 1.1) * basePerformance) + 4) : 0;
|
double starRating = basePerformance > 0.00001 ? Math.Cbrt(1.12) * 0.027 * (Math.Cbrt(100000 / Math.Pow(2, 1 / 1.1) * basePerformance) + 4) : 0;
|
||||||
|
|
||||||
double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
double preempt = (int)IBeatmapDifficultyInfo.DifficultyRange(beatmap.Difficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
||||||
|
|
||||||
int maxCombo = beatmap.HitObjects.Count;
|
int maxCombo = beatmap.HitObjects.Count;
|
||||||
// Add the ticks + tail of the slider. 1 is subtracted because the head circle would be counted twice (once for the slider itself in the line above)
|
// Add the ticks + tail of the slider. 1 is subtracted because the head circle would be counted twice (once for the slider itself in the line above)
|
||||||
@ -95,7 +98,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
|
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
|
||||||
{
|
{
|
||||||
HitWindows hitWindows = new OsuHitWindows();
|
HitWindows hitWindows = new OsuHitWindows();
|
||||||
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty);
|
||||||
|
|
||||||
// Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be removed in the future
|
// Todo: These int casts are temporary to achieve 1:1 results with osu!stable, and should be removed in the future
|
||||||
hitWindowGreat = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate;
|
hitWindowGreat = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate;
|
||||||
|
@ -49,6 +49,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
if (mods.Any(m => m is OsuModSpunOut))
|
if (mods.Any(m => m is OsuModSpunOut))
|
||||||
multiplier *= 1.0 - Math.Pow((double)Attributes.SpinnerCount / totalHits, 0.85);
|
multiplier *= 1.0 - Math.Pow((double)Attributes.SpinnerCount / totalHits, 0.85);
|
||||||
|
|
||||||
|
if (mods.Any(h => h is OsuModRelax))
|
||||||
|
{
|
||||||
|
countMiss += countOk + countMeh;
|
||||||
|
multiplier *= 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
double aimValue = computeAimValue();
|
double aimValue = computeAimValue();
|
||||||
double speedValue = computeSpeedValue();
|
double speedValue = computeSpeedValue();
|
||||||
double accuracyValue = computeAccuracyValue();
|
double accuracyValue = computeAccuracyValue();
|
||||||
@ -160,6 +166,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
|
|
||||||
private double computeAccuracyValue()
|
private double computeAccuracyValue()
|
||||||
{
|
{
|
||||||
|
if (mods.Any(h => h is OsuModRelax))
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
// This percentage only considers HitCircles of any value - in this part of the calculation we focus on hitting the timing hit window.
|
// This percentage only considers HitCircles of any value - in this part of the calculation we focus on hitting the timing hit window.
|
||||||
double betterAccuracyPercentage;
|
double betterAccuracyPercentage;
|
||||||
int amountHitObjectsWithAccuracy = Attributes.HitCircleCount;
|
int amountHitObjectsWithAccuracy = Attributes.HitCircleCount;
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Checks
|
|||||||
|
|
||||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||||
{
|
{
|
||||||
double od = context.Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty;
|
double od = context.Beatmap.Difficulty.OverallDifficulty;
|
||||||
|
|
||||||
// These are meant to reflect the duration necessary for auto to score at least 1000 points on the spinner.
|
// These are meant to reflect the duration necessary for auto to score at least 1000 points on the spinner.
|
||||||
// It's difficult to eliminate warnings here, as auto achieving 1000 points depends on the approach angle on some spinners.
|
// It's difficult to eliminate warnings here, as auto achieving 1000 points depends on the approach angle on some spinners.
|
||||||
|
@ -113,7 +113,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
|
|
||||||
#region Reduce AR (IApplicableToDifficulty)
|
#region Reduce AR (IApplicableToDifficulty)
|
||||||
|
|
||||||
public void ReadFromDifficulty(BeatmapDifficulty difficulty)
|
public void ReadFromDifficulty(IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
.Select(beat =>
|
.Select(beat =>
|
||||||
{
|
{
|
||||||
var newCircle = new HitCircle();
|
var newCircle = new HitCircle();
|
||||||
newCircle.ApplyDefaults(controlPointInfo, osuBeatmap.BeatmapInfo.BaseDifficulty);
|
newCircle.ApplyDefaults(controlPointInfo, osuBeatmap.Difficulty);
|
||||||
newCircle.StartTime = beat;
|
newCircle.StartTime = beat;
|
||||||
return (OsuHitObject)newCircle;
|
return (OsuHitObject)newCircle;
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
@ -122,11 +122,11 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, PREEMPT_MIN);
|
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, 1800, 1200, PREEMPT_MIN);
|
||||||
|
|
||||||
// Preempt time can go below 450ms. Normally, this is achieved via the DT mod which uniformly speeds up all animations game wide regardless of AR.
|
// Preempt time can go below 450ms. Normally, this is achieved via the DT mod which uniformly speeds up all animations game wide regardless of AR.
|
||||||
// This uniform speedup is hard to match 1:1, however we can at least make AR>10 (via mods) feel good by extending the upper linear function above.
|
// This uniform speedup is hard to match 1:1, however we can at least make AR>10 (via mods) feel good by extending the upper linear function above.
|
||||||
|
@ -135,7 +135,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
Path.Version.ValueChanged += _ => updateNestedPositions();
|
Path.Version.ValueChanged += _ => updateNestedPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
|
|
||||||
public double SpanDuration => slider.SpanDuration;
|
public double SpanDuration => slider.SpanDuration;
|
||||||
|
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
public int SpanIndex { get; set; }
|
public int SpanIndex { get; set; }
|
||||||
public double SpanStartTime { get; set; }
|
public double SpanStartTime { get; set; }
|
||||||
|
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int MaximumBonusSpins { get; protected set; } = 1;
|
public int MaximumBonusSpins { get; protected set; } = 1;
|
||||||
|
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
|
|
||||||
double secondsDuration = Duration / 1000;
|
double secondsDuration = Duration / 1000;
|
||||||
|
|
||||||
double minimumRotationsPerSecond = stable_matching_fudge * BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5);
|
double minimumRotationsPerSecond = stable_matching_fudge * IBeatmapDifficultyInfo.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5);
|
||||||
|
|
||||||
SpinsRequired = (int)(secondsDuration * minimumRotationsPerSecond);
|
SpinsRequired = (int)(secondsDuration * minimumRotationsPerSecond);
|
||||||
MaximumBonusSpins = (int)((maximum_rotations_per_second - minimumRotationsPerSecond) * secondsDuration);
|
MaximumBonusSpins = (int)((maximum_rotations_per_second - minimumRotationsPerSecond) * secondsDuration);
|
||||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Replays
|
|||||||
: base(beatmap, mods)
|
: base(beatmap, mods)
|
||||||
{
|
{
|
||||||
defaultHitWindows = new OsuHitWindows();
|
defaultHitWindows = new OsuHitWindows();
|
||||||
defaultHitWindows.SetDifficulty(Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
defaultHitWindows.SetDifficulty(Beatmap.Difficulty.OverallDifficulty);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
private OsuPlayfield playfield { get; set; }
|
private OsuPlayfield playfield { get; set; }
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private GameplayBeatmap gameplayBeatmap { get; set; }
|
private GameplayState gameplayState { get; set; }
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ISkinSource skin, OsuColour colours)
|
private void load(ISkinSource skin, OsuColour colours)
|
||||||
@ -75,12 +75,12 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
if (playfield == null || gameplayBeatmap == null) return;
|
if (playfield == null || gameplayState == null) return;
|
||||||
|
|
||||||
DrawableHitObject kiaiHitObject = null;
|
DrawableHitObject kiaiHitObject = null;
|
||||||
|
|
||||||
// Check whether currently in a kiai section first. This is only done as an optimisation to avoid enumerating AliveObjects when not necessary.
|
// Check whether currently in a kiai section first. This is only done as an optimisation to avoid enumerating AliveObjects when not necessary.
|
||||||
if (gameplayBeatmap.ControlPointInfo.EffectPointAt(Time.Current).KiaiMode)
|
if (gameplayState.Beatmap.ControlPointInfo.EffectPointAt(Time.Current).KiaiMode)
|
||||||
kiaiHitObject = playfield.HitObjectContainer.AliveObjects.FirstOrDefault(isTracking);
|
kiaiHitObject = playfield.HitObjectContainer.AliveObjects.FirstOrDefault(isTracking);
|
||||||
|
|
||||||
kiaiSpewer.Active.Value = kiaiHitObject != null;
|
kiaiSpewer.Active.Value = kiaiHitObject != null;
|
||||||
|
@ -35,8 +35,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
|
|
||||||
private Drawable hitCircleSprite;
|
private Drawable hitCircleSprite;
|
||||||
|
|
||||||
protected Drawable HitCircleOverlay { get; private set; }
|
protected Container OverlayLayer { get; private set; }
|
||||||
|
|
||||||
|
private Drawable hitCircleOverlay;
|
||||||
private SkinnableSpriteText hitCircleText;
|
private SkinnableSpriteText hitCircleText;
|
||||||
|
|
||||||
private readonly Bindable<Color4> accentColour = new Bindable<Color4>();
|
private readonly Bindable<Color4> accentColour = new Bindable<Color4>();
|
||||||
@ -78,17 +79,22 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
},
|
},
|
||||||
HitCircleOverlay = new KiaiFlashingSprite
|
OverlayLayer = new Container
|
||||||
{
|
{
|
||||||
Texture = overlayTexture,
|
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
},
|
Child = hitCircleOverlay = new KiaiFlashingSprite
|
||||||
|
{
|
||||||
|
Texture = overlayTexture,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (hasNumber)
|
if (hasNumber)
|
||||||
{
|
{
|
||||||
AddInternal(hitCircleText = new SkinnableSpriteText(new OsuSkinComponent(OsuSkinComponents.HitCircleText), _ => new OsuSpriteText
|
OverlayLayer.Add(hitCircleText = new SkinnableSpriteText(new OsuSkinComponent(OsuSkinComponents.HitCircleText), _ => new OsuSpriteText
|
||||||
{
|
{
|
||||||
Font = OsuFont.Numeric.With(size: 40),
|
Font = OsuFont.Numeric.With(size: 40),
|
||||||
UseFullGlyphHeight = false,
|
UseFullGlyphHeight = false,
|
||||||
@ -102,7 +108,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
bool overlayAboveNumber = skin.GetConfig<OsuSkinConfiguration, bool>(OsuSkinConfiguration.HitCircleOverlayAboveNumber)?.Value ?? true;
|
bool overlayAboveNumber = skin.GetConfig<OsuSkinConfiguration, bool>(OsuSkinConfiguration.HitCircleOverlayAboveNumber)?.Value ?? true;
|
||||||
|
|
||||||
if (overlayAboveNumber)
|
if (overlayAboveNumber)
|
||||||
ChangeInternalChildDepth(HitCircleOverlay, float.MinValue);
|
OverlayLayer.ChangeChildDepth(hitCircleOverlay, float.MinValue);
|
||||||
|
|
||||||
accentColour.BindTo(drawableObject.AccentColour);
|
accentColour.BindTo(drawableObject.AccentColour);
|
||||||
indexInCurrentCombo.BindTo(drawableOsuObject.IndexInCurrentComboBindable);
|
indexInCurrentCombo.BindTo(drawableOsuObject.IndexInCurrentComboBindable);
|
||||||
@ -147,8 +153,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
hitCircleSprite.FadeOut(legacy_fade_duration, Easing.Out);
|
hitCircleSprite.FadeOut(legacy_fade_duration, Easing.Out);
|
||||||
hitCircleSprite.ScaleTo(1.4f, legacy_fade_duration, Easing.Out);
|
hitCircleSprite.ScaleTo(1.4f, legacy_fade_duration, Easing.Out);
|
||||||
|
|
||||||
HitCircleOverlay.FadeOut(legacy_fade_duration, Easing.Out);
|
hitCircleOverlay.FadeOut(legacy_fade_duration, Easing.Out);
|
||||||
HitCircleOverlay.ScaleTo(1.4f, legacy_fade_duration, Easing.Out);
|
hitCircleOverlay.ScaleTo(1.4f, legacy_fade_duration, Easing.Out);
|
||||||
|
|
||||||
if (hasNumber)
|
if (hasNumber)
|
||||||
{
|
{
|
||||||
|
@ -13,26 +13,20 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
{
|
{
|
||||||
public class LegacyReverseArrow : CompositeDrawable
|
public class LegacyReverseArrow : CompositeDrawable
|
||||||
{
|
{
|
||||||
private ISkin skin { get; }
|
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private DrawableHitObject drawableHitObject { get; set; }
|
private DrawableHitObject drawableHitObject { get; set; }
|
||||||
|
|
||||||
private Drawable proxy;
|
private Drawable proxy;
|
||||||
|
|
||||||
public LegacyReverseArrow(ISkin skin)
|
|
||||||
{
|
|
||||||
this.skin = skin;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load(ISkinSource skinSource)
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
string lookupName = new OsuSkinComponent(OsuSkinComponents.ReverseArrow).LookupName;
|
string lookupName = new OsuSkinComponent(OsuSkinComponents.ReverseArrow).LookupName;
|
||||||
|
|
||||||
InternalChild = skin.GetAnimation(lookupName, true, true) ?? Empty();
|
var skin = skinSource.FindProvider(s => s.GetTexture(lookupName) != null);
|
||||||
|
InternalChild = skin?.GetAnimation(lookupName, true, true) ?? Empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private DrawableHitObject drawableHitObject { get; set; }
|
private DrawableHitObject drawableHitObject { get; set; }
|
||||||
|
|
||||||
private Drawable proxiedHitCircleOverlay;
|
private Drawable proxiedOverlayLayer;
|
||||||
|
|
||||||
public LegacySliderHeadHitCircle()
|
public LegacySliderHeadHitCircle()
|
||||||
: base("sliderstartcircle")
|
: base("sliderstartcircle")
|
||||||
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
proxiedHitCircleOverlay = HitCircleOverlay.CreateProxy();
|
proxiedOverlayLayer = OverlayLayer.CreateProxy();
|
||||||
|
|
||||||
if (drawableHitObject != null)
|
if (drawableHitObject != null)
|
||||||
{
|
{
|
||||||
@ -35,11 +35,11 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
|
|
||||||
private void onHitObjectApplied(DrawableHitObject drawableObject)
|
private void onHitObjectApplied(DrawableHitObject drawableObject)
|
||||||
{
|
{
|
||||||
Debug.Assert(proxiedHitCircleOverlay.Parent == null);
|
Debug.Assert(proxiedOverlayLayer.Parent == null);
|
||||||
|
|
||||||
// see logic in LegacyReverseArrow.
|
// see logic in LegacyReverseArrow.
|
||||||
(drawableObject as DrawableSliderHead)?.DrawableSlider
|
(drawableObject as DrawableSliderHead)?.DrawableSlider
|
||||||
.OverlayElementContainer.Add(proxiedHitCircleOverlay.With(d => d.Depth = float.MinValue));
|
.OverlayElementContainer.Add(proxiedOverlayLayer.With(d => d.Depth = float.MinValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
|
@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
|
|
||||||
case OsuSkinComponents.ReverseArrow:
|
case OsuSkinComponents.ReverseArrow:
|
||||||
if (hasHitCircle.Value)
|
if (hasHitCircle.Value)
|
||||||
return new LegacyReverseArrow(this);
|
return new LegacyReverseArrow();
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Osu.Statistics
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Todo: This should probably not be done like this.
|
// Todo: This should probably not be done like this.
|
||||||
float radius = OsuHitObject.OBJECT_RADIUS * (1.0f - 0.7f * (playableBeatmap.BeatmapInfo.BaseDifficulty.CircleSize - 5) / 5) / 2;
|
float radius = OsuHitObject.OBJECT_RADIUS * (1.0f - 0.7f * (playableBeatmap.Difficulty.CircleSize - 5) / 5) / 2;
|
||||||
|
|
||||||
foreach (var e in score.HitEvents.Where(e => e.HitObject is HitCircle && !(e.HitObject is SliderTailCircle)))
|
foreach (var e in score.HitEvents.Where(e => e.HitObject is HitCircle && !(e.HitObject is SliderTailCircle)))
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private GameplayBeatmap beatmap { get; set; }
|
private GameplayState state { get; set; }
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuConfigManager config { get; set; }
|
private OsuConfigManager config { get; set; }
|
||||||
@ -96,10 +96,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
{
|
{
|
||||||
float scale = userCursorScale.Value;
|
float scale = userCursorScale.Value;
|
||||||
|
|
||||||
if (autoCursorScale.Value && beatmap != null)
|
if (autoCursorScale.Value && state != null)
|
||||||
{
|
{
|
||||||
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
|
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
|
||||||
scale *= GetScaleForCircleSize(beatmap.BeatmapInfo.BaseDifficulty.CircleSize);
|
scale *= GetScaleForCircleSize(state.Beatmap.Difficulty.CircleSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
cursorScale.Value = scale;
|
cursorScale.Value = scale;
|
||||||
|
@ -10,6 +10,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Beatmaps.Formats;
|
using osu.Game.Beatmaps.Formats;
|
||||||
@ -46,11 +47,10 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
|
|
||||||
protected override Beatmap<TaikoHitObject> ConvertBeatmap(IBeatmap original, CancellationToken cancellationToken)
|
protected override Beatmap<TaikoHitObject> ConvertBeatmap(IBeatmap original, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!(original.BeatmapInfo.BaseDifficulty is TaikoMutliplierAppliedDifficulty))
|
if (!(original.Difficulty is TaikoMutliplierAppliedDifficulty))
|
||||||
{
|
{
|
||||||
// Rewrite the beatmap info to add the slider velocity multiplier
|
// Rewrite the beatmap info to add the slider velocity multiplier
|
||||||
original.BeatmapInfo = original.BeatmapInfo.Clone();
|
original.Difficulty = new TaikoMutliplierAppliedDifficulty(original.Difficulty);
|
||||||
original.BeatmapInfo.BaseDifficulty = new TaikoMutliplierAppliedDifficulty(original.BeatmapInfo.BaseDifficulty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Beatmap<TaikoHitObject> converted = base.ConvertBeatmap(original, cancellationToken);
|
Beatmap<TaikoHitObject> converted = base.ConvertBeatmap(original, cancellationToken);
|
||||||
@ -108,7 +108,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
StartTime = obj.StartTime,
|
StartTime = obj.StartTime,
|
||||||
Samples = obj.Samples,
|
Samples = obj.Samples,
|
||||||
Duration = taikoDuration,
|
Duration = taikoDuration,
|
||||||
TickRate = beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate == 3 ? 3 : 4
|
TickRate = beatmap.Difficulty.SliderTickRate == 3 ? 3 : 4
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
|
|
||||||
case IHasDuration endTimeData:
|
case IHasDuration endTimeData:
|
||||||
{
|
{
|
||||||
double hitMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier;
|
double hitMultiplier = IBeatmapDifficultyInfo.DifficultyRange(beatmap.Difficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier;
|
||||||
|
|
||||||
yield return new Swell
|
yield return new Swell
|
||||||
{
|
{
|
||||||
@ -164,10 +164,10 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
else
|
else
|
||||||
beatLength = timingPoint.BeatLength / difficultyPoint.SpeedMultiplier;
|
beatLength = timingPoint.BeatLength / difficultyPoint.SpeedMultiplier;
|
||||||
|
|
||||||
double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate;
|
double sliderScoringPointDistance = osu_base_scoring_distance * beatmap.Difficulty.SliderMultiplier / beatmap.Difficulty.SliderTickRate;
|
||||||
|
|
||||||
// The velocity and duration of the taiko hit object - calculated as the velocity of a drum roll.
|
// The velocity and duration of the taiko hit object - calculated as the velocity of a drum roll.
|
||||||
double taikoVelocity = sliderScoringPointDistance * beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate;
|
double taikoVelocity = sliderScoringPointDistance * beatmap.Difficulty.SliderTickRate;
|
||||||
taikoDuration = (int)(distance / taikoVelocity * beatLength);
|
taikoDuration = (int)(distance / taikoVelocity * beatLength);
|
||||||
|
|
||||||
if (isForCurrentRuleset)
|
if (isForCurrentRuleset)
|
||||||
@ -183,7 +183,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
beatLength = timingPoint.BeatLength;
|
beatLength = timingPoint.BeatLength;
|
||||||
|
|
||||||
// If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat
|
// If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat
|
||||||
tickSpacing = Math.Min(beatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, (double)taikoDuration / spans);
|
tickSpacing = Math.Min(beatLength / beatmap.Difficulty.SliderTickRate, (double)taikoDuration / spans);
|
||||||
|
|
||||||
return tickSpacing > 0
|
return tickSpacing > 0
|
||||||
&& distance / osuVelocity * 1000 < 2 * beatLength;
|
&& distance / osuVelocity * 1000 < 2 * beatLength;
|
||||||
@ -193,11 +193,33 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
|
|
||||||
private class TaikoMutliplierAppliedDifficulty : BeatmapDifficulty
|
private class TaikoMutliplierAppliedDifficulty : BeatmapDifficulty
|
||||||
{
|
{
|
||||||
public TaikoMutliplierAppliedDifficulty(BeatmapDifficulty difficulty)
|
public TaikoMutliplierAppliedDifficulty(IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
difficulty.CopyTo(this);
|
CopyFrom(difficulty);
|
||||||
SliderMultiplier *= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public TaikoMutliplierAppliedDifficulty()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of BeatmapDifficulty
|
||||||
|
|
||||||
|
public override void CopyTo(BeatmapDifficulty other)
|
||||||
|
{
|
||||||
|
base.CopyTo(other);
|
||||||
|
if (!(other is TaikoMutliplierAppliedDifficulty))
|
||||||
|
SliderMultiplier /= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CopyFrom(IBeatmapDifficultyInfo other)
|
||||||
|
{
|
||||||
|
base.CopyFrom(other);
|
||||||
|
if (!(other is TaikoMutliplierAppliedDifficulty))
|
||||||
|
SliderMultiplier *= LegacyBeatmapEncoder.LEGACY_TAIKO_VELOCITY_MULTIPLIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
starRating = rescale(starRating);
|
starRating = rescale(starRating);
|
||||||
|
|
||||||
HitWindows hitWindows = new TaikoHitWindows();
|
HitWindows hitWindows = new TaikoHitWindows();
|
||||||
hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty);
|
||||||
|
|
||||||
return new TaikoDifficultyAttributes
|
return new TaikoDifficultyAttributes
|
||||||
{
|
{
|
||||||
|
@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
|||||||
|
|
||||||
private float overallDifficulty = BeatmapDifficulty.DEFAULT_DIFFICULTY;
|
private float overallDifficulty = BeatmapDifficulty.DEFAULT_DIFFICULTY;
|
||||||
|
|
||||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, IBeatmapDifficultyInfo difficulty)
|
||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
{
|
{
|
||||||
base.ApplyBeatmap(beatmap);
|
base.ApplyBeatmap(beatmap);
|
||||||
|
|
||||||
hpMultiplier = 1 / (object_count_factor * Math.Max(1, beatmap.HitObjects.OfType<Hit>().Count()) * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98));
|
hpMultiplier = 1 / (object_count_factor * Math.Max(1, beatmap.HitObjects.OfType<Hit>().Count()) * IBeatmapDifficultyInfo.DifficultyRange(beatmap.Difficulty.DrainRate, 0.5, 0.75, 0.98));
|
||||||
hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
|
hpMissMultiplier = IBeatmapDifficultyInfo.DifficultyRange(beatmap.Difficulty.DrainRate, 0.0018, 0.0075, 0.0120);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override double GetHealthIncreaseFor(JudgementResult result)
|
protected override double GetHealthIncreaseFor(JudgementResult result)
|
||||||
|
@ -25,10 +25,10 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(GameplayBeatmap gameplayBeatmap)
|
private void load(GameplayState gameplayState)
|
||||||
{
|
{
|
||||||
if (gameplayBeatmap != null)
|
if (gameplayState != null)
|
||||||
((IBindable<JudgementResult>)LastResult).BindTo(gameplayBeatmap.LastJudgementResult);
|
((IBindable<JudgementResult>)LastResult).BindTo(gameplayState.LastJudgementResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool passing;
|
private bool passing;
|
||||||
|
@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(TextureStore textures, GameplayBeatmap gameplayBeatmap)
|
private void load(TextureStore textures, GameplayState gameplayState)
|
||||||
{
|
{
|
||||||
InternalChildren = new[]
|
InternalChildren = new[]
|
||||||
{
|
{
|
||||||
@ -49,8 +49,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
animations[TaikoMascotAnimationState.Fail] = new TaikoMascotAnimation(TaikoMascotAnimationState.Fail),
|
animations[TaikoMascotAnimationState.Fail] = new TaikoMascotAnimation(TaikoMascotAnimationState.Fail),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (gameplayBeatmap != null)
|
if (gameplayState != null)
|
||||||
((IBindable<JudgementResult>)LastResult).BindTo(gameplayBeatmap.LastJudgementResult);
|
((IBindable<JudgementResult>)LastResult).BindTo(gameplayState.LastJudgementResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
|
@ -129,7 +129,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
using (var resStream = TestResources.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||||
using (var stream = new LineBufferedReader(resStream))
|
using (var stream = new LineBufferedReader(resStream))
|
||||||
{
|
{
|
||||||
var difficulty = decoder.Decode(stream).BeatmapInfo.BaseDifficulty;
|
var difficulty = decoder.Decode(stream).Difficulty;
|
||||||
|
|
||||||
Assert.AreEqual(6.5f, difficulty.DrainRate);
|
Assert.AreEqual(6.5f, difficulty.DrainRate);
|
||||||
Assert.AreEqual(4, difficulty.CircleSize);
|
Assert.AreEqual(4, difficulty.CircleSize);
|
||||||
|
@ -149,5 +149,32 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
Assert.AreEqual(AnimationLoopType.LoopForever, ((StoryboardAnimation)foreground.Elements[5]).LoopType);
|
Assert.AreEqual(AnimationLoopType.LoopForever, ((StoryboardAnimation)foreground.Elements[5]).LoopType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDecodeLoopCount()
|
||||||
|
{
|
||||||
|
// all loop sequences in loop-count.osb have a total duration of 2000ms (fade in 0->1000ms, fade out 1000->2000ms).
|
||||||
|
const double loop_duration = 2000;
|
||||||
|
|
||||||
|
var decoder = new LegacyStoryboardDecoder();
|
||||||
|
|
||||||
|
using (var resStream = TestResources.OpenResource("loop-count.osb"))
|
||||||
|
using (var stream = new LineBufferedReader(resStream))
|
||||||
|
{
|
||||||
|
var storyboard = decoder.Decode(stream);
|
||||||
|
|
||||||
|
StoryboardLayer background = storyboard.Layers.Single(l => l.Depth == 3);
|
||||||
|
|
||||||
|
// stable ensures that any loop command executes at least once, even if the loop count specified in the .osb is zero or negative.
|
||||||
|
StoryboardSprite zeroTimes = background.Elements.OfType<StoryboardSprite>().Single(s => s.Path == "zero-times.png");
|
||||||
|
Assert.That(zeroTimes.EndTime, Is.EqualTo(1000 + loop_duration));
|
||||||
|
|
||||||
|
StoryboardSprite oneTime = background.Elements.OfType<StoryboardSprite>().Single(s => s.Path == "one-time.png");
|
||||||
|
Assert.That(oneTime.EndTime, Is.EqualTo(4000 + loop_duration));
|
||||||
|
|
||||||
|
StoryboardSprite manyTimes = background.Elements.OfType<StoryboardSprite>().Single(s => s.Path == "many-times.png");
|
||||||
|
Assert.That(manyTimes.EndTime, Is.EqualTo(9000 + 40 * loop_duration));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
public void TestDecodeDifficulty()
|
public void TestDecodeDifficulty()
|
||||||
{
|
{
|
||||||
var beatmap = decodeAsJson(normal);
|
var beatmap = decodeAsJson(normal);
|
||||||
var difficulty = beatmap.BeatmapInfo.BaseDifficulty;
|
var difficulty = beatmap.Difficulty;
|
||||||
Assert.AreEqual(6.5f, difficulty.DrainRate);
|
Assert.AreEqual(6.5f, difficulty.DrainRate);
|
||||||
Assert.AreEqual(4, difficulty.CircleSize);
|
Assert.AreEqual(4, difficulty.CircleSize);
|
||||||
Assert.AreEqual(8, difficulty.OverallDifficulty);
|
Assert.AreEqual(8, difficulty.OverallDifficulty);
|
||||||
@ -102,7 +102,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
|
|
||||||
processor.PreProcess();
|
processor.PreProcess();
|
||||||
foreach (var o in converted.HitObjects)
|
foreach (var o in converted.HitObjects)
|
||||||
o.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty);
|
o.ApplyDefaults(converted.ControlPointInfo, converted.Difficulty);
|
||||||
processor.PostProcess();
|
processor.PostProcess();
|
||||||
|
|
||||||
var beatmap = converted.Serialize().Deserialize<Beatmap>();
|
var beatmap = converted.Serialize().Deserialize<Beatmap>();
|
||||||
|
@ -86,7 +86,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||||
|
|
||||||
BeatmapSetInfo importedSet;
|
ILive<BeatmapSetInfo> importedSet;
|
||||||
|
|
||||||
using (var stream = File.OpenRead(tempPath))
|
using (var stream = File.OpenRead(tempPath))
|
||||||
{
|
{
|
||||||
@ -97,7 +97,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
Assert.IsTrue(File.Exists(tempPath), "Stream source file somehow went missing");
|
Assert.IsTrue(File.Exists(tempPath), "Stream source file somehow went missing");
|
||||||
File.Delete(tempPath);
|
File.Delete(tempPath);
|
||||||
|
|
||||||
var imported = manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.ID);
|
var imported = manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.Value.ID);
|
||||||
|
|
||||||
deleteBeatmapSet(imported, osu);
|
deleteBeatmapSet(imported, osu);
|
||||||
}
|
}
|
||||||
@ -172,8 +172,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
|
|
||||||
// but contents doesn't, so existing should still be used.
|
// but contents doesn't, so existing should still be used.
|
||||||
Assert.IsTrue(imported.ID == importedSecondTime.ID);
|
Assert.IsTrue(imported.ID == importedSecondTime.Value.ID);
|
||||||
Assert.IsTrue(imported.Beatmaps.First().ID == importedSecondTime.Beatmaps.First().ID);
|
Assert.IsTrue(imported.Beatmaps.First().ID == importedSecondTime.Value.Beatmaps.First().ID);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -226,8 +226,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
|
|
||||||
// check the newly "imported" beatmap is not the original.
|
// check the newly "imported" beatmap is not the original.
|
||||||
Assert.IsTrue(imported.ID != importedSecondTime.ID);
|
Assert.IsTrue(imported.ID != importedSecondTime.Value.ID);
|
||||||
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Beatmaps.First().ID);
|
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Value.Beatmaps.First().ID);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -278,8 +278,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
|
|
||||||
// check the newly "imported" beatmap is not the original.
|
// check the newly "imported" beatmap is not the original.
|
||||||
Assert.IsTrue(imported.ID != importedSecondTime.ID);
|
Assert.IsTrue(imported.ID != importedSecondTime.Value.ID);
|
||||||
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Beatmaps.First().ID);
|
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Value.Beatmaps.First().ID);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -329,8 +329,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
|
|
||||||
// check the newly "imported" beatmap is not the original.
|
// check the newly "imported" beatmap is not the original.
|
||||||
Assert.IsTrue(imported.ID != importedSecondTime.ID);
|
Assert.IsTrue(imported.ID != importedSecondTime.Value.ID);
|
||||||
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Beatmaps.First().ID);
|
Assert.IsTrue(imported.Beatmaps.First().ID != importedSecondTime.Value.Beatmaps.First().ID);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -570,8 +570,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
var imported = await manager.Import(toImport);
|
var imported = await manager.Import(toImport);
|
||||||
|
|
||||||
Assert.NotNull(imported);
|
Assert.NotNull(imported);
|
||||||
Assert.AreEqual(null, imported.Beatmaps[0].OnlineBeatmapID);
|
Assert.AreEqual(null, imported.Value.Beatmaps[0].OnlineBeatmapID);
|
||||||
Assert.AreEqual(null, imported.Beatmaps[1].OnlineBeatmapID);
|
Assert.AreEqual(null, imported.Value.Beatmaps[1].OnlineBeatmapID);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -582,7 +582,6 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
[NonParallelizable]
|
[NonParallelizable]
|
||||||
[Ignore("Binding IPC on Appveyor isn't working (port in use). Need to figure out why")]
|
|
||||||
public void TestImportOverIPC()
|
public void TestImportOverIPC()
|
||||||
{
|
{
|
||||||
using (HeadlessGameHost host = new CleanRunHeadlessGameHost($"{nameof(ImportBeatmapTest)}-host", true))
|
using (HeadlessGameHost host = new CleanRunHeadlessGameHost($"{nameof(ImportBeatmapTest)}-host", true))
|
||||||
@ -707,7 +706,7 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
|
|
||||||
Assert.IsFalse(imported.Files.Any(f => f.Filename.Contains("subfolder")), "Files contain common subfolder");
|
Assert.IsFalse(imported.Value.Files.Any(f => f.Filename.Contains("subfolder")), "Files contain common subfolder");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -760,8 +759,8 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
|
|
||||||
Assert.IsFalse(imported.Files.Any(f => f.Filename.Contains("__MACOSX")), "Files contain resource fork folder, which should be ignored");
|
Assert.IsFalse(imported.Value.Files.Any(f => f.Filename.Contains("__MACOSX")), "Files contain resource fork folder, which should be ignored");
|
||||||
Assert.IsFalse(imported.Files.Any(f => f.Filename.Contains("actual_data")), "Files contain common subfolder");
|
Assert.IsFalse(imported.Value.Files.Any(f => f.Filename.Contains("actual_data")), "Files contain common subfolder");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -910,13 +909,13 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||||
|
|
||||||
var importedSet = await manager.Import(new ImportTask(temp));
|
var importedSet = await manager.Import(new ImportTask(temp)).ConfigureAwait(false);
|
||||||
|
|
||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
|
|
||||||
waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000);
|
waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000);
|
||||||
|
|
||||||
return manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.ID);
|
return manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.Value.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<BeatmapSetInfo> LoadOszIntoOsu(OsuGameBase osu, string path = null, bool virtualTrack = false)
|
public static async Task<BeatmapSetInfo> LoadOszIntoOsu(OsuGameBase osu, string path = null, bool virtualTrack = false)
|
||||||
@ -925,13 +924,13 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
|
|
||||||
var manager = osu.Dependencies.Get<BeatmapManager>();
|
var manager = osu.Dependencies.Get<BeatmapManager>();
|
||||||
|
|
||||||
var importedSet = await manager.Import(new ImportTask(temp));
|
var importedSet = await manager.Import(new ImportTask(temp)).ConfigureAwait(false);
|
||||||
|
|
||||||
ensureLoaded(osu);
|
ensureLoaded(osu);
|
||||||
|
|
||||||
waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000);
|
waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000);
|
||||||
|
|
||||||
return manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.ID);
|
return manager.GetAllUsableBeatmapSets().Find(beatmapSet => beatmapSet.ID == importedSet.Value.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteBeatmapSet(BeatmapSetInfo imported, OsuGameBase osu)
|
private void deleteBeatmapSet(BeatmapSetInfo imported, OsuGameBase osu)
|
||||||
@ -946,13 +945,13 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
Assert.IsTrue(manager.QueryBeatmapSets(_ => true).First().DeletePending);
|
Assert.IsTrue(manager.QueryBeatmapSets(_ => true).First().DeletePending);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Task createScoreForBeatmap(OsuGameBase osu, BeatmapInfo beatmap)
|
private static Task createScoreForBeatmap(OsuGameBase osu, BeatmapInfo beatmapInfo)
|
||||||
{
|
{
|
||||||
return ImportScoreTest.LoadScoreIntoOsu(osu, new ScoreInfo
|
return ImportScoreTest.LoadScoreIntoOsu(osu, new ScoreInfo
|
||||||
{
|
{
|
||||||
OnlineScoreID = 2,
|
OnlineScoreID = 2,
|
||||||
Beatmap = beatmap,
|
BeatmapInfo = beatmapInfo,
|
||||||
BeatmapInfoID = beatmap.ID
|
BeatmapInfoID = beatmapInfo.ID
|
||||||
}, new ImportScoreTest.TestArchiveReader());
|
}, new ImportScoreTest.TestArchiveReader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
osu.Game.Tests/Database/GeneralUsageTests.cs
Normal file
64
osu.Game.Tests/Database/GeneralUsageTests.cs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Database
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class GeneralUsageTests : RealmTest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Just test the construction of a new database works.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestConstructRealm()
|
||||||
|
{
|
||||||
|
RunTestWithRealm((realmFactory, _) => { realmFactory.CreateContext().Refresh(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBlockOperations()
|
||||||
|
{
|
||||||
|
RunTestWithRealm((realmFactory, _) =>
|
||||||
|
{
|
||||||
|
using (realmFactory.BlockAllOperations())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBlockOperationsWithContention()
|
||||||
|
{
|
||||||
|
RunTestWithRealm((realmFactory, _) =>
|
||||||
|
{
|
||||||
|
ManualResetEventSlim stopThreadedUsage = new ManualResetEventSlim();
|
||||||
|
ManualResetEventSlim hasThreadedUsage = new ManualResetEventSlim();
|
||||||
|
|
||||||
|
Task.Factory.StartNew(() =>
|
||||||
|
{
|
||||||
|
using (realmFactory.CreateContext())
|
||||||
|
{
|
||||||
|
hasThreadedUsage.Set();
|
||||||
|
|
||||||
|
stopThreadedUsage.Wait();
|
||||||
|
}
|
||||||
|
}, TaskCreationOptions.LongRunning | TaskCreationOptions.HideScheduler);
|
||||||
|
|
||||||
|
hasThreadedUsage.Wait();
|
||||||
|
|
||||||
|
Assert.Throws<TimeoutException>(() =>
|
||||||
|
{
|
||||||
|
using (realmFactory.BlockAllOperations())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
stopThreadedUsage.Set();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
83
osu.Game.Tests/Database/RealmTest.cs
Normal file
83
osu.Game.Tests/Database/RealmTest.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// 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.Runtime.CompilerServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Nito.AsyncEx;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Logging;
|
||||||
|
using osu.Framework.Platform;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Database;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Database
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public abstract class RealmTest
|
||||||
|
{
|
||||||
|
private static readonly TemporaryNativeStorage storage;
|
||||||
|
|
||||||
|
static RealmTest()
|
||||||
|
{
|
||||||
|
storage = new TemporaryNativeStorage("realm-test");
|
||||||
|
storage.DeleteDirectory(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void RunTestWithRealm(Action<RealmContextFactory, Storage> testAction, [CallerMemberName] string caller = "")
|
||||||
|
{
|
||||||
|
AsyncContext.Run(() =>
|
||||||
|
{
|
||||||
|
var testStorage = storage.GetStorageForDirectory(caller);
|
||||||
|
|
||||||
|
using (var realmFactory = new RealmContextFactory(testStorage, caller))
|
||||||
|
{
|
||||||
|
Logger.Log($"Running test using realm file {testStorage.GetFullPath(realmFactory.Filename)}");
|
||||||
|
testAction(realmFactory, testStorage);
|
||||||
|
|
||||||
|
realmFactory.Dispose();
|
||||||
|
|
||||||
|
Logger.Log($"Final database size: {getFileSize(testStorage, realmFactory)}");
|
||||||
|
realmFactory.Compact();
|
||||||
|
Logger.Log($"Final database size after compact: {getFileSize(testStorage, realmFactory)}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void RunTestWithRealmAsync(Func<RealmContextFactory, Storage, Task> testAction, [CallerMemberName] string caller = "")
|
||||||
|
{
|
||||||
|
AsyncContext.Run(async () =>
|
||||||
|
{
|
||||||
|
var testStorage = storage.GetStorageForDirectory(caller);
|
||||||
|
|
||||||
|
using (var realmFactory = new RealmContextFactory(testStorage, caller))
|
||||||
|
{
|
||||||
|
Logger.Log($"Running test using realm file {testStorage.GetFullPath(realmFactory.Filename)}");
|
||||||
|
await testAction(realmFactory, testStorage);
|
||||||
|
|
||||||
|
realmFactory.Dispose();
|
||||||
|
|
||||||
|
Logger.Log($"Final database size: {getFileSize(testStorage, realmFactory)}");
|
||||||
|
realmFactory.Compact();
|
||||||
|
Logger.Log($"Final database size after compact: {getFileSize(testStorage, realmFactory)}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long getFileSize(Storage testStorage, RealmContextFactory realmFactory)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var stream = testStorage.GetStream(realmFactory.Filename))
|
||||||
|
return stream?.Length ?? 0;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// windows runs may error due to file still being open.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -32,7 +32,7 @@ namespace osu.Game.Tests.Database
|
|||||||
|
|
||||||
storage = new NativeStorage(directory.FullName);
|
storage = new NativeStorage(directory.FullName);
|
||||||
|
|
||||||
realmContextFactory = new RealmContextFactory(storage);
|
realmContextFactory = new RealmContextFactory(storage, "test");
|
||||||
keyBindingStore = new RealmKeyBindingStore(realmContextFactory);
|
keyBindingStore = new RealmKeyBindingStore(realmContextFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,9 +53,9 @@ namespace osu.Game.Tests.Database
|
|||||||
|
|
||||||
private int queryCount(GlobalAction? match = null)
|
private int queryCount(GlobalAction? match = null)
|
||||||
{
|
{
|
||||||
using (var usage = realmContextFactory.GetForRead())
|
using (var realm = realmContextFactory.CreateContext())
|
||||||
{
|
{
|
||||||
var results = usage.Realm.All<RealmKeyBinding>();
|
var results = realm.All<RealmKeyBinding>();
|
||||||
if (match.HasValue)
|
if (match.HasValue)
|
||||||
results = results.Where(k => k.ActionInt == (int)match.Value);
|
results = results.Where(k => k.ActionInt == (int)match.Value);
|
||||||
return results.Count();
|
return results.Count();
|
||||||
@ -69,26 +69,24 @@ namespace osu.Game.Tests.Database
|
|||||||
|
|
||||||
keyBindingStore.Register(testContainer, Enumerable.Empty<RulesetInfo>());
|
keyBindingStore.Register(testContainer, Enumerable.Empty<RulesetInfo>());
|
||||||
|
|
||||||
using (var primaryUsage = realmContextFactory.GetForRead())
|
using (var primaryRealm = realmContextFactory.CreateContext())
|
||||||
{
|
{
|
||||||
var backBinding = primaryUsage.Realm.All<RealmKeyBinding>().Single(k => k.ActionInt == (int)GlobalAction.Back);
|
var backBinding = primaryRealm.All<RealmKeyBinding>().Single(k => k.ActionInt == (int)GlobalAction.Back);
|
||||||
|
|
||||||
Assert.That(backBinding.KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.Escape }));
|
Assert.That(backBinding.KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.Escape }));
|
||||||
|
|
||||||
var tsr = ThreadSafeReference.Create(backBinding);
|
var tsr = ThreadSafeReference.Create(backBinding);
|
||||||
|
|
||||||
using (var usage = realmContextFactory.GetForWrite())
|
using (var threadedContext = realmContextFactory.CreateContext())
|
||||||
{
|
{
|
||||||
var binding = usage.Realm.ResolveReference(tsr);
|
var binding = threadedContext.ResolveReference(tsr);
|
||||||
binding.KeyCombination = new KeyCombination(InputKey.BackSpace);
|
threadedContext.Write(() => binding.KeyCombination = new KeyCombination(InputKey.BackSpace));
|
||||||
|
|
||||||
usage.Commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.That(backBinding.KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.BackSpace }));
|
Assert.That(backBinding.KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.BackSpace }));
|
||||||
|
|
||||||
// check still correct after re-query.
|
// check still correct after re-query.
|
||||||
backBinding = primaryUsage.Realm.All<RealmKeyBinding>().Single(k => k.ActionInt == (int)GlobalAction.Back);
|
backBinding = primaryRealm.All<RealmKeyBinding>().Single(k => k.ActionInt == (int)GlobalAction.Back);
|
||||||
Assert.That(backBinding.KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.BackSpace }));
|
Assert.That(backBinding.KeyCombination.Keys, Is.EquivalentTo(new[] { InputKey.BackSpace }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ namespace osu.Game.Tests.Editing
|
|||||||
|
|
||||||
BeatDivisor.Value = 1;
|
BeatDivisor.Value = 1;
|
||||||
|
|
||||||
composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 1;
|
composer.EditorBeatmap.Difficulty.SliderMultiplier = 1;
|
||||||
composer.EditorBeatmap.ControlPointInfo.Clear();
|
composer.EditorBeatmap.ControlPointInfo.Clear();
|
||||||
|
|
||||||
composer.EditorBeatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 1 });
|
composer.EditorBeatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 1 });
|
||||||
@ -64,7 +64,7 @@ namespace osu.Game.Tests.Editing
|
|||||||
[TestCase(2)]
|
[TestCase(2)]
|
||||||
public void TestSliderMultiplier(float multiplier)
|
public void TestSliderMultiplier(float multiplier)
|
||||||
{
|
{
|
||||||
AddStep($"set multiplier = {multiplier}", () => composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = multiplier);
|
AddStep($"set multiplier = {multiplier}", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = multiplier);
|
||||||
|
|
||||||
assertSnapDistance(100 * multiplier);
|
assertSnapDistance(100 * multiplier);
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ namespace osu.Game.Tests.Editing
|
|||||||
assertDurationToDistance(500, 50);
|
assertDurationToDistance(500, 50);
|
||||||
assertDurationToDistance(1000, 100);
|
assertDurationToDistance(1000, 100);
|
||||||
|
|
||||||
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2);
|
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2);
|
||||||
|
|
||||||
assertDurationToDistance(500, 100);
|
assertDurationToDistance(500, 100);
|
||||||
assertDurationToDistance(1000, 200);
|
assertDurationToDistance(1000, 200);
|
||||||
@ -118,7 +118,7 @@ namespace osu.Game.Tests.Editing
|
|||||||
assertDistanceToDuration(50, 500);
|
assertDistanceToDuration(50, 500);
|
||||||
assertDistanceToDuration(100, 1000);
|
assertDistanceToDuration(100, 1000);
|
||||||
|
|
||||||
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2);
|
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2);
|
||||||
|
|
||||||
assertDistanceToDuration(100, 500);
|
assertDistanceToDuration(100, 500);
|
||||||
assertDistanceToDuration(200, 1000);
|
assertDistanceToDuration(200, 1000);
|
||||||
@ -143,7 +143,7 @@ namespace osu.Game.Tests.Editing
|
|||||||
assertSnappedDuration(200, 2000);
|
assertSnappedDuration(200, 2000);
|
||||||
assertSnappedDuration(250, 3000);
|
assertSnappedDuration(250, 3000);
|
||||||
|
|
||||||
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2);
|
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2);
|
||||||
|
|
||||||
assertSnappedDuration(0, 0);
|
assertSnappedDuration(0, 0);
|
||||||
assertSnappedDuration(50, 0);
|
assertSnappedDuration(50, 0);
|
||||||
@ -175,7 +175,7 @@ namespace osu.Game.Tests.Editing
|
|||||||
assertSnappedDistance(200, 200);
|
assertSnappedDistance(200, 200);
|
||||||
assertSnappedDistance(250, 200);
|
assertSnappedDistance(250, 200);
|
||||||
|
|
||||||
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2);
|
AddStep("set slider multiplier = 2", () => composer.EditorBeatmap.Difficulty.SliderMultiplier = 2);
|
||||||
|
|
||||||
assertSnappedDistance(50, 0);
|
assertSnappedDistance(50, 0);
|
||||||
assertSnappedDistance(100, 0);
|
assertSnappedDistance(100, 0);
|
||||||
|
@ -165,7 +165,7 @@ namespace osu.Game.Tests.Gameplay
|
|||||||
{
|
{
|
||||||
var beatmap = new Beatmap
|
var beatmap = new Beatmap
|
||||||
{
|
{
|
||||||
BeatmapInfo = { BaseDifficulty = { DrainRate = 10 } },
|
Difficulty = { DrainRate = 10 }
|
||||||
};
|
};
|
||||||
|
|
||||||
beatmap.HitObjects.Add(new JudgeableHitObject { StartTime = 0 });
|
beatmap.HitObjects.Add(new JudgeableHitObject { StartTime = 0 });
|
||||||
@ -200,7 +200,7 @@ namespace osu.Game.Tests.Gameplay
|
|||||||
{
|
{
|
||||||
var beatmap = new Beatmap
|
var beatmap = new Beatmap
|
||||||
{
|
{
|
||||||
BeatmapInfo = { BaseDifficulty = { DrainRate = 10 } },
|
Difficulty = { DrainRate = 10 }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (double time = startTime; time <= endTime; time += 100)
|
for (double time = startTime; time <= endTime; time += 100)
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Tests.Localisation
|
|||||||
Title = "Romanised title",
|
Title = "Romanised title",
|
||||||
TitleUnicode = "Unicode Title"
|
TitleUnicode = "Unicode Title"
|
||||||
};
|
};
|
||||||
var romanisableString = metadata.ToRomanisableString();
|
var romanisableString = metadata.GetDisplayTitleRomanisable();
|
||||||
|
|
||||||
Assert.AreEqual(metadata.ToString(), romanisableString.Romanised);
|
Assert.AreEqual(metadata.ToString(), romanisableString.Romanised);
|
||||||
Assert.AreEqual($"{metadata.ArtistUnicode} - {metadata.TitleUnicode}", romanisableString.Original);
|
Assert.AreEqual($"{metadata.ArtistUnicode} - {metadata.TitleUnicode}", romanisableString.Original);
|
||||||
@ -33,7 +33,7 @@ namespace osu.Game.Tests.Localisation
|
|||||||
Artist = "Romanised Artist",
|
Artist = "Romanised Artist",
|
||||||
Title = "Romanised title"
|
Title = "Romanised title"
|
||||||
};
|
};
|
||||||
var romanisableString = metadata.ToRomanisableString();
|
var romanisableString = metadata.GetDisplayTitleRomanisable();
|
||||||
|
|
||||||
Assert.AreEqual(romanisableString.Romanised, romanisableString.Original);
|
Assert.AreEqual(romanisableString.Romanised, romanisableString.Original);
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
|
|||||||
match = shouldMatch;
|
match = shouldMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Matches(BeatmapInfo beatmap) => match;
|
public bool Matches(BeatmapInfo beatmapInfo) => match;
|
||||||
public bool TryParseCustomKeywordCriteria(string key, Operator op, string value) => false;
|
public bool TryParseCustomKeywordCriteria(string key, Operator op, string value) => false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
|
|||||||
{
|
{
|
||||||
public string CustomValue { get; set; }
|
public string CustomValue { get; set; }
|
||||||
|
|
||||||
public bool Matches(BeatmapInfo beatmap) => true;
|
public bool Matches(BeatmapInfo beatmapInfo) => true;
|
||||||
|
|
||||||
public bool TryParseCustomKeywordCriteria(string key, Operator op, string value)
|
public bool TryParseCustomKeywordCriteria(string key, Operator op, string value)
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,7 @@ namespace osu.Game.Tests.Online
|
|||||||
|
|
||||||
AddAssert("response event fired", () => response != null);
|
AddAssert("response event fired", () => response != null);
|
||||||
|
|
||||||
AddAssert("request has response", () => request.Result == response);
|
AddAssert("request has response", () => request.Response == response);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -156,20 +156,49 @@ namespace osu.Game.Tests.Online
|
|||||||
{
|
{
|
||||||
public TaskCompletionSource<bool> AllowImport = new TaskCompletionSource<bool>();
|
public TaskCompletionSource<bool> AllowImport = new TaskCompletionSource<bool>();
|
||||||
|
|
||||||
public Task<BeatmapSetInfo> CurrentImportTask { get; private set; }
|
public Task<ILive<BeatmapSetInfo>> CurrentImportTask { get; private set; }
|
||||||
|
|
||||||
protected override ArchiveDownloadRequest<BeatmapSetInfo> CreateDownloadRequest(BeatmapSetInfo set, bool minimiseDownloadSize)
|
public TestBeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host = null, WorkingBeatmap defaultBeatmap = null)
|
||||||
=> new TestDownloadRequest(set);
|
: base(storage, contextFactory, rulesets, api, audioManager, resources, host, defaultBeatmap)
|
||||||
|
|
||||||
public TestBeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore<byte[]> resources, GameHost host = null, WorkingBeatmap defaultBeatmap = null, bool performOnlineLookups = false)
|
|
||||||
: base(storage, contextFactory, rulesets, api, audioManager, resources, host, defaultBeatmap, performOnlineLookups)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<BeatmapSetInfo> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
protected override BeatmapModelManager CreateBeatmapModelManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, GameHost host)
|
||||||
{
|
{
|
||||||
await AllowImport.Task.ConfigureAwait(false);
|
return new TestBeatmapModelManager(this, storage, contextFactory, rulesets, api, host);
|
||||||
return await (CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken)).ConfigureAwait(false);
|
}
|
||||||
|
|
||||||
|
protected override BeatmapModelDownloader CreateBeatmapModelDownloader(BeatmapModelManager modelManager, IAPIProvider api, GameHost host)
|
||||||
|
{
|
||||||
|
return new TestBeatmapModelDownloader(modelManager, api, host);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class TestBeatmapModelDownloader : BeatmapModelDownloader
|
||||||
|
{
|
||||||
|
public TestBeatmapModelDownloader(BeatmapModelManager modelManager, IAPIProvider apiProvider, GameHost gameHost)
|
||||||
|
: base(modelManager, apiProvider, gameHost)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ArchiveDownloadRequest<BeatmapSetInfo> CreateDownloadRequest(BeatmapSetInfo set, bool minimiseDownloadSize)
|
||||||
|
=> new TestDownloadRequest(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class TestBeatmapModelManager : BeatmapModelManager
|
||||||
|
{
|
||||||
|
private readonly TestBeatmapManager testBeatmapManager;
|
||||||
|
|
||||||
|
public TestBeatmapModelManager(TestBeatmapManager testBeatmapManager, Storage storage, IDatabaseContextFactory databaseContextFactory, RulesetStore rulesetStore, IAPIProvider apiProvider, GameHost gameHost)
|
||||||
|
: base(storage, databaseContextFactory, rulesetStore, gameHost)
|
||||||
|
{
|
||||||
|
this.testBeatmapManager = testBeatmapManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<ILive<BeatmapSetInfo>> Import(BeatmapSetInfo item, ArchiveReader archive = null, bool lowPriority = false, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
await testBeatmapManager.AllowImport.Task.ConfigureAwait(false);
|
||||||
|
return await (testBeatmapManager.CurrentImportTask = base.Import(item, archive, lowPriority, cancellationToken)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
osu.Game.Tests/Resources/loop-count.osb
Normal file
15
osu.Game.Tests/Resources/loop-count.osb
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[Events]
|
||||||
|
Sprite,Background,TopCentre,"zero-times.png",320,240
|
||||||
|
L,1000,0
|
||||||
|
F,0,0,1000,0,1
|
||||||
|
F,0,1000,2000,1,0
|
||||||
|
Sprite,Background,TopCentre,"one-time.png",320,240
|
||||||
|
L,4000,1
|
||||||
|
F,0,0,1000,0,1
|
||||||
|
F,0,1000,2000,1,0
|
||||||
|
Sprite,Background,TopCentre,"many-times.png",320,240
|
||||||
|
L,9000,40
|
||||||
|
F,0,0,1000,0,1
|
||||||
|
F,0,1000,2000,1,0
|
@ -141,7 +141,7 @@ namespace osu.Game.Tests.Scores.IO
|
|||||||
var beatmapManager = osu.Dependencies.Get<BeatmapManager>();
|
var beatmapManager = osu.Dependencies.Get<BeatmapManager>();
|
||||||
var scoreManager = osu.Dependencies.Get<ScoreManager>();
|
var scoreManager = osu.Dependencies.Get<ScoreManager>();
|
||||||
|
|
||||||
beatmapManager.Delete(beatmapManager.QueryBeatmapSet(s => s.Beatmaps.Any(b => b.ID == imported.Beatmap.ID)));
|
beatmapManager.Delete(beatmapManager.QueryBeatmapSet(s => s.Beatmaps.Any(b => b.ID == imported.BeatmapInfo.ID)));
|
||||||
Assert.That(scoreManager.Query(s => s.ID == imported.ID).DeletePending, Is.EqualTo(true));
|
Assert.That(scoreManager.Query(s => s.ID == imported.ID).DeletePending, Is.EqualTo(true));
|
||||||
|
|
||||||
var secondImport = await LoadScoreIntoOsu(osu, imported);
|
var secondImport = await LoadScoreIntoOsu(osu, imported);
|
||||||
@ -181,7 +181,7 @@ namespace osu.Game.Tests.Scores.IO
|
|||||||
{
|
{
|
||||||
var beatmapManager = osu.Dependencies.Get<BeatmapManager>();
|
var beatmapManager = osu.Dependencies.Get<BeatmapManager>();
|
||||||
|
|
||||||
score.Beatmap ??= beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First();
|
score.BeatmapInfo ??= beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First();
|
||||||
score.Ruleset ??= new OsuRuleset().RulesetInfo;
|
score.Ruleset ??= new OsuRuleset().RulesetInfo;
|
||||||
|
|
||||||
var scoreManager = osu.Dependencies.Get<ScoreManager>();
|
var scoreManager = osu.Dependencies.Get<ScoreManager>();
|
||||||
|
@ -196,7 +196,7 @@ namespace osu.Game.Tests.Skins.IO
|
|||||||
private async Task<SkinInfo> loadSkinIntoOsu(OsuGameBase osu, ArchiveReader archive = null)
|
private async Task<SkinInfo> loadSkinIntoOsu(OsuGameBase osu, ArchiveReader archive = null)
|
||||||
{
|
{
|
||||||
var skinManager = osu.Dependencies.Get<SkinManager>();
|
var skinManager = osu.Dependencies.Get<SkinManager>();
|
||||||
return await skinManager.Import(archive);
|
return (await skinManager.Import(archive)).Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Tests.Skins
|
|||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
var imported = beatmaps.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-beatmap.osz"))).Result;
|
var imported = beatmaps.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-beatmap.osz"))).Result;
|
||||||
beatmap = beatmaps.GetWorkingBeatmap(imported.Beatmaps[0]);
|
beatmap = beatmaps.GetWorkingBeatmap(imported.Value.Beatmaps[0]);
|
||||||
beatmap.LoadTrack();
|
beatmap.LoadTrack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Tests.Skins
|
|||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
var imported = skins.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-skin.osk"))).Result;
|
var imported = skins.Import(new ZipArchiveReader(TestResources.OpenResource("Archives/ogg-skin.osk"))).Result;
|
||||||
skin = skins.GetSkin(imported);
|
skin = skins.GetSkin(imported.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
127
osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs
Normal file
127
osu.Game.Tests/Visual/Audio/TestSceneAudioFilter.cs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// 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 ManagedBass.Fx;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Audio.Track;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Audio.Effects;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Audio
|
||||||
|
{
|
||||||
|
public class TestSceneAudioFilter : OsuTestScene
|
||||||
|
{
|
||||||
|
private OsuSpriteText lowpassText;
|
||||||
|
private AudioFilter lowpassFilter;
|
||||||
|
|
||||||
|
private OsuSpriteText highpassText;
|
||||||
|
private AudioFilter highpassFilter;
|
||||||
|
|
||||||
|
private Track track;
|
||||||
|
|
||||||
|
private WaveformTestBeatmap beatmap;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(AudioManager audio)
|
||||||
|
{
|
||||||
|
beatmap = new WaveformTestBeatmap(audio);
|
||||||
|
track = beatmap.LoadTrack();
|
||||||
|
|
||||||
|
Add(new FillFlowContainer
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
lowpassFilter = new AudioFilter(audio.TrackMixer),
|
||||||
|
highpassFilter = new AudioFilter(audio.TrackMixer, BQFType.HighPass),
|
||||||
|
lowpassText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Padding = new MarginPadding(20),
|
||||||
|
Text = $"Low Pass: {lowpassFilter.Cutoff.Value}hz",
|
||||||
|
Font = new FontUsage(size: 40)
|
||||||
|
},
|
||||||
|
new OsuSliderBar<int>
|
||||||
|
{
|
||||||
|
Width = 500,
|
||||||
|
Height = 50,
|
||||||
|
Padding = new MarginPadding(20),
|
||||||
|
Current = { BindTarget = lowpassFilter.Cutoff }
|
||||||
|
},
|
||||||
|
highpassText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Padding = new MarginPadding(20),
|
||||||
|
Text = $"High Pass: {highpassFilter.Cutoff.Value}hz",
|
||||||
|
Font = new FontUsage(size: 40)
|
||||||
|
},
|
||||||
|
new OsuSliderBar<int>
|
||||||
|
{
|
||||||
|
Width = 500,
|
||||||
|
Height = 50,
|
||||||
|
Padding = new MarginPadding(20),
|
||||||
|
Current = { BindTarget = highpassFilter.Cutoff }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
lowpassFilter.Cutoff.ValueChanged += e => lowpassText.Text = $"Low Pass: {e.NewValue}hz";
|
||||||
|
highpassFilter.Cutoff.ValueChanged += e => highpassText.Text = $"High Pass: {e.NewValue}hz";
|
||||||
|
}
|
||||||
|
|
||||||
|
[SetUpSteps]
|
||||||
|
public void SetUpSteps()
|
||||||
|
{
|
||||||
|
AddStep("Play Track", () => track.Start());
|
||||||
|
waitTrackPlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestLowPass()
|
||||||
|
{
|
||||||
|
AddStep("Filter Sweep", () =>
|
||||||
|
{
|
||||||
|
lowpassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF).Then()
|
||||||
|
.CutoffTo(0, 2000, Easing.OutCubic);
|
||||||
|
});
|
||||||
|
|
||||||
|
waitTrackPlay();
|
||||||
|
|
||||||
|
AddStep("Filter Sweep (reverse)", () =>
|
||||||
|
{
|
||||||
|
lowpassFilter.CutoffTo(0).Then()
|
||||||
|
.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF, 2000, Easing.InCubic);
|
||||||
|
});
|
||||||
|
|
||||||
|
waitTrackPlay();
|
||||||
|
AddStep("Stop track", () => track.Stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestHighPass()
|
||||||
|
{
|
||||||
|
AddStep("Filter Sweep", () =>
|
||||||
|
{
|
||||||
|
highpassFilter.CutoffTo(0).Then()
|
||||||
|
.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF, 2000, Easing.InCubic);
|
||||||
|
});
|
||||||
|
|
||||||
|
waitTrackPlay();
|
||||||
|
|
||||||
|
AddStep("Filter Sweep (reverse)", () =>
|
||||||
|
{
|
||||||
|
highpassFilter.CutoffTo(AudioFilter.MAX_LOWPASS_CUTOFF).Then()
|
||||||
|
.CutoffTo(0, 2000, Easing.OutCubic);
|
||||||
|
});
|
||||||
|
|
||||||
|
waitTrackPlay();
|
||||||
|
|
||||||
|
AddStep("Stop track", () => track.Stop());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitTrackPlay() => AddWaitStep("Let track play", 10);
|
||||||
|
}
|
||||||
|
}
|
@ -232,7 +232,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
AddStep("Transition to Results", () => player.Push(results = new FadeAccessibleResults(new ScoreInfo
|
AddStep("Transition to Results", () => player.Push(results = new FadeAccessibleResults(new ScoreInfo
|
||||||
{
|
{
|
||||||
User = new User { Username = "osu!" },
|
User = new User { Username = "osu!" },
|
||||||
Beatmap = new TestBeatmap(Ruleset.Value).BeatmapInfo,
|
BeatmapInfo = new TestBeatmap(Ruleset.Value).BeatmapInfo,
|
||||||
Ruleset = Ruleset.Value,
|
Ruleset = Ruleset.Value,
|
||||||
})));
|
})));
|
||||||
|
|
||||||
@ -286,7 +286,7 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
private void setupUserSettings()
|
private void setupUserSettings()
|
||||||
{
|
{
|
||||||
AddUntilStep("Song select is current", () => songSelect.IsCurrentScreen());
|
AddUntilStep("Song select is current", () => songSelect.IsCurrentScreen());
|
||||||
AddUntilStep("Song select has selection", () => songSelect.Carousel?.SelectedBeatmap != null);
|
AddUntilStep("Song select has selection", () => songSelect.Carousel?.SelectedBeatmapInfo != null);
|
||||||
AddStep("Set default user settings", () =>
|
AddStep("Set default user settings", () =>
|
||||||
{
|
{
|
||||||
SelectedMods.Value = SelectedMods.Value.Concat(new[] { new OsuModNoFail() }).ToArray();
|
SelectedMods.Value = SelectedMods.Value.Concat(new[] { new OsuModNoFail() }).ToArray();
|
||||||
|
132
osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs
Normal file
132
osu.Game.Tests/Visual/Editing/TestSceneBlueprintOrdering.cs
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
|
||||||
|
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osu.Game.Screens.Edit.Compose.Components;
|
||||||
|
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
|
{
|
||||||
|
public class TestSceneBlueprintOrdering : EditorTestScene
|
||||||
|
{
|
||||||
|
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||||
|
|
||||||
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||||
|
|
||||||
|
private EditorBlueprintContainer blueprintContainer
|
||||||
|
=> Editor.ChildrenOfType<EditorBlueprintContainer>().First();
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSelectedObjectHasPriorityWhenOverlapping()
|
||||||
|
{
|
||||||
|
var firstSlider = new Slider
|
||||||
|
{
|
||||||
|
Path = new SliderPath(new[]
|
||||||
|
{
|
||||||
|
new PathControlPoint(new Vector2()),
|
||||||
|
new PathControlPoint(new Vector2(150, -50)),
|
||||||
|
new PathControlPoint(new Vector2(300, 0))
|
||||||
|
}),
|
||||||
|
Position = new Vector2(0, 100)
|
||||||
|
};
|
||||||
|
var secondSlider = new Slider
|
||||||
|
{
|
||||||
|
Path = new SliderPath(new[]
|
||||||
|
{
|
||||||
|
new PathControlPoint(new Vector2()),
|
||||||
|
new PathControlPoint(new Vector2(-50, 50)),
|
||||||
|
new PathControlPoint(new Vector2(-100, 100))
|
||||||
|
}),
|
||||||
|
Position = new Vector2(200, 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
AddStep("add overlapping sliders", () =>
|
||||||
|
{
|
||||||
|
EditorBeatmap.Add(firstSlider);
|
||||||
|
EditorBeatmap.Add(secondSlider);
|
||||||
|
});
|
||||||
|
AddStep("select first slider", () => EditorBeatmap.SelectedHitObjects.Add(firstSlider));
|
||||||
|
|
||||||
|
AddStep("move mouse to common point", () =>
|
||||||
|
{
|
||||||
|
var pos = blueprintContainer.ChildrenOfType<PathControlPointPiece>().ElementAt(1).ScreenSpaceDrawQuad.Centre;
|
||||||
|
InputManager.MoveMouseTo(pos);
|
||||||
|
});
|
||||||
|
AddStep("right click", () => InputManager.Click(MouseButton.Right));
|
||||||
|
|
||||||
|
AddAssert("selection is unchanged", () => EditorBeatmap.SelectedHitObjects.Single() == firstSlider);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestOverlappingObjectsWithSameStartTime()
|
||||||
|
{
|
||||||
|
AddStep("add overlapping circles", () =>
|
||||||
|
{
|
||||||
|
EditorBeatmap.Add(createHitCircle(50, OsuPlayfield.BASE_SIZE / 2));
|
||||||
|
EditorBeatmap.Add(createHitCircle(50, OsuPlayfield.BASE_SIZE / 2 + new Vector2(-10, -20)));
|
||||||
|
EditorBeatmap.Add(createHitCircle(50, OsuPlayfield.BASE_SIZE / 2 + new Vector2(10, -20)));
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("click at centre of playfield", () =>
|
||||||
|
{
|
||||||
|
var hitObjectContainer = Editor.ChildrenOfType<HitObjectContainer>().Single();
|
||||||
|
var centre = hitObjectContainer.ToScreenSpace(OsuPlayfield.BASE_SIZE / 2);
|
||||||
|
InputManager.MoveMouseTo(centre);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("frontmost object selected", () =>
|
||||||
|
{
|
||||||
|
var hasCombo = Editor.ChildrenOfType<HitCircleSelectionBlueprint>().Single(b => b.IsSelected).Item as IHasComboInformation;
|
||||||
|
return hasCombo?.IndexInCurrentCombo == 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlacementOfConcurrentObjectWithDuration()
|
||||||
|
{
|
||||||
|
AddStep("seek to timing point", () => EditorClock.Seek(2170));
|
||||||
|
AddStep("add hit circle", () => EditorBeatmap.Add(createHitCircle(2170, Vector2.Zero)));
|
||||||
|
|
||||||
|
AddStep("choose spinner placement tool", () =>
|
||||||
|
{
|
||||||
|
InputManager.Key(Key.Number4);
|
||||||
|
var hitObjectContainer = Editor.ChildrenOfType<HitObjectContainer>().Single();
|
||||||
|
InputManager.MoveMouseTo(hitObjectContainer.ScreenSpaceDrawQuad.Centre);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("begin placing spinner", () =>
|
||||||
|
{
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
AddStep("end placing spinner", () =>
|
||||||
|
{
|
||||||
|
EditorClock.Seek(2500);
|
||||||
|
InputManager.Click(MouseButton.Right);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("two timeline blueprints present", () => Editor.ChildrenOfType<TimelineHitObjectBlueprint>().Count() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HitCircle createHitCircle(double startTime, Vector2 position) => new HitCircle
|
||||||
|
{
|
||||||
|
StartTime = startTime,
|
||||||
|
Position = position,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,70 +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.Linq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using osu.Framework.Testing;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
using osu.Game.Rulesets.Osu;
|
|
||||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
|
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
|
||||||
using osu.Game.Screens.Edit.Compose.Components;
|
|
||||||
using osu.Game.Tests.Beatmaps;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Input;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editing
|
|
||||||
{
|
|
||||||
public class TestSceneBlueprintSelection : EditorTestScene
|
|
||||||
{
|
|
||||||
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
|
||||||
|
|
||||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
|
||||||
|
|
||||||
private EditorBlueprintContainer blueprintContainer
|
|
||||||
=> Editor.ChildrenOfType<EditorBlueprintContainer>().First();
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestSelectedObjectHasPriorityWhenOverlapping()
|
|
||||||
{
|
|
||||||
var firstSlider = new Slider
|
|
||||||
{
|
|
||||||
Path = new SliderPath(new[]
|
|
||||||
{
|
|
||||||
new PathControlPoint(new Vector2()),
|
|
||||||
new PathControlPoint(new Vector2(150, -50)),
|
|
||||||
new PathControlPoint(new Vector2(300, 0))
|
|
||||||
}),
|
|
||||||
Position = new Vector2(0, 100)
|
|
||||||
};
|
|
||||||
var secondSlider = new Slider
|
|
||||||
{
|
|
||||||
Path = new SliderPath(new[]
|
|
||||||
{
|
|
||||||
new PathControlPoint(new Vector2()),
|
|
||||||
new PathControlPoint(new Vector2(-50, 50)),
|
|
||||||
new PathControlPoint(new Vector2(-100, 100))
|
|
||||||
}),
|
|
||||||
Position = new Vector2(200, 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
AddStep("add overlapping sliders", () =>
|
|
||||||
{
|
|
||||||
EditorBeatmap.Add(firstSlider);
|
|
||||||
EditorBeatmap.Add(secondSlider);
|
|
||||||
});
|
|
||||||
AddStep("select first slider", () => EditorBeatmap.SelectedHitObjects.Add(firstSlider));
|
|
||||||
|
|
||||||
AddStep("move mouse to common point", () =>
|
|
||||||
{
|
|
||||||
var pos = blueprintContainer.ChildrenOfType<PathControlPointPiece>().ElementAt(1).ScreenSpaceDrawQuad.Centre;
|
|
||||||
InputManager.MoveMouseTo(pos);
|
|
||||||
});
|
|
||||||
AddStep("right click", () => InputManager.Click(MouseButton.Right));
|
|
||||||
|
|
||||||
AddAssert("selection is unchanged", () => EditorBeatmap.SelectedHitObjects.Single() == firstSlider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,14 +20,14 @@ using osuTK.Input;
|
|||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editing
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
{
|
{
|
||||||
public class TestSceneEditorSelection : EditorTestScene
|
public class TestSceneComposerSelection : EditorTestScene
|
||||||
{
|
{
|
||||||
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||||
|
|
||||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||||
|
|
||||||
private EditorBlueprintContainer blueprintContainer
|
private ComposeBlueprintContainer blueprintContainer
|
||||||
=> Editor.ChildrenOfType<EditorBlueprintContainer>().First();
|
=> Editor.ChildrenOfType<ComposeBlueprintContainer>().First();
|
||||||
|
|
||||||
private void moveMouseToObject(Func<HitObject> targetFunc)
|
private void moveMouseToObject(Func<HitObject> targetFunc)
|
||||||
{
|
{
|
62
osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs
Normal file
62
osu.Game.Tests/Visual/Editing/TestSceneEditorSaving.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Rulesets.Edit;
|
||||||
|
using osu.Game.Screens.Edit;
|
||||||
|
using osu.Game.Screens.Menu;
|
||||||
|
using osu.Game.Screens.Select;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
|
{
|
||||||
|
public class TestSceneEditorSaving : OsuGameTestScene
|
||||||
|
{
|
||||||
|
private Editor editor => Game.ChildrenOfType<Editor>().FirstOrDefault();
|
||||||
|
|
||||||
|
private EditorBeatmap editorBeatmap => (EditorBeatmap)editor.Dependencies.Get(typeof(EditorBeatmap));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests the general expected flow of creating a new beatmap, saving it, then loading it back from song select.
|
||||||
|
/// </summary>
|
||||||
|
[Test]
|
||||||
|
public void TestNewBeatmapSaveThenLoad()
|
||||||
|
{
|
||||||
|
AddStep("set default beatmap", () => Game.Beatmap.SetDefault());
|
||||||
|
|
||||||
|
PushAndConfirm(() => new EditorLoader());
|
||||||
|
|
||||||
|
AddUntilStep("wait for editor load", () => editor != null);
|
||||||
|
|
||||||
|
AddStep("Add timing point", () => editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint()));
|
||||||
|
|
||||||
|
AddStep("Enter compose mode", () => InputManager.Key(Key.F1));
|
||||||
|
AddUntilStep("Wait for compose mode load", () => editor.ChildrenOfType<HitObjectComposer>().FirstOrDefault()?.IsLoaded == true);
|
||||||
|
|
||||||
|
AddStep("Change to placement mode", () => InputManager.Key(Key.Number2));
|
||||||
|
AddStep("Move to playfield", () => InputManager.MoveMouseTo(Game.ScreenSpaceDrawQuad.Centre));
|
||||||
|
AddStep("Place single hitcircle", () => InputManager.Click(MouseButton.Left));
|
||||||
|
|
||||||
|
AddStep("Save and exit", () =>
|
||||||
|
{
|
||||||
|
InputManager.Keys(PlatformAction.Save);
|
||||||
|
InputManager.Key(Key.Escape);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("Wait for main menu", () => Game.ScreenStack.CurrentScreen is MainMenu);
|
||||||
|
|
||||||
|
PushAndConfirm(() => new PlaySongSelect());
|
||||||
|
|
||||||
|
AddUntilStep("Wait for beatmap selected", () => !Game.Beatmap.IsDefault);
|
||||||
|
AddStep("Open options", () => InputManager.Key(Key.F3));
|
||||||
|
AddStep("Enter editor", () => InputManager.Key(Key.Number5));
|
||||||
|
|
||||||
|
AddUntilStep("Wait for editor load", () => editor != null);
|
||||||
|
AddAssert("Beatmap contains single hitcircle", () => editorBeatmap.HitObjects.Count == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
266
osu.Game.Tests/Visual/Editing/TestSceneTimelineSelection.cs
Normal file
266
osu.Game.Tests/Visual/Editing/TestSceneTimelineSelection.cs
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
|
{
|
||||||
|
public class TestSceneTimelineSelection : EditorTestScene
|
||||||
|
{
|
||||||
|
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||||
|
|
||||||
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||||
|
|
||||||
|
private TimelineBlueprintContainer blueprintContainer
|
||||||
|
=> Editor.ChildrenOfType<TimelineBlueprintContainer>().First();
|
||||||
|
|
||||||
|
private void moveMouseToObject(Func<HitObject> targetFunc)
|
||||||
|
{
|
||||||
|
AddStep("move mouse to object", () =>
|
||||||
|
{
|
||||||
|
var pos = blueprintContainer.SelectionBlueprints
|
||||||
|
.First(s => s.Item == targetFunc())
|
||||||
|
.ChildrenOfType<TimelineHitObjectBlueprint>()
|
||||||
|
.First().ScreenSpaceDrawQuad.Centre;
|
||||||
|
|
||||||
|
InputManager.MoveMouseTo(pos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestNudgeSelection()
|
||||||
|
{
|
||||||
|
HitCircle[] addedObjects = null;
|
||||||
|
|
||||||
|
AddStep("add hitobjects", () => EditorBeatmap.AddRange(addedObjects = new[]
|
||||||
|
{
|
||||||
|
new HitCircle { StartTime = 100 },
|
||||||
|
new HitCircle { StartTime = 200, Position = new Vector2(100) },
|
||||||
|
new HitCircle { StartTime = 300, Position = new Vector2(200) },
|
||||||
|
new HitCircle { StartTime = 400, Position = new Vector2(300) },
|
||||||
|
}));
|
||||||
|
|
||||||
|
AddStep("select objects", () => EditorBeatmap.SelectedHitObjects.AddRange(addedObjects));
|
||||||
|
|
||||||
|
AddStep("nudge forwards", () => InputManager.Key(Key.K));
|
||||||
|
AddAssert("objects moved forwards in time", () => addedObjects[0].StartTime > 100);
|
||||||
|
|
||||||
|
AddStep("nudge backwards", () => InputManager.Key(Key.J));
|
||||||
|
AddAssert("objects reverted to original position", () => addedObjects[0].StartTime == 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBasicSelect()
|
||||||
|
{
|
||||||
|
var addedObject = new HitCircle { StartTime = 100 };
|
||||||
|
AddStep("add hitobject", () => EditorBeatmap.Add(addedObject));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObject);
|
||||||
|
AddStep("left click", () => InputManager.Click(MouseButton.Left));
|
||||||
|
|
||||||
|
AddAssert("hitobject selected", () => EditorBeatmap.SelectedHitObjects.Single() == addedObject);
|
||||||
|
|
||||||
|
var addedObject2 = new HitCircle
|
||||||
|
{
|
||||||
|
StartTime = 200,
|
||||||
|
Position = new Vector2(100),
|
||||||
|
};
|
||||||
|
|
||||||
|
AddStep("add one more hitobject", () => EditorBeatmap.Add(addedObject2));
|
||||||
|
AddAssert("selection unchanged", () => EditorBeatmap.SelectedHitObjects.Single() == addedObject);
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObject2);
|
||||||
|
AddStep("left click", () => InputManager.Click(MouseButton.Left));
|
||||||
|
AddAssert("hitobject selected", () => EditorBeatmap.SelectedHitObjects.Single() == addedObject2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMultiSelect()
|
||||||
|
{
|
||||||
|
var addedObjects = new[]
|
||||||
|
{
|
||||||
|
new HitCircle { StartTime = 100 },
|
||||||
|
new HitCircle { StartTime = 200, Position = new Vector2(100) },
|
||||||
|
new HitCircle { StartTime = 300, Position = new Vector2(200) },
|
||||||
|
new HitCircle { StartTime = 400, Position = new Vector2(300) },
|
||||||
|
};
|
||||||
|
|
||||||
|
AddStep("add hitobjects", () => EditorBeatmap.AddRange(addedObjects));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[0]);
|
||||||
|
AddStep("click first", () => InputManager.Click(MouseButton.Left));
|
||||||
|
|
||||||
|
AddAssert("hitobject selected", () => EditorBeatmap.SelectedHitObjects.Single() == addedObjects[0]);
|
||||||
|
|
||||||
|
AddStep("hold control", () => InputManager.PressKey(Key.ControlLeft));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[1]);
|
||||||
|
AddStep("click second", () => InputManager.Click(MouseButton.Left));
|
||||||
|
AddAssert("2 hitobjects selected", () => EditorBeatmap.SelectedHitObjects.Count == 2 && EditorBeatmap.SelectedHitObjects.Contains(addedObjects[1]));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[2]);
|
||||||
|
AddStep("click third", () => InputManager.Click(MouseButton.Left));
|
||||||
|
AddAssert("3 hitobjects selected", () => EditorBeatmap.SelectedHitObjects.Count == 3 && EditorBeatmap.SelectedHitObjects.Contains(addedObjects[2]));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[1]);
|
||||||
|
AddStep("click second", () => InputManager.Click(MouseButton.Left));
|
||||||
|
AddAssert("2 hitobjects selected", () => EditorBeatmap.SelectedHitObjects.Count == 2 && !EditorBeatmap.SelectedHitObjects.Contains(addedObjects[1]));
|
||||||
|
|
||||||
|
AddStep("release control", () => InputManager.ReleaseKey(Key.ControlLeft));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBasicDeselect()
|
||||||
|
{
|
||||||
|
var addedObject = new HitCircle { StartTime = 100 };
|
||||||
|
AddStep("add hitobject", () => EditorBeatmap.Add(addedObject));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObject);
|
||||||
|
AddStep("left click", () => InputManager.Click(MouseButton.Left));
|
||||||
|
|
||||||
|
AddAssert("hitobject selected", () => EditorBeatmap.SelectedHitObjects.Single() == addedObject);
|
||||||
|
|
||||||
|
AddStep("click away", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(Editor.ChildrenOfType<TimelineArea>().Single().ScreenSpaceDrawQuad.TopLeft + Vector2.One);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("selection lost", () => EditorBeatmap.SelectedHitObjects.Count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestQuickDelete()
|
||||||
|
{
|
||||||
|
var addedObject = new HitCircle
|
||||||
|
{
|
||||||
|
StartTime = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
AddStep("add hitobject", () => EditorBeatmap.Add(addedObject));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObject);
|
||||||
|
|
||||||
|
AddStep("hold shift", () => InputManager.PressKey(Key.ShiftLeft));
|
||||||
|
AddStep("right click", () => InputManager.Click(MouseButton.Right));
|
||||||
|
AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft));
|
||||||
|
|
||||||
|
AddAssert("no hitobjects in beatmap", () => EditorBeatmap.HitObjects.Count == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestRangeSelect()
|
||||||
|
{
|
||||||
|
var addedObjects = new[]
|
||||||
|
{
|
||||||
|
new HitCircle { StartTime = 100 },
|
||||||
|
new HitCircle { StartTime = 200, Position = new Vector2(100) },
|
||||||
|
new HitCircle { StartTime = 300, Position = new Vector2(200) },
|
||||||
|
new HitCircle { StartTime = 400, Position = new Vector2(300) },
|
||||||
|
new HitCircle { StartTime = 500, Position = new Vector2(400) },
|
||||||
|
};
|
||||||
|
|
||||||
|
AddStep("add hitobjects", () => EditorBeatmap.AddRange(addedObjects));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[1]);
|
||||||
|
AddStep("click second", () => InputManager.Click(MouseButton.Left));
|
||||||
|
|
||||||
|
AddAssert("hitobject selected", () => EditorBeatmap.SelectedHitObjects.Single() == addedObjects[1]);
|
||||||
|
|
||||||
|
AddStep("hold shift", () => InputManager.PressKey(Key.ShiftLeft));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[3]);
|
||||||
|
AddStep("click fourth", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(addedObjects.Skip(1).Take(3));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[0]);
|
||||||
|
AddStep("click first", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(addedObjects.Take(2));
|
||||||
|
|
||||||
|
AddStep("clear selection", () => EditorBeatmap.SelectedHitObjects.Clear());
|
||||||
|
AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[0]);
|
||||||
|
AddStep("click first", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(addedObjects.Take(1));
|
||||||
|
|
||||||
|
AddStep("hold ctrl", () => InputManager.PressKey(Key.ControlLeft));
|
||||||
|
moveMouseToObject(() => addedObjects[2]);
|
||||||
|
AddStep("click third", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(new[] { addedObjects[0], addedObjects[2] });
|
||||||
|
|
||||||
|
AddStep("hold shift", () => InputManager.PressKey(Key.ShiftLeft));
|
||||||
|
moveMouseToObject(() => addedObjects[4]);
|
||||||
|
AddStep("click fifth", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(addedObjects.Except(new[] { addedObjects[1] }));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[0]);
|
||||||
|
AddStep("click first", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(addedObjects);
|
||||||
|
|
||||||
|
AddStep("clear selection", () => EditorBeatmap.SelectedHitObjects.Clear());
|
||||||
|
moveMouseToObject(() => addedObjects[0]);
|
||||||
|
AddStep("click first", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(addedObjects.Take(1));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[1]);
|
||||||
|
AddStep("click first", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(addedObjects.Take(2));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[2]);
|
||||||
|
AddStep("click first", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(addedObjects.Take(3));
|
||||||
|
|
||||||
|
AddStep("release keys", () =>
|
||||||
|
{
|
||||||
|
InputManager.ReleaseKey(Key.ControlLeft);
|
||||||
|
InputManager.ReleaseKey(Key.ShiftLeft);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestRangeSelectAfterExternalSelection()
|
||||||
|
{
|
||||||
|
var addedObjects = new[]
|
||||||
|
{
|
||||||
|
new HitCircle { StartTime = 100 },
|
||||||
|
new HitCircle { StartTime = 200, Position = new Vector2(100) },
|
||||||
|
new HitCircle { StartTime = 300, Position = new Vector2(200) },
|
||||||
|
new HitCircle { StartTime = 400, Position = new Vector2(300) },
|
||||||
|
};
|
||||||
|
|
||||||
|
AddStep("add hitobjects", () => EditorBeatmap.AddRange(addedObjects));
|
||||||
|
|
||||||
|
AddStep("select all without mouse", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects));
|
||||||
|
assertSelectionIs(addedObjects);
|
||||||
|
|
||||||
|
AddStep("hold down shift", () => InputManager.PressKey(Key.ShiftLeft));
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[1]);
|
||||||
|
AddStep("click second object", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(addedObjects);
|
||||||
|
|
||||||
|
moveMouseToObject(() => addedObjects[3]);
|
||||||
|
AddStep("click fourth object", () => InputManager.Click(MouseButton.Left));
|
||||||
|
assertSelectionIs(addedObjects.Skip(1));
|
||||||
|
|
||||||
|
AddStep("release shift", () => InputManager.ReleaseKey(Key.ShiftLeft));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertSelectionIs(IEnumerable<HitObject> hitObjects)
|
||||||
|
=> AddAssert("correct hitobjects selected", () => EditorBeatmap.SelectedHitObjects.OrderBy(h => h.StartTime).SequenceEqual(hitObjects));
|
||||||
|
}
|
||||||
|
}
|
@ -42,6 +42,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
public void TestEmptyLegacyBeatmapSkinFallsBack()
|
public void TestEmptyLegacyBeatmapSkinFallsBack()
|
||||||
{
|
{
|
||||||
CreateSkinTest(SkinInfo.Default, () => new LegacyBeatmapSkin(new BeatmapInfo(), null, null));
|
CreateSkinTest(SkinInfo.Default, () => new LegacyBeatmapSkin(new BeatmapInfo(), null, null));
|
||||||
|
AddUntilStep("wait for hud load", () => Player.ChildrenOfType<SkinnableTargetContainer>().All(c => c.ComponentsLoaded));
|
||||||
AddAssert("hud from default skin", () => AssertComponentsFromExpectedSource(SkinnableTarget.MainHUDComponents, skinManager.CurrentSkin.Value));
|
AddAssert("hud from default skin", () => AssertComponentsFromExpectedSource(SkinnableTarget.MainHUDComponents, skinManager.CurrentSkin.Value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,18 +85,18 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
Remove(expectedComponentsAdjustmentContainer);
|
Remove(expectedComponentsAdjustmentContainer);
|
||||||
|
|
||||||
return almostEqual(actualInfo, expectedInfo);
|
return almostEqual(actualInfo, expectedInfo);
|
||||||
|
|
||||||
static bool almostEqual(SkinnableInfo info, SkinnableInfo other) =>
|
|
||||||
other != null
|
|
||||||
&& info.Type == other.Type
|
|
||||||
&& info.Anchor == other.Anchor
|
|
||||||
&& info.Origin == other.Origin
|
|
||||||
&& Precision.AlmostEquals(info.Position, other.Position)
|
|
||||||
&& Precision.AlmostEquals(info.Scale, other.Scale)
|
|
||||||
&& Precision.AlmostEquals(info.Rotation, other.Rotation)
|
|
||||||
&& info.Children.SequenceEqual(other.Children, new FuncEqualityComparer<SkinnableInfo>(almostEqual));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool almostEqual(SkinnableInfo info, SkinnableInfo other) =>
|
||||||
|
other != null
|
||||||
|
&& info.Type == other.Type
|
||||||
|
&& info.Anchor == other.Anchor
|
||||||
|
&& info.Origin == other.Origin
|
||||||
|
&& Precision.AlmostEquals(info.Position, other.Position, 1)
|
||||||
|
&& Precision.AlmostEquals(info.Scale, other.Scale)
|
||||||
|
&& Precision.AlmostEquals(info.Rotation, other.Rotation)
|
||||||
|
&& info.Children.SequenceEqual(other.Children, new FuncEqualityComparer<SkinnableInfo>(almostEqual));
|
||||||
|
|
||||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)
|
||||||
=> new CustomSkinWorkingBeatmap(beatmap, storyboard, Clock, Audio, currentBeatmapSkin);
|
=> new CustomSkinWorkingBeatmap(beatmap, storyboard, Clock, Audio, currentBeatmapSkin);
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
var beatmap = createBeatmap();
|
var beatmap = createBeatmap();
|
||||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range });
|
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range });
|
||||||
beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2;
|
beatmap.Difficulty.SliderMultiplier = 2;
|
||||||
|
|
||||||
createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true);
|
createTest(beatmap, d => d.RelativeScaleBeatLengthsOverride = true);
|
||||||
AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 5000);
|
AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 5000);
|
||||||
@ -196,7 +196,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
var beatmap = createBeatmap();
|
var beatmap = createBeatmap();
|
||||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range });
|
beatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = time_range });
|
||||||
beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier = 2;
|
beatmap.Difficulty.SliderMultiplier = 2;
|
||||||
|
|
||||||
createTest(beatmap);
|
createTest(beatmap);
|
||||||
AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 2000);
|
AddStep("adjust time range", () => drawableRuleset.TimeRange.Value = 2000);
|
||||||
|
@ -55,7 +55,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
var beatmap = new Beatmap
|
var beatmap = new Beatmap
|
||||||
{
|
{
|
||||||
BeatmapInfo = { BaseDifficulty = { ApproachRate = 9 } },
|
Difficulty = { ApproachRate = 9 },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < 15; i++)
|
for (int i = 0; i < 15; i++)
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Cursor;
|
using osu.Game.Graphics.Cursor;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -39,6 +41,45 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
confirmClockRunning(true);
|
confirmClockRunning(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPauseWithLargeOffset()
|
||||||
|
{
|
||||||
|
double lastTime;
|
||||||
|
bool alwaysGoingForward = true;
|
||||||
|
|
||||||
|
AddStep("force large offset", () =>
|
||||||
|
{
|
||||||
|
var offset = (BindableDouble)LocalConfig.GetBindable<double>(OsuSetting.AudioOffset);
|
||||||
|
|
||||||
|
// use a large negative offset to avoid triggering a fail from forwards seeking.
|
||||||
|
offset.MinValue = -5000;
|
||||||
|
offset.Value = -5000;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("add time forward check hook", () =>
|
||||||
|
{
|
||||||
|
lastTime = double.MinValue;
|
||||||
|
alwaysGoingForward = true;
|
||||||
|
|
||||||
|
Player.OnUpdate += _ =>
|
||||||
|
{
|
||||||
|
double currentTime = Player.GameplayClockContainer.CurrentTime;
|
||||||
|
alwaysGoingForward &= currentTime >= lastTime;
|
||||||
|
lastTime = currentTime;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("move cursor outside", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft - new Vector2(10)));
|
||||||
|
|
||||||
|
pauseAndConfirm();
|
||||||
|
|
||||||
|
resumeAndConfirm();
|
||||||
|
|
||||||
|
AddAssert("time didn't go backwards", () => alwaysGoingForward);
|
||||||
|
|
||||||
|
AddStep("reset offset", () => LocalConfig.SetValue(OsuSetting.AudioOffset, 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestPauseResume()
|
public void TestPauseResume()
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,108 @@
|
|||||||
|
// 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.Diagnostics;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Judgements;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
using osu.Game.Screens.Play.HUD;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
|
{
|
||||||
|
public class TestScenePerformancePointsCounter : OsuTestScene
|
||||||
|
{
|
||||||
|
[Cached]
|
||||||
|
private GameplayState gameplayState;
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private ScoreProcessor scoreProcessor;
|
||||||
|
|
||||||
|
private int iteration;
|
||||||
|
private PerformancePointsCounter counter;
|
||||||
|
|
||||||
|
public TestScenePerformancePointsCounter()
|
||||||
|
{
|
||||||
|
var ruleset = CreateRuleset();
|
||||||
|
|
||||||
|
Debug.Assert(ruleset != null);
|
||||||
|
|
||||||
|
var beatmap = CreateWorkingBeatmap(ruleset.RulesetInfo)
|
||||||
|
.GetPlayableBeatmap(ruleset.RulesetInfo);
|
||||||
|
|
||||||
|
gameplayState = new GameplayState(beatmap, ruleset);
|
||||||
|
scoreProcessor = new ScoreProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Ruleset CreateRuleset() => new OsuRuleset();
|
||||||
|
|
||||||
|
[SetUpSteps]
|
||||||
|
public void SetUpSteps()
|
||||||
|
{
|
||||||
|
AddStep("Create counter", () =>
|
||||||
|
{
|
||||||
|
iteration = 0;
|
||||||
|
|
||||||
|
Child = counter = new PerformancePointsCounter
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Scale = new Vector2(5),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBasicCounting()
|
||||||
|
{
|
||||||
|
int previousValue = 0;
|
||||||
|
|
||||||
|
AddAssert("counter displaying zero", () => counter.Current.Value == 0);
|
||||||
|
|
||||||
|
AddRepeatStep("Add judgement", applyOneJudgement, 10);
|
||||||
|
|
||||||
|
AddUntilStep("counter non-zero", () => counter.Current.Value > 0);
|
||||||
|
AddUntilStep("counter opaque", () => counter.Child.Alpha == 1);
|
||||||
|
|
||||||
|
AddStep("Revert judgement", () =>
|
||||||
|
{
|
||||||
|
previousValue = counter.Current.Value;
|
||||||
|
|
||||||
|
scoreProcessor.RevertResult(new JudgementResult(new HitObject(), new OsuJudgement()));
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("counter decreased", () => counter.Current.Value < previousValue);
|
||||||
|
|
||||||
|
AddStep("Add judgement", applyOneJudgement);
|
||||||
|
|
||||||
|
AddUntilStep("counter non-zero", () => counter.Current.Value > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyOneJudgement()
|
||||||
|
{
|
||||||
|
var scoreInfo = gameplayState.Score.ScoreInfo;
|
||||||
|
|
||||||
|
scoreInfo.MaxCombo = iteration * 1000;
|
||||||
|
scoreInfo.Accuracy = 1;
|
||||||
|
scoreInfo.Statistics[HitResult.Great] = iteration * 1000;
|
||||||
|
|
||||||
|
scoreProcessor.ApplyResult(new OsuJudgementResult(new HitObject
|
||||||
|
{
|
||||||
|
StartTime = iteration * 10000,
|
||||||
|
}, new OsuJudgement())
|
||||||
|
{
|
||||||
|
Type = HitResult.Perfect,
|
||||||
|
});
|
||||||
|
|
||||||
|
iteration++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -205,7 +205,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen());
|
AddUntilStep("wait for loader to become current", () => loader.IsCurrentScreen());
|
||||||
AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre));
|
AddStep("mouse in centre", () => InputManager.MoveMouseTo(loader.ScreenSpaceDrawQuad.Centre));
|
||||||
AddUntilStep("wait for player to be current", () => player.IsCurrentScreen());
|
AddUntilStep("wait for player to be current", () => player.IsCurrentScreen());
|
||||||
AddStep("retrieve mods", () => playerMod1 = (TestMod)player.Mods.Value.Single());
|
AddStep("retrieve mods", () => playerMod1 = (TestMod)player.GameplayState.Mods.Single());
|
||||||
AddAssert("game mods not applied", () => gameMod.Applied == false);
|
AddAssert("game mods not applied", () => gameMod.Applied == false);
|
||||||
AddAssert("player mods applied", () => playerMod1.Applied);
|
AddAssert("player mods applied", () => playerMod1.Applied);
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for player to be current", () => player.IsCurrentScreen());
|
AddUntilStep("wait for player to be current", () => player.IsCurrentScreen());
|
||||||
AddStep("retrieve mods", () => playerMod2 = (TestMod)player.Mods.Value.Single());
|
AddStep("retrieve mods", () => playerMod2 = (TestMod)player.GameplayState.Mods.Single());
|
||||||
AddAssert("game mods not applied", () => gameMod.Applied == false);
|
AddAssert("game mods not applied", () => gameMod.Applied == false);
|
||||||
AddAssert("player has different mods", () => playerMod1 != playerMod2);
|
AddAssert("player has different mods", () => playerMod1 != playerMod2);
|
||||||
AddAssert("player mods applied", () => playerMod2.Applied);
|
AddAssert("player mods applied", () => playerMod2.Applied);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Online;
|
using osu.Game.Online;
|
||||||
@ -8,34 +9,29 @@ using osu.Game.Online.API.Requests.Responses;
|
|||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Screens.Ranking;
|
using osu.Game.Screens.Ranking;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Gameplay
|
namespace osu.Game.Tests.Visual.Gameplay
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneReplayDownloadButton : OsuTestScene
|
public class TestSceneReplayDownloadButton : OsuManualInputManagerTestScene
|
||||||
{
|
{
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private RulesetStore rulesets { get; set; }
|
private RulesetStore rulesets { get; set; }
|
||||||
|
|
||||||
private TestReplayDownloadButton downloadButton;
|
private TestReplayDownloadButton downloadButton;
|
||||||
|
|
||||||
public TestSceneReplayDownloadButton()
|
[Test]
|
||||||
|
public void TestDisplayStates()
|
||||||
{
|
{
|
||||||
createButton(true);
|
AddStep(@"create button with replay", () =>
|
||||||
AddStep(@"downloading state", () => downloadButton.SetDownloadState(DownloadState.Downloading));
|
|
||||||
AddStep(@"locally available state", () => downloadButton.SetDownloadState(DownloadState.LocallyAvailable));
|
|
||||||
AddStep(@"not downloaded state", () => downloadButton.SetDownloadState(DownloadState.NotDownloaded));
|
|
||||||
createButton(false);
|
|
||||||
createButtonNoScore();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createButton(bool withReplay)
|
|
||||||
{
|
|
||||||
AddStep(withReplay ? @"create button with replay" : "create button without replay", () =>
|
|
||||||
{
|
{
|
||||||
Child = downloadButton = new TestReplayDownloadButton(getScoreInfo(withReplay))
|
Child = downloadButton = new TestReplayDownloadButton(getScoreInfo(true))
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -43,9 +39,81 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for load", () => downloadButton.IsLoaded);
|
AddUntilStep("wait for load", () => downloadButton.IsLoaded);
|
||||||
|
|
||||||
|
AddStep(@"downloading state", () => downloadButton.SetDownloadState(DownloadState.Downloading));
|
||||||
|
AddStep(@"locally available state", () => downloadButton.SetDownloadState(DownloadState.LocallyAvailable));
|
||||||
|
AddStep(@"not downloaded state", () => downloadButton.SetDownloadState(DownloadState.NotDownloaded));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createButtonNoScore()
|
[Test]
|
||||||
|
public void TestButtonWithReplayStartsDownload()
|
||||||
|
{
|
||||||
|
bool downloadStarted = false;
|
||||||
|
bool downloadFinished = false;
|
||||||
|
|
||||||
|
AddStep(@"create button with replay", () =>
|
||||||
|
{
|
||||||
|
downloadStarted = false;
|
||||||
|
downloadFinished = false;
|
||||||
|
|
||||||
|
Child = downloadButton = new TestReplayDownloadButton(getScoreInfo(true))
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
};
|
||||||
|
|
||||||
|
downloadButton.State.BindValueChanged(state =>
|
||||||
|
{
|
||||||
|
switch (state.NewValue)
|
||||||
|
{
|
||||||
|
case DownloadState.Downloading:
|
||||||
|
downloadStarted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state.OldValue)
|
||||||
|
{
|
||||||
|
case DownloadState.Downloading:
|
||||||
|
downloadFinished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for load", () => downloadButton.IsLoaded);
|
||||||
|
|
||||||
|
AddAssert("state is available", () => downloadButton.State.Value == DownloadState.NotDownloaded);
|
||||||
|
|
||||||
|
AddStep("click button", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(downloadButton);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("state entered downloading", () => downloadStarted);
|
||||||
|
AddUntilStep("state left downloading", () => downloadFinished);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestButtonWithoutReplay()
|
||||||
|
{
|
||||||
|
AddStep("create button without replay", () =>
|
||||||
|
{
|
||||||
|
Child = downloadButton = new TestReplayDownloadButton(getScoreInfo(false))
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for load", () => downloadButton.IsLoaded);
|
||||||
|
|
||||||
|
AddAssert("state is not downloaded", () => downloadButton.State.Value == DownloadState.NotDownloaded);
|
||||||
|
AddAssert("button is not enabled", () => !downloadButton.ChildrenOfType<DownloadButton>().First().Enabled.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CreateButtonWithNoScore()
|
||||||
{
|
{
|
||||||
AddStep("create button with null score", () =>
|
AddStep("create button with null score", () =>
|
||||||
{
|
{
|
||||||
@ -57,6 +125,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for load", () => downloadButton.IsLoaded);
|
AddUntilStep("wait for load", () => downloadButton.IsLoaded);
|
||||||
|
|
||||||
|
AddAssert("state is not downloaded", () => downloadButton.State.Value == DownloadState.NotDownloaded);
|
||||||
|
AddAssert("button is not enabled", () => !downloadButton.ChildrenOfType<DownloadButton>().First().Enabled.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScoreInfo getScoreInfo(bool replayAvailable)
|
private ScoreInfo getScoreInfo(bool replayAvailable)
|
||||||
@ -78,6 +149,8 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
public void SetDownloadState(DownloadState state) => State.Value = state;
|
public void SetDownloadState(DownloadState state) => State.Value = state;
|
||||||
|
|
||||||
|
public new Bindable<DownloadState> State => base.State;
|
||||||
|
|
||||||
public TestReplayDownloadButton(ScoreInfo score)
|
public TestReplayDownloadButton(ScoreInfo score)
|
||||||
: base(score)
|
: base(score)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -17,6 +18,8 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Replays;
|
using osu.Game.Rulesets.Replays;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -38,7 +41,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
private TestReplayRecorder recorder;
|
private TestReplayRecorder recorder;
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private GameplayBeatmap gameplayBeatmap = new GameplayBeatmap(new Beatmap());
|
private GameplayState gameplayState = new GameplayState(new Beatmap(), new OsuRuleset(), Array.Empty<Mod>());
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
@ -57,7 +60,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
Recorder = recorder = new TestReplayRecorder(new Score
|
Recorder = recorder = new TestReplayRecorder(new Score
|
||||||
{
|
{
|
||||||
Replay = replay,
|
Replay = replay,
|
||||||
ScoreInfo = { Beatmap = gameplayBeatmap.BeatmapInfo }
|
ScoreInfo = { BeatmapInfo = gameplayState.Beatmap.BeatmapInfo }
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos),
|
ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -13,6 +14,8 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Replays;
|
using osu.Game.Rulesets.Replays;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -30,7 +33,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
private readonly TestRulesetInputManager recordingManager;
|
private readonly TestRulesetInputManager recordingManager;
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private GameplayBeatmap gameplayBeatmap = new GameplayBeatmap(new Beatmap());
|
private GameplayState gameplayState = new GameplayState(new Beatmap(), new OsuRuleset(), Array.Empty<Mod>());
|
||||||
|
|
||||||
public TestSceneReplayRecording()
|
public TestSceneReplayRecording()
|
||||||
{
|
{
|
||||||
@ -48,7 +51,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
Recorder = new TestReplayRecorder(new Score
|
Recorder = new TestReplayRecorder(new Score
|
||||||
{
|
{
|
||||||
Replay = replay,
|
Replay = replay,
|
||||||
ScoreInfo = { Beatmap = gameplayBeatmap.BeatmapInfo }
|
ScoreInfo = { BeatmapInfo = gameplayState.Beatmap.BeatmapInfo }
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos)
|
ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos)
|
||||||
|
@ -25,6 +25,8 @@ using osu.Game.Online.Spectator;
|
|||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
using osu.Game.Replays.Legacy;
|
using osu.Game.Replays.Legacy;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Replays;
|
using osu.Game.Rulesets.Replays;
|
||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
@ -62,7 +64,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
private SpectatorClient spectatorClient { get; set; }
|
private SpectatorClient spectatorClient { get; set; }
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private GameplayBeatmap gameplayBeatmap = new GameplayBeatmap(new Beatmap());
|
private GameplayState gameplayState = new GameplayState(new Beatmap(), new OsuRuleset(), Array.Empty<Mod>());
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
@ -354,7 +356,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
internal class TestReplayRecorder : ReplayRecorder<TestAction>
|
internal class TestReplayRecorder : ReplayRecorder<TestAction>
|
||||||
{
|
{
|
||||||
public TestReplayRecorder()
|
public TestReplayRecorder()
|
||||||
: base(new Score { ScoreInfo = { Beatmap = new BeatmapInfo() } })
|
: base(new Score { ScoreInfo = { BeatmapInfo = new BeatmapInfo() } })
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ using NUnit.Framework;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Screens;
|
|
||||||
using osu.Game.Screens;
|
using osu.Game.Screens;
|
||||||
using osu.Game.Screens.Menu;
|
using osu.Game.Screens.Menu;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -21,6 +20,8 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
|
|
||||||
protected OsuScreenStack IntroStack;
|
protected OsuScreenStack IntroStack;
|
||||||
|
|
||||||
|
private IntroScreen intro;
|
||||||
|
|
||||||
protected IntroTestScene()
|
protected IntroTestScene()
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -39,7 +40,11 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
Position = new Vector2(0.5f),
|
Position = new Vector2(0.5f),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public virtual void TestPlayIntro()
|
||||||
|
{
|
||||||
AddStep("restart sequence", () =>
|
AddStep("restart sequence", () =>
|
||||||
{
|
{
|
||||||
logo.FinishTransforms();
|
logo.FinishTransforms();
|
||||||
@ -52,12 +57,12 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
});
|
});
|
||||||
|
|
||||||
IntroStack.Push(CreateScreen());
|
IntroStack.Push(intro = CreateScreen());
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("wait for menu", () => IntroStack.CurrentScreen is MainMenu);
|
AddUntilStep("wait for menu", () => intro.DidLoadMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract IScreen CreateScreen();
|
protected abstract IntroScreen CreateScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Screens;
|
|
||||||
using osu.Game.Screens.Menu;
|
using osu.Game.Screens.Menu;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Menus
|
namespace osu.Game.Tests.Visual.Menus
|
||||||
@ -10,6 +9,6 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneIntroCircles : IntroTestScene
|
public class TestSceneIntroCircles : IntroTestScene
|
||||||
{
|
{
|
||||||
protected override IScreen CreateScreen() => new IntroCircles();
|
protected override IntroScreen CreateScreen() => new IntroCircles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Screens;
|
|
||||||
using osu.Game.Screens.Menu;
|
using osu.Game.Screens.Menu;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Menus
|
namespace osu.Game.Tests.Visual.Menus
|
||||||
@ -10,6 +9,6 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneIntroTriangles : IntroTestScene
|
public class TestSceneIntroTriangles : IntroTestScene
|
||||||
{
|
{
|
||||||
protected override IScreen CreateScreen() => new IntroTriangles();
|
protected override IntroScreen CreateScreen() => new IntroTriangles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Screens;
|
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Screens.Menu;
|
using osu.Game.Screens.Menu;
|
||||||
|
|
||||||
@ -11,10 +10,12 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneIntroWelcome : IntroTestScene
|
public class TestSceneIntroWelcome : IntroTestScene
|
||||||
{
|
{
|
||||||
protected override IScreen CreateScreen() => new IntroWelcome();
|
protected override IntroScreen CreateScreen() => new IntroWelcome();
|
||||||
|
|
||||||
public TestSceneIntroWelcome()
|
public override void TestPlayIntro()
|
||||||
{
|
{
|
||||||
|
base.TestPlayIntro();
|
||||||
|
|
||||||
AddUntilStep("wait for load", () => MusicController.TrackLoaded);
|
AddUntilStep("wait for load", () => MusicController.TrackLoaded);
|
||||||
AddAssert("correct track", () => Precision.AlmostEquals(MusicController.CurrentTrack.Length, 48000, 1));
|
AddAssert("correct track", () => Precision.AlmostEquals(MusicController.CurrentTrack.Length, 48000, 1));
|
||||||
AddAssert("check if menu music loops", () => MusicController.CurrentTrack.Looping);
|
AddAssert("check if menu music loops", () => MusicController.CurrentTrack.Looping);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user