mirror of
https://github.com/ppy/osu.git
synced 2024-11-18 22:02:54 +08:00
Merge branch 'master' of https://github.com/odgaard/osu
This commit is contained in:
commit
28e8d10d8d
@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
public class CatchBeatmapConversionTest : BeatmapConversionTest<ConvertValue>
|
||||
public class CatchBeatmapConversionTest : BeatmapConversionTest<TestCatchRuleset, ConvertValue>
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Catch";
|
||||
|
||||
@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
}
|
||||
}
|
||||
|
||||
protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new CatchBeatmapConverter();
|
||||
protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap);
|
||||
}
|
||||
|
||||
public struct ConvertValue : IEquatable<ConvertValue>
|
||||
@ -64,4 +64,8 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
=> Precision.AlmostEquals(StartTime, other.StartTime, conversion_lenience)
|
||||
&& Precision.AlmostEquals(Position, other.Position, conversion_lenience);
|
||||
}
|
||||
|
||||
public class TestCatchRuleset : CatchRuleset
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override Beatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
|
@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override Beatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override Beatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override Beatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap { BeatmapInfo = { Ruleset = ruleset.RulesetInfo } };
|
||||
|
||||
|
@ -13,9 +13,14 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
{
|
||||
public class CatchBeatmapConverter : BeatmapConverter<CatchHitObject>
|
||||
{
|
||||
public CatchBeatmapConverter(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) };
|
||||
|
||||
protected override IEnumerable<CatchHitObject> ConvertHitObject(HitObject obj, Beatmap beatmap)
|
||||
protected override IEnumerable<CatchHitObject> ConvertHitObject(HitObject obj, IBeatmap beatmap)
|
||||
{
|
||||
var curveData = obj as IHasCurve;
|
||||
var positionData = obj as IHasXPosition;
|
||||
|
@ -12,16 +12,21 @@ using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
{
|
||||
public class CatchBeatmapProcessor : BeatmapProcessor<CatchHitObject>
|
||||
public class CatchBeatmapProcessor : BeatmapProcessor
|
||||
{
|
||||
public override void PostProcess(Beatmap<CatchHitObject> beatmap)
|
||||
public CatchBeatmapProcessor(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
initialiseHyperDash(beatmap.HitObjects);
|
||||
}
|
||||
|
||||
base.PostProcess(beatmap);
|
||||
public override void PostProcess()
|
||||
{
|
||||
initialiseHyperDash((List<CatchHitObject>)Beatmap.HitObjects);
|
||||
|
||||
base.PostProcess();
|
||||
|
||||
int index = 0;
|
||||
foreach (var obj in beatmap.HitObjects)
|
||||
foreach (var obj in Beatmap.HitObjects.OfType<CatchHitObject>())
|
||||
obj.IndexInBeatmap = index++;
|
||||
}
|
||||
|
||||
|
@ -2,20 +2,16 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch
|
||||
{
|
||||
public class CatchDifficultyCalculator : DifficultyCalculator<CatchHitObject>
|
||||
public class CatchDifficultyCalculator : DifficultyCalculator
|
||||
{
|
||||
public CatchDifficultyCalculator(Beatmap beatmap) : base(beatmap)
|
||||
public CatchDifficultyCalculator(IBeatmap beatmap) : base(beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
public override double Calculate(Dictionary<string, double> categoryDifficulty = null) => 0;
|
||||
|
||||
protected override BeatmapConverter<CatchHitObject> CreateBeatmapConverter(Beatmap beatmap) => new CatchBeatmapConverter();
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,15 @@ using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Catch.Replays;
|
||||
using osu.Game.Rulesets.Replays.Types;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch
|
||||
{
|
||||
public class CatchRuleset : Ruleset
|
||||
{
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new CatchRulesetContainer(this, beatmap, isForCurrentRuleset);
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new CatchRulesetContainer(this, beatmap);
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap);
|
||||
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new CatchBeatmapProcessor(beatmap);
|
||||
|
||||
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
|
||||
{
|
||||
@ -138,7 +141,7 @@ namespace osu.Game.Rulesets.Catch
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o };
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new CatchDifficultyCalculator(beatmap);
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new CatchDifficultyCalculator(beatmap);
|
||||
|
||||
public override int? LegacyID => 2;
|
||||
|
||||
|
@ -6,10 +6,11 @@ using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using System;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Mods
|
||||
{
|
||||
public class CatchModHardRock : ModHardRock, IApplicableToHitObject<CatchHitObject>
|
||||
public class CatchModHardRock : ModHardRock, IApplicableToHitObject
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
public override bool Ranked => true;
|
||||
@ -17,9 +18,11 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
private float lastStartX;
|
||||
private int lastStartTime;
|
||||
|
||||
public void ApplyToHitObject(CatchHitObject hitObject)
|
||||
public void ApplyToHitObject(HitObject hitObject)
|
||||
{
|
||||
float position = hitObject.X;
|
||||
var catchObject = (CatchHitObject)hitObject;
|
||||
|
||||
float position = catchObject.X;
|
||||
int startTime = (int)hitObject.StartTime;
|
||||
|
||||
if (lastStartX == 0)
|
||||
@ -60,7 +63,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
position += rand;
|
||||
}
|
||||
|
||||
hitObject.X = position;
|
||||
catchObject.X = position;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -79,7 +82,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
}
|
||||
}
|
||||
|
||||
hitObject.X = position;
|
||||
catchObject.X = position;
|
||||
|
||||
lastStartX = position;
|
||||
lastStartTime = startTime;
|
||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
Dashing = dashing;
|
||||
}
|
||||
|
||||
public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap)
|
||||
public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap)
|
||||
{
|
||||
Position = legacyFrame.Position.X / CatchPlayfield.BASE_WIDTH;
|
||||
Dashing = legacyFrame.ButtonState == ReplayButtonState.Left1;
|
||||
|
@ -4,7 +4,6 @@
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Input.Handlers;
|
||||
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawable;
|
||||
using osu.Game.Rulesets.Catch.Replays;
|
||||
@ -20,8 +19,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatchRulesetContainer : ScrollingRulesetContainer<CatchPlayfield, CatchHitObject>
|
||||
{
|
||||
public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset, beatmap, isForCurrentRuleset)
|
||||
public CatchRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
@ -29,10 +28,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
|
||||
|
||||
protected override BeatmapProcessor<CatchHitObject> CreateBeatmapProcessor() => new CatchBeatmapProcessor();
|
||||
|
||||
protected override BeatmapConverter<CatchHitObject> CreateBeatmapConverter() => new CatchBeatmapConverter();
|
||||
|
||||
protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, GetVisualRepresentation);
|
||||
|
||||
public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo);
|
||||
|
@ -14,17 +14,14 @@ using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
public class ManiaBeatmapConversionTest : BeatmapConversionTest<ConvertValue>
|
||||
public class ManiaBeatmapConversionTest : BeatmapConversionTest<TestManiaRuleset, ConvertValue>
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Mania";
|
||||
|
||||
private bool isForCurrentRuleset;
|
||||
|
||||
[NonParallelizable]
|
||||
[TestCase("basic", false)]
|
||||
public void Test(string name, bool isForCurrentRuleset)
|
||||
[TestCase("basic")]
|
||||
public new void Test(string name)
|
||||
{
|
||||
this.isForCurrentRuleset = isForCurrentRuleset;
|
||||
base.Test(name);
|
||||
}
|
||||
|
||||
@ -38,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
};
|
||||
}
|
||||
|
||||
protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new ManiaBeatmapConverter(isForCurrentRuleset, beatmap);
|
||||
protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap);
|
||||
}
|
||||
|
||||
public struct ConvertValue : IEquatable<ConvertValue>
|
||||
@ -57,4 +54,8 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
&& Precision.AlmostEquals(EndTime, other.EndTime, conversion_lenience)
|
||||
&& Column == other.Column;
|
||||
}
|
||||
|
||||
public class TestManiaRuleset : ManiaRuleset
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -33,18 +33,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
|
||||
private ManiaBeatmap beatmap;
|
||||
|
||||
public ManiaBeatmapConverter(bool isForCurrentRuleset, Beatmap original)
|
||||
public ManiaBeatmapConverter(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
IsForCurrentRuleset = isForCurrentRuleset;
|
||||
IsForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo);
|
||||
|
||||
var roundedCircleSize = Math.Round(original.BeatmapInfo.BaseDifficulty.CircleSize);
|
||||
var roundedOverallDifficulty = Math.Round(original.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
||||
var roundedCircleSize = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.CircleSize);
|
||||
var roundedOverallDifficulty = Math.Round(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty);
|
||||
|
||||
if (isForCurrentRuleset)
|
||||
if (IsForCurrentRuleset)
|
||||
TargetColumns = (int)Math.Max(1, roundedCircleSize);
|
||||
else
|
||||
{
|
||||
float percentSliderOrSpinner = (float)original.HitObjects.Count(h => h is IHasEndTime) / original.HitObjects.Count;
|
||||
float percentSliderOrSpinner = (float)beatmap.HitObjects.Count(h => h is IHasEndTime) / beatmap.HitObjects.Count();
|
||||
if (percentSliderOrSpinner < 0.2)
|
||||
TargetColumns = 7;
|
||||
else if (percentSliderOrSpinner < 0.3 || roundedCircleSize >= 5)
|
||||
@ -56,8 +57,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
}
|
||||
}
|
||||
|
||||
protected override Beatmap<ManiaHitObject> ConvertBeatmap(Beatmap original)
|
||||
protected override Beatmap<ManiaHitObject> ConvertBeatmap(IBeatmap original)
|
||||
{
|
||||
|
||||
BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty;
|
||||
|
||||
int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate);
|
||||
@ -68,7 +70,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
|
||||
protected override Beatmap<ManiaHitObject> CreateBeatmap() => beatmap = new ManiaBeatmap(new StageDefinition { Columns = TargetColumns });
|
||||
|
||||
protected override IEnumerable<ManiaHitObject> ConvertHitObject(HitObject original, Beatmap beatmap)
|
||||
protected override IEnumerable<ManiaHitObject> ConvertHitObject(HitObject original, IBeatmap beatmap)
|
||||
{
|
||||
var maniaOriginal = original as ManiaHitObject;
|
||||
if (maniaOriginal != null)
|
||||
@ -112,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
/// <param name="original">The original hit object.</param>
|
||||
/// <param name="originalBeatmap">The original beatmap. This is used to look-up any values dependent on a fully-loaded beatmap.</param>
|
||||
/// <returns>The hit objects generated.</returns>
|
||||
private IEnumerable<ManiaHitObject> generateSpecific(HitObject original, Beatmap originalBeatmap)
|
||||
private IEnumerable<ManiaHitObject> generateSpecific(HitObject original, IBeatmap originalBeatmap)
|
||||
{
|
||||
var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern, originalBeatmap);
|
||||
|
||||
@ -128,7 +130,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
/// <param name="original">The original hit object.</param>
|
||||
/// <param name="originalBeatmap">The original beatmap. This is used to look-up any values dependent on a fully-loaded beatmap.</param>
|
||||
/// <returns>The hit objects generated.</returns>
|
||||
private IEnumerable<ManiaHitObject> generateConverted(HitObject original, Beatmap originalBeatmap)
|
||||
private IEnumerable<ManiaHitObject> generateConverted(HitObject original, IBeatmap originalBeatmap)
|
||||
{
|
||||
var endTimeData = original as IHasEndTime;
|
||||
var distanceData = original as IHasDistance;
|
||||
@ -165,7 +167,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
/// </summary>
|
||||
private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator
|
||||
{
|
||||
public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap)
|
||||
public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap)
|
||||
: base(random, hitObject, beatmap, previousPattern, originalBeatmap)
|
||||
{
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
|
||||
private PatternType convertType;
|
||||
|
||||
public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap)
|
||||
public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap)
|
||||
: base(random, hitObject, beatmap, previousPattern, originalBeatmap)
|
||||
{
|
||||
convertType = PatternType.None;
|
||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
{
|
||||
private readonly double endTime;
|
||||
|
||||
public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Beatmap originalBeatmap)
|
||||
public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, IBeatmap originalBeatmap)
|
||||
: base(random, hitObject, beatmap, new Pattern(), originalBeatmap)
|
||||
{
|
||||
var endtimeData = HitObject as IHasEndTime;
|
||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
|
||||
private readonly PatternType convertType;
|
||||
|
||||
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, Beatmap originalBeatmap)
|
||||
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair, IBeatmap originalBeatmap)
|
||||
: base(random, hitObject, beatmap, previousPattern, originalBeatmap)
|
||||
{
|
||||
if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime));
|
||||
|
@ -28,9 +28,9 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
/// <summary>
|
||||
/// The beatmap which <see cref="HitObject"/> is being converted from.
|
||||
/// </summary>
|
||||
protected readonly Beatmap OriginalBeatmap;
|
||||
protected readonly IBeatmap OriginalBeatmap;
|
||||
|
||||
protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, Beatmap originalBeatmap)
|
||||
protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, IBeatmap originalBeatmap)
|
||||
: base(hitObject, beatmap, previousPattern)
|
||||
{
|
||||
if (random == null) throw new ArgumentNullException(nameof(random));
|
||||
@ -113,7 +113,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
drainTime /= 1000;
|
||||
|
||||
BeatmapDifficulty difficulty = OriginalBeatmap.BeatmapInfo.BaseDifficulty;
|
||||
conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + OriginalBeatmap.HitObjects.Count / drainTime * 9f) / 38f * 5f / 1.15;
|
||||
conversionDifficulty = ((difficulty.DrainRate + MathHelper.Clamp(difficulty.ApproachRate, 4, 7)) / 1.5 + OriginalBeatmap.HitObjects.Count() / drainTime * 9f) / 38f * 5f / 1.15;
|
||||
conversionDifficulty = Math.Min(conversionDifficulty.Value, 12);
|
||||
|
||||
return conversionDifficulty.Value;
|
||||
|
@ -10,7 +10,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania
|
||||
{
|
||||
internal class ManiaDifficultyCalculator : DifficultyCalculator<ManiaHitObject>
|
||||
internal class ManiaDifficultyCalculator : DifficultyCalculator
|
||||
{
|
||||
private const double star_scaling_factor = 0.018;
|
||||
|
||||
@ -31,12 +31,12 @@ namespace osu.Game.Rulesets.Mania
|
||||
/// </summary>
|
||||
private readonly List<ManiaHitObjectDifficulty> difficultyHitObjects = new List<ManiaHitObjectDifficulty>();
|
||||
|
||||
public ManiaDifficultyCalculator(Beatmap beatmap)
|
||||
public ManiaDifficultyCalculator(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
public ManiaDifficultyCalculator(Beatmap beatmap, Mod[] mods)
|
||||
public ManiaDifficultyCalculator(IBeatmap beatmap, Mod[] mods)
|
||||
: base(beatmap, mods)
|
||||
{
|
||||
}
|
||||
@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Mania
|
||||
int columnCount = (Beatmap as ManiaBeatmap)?.TotalColumns ?? 7;
|
||||
|
||||
foreach (var hitObject in Beatmap.HitObjects)
|
||||
difficultyHitObjects.Add(new ManiaHitObjectDifficulty(hitObject, columnCount));
|
||||
difficultyHitObjects.Add(new ManiaHitObjectDifficulty((ManiaHitObject)hitObject, columnCount));
|
||||
|
||||
// Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure.
|
||||
difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
|
||||
@ -140,7 +140,5 @@ namespace osu.Game.Rulesets.Mania
|
||||
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter(Beatmap beatmap) => new ManiaBeatmapConverter(true, beatmap);
|
||||
}
|
||||
}
|
||||
|
@ -15,12 +15,14 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Replays;
|
||||
using osu.Game.Rulesets.Replays.Types;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania
|
||||
{
|
||||
public class ManiaRuleset : Ruleset
|
||||
{
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ManiaRulesetContainer(this, beatmap, isForCurrentRuleset);
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new ManiaRulesetContainer(this, beatmap);
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap);
|
||||
|
||||
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
|
||||
{
|
||||
@ -182,7 +184,7 @@ namespace osu.Game.Rulesets.Mania
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o };
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap, mods);
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap, mods);
|
||||
|
||||
public override int? LegacyID => 3;
|
||||
|
||||
|
@ -3,19 +3,18 @@
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter<ManiaHitObject>
|
||||
public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter
|
||||
{
|
||||
public override string ShortenedName => Name;
|
||||
public abstract int KeyCount { get; }
|
||||
public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToBeatmapConverter(BeatmapConverter<ManiaHitObject> beatmapConverter)
|
||||
public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
|
||||
{
|
||||
var mbc = (ManiaBeatmapConverter)beatmapConverter;
|
||||
|
||||
|
@ -11,19 +11,23 @@ using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter<ManiaHitObject>, IApplicableToRulesetContainer<ManiaHitObject>
|
||||
public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter, IApplicableToRulesetContainer<ManiaHitObject>
|
||||
{
|
||||
public override string Name => "Dual Stages";
|
||||
public override string ShortenedName => "DS";
|
||||
public override string Description => @"Double the stages, double the fun!";
|
||||
public override double ScoreMultiplier => 0;
|
||||
|
||||
public void ApplyToBeatmapConverter(BeatmapConverter<ManiaHitObject> beatmapConverter)
|
||||
private bool isForCurrentRuleset;
|
||||
|
||||
public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
|
||||
{
|
||||
var mbc = (ManiaBeatmapConverter)beatmapConverter;
|
||||
|
||||
isForCurrentRuleset = mbc.IsForCurrentRuleset;
|
||||
|
||||
// Although this can work, for now let's not allow keymods for mania-specific beatmaps
|
||||
if (mbc.IsForCurrentRuleset)
|
||||
if (isForCurrentRuleset)
|
||||
return;
|
||||
|
||||
mbc.TargetColumns *= 2;
|
||||
@ -34,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
var mrc = (ManiaRulesetContainer)rulesetContainer;
|
||||
|
||||
// Although this can work, for now let's not allow keymods for mania-specific beatmaps
|
||||
if (mrc.IsForCurrentRuleset)
|
||||
if (isForCurrentRuleset)
|
||||
return;
|
||||
|
||||
var newDefinitions = new List<StageDefinition>();
|
||||
|
@ -24,10 +24,10 @@ namespace osu.Game.Rulesets.Mania.Replays
|
||||
Actions.AddRange(actions);
|
||||
}
|
||||
|
||||
public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap)
|
||||
public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap)
|
||||
{
|
||||
// We don't need to fully convert, just create the converter
|
||||
var converter = new ManiaBeatmapConverter(beatmap.BeatmapInfo.RulesetID == 3, beatmap);
|
||||
var converter = new ManiaBeatmapConverter(beatmap);
|
||||
|
||||
// NB: Via co-op mod, osu-stable can have two stages with floor(col/2) and ceil(col/2) columns. This will need special handling
|
||||
// elsewhere in the game if we do choose to support the old co-op mod anyway. For now, assume that there is only one stage.
|
||||
|
@ -36,8 +36,8 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
public IEnumerable<BarLine> BarLines;
|
||||
|
||||
public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset, beatmap, isForCurrentRuleset)
|
||||
public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
{
|
||||
// Generate the bar lines
|
||||
double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue;
|
||||
@ -85,8 +85,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant);
|
||||
|
||||
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter() => new ManiaBeatmapConverter(IsForCurrentRuleset, WorkingBeatmap.Beatmap);
|
||||
|
||||
protected override DrawableHitObject<ManiaHitObject> GetVisualRepresentation(ManiaHitObject h)
|
||||
{
|
||||
ManiaAction action = Playfield.Columns.ElementAt(h.Column).Action;
|
||||
|
@ -15,7 +15,7 @@ using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class OsuBeatmapConversionTest : BeatmapConversionTest<ConvertValue>
|
||||
public class OsuBeatmapConversionTest : BeatmapConversionTest<TestOsuRuleset, ConvertValue>
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Osu";
|
||||
|
||||
@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
};
|
||||
}
|
||||
|
||||
protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new OsuBeatmapConverter();
|
||||
protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap);
|
||||
}
|
||||
|
||||
public struct ConvertValue : IEquatable<ConvertValue>
|
||||
@ -67,4 +67,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
&& Precision.AlmostEquals(EndX, other.EndX, conversion_lenience)
|
||||
&& Precision.AlmostEquals(EndY, other.EndY, conversion_lenience);
|
||||
}
|
||||
|
||||
public class TestOsuRuleset : OsuRuleset
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,14 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
{
|
||||
internal class OsuBeatmapConverter : BeatmapConverter<OsuHitObject>
|
||||
{
|
||||
public OsuBeatmapConverter(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasPosition) };
|
||||
|
||||
protected override IEnumerable<OsuHitObject> ConvertHitObject(HitObject original, Beatmap beatmap)
|
||||
protected override IEnumerable<OsuHitObject> ConvertHitObject(HitObject original, IBeatmap beatmap)
|
||||
{
|
||||
var curveData = original as IHasCurve;
|
||||
var endTimeData = original as IHasEndTime;
|
||||
|
@ -8,12 +8,17 @@ using osu.Game.Rulesets.Osu.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
{
|
||||
internal class OsuBeatmapProcessor : BeatmapProcessor<OsuHitObject>
|
||||
internal class OsuBeatmapProcessor : BeatmapProcessor
|
||||
{
|
||||
public override void PostProcess(Beatmap<OsuHitObject> beatmap)
|
||||
public OsuBeatmapProcessor(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
applyStacking(beatmap);
|
||||
base.PostProcess(beatmap);
|
||||
}
|
||||
|
||||
public override void PostProcess()
|
||||
{
|
||||
applyStacking((Beatmap<OsuHitObject>)Beatmap);
|
||||
base.PostProcess();
|
||||
}
|
||||
|
||||
private void applyStacking(Beatmap<OsuHitObject> beatmap)
|
||||
|
@ -11,8 +11,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
public class OsuEditRulesetContainer : OsuRulesetContainer
|
||||
{
|
||||
public OsuEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset, beatmap, isForCurrentRuleset)
|
||||
public OsuEditRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
}
|
||||
|
||||
protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new OsuEditRulesetContainer(ruleset, beatmap, true);
|
||||
protected override RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => new OsuEditRulesetContainer(ruleset, beatmap);
|
||||
|
||||
protected override IReadOnlyList<ICompositionTool> CompositionTools => new ICompositionTool[]
|
||||
{
|
||||
|
@ -5,20 +5,23 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModHardRock : ModHardRock, IApplicableToHitObject<OsuHitObject>
|
||||
public class OsuModHardRock : ModHardRock, IApplicableToHitObject
|
||||
{
|
||||
public override double ScoreMultiplier => 1.06;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToHitObject(OsuHitObject hitObject)
|
||||
public void ApplyToHitObject(HitObject hitObject)
|
||||
{
|
||||
hitObject.Position = new Vector2(hitObject.Position.X, OsuPlayfield.BASE_SIZE.Y - hitObject.Y);
|
||||
var osuObject = (OsuHitObject)hitObject;
|
||||
|
||||
osuObject.Position = new Vector2(osuObject.Position.X, OsuPlayfield.BASE_SIZE.Y - osuObject.Y);
|
||||
|
||||
var slider = hitObject as Slider;
|
||||
if (slider == null)
|
||||
|
@ -5,36 +5,30 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Osu.OsuDifficulty.Skills;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.OsuDifficulty
|
||||
{
|
||||
public class OsuDifficultyCalculator : DifficultyCalculator<OsuHitObject>
|
||||
public class OsuDifficultyCalculator : DifficultyCalculator
|
||||
{
|
||||
private const int section_length = 400;
|
||||
private const double difficulty_multiplier = 0.0675;
|
||||
|
||||
public OsuDifficultyCalculator(Beatmap beatmap)
|
||||
public OsuDifficultyCalculator(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
public OsuDifficultyCalculator(Beatmap beatmap, Mod[] mods)
|
||||
public OsuDifficultyCalculator(IBeatmap beatmap, Mod[] mods)
|
||||
: base(beatmap, mods)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void PreprocessHitObjects()
|
||||
{
|
||||
new OsuBeatmapProcessor().PostProcess(Beatmap);
|
||||
}
|
||||
|
||||
public override double Calculate(Dictionary<string, double> categoryDifficulty = null)
|
||||
{
|
||||
OsuDifficultyBeatmap beatmap = new OsuDifficultyBeatmap(Beatmap.HitObjects, TimeRate);
|
||||
OsuDifficultyBeatmap beatmap = new OsuDifficultyBeatmap((List<OsuHitObject>)Beatmap.HitObjects, TimeRate);
|
||||
Skill[] skills =
|
||||
{
|
||||
new Aim(),
|
||||
@ -72,7 +66,5 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty
|
||||
|
||||
return starRating;
|
||||
}
|
||||
|
||||
protected override BeatmapConverter<OsuHitObject> CreateBeatmapConverter(Beatmap beatmap) => new OsuBeatmapConverter();
|
||||
}
|
||||
}
|
||||
|
@ -22,12 +22,15 @@ using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Rulesets.Replays.Types;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu
|
||||
{
|
||||
public class OsuRuleset : Ruleset
|
||||
{
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new OsuRulesetContainer(this, beatmap, isForCurrentRuleset);
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new OsuRulesetContainer(this, beatmap);
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap);
|
||||
public override IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => new OsuBeatmapProcessor(beatmap);
|
||||
|
||||
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
|
||||
{
|
||||
@ -181,9 +184,9 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_osu_o };
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new OsuDifficultyCalculator(beatmap, mods);
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new OsuDifficultyCalculator(beatmap, mods);
|
||||
|
||||
public override PerformanceCalculator CreatePerformanceCalculator(Beatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score);
|
||||
public override PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score);
|
||||
|
||||
public override HitObjectComposer CreateHitObjectComposer() => new OsuHitObjectComposer(this);
|
||||
|
||||
|
@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
Actions.AddRange(actions);
|
||||
}
|
||||
|
||||
public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap)
|
||||
public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap)
|
||||
{
|
||||
Position = legacyFrame.Position;
|
||||
if (legacyFrame.MouseLeft) Actions.Add(OsuAction.LeftButton);
|
||||
|
@ -6,14 +6,13 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Scoring
|
||||
{
|
||||
public class OsuPerformanceCalculator : PerformanceCalculator<OsuHitObject>
|
||||
public class OsuPerformanceCalculator : PerformanceCalculator
|
||||
{
|
||||
private readonly int countHitCircles;
|
||||
private readonly int beatmapMaxCombo;
|
||||
@ -27,12 +26,12 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
private int count50;
|
||||
private int countMiss;
|
||||
|
||||
public OsuPerformanceCalculator(Ruleset ruleset, Beatmap beatmap, Score score)
|
||||
public OsuPerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score)
|
||||
: base(ruleset, beatmap, score)
|
||||
{
|
||||
countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle);
|
||||
|
||||
beatmapMaxCombo = Beatmap.HitObjects.Count;
|
||||
beatmapMaxCombo = Beatmap.HitObjects.Count();
|
||||
beatmapMaxCombo += Beatmap.HitObjects.OfType<Slider>().Sum(s => s.NestedHitObjects.Count) + 1;
|
||||
}
|
||||
|
||||
@ -193,7 +192,5 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
|
||||
private double totalHits => count300 + count100 + count50 + countMiss;
|
||||
private double totalSuccessfulHits => count300 + count100 + count50;
|
||||
|
||||
protected override BeatmapConverter<OsuHitObject> CreateBeatmapConverter() => new OsuBeatmapConverter();
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ using OpenTK;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Input.Handlers;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Replays;
|
||||
@ -21,17 +20,13 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
{
|
||||
public class OsuRulesetContainer : RulesetContainer<OsuHitObject>
|
||||
{
|
||||
public OsuRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset, beatmap, isForCurrentRuleset)
|
||||
public OsuRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(this);
|
||||
|
||||
protected override BeatmapConverter<OsuHitObject> CreateBeatmapConverter() => new OsuBeatmapConverter();
|
||||
|
||||
protected override BeatmapProcessor<OsuHitObject> CreateBeatmapProcessor() => new OsuBeatmapProcessor();
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuPlayfield();
|
||||
|
||||
public override PassThroughInputManager CreateInputManager() => new OsuInputManager(Ruleset.RulesetInfo);
|
||||
|
@ -14,18 +14,15 @@ using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
public class TaikoBeatmapConversionTest : BeatmapConversionTest<ConvertValue>
|
||||
public class TaikoBeatmapConversionTest : BeatmapConversionTest<TestTaikoRuleset, ConvertValue>
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko";
|
||||
|
||||
private bool isForCurrentRuleset;
|
||||
|
||||
[NonParallelizable]
|
||||
[TestCase("basic", false), Ignore("See: https://github.com/ppy/osu/issues/2152")]
|
||||
[TestCase("slider-generating-drumroll", false)]
|
||||
public void Test(string name, bool isForCurrentRuleset)
|
||||
public new void Test(string name)
|
||||
{
|
||||
this.isForCurrentRuleset = isForCurrentRuleset;
|
||||
base.Test(name);
|
||||
}
|
||||
|
||||
@ -43,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
};
|
||||
}
|
||||
|
||||
protected override IBeatmapConverter CreateConverter(Beatmap beatmap) => new TaikoBeatmapConverter(isForCurrentRuleset);
|
||||
protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap);
|
||||
}
|
||||
|
||||
public struct ConvertValue : IEquatable<ConvertValue>
|
||||
@ -70,4 +67,8 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
&& IsSwell == other.IsSwell
|
||||
&& IsStrong == other.IsStrong;
|
||||
}
|
||||
|
||||
public class TestTaikoRuleset : TaikoRuleset
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
private Container playfieldContainer;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
private void load()
|
||||
{
|
||||
AddStep("Hit!", () => addHitJudgement(false));
|
||||
AddStep("Kiai hit", () => addHitJudgement(true));
|
||||
@ -73,6 +73,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
Title = @"Sample Beatmap",
|
||||
AuthorString = @"peppy",
|
||||
},
|
||||
Ruleset = new TaikoRuleset().RulesetInfo
|
||||
},
|
||||
ControlPointInfo = controlPointInfo
|
||||
});
|
||||
@ -86,7 +87,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 768,
|
||||
Clock = new FramedClock(rateAdjustClock),
|
||||
Children = new[] { rulesetContainer = new TaikoRulesetContainer(rulesets.GetRuleset(1).CreateInstance(), beatmap, true) }
|
||||
Children = new[] { rulesetContainer = new TaikoRulesetContainer(new TaikoRuleset(), beatmap) }
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -42,12 +42,13 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
||||
|
||||
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(HitObject) };
|
||||
|
||||
public TaikoBeatmapConverter(bool isForCurrentRuleset)
|
||||
public TaikoBeatmapConverter(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
this.isForCurrentRuleset = isForCurrentRuleset;
|
||||
isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(new TaikoRuleset().RulesetInfo);
|
||||
}
|
||||
|
||||
protected override Beatmap<TaikoHitObject> ConvertBeatmap(Beatmap original)
|
||||
protected override Beatmap<TaikoHitObject> ConvertBeatmap(IBeatmap original)
|
||||
{
|
||||
// Rewrite the beatmap info to add the slider velocity multiplier
|
||||
BeatmapInfo info = original.BeatmapInfo.DeepClone();
|
||||
@ -70,7 +71,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
||||
return converted;
|
||||
}
|
||||
|
||||
protected override IEnumerable<TaikoHitObject> ConvertHitObject(HitObject obj, Beatmap beatmap)
|
||||
protected override IEnumerable<TaikoHitObject> ConvertHitObject(HitObject obj, IBeatmap beatmap)
|
||||
{
|
||||
var distanceData = obj as IHasDistance;
|
||||
var repeatsData = obj as IHasRepeats;
|
||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Replays
|
||||
Actions.AddRange(actions);
|
||||
}
|
||||
|
||||
public void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap)
|
||||
public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap)
|
||||
{
|
||||
if (legacyFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim);
|
||||
if (legacyFrame.MouseRight2) Actions.Add(TaikoAction.RightRim);
|
||||
|
@ -2,14 +2,13 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko
|
||||
{
|
||||
internal class TaikoDifficultyCalculator : DifficultyCalculator<TaikoHitObject>
|
||||
internal class TaikoDifficultyCalculator : DifficultyCalculator
|
||||
{
|
||||
private const double star_scaling_factor = 0.04125;
|
||||
|
||||
@ -30,7 +29,7 @@ namespace osu.Game.Rulesets.Taiko
|
||||
/// </summary>
|
||||
private readonly List<TaikoHitObjectDifficulty> difficultyHitObjects = new List<TaikoHitObjectDifficulty>();
|
||||
|
||||
public TaikoDifficultyCalculator(Beatmap beatmap)
|
||||
public TaikoDifficultyCalculator(IBeatmap beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
}
|
||||
@ -41,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko
|
||||
difficultyHitObjects.Clear();
|
||||
|
||||
foreach (var hitObject in Beatmap.HitObjects)
|
||||
difficultyHitObjects.Add(new TaikoHitObjectDifficulty(hitObject));
|
||||
difficultyHitObjects.Add(new TaikoHitObjectDifficulty((TaikoHitObject)hitObject));
|
||||
|
||||
// Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure.
|
||||
difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
|
||||
@ -132,7 +131,5 @@ namespace osu.Game.Rulesets.Taiko
|
||||
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
protected override BeatmapConverter<TaikoHitObject> CreateBeatmapConverter(Beatmap beatmap) => new TaikoBeatmapConverter(true);
|
||||
}
|
||||
}
|
||||
|
@ -13,12 +13,14 @@ using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Replays.Types;
|
||||
using osu.Game.Rulesets.Taiko.Replays;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko
|
||||
{
|
||||
public class TaikoRuleset : Ruleset
|
||||
{
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new TaikoRulesetContainer(this, beatmap, isForCurrentRuleset);
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new TaikoRulesetContainer(this, beatmap);
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap);
|
||||
|
||||
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
|
||||
{
|
||||
@ -140,7 +142,7 @@ namespace osu.Game.Rulesets.Taiko
|
||||
|
||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o };
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap);
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap);
|
||||
|
||||
public override int? LegacyID => 1;
|
||||
|
||||
|
@ -8,7 +8,6 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Taiko.Scoring;
|
||||
@ -24,8 +23,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
public class TaikoRulesetContainer : ScrollingRulesetContainer<TaikoPlayfield, TaikoHitObject>
|
||||
{
|
||||
public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset, beatmap, isForCurrentRuleset)
|
||||
public TaikoRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
@ -93,8 +92,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this);
|
||||
|
||||
protected override BeatmapConverter<TaikoHitObject> CreateBeatmapConverter() => new TaikoBeatmapConverter(IsForCurrentRuleset);
|
||||
|
||||
public override PassThroughInputManager CreateInputManager() => new TaikoInputManager(Ruleset.RulesetInfo);
|
||||
|
||||
protected override Playfield CreatePlayfield() => new TaikoPlayfield(Beatmap.ControlPointInfo)
|
||||
|
@ -275,13 +275,13 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
Assert.IsTrue(set.Beatmaps.Any(c => c.OnlineBeatmapID == b.OnlineBeatmapID));
|
||||
Assert.IsTrue(set.Beatmaps.Count > 0);
|
||||
var beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap;
|
||||
Assert.IsTrue(beatmap?.HitObjects.Count > 0);
|
||||
Assert.IsTrue(beatmap?.HitObjects.Any() == true);
|
||||
beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.Beatmap;
|
||||
Assert.IsTrue(beatmap?.HitObjects.Count > 0);
|
||||
Assert.IsTrue(beatmap?.HitObjects.Any() == true);
|
||||
beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.Beatmap;
|
||||
Assert.IsTrue(beatmap?.HitObjects.Count > 0);
|
||||
Assert.IsTrue(beatmap?.HitObjects.Any() == true);
|
||||
beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap;
|
||||
Assert.IsTrue(beatmap?.HitObjects.Count > 0);
|
||||
Assert.IsTrue(beatmap?.HitObjects.Any() == true);
|
||||
}
|
||||
|
||||
private void waitForOrAssert(Func<bool> result, string failureMessage, int timeout = 60000)
|
||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
private RulesetStore rulesets;
|
||||
private TestBeatmapInfoWedge infoWedge;
|
||||
private readonly List<Beatmap> beatmaps = new List<Beatmap>();
|
||||
private readonly List<IBeatmap> beatmaps = new List<IBeatmap>();
|
||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -112,7 +112,7 @@ namespace osu.Game.Tests.Visual
|
||||
AddAssert("check no infolabels", () => !infoWedge.Info.InfoLabelContainer.Children.Any());
|
||||
}
|
||||
|
||||
private void selectBeatmap(Beatmap b)
|
||||
private void selectBeatmap(IBeatmap b)
|
||||
{
|
||||
BeatmapInfoWedge.BufferedWedgeInfo infoBefore = null;
|
||||
|
||||
@ -134,7 +134,7 @@ namespace osu.Game.Tests.Visual
|
||||
});
|
||||
}
|
||||
|
||||
private Beatmap createTestBeatmap(RulesetInfo ruleset)
|
||||
private IBeatmap createTestBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
List<HitObject> objects = new List<HitObject>();
|
||||
for (double i = 0; i < 50000; i += 1000)
|
||||
|
@ -332,7 +332,7 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
private readonly Drawable tracker;
|
||||
|
||||
public TimingPointVisualiser(Beatmap beatmap, double length)
|
||||
public TimingPointVisualiser(IBeatmap beatmap, double length)
|
||||
{
|
||||
this.length = length;
|
||||
|
||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual
|
||||
// We create a dummy RulesetContainer just to get the replay - we don't want to use mods here
|
||||
// to simulate setting a replay rather than having the replay already set for us
|
||||
beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() });
|
||||
var dummyRulesetContainer = ruleset.CreateRulesetContainerWith(beatmap, beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo));
|
||||
var dummyRulesetContainer = ruleset.CreateRulesetContainerWith(beatmap);
|
||||
|
||||
// We have the replay
|
||||
var replay = dummyRulesetContainer.Replay;
|
||||
|
@ -15,21 +15,27 @@ namespace osu.Game.Beatmaps
|
||||
/// <summary>
|
||||
/// A Beatmap containing converted HitObjects.
|
||||
/// </summary>
|
||||
public class Beatmap<T> : IJsonSerializable
|
||||
public class Beatmap<T> : IBeatmap
|
||||
where T : HitObject
|
||||
{
|
||||
public BeatmapInfo BeatmapInfo = new BeatmapInfo();
|
||||
public ControlPointInfo ControlPointInfo = new ControlPointInfo();
|
||||
public List<BreakPeriod> Breaks = new List<BreakPeriod>();
|
||||
public BeatmapInfo BeatmapInfo { get; set; } = new BeatmapInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Artist = @"Unknown",
|
||||
Title = @"Unknown",
|
||||
AuthorString = @"Unknown Creator",
|
||||
},
|
||||
Version = @"Normal",
|
||||
BaseDifficulty = new BeatmapDifficulty()
|
||||
};
|
||||
|
||||
[JsonIgnore]
|
||||
public BeatmapMetadata Metadata => BeatmapInfo?.Metadata ?? BeatmapInfo?.BeatmapSet?.Metadata;
|
||||
|
||||
/// <summary>
|
||||
/// The HitObjects this Beatmap contains.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(TypedListConverter<HitObject>))]
|
||||
public List<T> HitObjects = new List<T>();
|
||||
public ControlPointInfo ControlPointInfo { get; set; } = new ControlPointInfo();
|
||||
|
||||
public List<BreakPeriod> Breaks { get; set; } = new List<BreakPeriod>();
|
||||
|
||||
/// <summary>
|
||||
/// Total amount of break time in the beatmap.
|
||||
@ -38,51 +44,26 @@ namespace osu.Game.Beatmaps
|
||||
public double TotalBreakTime => Breaks.Sum(b => b.Duration);
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new beatmap.
|
||||
/// The HitObjects this Beatmap contains.
|
||||
/// </summary>
|
||||
/// <param name="original">The original beatmap to use the parameters of.</param>
|
||||
public Beatmap(Beatmap<T> original = null)
|
||||
{
|
||||
BeatmapInfo = original?.BeatmapInfo.DeepClone() ?? BeatmapInfo;
|
||||
ControlPointInfo = original?.ControlPointInfo ?? ControlPointInfo;
|
||||
Breaks = original?.Breaks ?? Breaks;
|
||||
HitObjects = original?.HitObjects ?? HitObjects;
|
||||
[JsonConverter(typeof(TypedListConverter<HitObject>))]
|
||||
public List<T> HitObjects = new List<T>();
|
||||
|
||||
if (original == null && Metadata == null)
|
||||
{
|
||||
// we may have no metadata in cases we weren't sourced from the database.
|
||||
// let's fill it (and other related fields) so we don't need to null-check it in future usages.
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Artist = @"Unknown",
|
||||
Title = @"Unknown",
|
||||
AuthorString = @"Unknown Creator",
|
||||
},
|
||||
Version = @"Normal",
|
||||
BaseDifficulty = new BeatmapDifficulty()
|
||||
};
|
||||
}
|
||||
IEnumerable<HitObject> IBeatmap.HitObjects => HitObjects;
|
||||
|
||||
IBeatmap IBeatmap.Clone() => Clone();
|
||||
|
||||
public Beatmap<T> Clone()
|
||||
{
|
||||
var newInstance = (Beatmap<T>)MemberwiseClone();
|
||||
newInstance.BeatmapInfo = BeatmapInfo.DeepClone();
|
||||
|
||||
return newInstance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A Beatmap containing un-converted HitObjects.
|
||||
/// </summary>
|
||||
public class Beatmap : Beatmap<HitObject>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs a new beatmap.
|
||||
/// </summary>
|
||||
/// <param name="original">The original beatmap to use the parameters of.</param>
|
||||
public Beatmap(Beatmap original)
|
||||
: base(original)
|
||||
{
|
||||
}
|
||||
|
||||
public Beatmap()
|
||||
{
|
||||
}
|
||||
public Beatmap Clone() => (Beatmap)base.Clone();
|
||||
}
|
||||
}
|
||||
|
@ -22,32 +22,34 @@ namespace osu.Game.Beatmaps
|
||||
remove => ObjectConverted -= value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a Beatmap can be converted using this Beatmap Converter.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The Beatmap to check.</param>
|
||||
/// <returns>Whether the Beatmap can be converted using this Beatmap Converter.</returns>
|
||||
public bool CanConvert(Beatmap beatmap) => ValidConversionTypes.All(t => beatmap.HitObjects.Any(t.IsInstanceOfType));
|
||||
public IBeatmap Beatmap { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Beatmap using this Beatmap Converter.
|
||||
/// </summary>
|
||||
/// <param name="original">The un-converted Beatmap.</param>
|
||||
/// <returns>The converted Beatmap.</returns>
|
||||
public Beatmap<T> Convert(Beatmap original)
|
||||
protected BeatmapConverter(IBeatmap beatmap)
|
||||
{
|
||||
// We always operate on a clone of the original beatmap, to not modify it game-wide
|
||||
return ConvertBeatmap(new Beatmap(original));
|
||||
Beatmap = beatmap;
|
||||
}
|
||||
|
||||
void IBeatmapConverter.Convert(Beatmap original) => Convert(original);
|
||||
/// <summary>
|
||||
/// Whether <see cref="Beatmap"/> can be converted by this <see cref="BeatmapConverter{T}"/>.
|
||||
/// </summary>
|
||||
public bool CanConvert => !Beatmap.HitObjects.Any() || ValidConversionTypes.All(t => Beatmap.HitObjects.Any(t.IsInstanceOfType));
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="Beatmap"/>.
|
||||
/// </summary>
|
||||
/// <returns>The converted Beatmap.</returns>
|
||||
public IBeatmap Convert()
|
||||
{
|
||||
// We always operate on a clone of the original beatmap, to not modify it game-wide
|
||||
return ConvertBeatmap(Beatmap.Clone());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the conversion of a Beatmap using this Beatmap Converter.
|
||||
/// </summary>
|
||||
/// <param name="original">The un-converted Beatmap.</param>
|
||||
/// <returns>The converted Beatmap.</returns>
|
||||
protected virtual Beatmap<T> ConvertBeatmap(Beatmap original)
|
||||
protected virtual Beatmap<T> ConvertBeatmap(IBeatmap original)
|
||||
{
|
||||
var beatmap = CreateBeatmap();
|
||||
|
||||
@ -67,7 +69,7 @@ namespace osu.Game.Beatmaps
|
||||
/// <param name="original">The hit object to convert.</param>
|
||||
/// <param name="beatmap">The un-converted Beatmap.</param>
|
||||
/// <returns>The converted hit object.</returns>
|
||||
private IEnumerable<T> convert(HitObject original, Beatmap beatmap)
|
||||
private IEnumerable<T> convert(HitObject original, IBeatmap beatmap)
|
||||
{
|
||||
// Check if the hitobject is already the converted type
|
||||
T tObject = original as T;
|
||||
@ -107,6 +109,6 @@ namespace osu.Game.Beatmaps
|
||||
/// <param name="original">The hit object to convert.</param>
|
||||
/// <param name="beatmap">The un-converted Beatmap.</param>
|
||||
/// <returns>The converted hit object.</returns>
|
||||
protected abstract IEnumerable<T> ConvertHitObject(HitObject original, Beatmap beatmap);
|
||||
protected abstract IEnumerable<T> ConvertHitObject(HitObject original, IBeatmap beatmap);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,9 @@ using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
@ -333,7 +335,7 @@ namespace osu.Game.Beatmaps
|
||||
ms.Position = 0;
|
||||
|
||||
var decoder = Decoder.GetDecoder<Beatmap>(sr);
|
||||
Beatmap beatmap = decoder.Decode(sr);
|
||||
IBeatmap beatmap = decoder.Decode(sr);
|
||||
|
||||
beatmap.BeatmapInfo.Path = name;
|
||||
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
|
||||
@ -341,9 +343,16 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
RulesetInfo ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID);
|
||||
|
||||
// TODO: this should be done in a better place once we actually need to dynamically update it.
|
||||
beatmap.BeatmapInfo.Ruleset = ruleset;
|
||||
beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance()?.CreateDifficultyCalculator(beatmap).Calculate() ?? 0;
|
||||
|
||||
if (ruleset != null)
|
||||
{
|
||||
// TODO: this should be done in a better place once we actually need to dynamically update it.
|
||||
var converted = new DummyConversionBeatmap(beatmap).GetPlayableBeatmap(ruleset);
|
||||
beatmap.BeatmapInfo.StarDifficulty = ruleset.CreateInstance().CreateDifficultyCalculator(converted).Calculate();
|
||||
}
|
||||
else
|
||||
beatmap.BeatmapInfo.StarDifficulty = 0;
|
||||
|
||||
beatmapInfos.Add(beatmap.BeatmapInfo);
|
||||
}
|
||||
@ -351,5 +360,23 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
return beatmapInfos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A dummy WorkingBeatmap for the purpose of retrieving a beatmap for star difficulty calculation.
|
||||
/// </summary>
|
||||
private class DummyConversionBeatmap : WorkingBeatmap
|
||||
{
|
||||
private readonly IBeatmap beatmap;
|
||||
|
||||
public DummyConversionBeatmap(IBeatmap beatmap)
|
||||
: base(beatmap.BeatmapInfo)
|
||||
{
|
||||
this.beatmap = beatmap;
|
||||
}
|
||||
|
||||
protected override IBeatmap GetBeatmap() => beatmap;
|
||||
protected override Texture GetBackground() => null;
|
||||
protected override Track GetTrack() => null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Beatmaps
|
||||
this.audioManager = audioManager;
|
||||
}
|
||||
|
||||
protected override Beatmap GetBeatmap()
|
||||
protected override IBeatmap GetBeatmap()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -2,30 +2,47 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
{
|
||||
public interface IBeatmapProcessor
|
||||
{
|
||||
IBeatmap Beatmap { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Post-processes <see cref="Beatmap"/> to add mode-specific components that aren't added during conversion.
|
||||
/// <para>
|
||||
/// An example of such a usage is for combo colours.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
void PostProcess();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes a post-converted Beatmap.
|
||||
/// </summary>
|
||||
/// <typeparam name="TObject">The type of HitObject contained in the Beatmap.</typeparam>
|
||||
public class BeatmapProcessor<TObject>
|
||||
where TObject : HitObject
|
||||
public class BeatmapProcessor : IBeatmapProcessor
|
||||
{
|
||||
public IBeatmap Beatmap { get; }
|
||||
|
||||
public BeatmapProcessor(IBeatmap beatmap)
|
||||
{
|
||||
Beatmap = beatmap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Post-processes a Beatmap to add mode-specific components that aren't added during conversion.
|
||||
/// <para>
|
||||
/// An example of such a usage is for combo colours.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The Beatmap to process.</param>
|
||||
public virtual void PostProcess(Beatmap<TObject> beatmap)
|
||||
public virtual void PostProcess()
|
||||
{
|
||||
IHasComboInformation lastObj = null;
|
||||
|
||||
foreach (var obj in beatmap.HitObjects.OfType<IHasComboInformation>())
|
||||
foreach (var obj in Beatmap.HitObjects.OfType<IHasComboInformation>())
|
||||
{
|
||||
if (obj.NewCombo)
|
||||
{
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Framework.Timing;
|
||||
@ -12,30 +11,17 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
public abstract class DifficultyCalculator
|
||||
{
|
||||
protected double TimeRate = 1;
|
||||
|
||||
public abstract double Calculate(Dictionary<string, double> categoryDifficulty = null);
|
||||
}
|
||||
|
||||
public abstract class DifficultyCalculator<T> : DifficultyCalculator where T : HitObject
|
||||
{
|
||||
protected readonly Beatmap<T> Beatmap;
|
||||
protected readonly IBeatmap Beatmap;
|
||||
protected readonly Mod[] Mods;
|
||||
|
||||
protected DifficultyCalculator(Beatmap beatmap, Mod[] mods = null)
|
||||
protected double TimeRate = 1;
|
||||
|
||||
protected DifficultyCalculator(IBeatmap beatmap, Mod[] mods = null)
|
||||
{
|
||||
Beatmap = beatmap;
|
||||
Mods = mods ?? new Mod[0];
|
||||
|
||||
var converter = CreateBeatmapConverter(beatmap);
|
||||
|
||||
foreach (var mod in Mods.OfType<IApplicableToBeatmapConverter<T>>())
|
||||
mod.ApplyToBeatmapConverter(converter);
|
||||
|
||||
Beatmap = converter.Convert(beatmap);
|
||||
|
||||
ApplyMods(Mods);
|
||||
|
||||
PreprocessHitObjects();
|
||||
}
|
||||
|
||||
protected virtual void ApplyMods(Mod[] mods)
|
||||
@ -43,22 +29,12 @@ namespace osu.Game.Beatmaps
|
||||
var clock = new StopwatchClock();
|
||||
mods.OfType<IApplicableToClock>().ForEach(m => m.ApplyToClock(clock));
|
||||
TimeRate = clock.Rate;
|
||||
|
||||
foreach (var mod in Mods.OfType<IApplicableToDifficulty>())
|
||||
mod.ApplyToDifficulty(Beatmap.BeatmapInfo.BaseDifficulty);
|
||||
|
||||
foreach (var h in Beatmap.HitObjects)
|
||||
h.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty);
|
||||
|
||||
foreach (var mod in mods.OfType<IApplicableToHitObject<T>>())
|
||||
foreach (var obj in Beatmap.HitObjects)
|
||||
mod.ApplyToHitObject(obj);
|
||||
}
|
||||
|
||||
protected virtual void PreprocessHitObjects()
|
||||
{
|
||||
}
|
||||
|
||||
protected abstract BeatmapConverter<T> CreateBeatmapConverter(Beatmap beatmap);
|
||||
public abstract double Calculate(Dictionary<string, double> categoryDifficulty = null);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
@ -39,7 +40,7 @@ namespace osu.Game.Beatmaps
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
protected override Beatmap GetBeatmap() => new Beatmap();
|
||||
protected override IBeatmap GetBeatmap() => new Beatmap();
|
||||
|
||||
protected override Texture GetBackground() => game.Textures.Get(@"Backgrounds/bg4");
|
||||
|
||||
@ -53,12 +54,14 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type) => new Mod[] { };
|
||||
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => null;
|
||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new DummyBeatmapConverter { Beatmap = beatmap };
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null) => null;
|
||||
|
||||
public override string Description => "dummy";
|
||||
|
||||
@ -68,6 +71,14 @@ namespace osu.Game.Beatmaps
|
||||
: base(rulesetInfo)
|
||||
{
|
||||
}
|
||||
|
||||
private class DummyBeatmapConverter : IBeatmapConverter
|
||||
{
|
||||
public event Action<HitObject, IEnumerable<HitObject>> ObjectConverted;
|
||||
public IBeatmap Beatmap { get; set; }
|
||||
public bool CanConvert => true;
|
||||
public IBeatmap Convert() => Beatmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
50
osu.Game/Beatmaps/IBeatmap.cs
Normal file
50
osu.Game/Beatmaps/IBeatmap.cs
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.IO.Serialization;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
{
|
||||
public interface IBeatmap : IJsonSerializable
|
||||
{
|
||||
/// <summary>
|
||||
/// This beatmap's info.
|
||||
/// </summary>
|
||||
BeatmapInfo BeatmapInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This beatmap's metadata.
|
||||
/// </summary>
|
||||
BeatmapMetadata Metadata { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The control points in this beatmap.
|
||||
/// </summary>
|
||||
ControlPointInfo ControlPointInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The breaks in this beatmap.
|
||||
/// </summary>
|
||||
List<BreakPeriod> Breaks { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Total amount of break time in the beatmap.
|
||||
/// </summary>
|
||||
double TotalBreakTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The hitobjects contained by this beatmap.
|
||||
/// </summary>
|
||||
IEnumerable<HitObject> HitObjects { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a shallow-clone of this beatmap and returns it.
|
||||
/// </summary>
|
||||
/// <returns>The shallow-cloned beatmap.</returns>
|
||||
IBeatmap Clone();
|
||||
}
|
||||
}
|
@ -16,10 +16,16 @@ namespace osu.Game.Beatmaps
|
||||
/// </summary>
|
||||
event Action<HitObject, IEnumerable<HitObject>> ObjectConverted;
|
||||
|
||||
IBeatmap Beatmap { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Beatmap using this Beatmap Converter.
|
||||
/// Whether <see cref="Beatmap"/> can be converted by this <see cref="IBeatmapConverter"/>.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The un-converted Beatmap.</param>
|
||||
void Convert(Beatmap beatmap);
|
||||
bool CanConvert { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Converts <see cref="Beatmap"/>.
|
||||
/// </summary>
|
||||
IBeatmap Convert();
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Beatmaps.Legacy
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of Beatmap loaded from a legacy .osu beatmap file (version <=15).
|
||||
/// </summary>
|
||||
public class LegacyBeatmap : Beatmap
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs a new beatmap.
|
||||
/// </summary>
|
||||
/// <param name="original">The original beatmap to use the parameters of.</param>
|
||||
internal LegacyBeatmap(Beatmap original = null)
|
||||
: base(original)
|
||||
{
|
||||
HitObjects = original?.HitObjects;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,8 @@ using osu.Framework.IO.File;
|
||||
using System.IO;
|
||||
using osu.Game.IO.Serialization;
|
||||
using System.Diagnostics;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
@ -36,7 +38,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
Mods.ValueChanged += mods => applyRateAdjustments();
|
||||
|
||||
beatmap = new AsyncLazy<Beatmap>(populateBeatmap);
|
||||
beatmap = new AsyncLazy<IBeatmap>(populateBeatmap);
|
||||
background = new AsyncLazy<Texture>(populateBackground, b => b == null || !b.IsDisposed);
|
||||
track = new AsyncLazy<Track>(populateTrack);
|
||||
waveform = new AsyncLazy<Waveform>(populateWaveform);
|
||||
@ -45,7 +47,7 @@ namespace osu.Game.Beatmaps
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the <see cref="Beatmap"/>.
|
||||
/// Saves the <see cref="Beatmaps.Beatmap"/>.
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
@ -55,7 +57,7 @@ namespace osu.Game.Beatmaps
|
||||
Process.Start(path);
|
||||
}
|
||||
|
||||
protected abstract Beatmap GetBeatmap();
|
||||
protected abstract IBeatmap GetBeatmap();
|
||||
protected abstract Texture GetBackground();
|
||||
protected abstract Track GetTrack();
|
||||
protected virtual Skin GetSkin() => new DefaultSkin();
|
||||
@ -63,12 +65,11 @@ namespace osu.Game.Beatmaps
|
||||
protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo };
|
||||
|
||||
public bool BeatmapLoaded => beatmap.IsResultAvailable;
|
||||
public Beatmap Beatmap => beatmap.Value.Result;
|
||||
public async Task<Beatmap> GetBeatmapAsync() => await beatmap.Value;
|
||||
public IBeatmap Beatmap => beatmap.Value.Result;
|
||||
public async Task<IBeatmap> GetBeatmapAsync() => await beatmap.Value;
|
||||
private readonly AsyncLazy<IBeatmap> beatmap;
|
||||
|
||||
private readonly AsyncLazy<Beatmap> beatmap;
|
||||
|
||||
private Beatmap populateBeatmap()
|
||||
private IBeatmap populateBeatmap()
|
||||
{
|
||||
var b = GetBeatmap() ?? new Beatmap();
|
||||
|
||||
@ -78,6 +79,51 @@ namespace osu.Game.Beatmaps
|
||||
return b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a playable <see cref="IBeatmap"/> from <see cref="Beatmap"/> using the applicable converters for a specific <see cref="RulesetInfo"/>.
|
||||
/// <para>
|
||||
/// The returned <see cref="IBeatmap"/> is in a playable state - all <see cref="HitObject"/> and <see cref="BeatmapDifficulty"/> <see cref="Mod"/>s
|
||||
/// have been applied, and <see cref="HitObject"/>s have been fully constructed.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="ruleset">The <see cref="RulesetInfo"/> to create a playable <see cref="IBeatmap"/> for.</param>
|
||||
/// <returns>The converted <see cref="IBeatmap"/>.</returns>
|
||||
/// <exception cref="BeatmapInvalidForRulesetException">If <see cref="Beatmap"/> could not be converted to <paramref name="ruleset"/>.</exception>
|
||||
public IBeatmap GetPlayableBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var rulesetInstance = ruleset.CreateInstance();
|
||||
|
||||
IBeatmapConverter converter = rulesetInstance.CreateBeatmapConverter(Beatmap);
|
||||
|
||||
// Check if the beatmap can be converted
|
||||
if (!converter.CanConvert)
|
||||
throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset.InstantiationInfo}, converter: {converter}).");
|
||||
|
||||
// Apply conversion mods
|
||||
foreach (var mod in Mods.Value.OfType<IApplicableToBeatmapConverter>())
|
||||
mod.ApplyToBeatmapConverter(converter);
|
||||
|
||||
// Convert
|
||||
IBeatmap converted = converter.Convert();
|
||||
|
||||
// Apply difficulty mods
|
||||
foreach (var mod in Mods.Value.OfType<IApplicableToDifficulty>())
|
||||
mod.ApplyToDifficulty(converted.BeatmapInfo.BaseDifficulty);
|
||||
|
||||
// Post-process
|
||||
rulesetInstance.CreateBeatmapProcessor(converted)?.PostProcess();
|
||||
|
||||
// Compute default values for hitobjects, including creating nested hitobjects in-case they're needed
|
||||
foreach (var obj in converted.HitObjects)
|
||||
obj.ApplyDefaults(converted.ControlPointInfo, converted.BeatmapInfo.BaseDifficulty);
|
||||
|
||||
foreach (var mod in Mods.Value.OfType<IApplicableToHitObject>())
|
||||
foreach (var obj in converted.HitObjects)
|
||||
mod.ApplyToHitObject(obj);
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
public bool BackgroundLoaded => background.IsResultAvailable;
|
||||
public Texture Background => background.Value.Result;
|
||||
public async Task<Texture> GetBackgroundAsync() => await background.Value;
|
||||
|
@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool;
|
||||
|
||||
protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true);
|
||||
protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap);
|
||||
|
||||
protected abstract IReadOnlyList<ICompositionTool> CompositionTools { get; }
|
||||
|
||||
|
@ -10,13 +10,12 @@ namespace osu.Game.Rulesets.Mods
|
||||
/// Interface for a <see cref="Mod"/> that applies changes to a <see cref="BeatmapConverter{TObject}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TObject">The type of converted <see cref="HitObject"/>.</typeparam>
|
||||
public interface IApplicableToBeatmapConverter<TObject> : IApplicableMod
|
||||
where TObject : HitObject
|
||||
public interface IApplicableToBeatmapConverter : IApplicableMod
|
||||
{
|
||||
/// <summary>
|
||||
/// Applies this <see cref="Mod"/> to a <see cref="BeatmapConverter{TObject}"/>.
|
||||
/// </summary>
|
||||
/// <param name="beatmapConverter">The <see cref="BeatmapConverter{TObject}"/> to apply to.</param>
|
||||
void ApplyToBeatmapConverter(BeatmapConverter<TObject> beatmapConverter);
|
||||
void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter);
|
||||
}
|
||||
}
|
||||
|
@ -8,13 +8,12 @@ namespace osu.Game.Rulesets.Mods
|
||||
/// <summary>
|
||||
/// An interface for <see cref="Mod"/>s that can be applied to <see cref="HitObject"/>s.
|
||||
/// </summary>
|
||||
public interface IApplicableToHitObject<in TObject> : IApplicableMod
|
||||
where TObject : HitObject
|
||||
public interface IApplicableToHitObject : IApplicableMod
|
||||
{
|
||||
/// <summary>
|
||||
/// Applies this <see cref="IApplicableToHitObject{TObject}"/> to a <see cref="HitObject"/>.
|
||||
/// </summary>
|
||||
/// <param name="hitObject">The <see cref="HitObject"/> to apply to.</param>
|
||||
void ApplyToHitObject(TObject hitObject);
|
||||
void ApplyToHitObject(HitObject hitObject);
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Replays.Types
|
||||
/// </summary>
|
||||
/// <param name="legacyFrame">The <see cref="LegacyReplayFrame"/> to extract values from.</param>
|
||||
/// <param name="beatmap">The beatmap.</param>
|
||||
void ConvertFrom(LegacyReplayFrame legacyFrame, Beatmap beatmap);
|
||||
void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap);
|
||||
}
|
||||
}
|
||||
|
@ -52,14 +52,17 @@ namespace osu.Game.Rulesets
|
||||
/// Attempt to create a hit renderer for a beatmap
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap to create the hit renderer for.</param>
|
||||
/// <param name="isForCurrentRuleset">Whether the hit renderer should assume the beatmap is for the current ruleset.</param>
|
||||
/// <exception cref="BeatmapInvalidForRulesetException">Unable to successfully load the beatmap to be usable with this ruleset.</exception>
|
||||
/// <returns></returns>
|
||||
public abstract RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset);
|
||||
public abstract RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap);
|
||||
|
||||
public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null);
|
||||
public abstract IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap);
|
||||
|
||||
public virtual PerformanceCalculator CreatePerformanceCalculator(Beatmap beatmap, Score score) => null;
|
||||
public virtual IBeatmapProcessor CreateBeatmapProcessor(IBeatmap beatmap) => null;
|
||||
|
||||
public abstract DifficultyCalculator CreateDifficultyCalculator(IBeatmap beatmap, Mod[] mods = null);
|
||||
|
||||
public virtual PerformanceCalculator CreatePerformanceCalculator(IBeatmap beatmap, Score score) => null;
|
||||
|
||||
public virtual HitObjectComposer CreateHitObjectComposer() => null;
|
||||
|
||||
@ -114,7 +117,8 @@ namespace osu.Game.Rulesets
|
||||
Name = Description,
|
||||
ShortName = ShortName,
|
||||
InstantiationInfo = GetType().AssemblyQualifiedName,
|
||||
ID = LegacyID
|
||||
ID = LegacyID,
|
||||
Available = true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Scoring.Legacy
|
||||
this.beatmaps = beatmaps;
|
||||
}
|
||||
|
||||
private Beatmap currentBeatmap;
|
||||
private IBeatmap currentBeatmap;
|
||||
private Ruleset currentRuleset;
|
||||
|
||||
public Score Parse(Stream stream)
|
||||
|
@ -2,42 +2,28 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Scoring
|
||||
{
|
||||
public abstract class PerformanceCalculator
|
||||
{
|
||||
public abstract double Calculate(Dictionary<string, double> categoryDifficulty = null);
|
||||
}
|
||||
|
||||
public abstract class PerformanceCalculator<TObject> : PerformanceCalculator
|
||||
where TObject : HitObject
|
||||
{
|
||||
private readonly Dictionary<string, double> attributes = new Dictionary<string, double>();
|
||||
protected IDictionary<string, double> Attributes => attributes;
|
||||
|
||||
protected readonly Beatmap<TObject> Beatmap;
|
||||
protected readonly IBeatmap Beatmap;
|
||||
protected readonly Score Score;
|
||||
|
||||
protected PerformanceCalculator(Ruleset ruleset, Beatmap beatmap, Score score)
|
||||
protected PerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score)
|
||||
{
|
||||
Score = score;
|
||||
|
||||
var converter = CreateBeatmapConverter();
|
||||
|
||||
foreach (var mod in score.Mods.OfType<IApplicableToBeatmapConverter<TObject>>())
|
||||
mod.ApplyToBeatmapConverter(converter);
|
||||
|
||||
Beatmap = converter.Convert(beatmap);
|
||||
Beatmap = beatmap;
|
||||
|
||||
var diffCalc = ruleset.CreateDifficultyCalculator(beatmap, score.Mods);
|
||||
diffCalc.Calculate(attributes);
|
||||
}
|
||||
|
||||
protected abstract BeatmapConverter<TObject> CreateBeatmapConverter();
|
||||
public abstract double Calculate(Dictionary<string, double> categoryDifficulty = null);
|
||||
}
|
||||
}
|
||||
|
@ -190,11 +190,6 @@ namespace osu.Game.Rulesets.UI
|
||||
/// </summary>
|
||||
protected readonly WorkingBeatmap WorkingBeatmap;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the specified beatmap is assumed to be specific to the current ruleset.
|
||||
/// </summary>
|
||||
public readonly bool IsForCurrentRuleset;
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor<TObject>(this);
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
@ -206,43 +201,18 @@ namespace osu.Game.Rulesets.UI
|
||||
/// </summary>
|
||||
/// <param name="ruleset">The ruleset being repesented.</param>
|
||||
/// <param name="workingBeatmap">The beatmap to create the hit renderer for.</param>
|
||||
/// <param name="isForCurrentRuleset">Whether to assume the beatmap is for the current ruleset.</param>
|
||||
protected RulesetContainer(Ruleset ruleset, WorkingBeatmap workingBeatmap, bool isForCurrentRuleset)
|
||||
protected RulesetContainer(Ruleset ruleset, WorkingBeatmap workingBeatmap)
|
||||
: base(ruleset)
|
||||
{
|
||||
Debug.Assert(workingBeatmap != null, "RulesetContainer initialized with a null beatmap.");
|
||||
|
||||
WorkingBeatmap = workingBeatmap;
|
||||
IsForCurrentRuleset = isForCurrentRuleset;
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
Mods = workingBeatmap.Mods.Value;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
BeatmapConverter<TObject> converter = CreateBeatmapConverter();
|
||||
BeatmapProcessor<TObject> processor = CreateBeatmapProcessor();
|
||||
|
||||
// Check if the beatmap can be converted
|
||||
if (!converter.CanConvert(workingBeatmap.Beatmap))
|
||||
throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can not be converted for the current ruleset (converter: {converter}).");
|
||||
|
||||
// Apply conversion adjustments before converting
|
||||
foreach (var mod in Mods.OfType<IApplicableToBeatmapConverter<TObject>>())
|
||||
mod.ApplyToBeatmapConverter(converter);
|
||||
|
||||
// Convert the beatmap
|
||||
Beatmap = converter.Convert(workingBeatmap.Beatmap);
|
||||
|
||||
// Apply difficulty adjustments from mods before using Difficulty.
|
||||
foreach (var mod in Mods.OfType<IApplicableToDifficulty>())
|
||||
mod.ApplyToDifficulty(Beatmap.BeatmapInfo.BaseDifficulty);
|
||||
|
||||
// Post-process the beatmap
|
||||
processor.PostProcess(Beatmap);
|
||||
|
||||
// Apply defaults
|
||||
foreach (var h in Beatmap.HitObjects)
|
||||
h.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty);
|
||||
Beatmap = (Beatmap<TObject>)workingBeatmap.GetPlayableBeatmap(ruleset.RulesetInfo);
|
||||
|
||||
KeyBindingInputManager = CreateInputManager();
|
||||
KeyBindingInputManager.RelativeSizeAxes = Axes.Both;
|
||||
@ -277,10 +247,6 @@ namespace osu.Game.Rulesets.UI
|
||||
if (mods == null)
|
||||
return;
|
||||
|
||||
foreach (var mod in mods.OfType<IApplicableToHitObject<TObject>>())
|
||||
foreach (var obj in Beatmap.HitObjects)
|
||||
mod.ApplyToHitObject(obj);
|
||||
|
||||
foreach (var mod in mods.OfType<IApplicableToRulesetContainer<TObject>>())
|
||||
mod.ApplyToRulesetContainer(this);
|
||||
}
|
||||
@ -324,13 +290,6 @@ namespace osu.Game.Rulesets.UI
|
||||
Playfield.Size = GetAspectAdjustedSize() * PlayfieldArea;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a processor to perform post-processing operations
|
||||
/// on HitObjects in converted Beatmaps.
|
||||
/// </summary>
|
||||
/// <returns>The Beatmap processor.</returns>
|
||||
protected virtual BeatmapProcessor<TObject> CreateBeatmapProcessor() => new BeatmapProcessor<TObject>();
|
||||
|
||||
/// <summary>
|
||||
/// Computes the size of the <see cref="Playfield"/> in relative coordinate space after aspect adjustments.
|
||||
/// </summary>
|
||||
@ -344,12 +303,6 @@ namespace osu.Game.Rulesets.UI
|
||||
/// </summary>
|
||||
protected virtual Vector2 PlayfieldArea => new Vector2(0.75f); // A sane default
|
||||
|
||||
/// <summary>
|
||||
/// Creates a converter to convert Beatmap to a specific mode.
|
||||
/// </summary>
|
||||
/// <returns>The Beatmap converter.</returns>
|
||||
protected abstract BeatmapConverter<TObject> CreateBeatmapConverter();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a DrawableHitObject from a HitObject.
|
||||
/// </summary>
|
||||
@ -377,9 +330,8 @@ namespace osu.Game.Rulesets.UI
|
||||
/// </summary>
|
||||
/// <param name="ruleset">The ruleset being repesented.</param>
|
||||
/// <param name="beatmap">The beatmap to create the hit renderer for.</param>
|
||||
/// <param name="isForCurrentRuleset">Whether to assume the beatmap is for the current ruleset.</param>
|
||||
protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset, beatmap, isForCurrentRuleset)
|
||||
protected RulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
/// <returns></returns>
|
||||
protected readonly SortedList<MultiplierControlPoint> DefaultControlPoints = new SortedList<MultiplierControlPoint>(Comparer<MultiplierControlPoint>.Default);
|
||||
|
||||
protected ScrollingRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
|
||||
: base(ruleset, beatmap, isForCurrentRuleset)
|
||||
protected ScrollingRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ namespace osu.Game.Screens.Play
|
||||
mouseWheelDisabled = config.GetBindable<bool>(OsuSetting.MouseDisableWheel);
|
||||
userAudioOffset = config.GetBindable<double>(OsuSetting.AudioOffset);
|
||||
|
||||
Beatmap beatmap;
|
||||
IBeatmap beatmap;
|
||||
|
||||
try
|
||||
{
|
||||
@ -109,7 +109,7 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
try
|
||||
{
|
||||
RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working, ruleset.ID == beatmap.BeatmapInfo.Ruleset.ID);
|
||||
RulesetContainer = rulesetInstance.CreateRulesetContainerWith(working);
|
||||
}
|
||||
catch (BeatmapInvalidForRulesetException)
|
||||
{
|
||||
@ -117,7 +117,7 @@ namespace osu.Game.Screens.Play
|
||||
// let's try again forcing the beatmap's ruleset.
|
||||
ruleset = beatmap.BeatmapInfo.Ruleset;
|
||||
rulesetInstance = ruleset.CreateInstance();
|
||||
RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap, true);
|
||||
RulesetContainer = rulesetInstance.CreateRulesetContainerWith(Beatmap);
|
||||
}
|
||||
|
||||
if (!RulesetContainer.Objects.Any())
|
||||
|
@ -215,7 +215,7 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
List<InfoLabel> labels = new List<InfoLabel>();
|
||||
|
||||
if (beatmap?.HitObjects?.Count > 0)
|
||||
if (beatmap?.HitObjects?.Any() == true)
|
||||
{
|
||||
HitObject lastObject = beatmap.HitObjects.LastOrDefault();
|
||||
double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0;
|
||||
@ -224,7 +224,7 @@ namespace osu.Game.Screens.Select
|
||||
{
|
||||
Name = "Length",
|
||||
Icon = FontAwesome.fa_clock_o,
|
||||
Content = beatmap.HitObjects.Count == 0 ? "-" : TimeSpan.FromMilliseconds(endTime - beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"),
|
||||
Content = TimeSpan.FromMilliseconds(endTime - beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"),
|
||||
}));
|
||||
|
||||
labels.Add(new InfoLabel(new BeatmapStatistic
|
||||
@ -241,7 +241,7 @@ namespace osu.Game.Screens.Select
|
||||
return labels.ToArray();
|
||||
}
|
||||
|
||||
private string getBPMRange(Beatmap beatmap)
|
||||
private string getBPMRange(IBeatmap beatmap)
|
||||
{
|
||||
double bpmMax = beatmap.ControlPointInfo.BPMMaximum;
|
||||
double bpmMin = beatmap.ControlPointInfo.BPMMinimum;
|
||||
|
@ -10,12 +10,14 @@ using NUnit.Framework;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
|
||||
namespace osu.Game.Tests.Beatmaps
|
||||
{
|
||||
[TestFixture]
|
||||
public abstract class BeatmapConversionTest<TConvertValue>
|
||||
public abstract class BeatmapConversionTest<TRuleset, TConvertValue>
|
||||
where TRuleset : Ruleset, new()
|
||||
where TConvertValue : IEquatable<TConvertValue>
|
||||
{
|
||||
private const string resource_namespace = "Testing.Beatmaps";
|
||||
@ -79,6 +81,9 @@ namespace osu.Game.Tests.Beatmaps
|
||||
{
|
||||
var beatmap = getBeatmap(name);
|
||||
|
||||
var rulesetInstance = new TRuleset();
|
||||
beatmap.BeatmapInfo.Ruleset = beatmap.BeatmapInfo.RulesetID == rulesetInstance.RulesetInfo.ID ? rulesetInstance.RulesetInfo : new RulesetInfo();
|
||||
|
||||
var result = new ConvertResult();
|
||||
|
||||
var converter = CreateConverter(beatmap);
|
||||
@ -92,7 +97,7 @@ namespace osu.Game.Tests.Beatmaps
|
||||
result.Mappings.Add(mapping);
|
||||
};
|
||||
|
||||
converter.Convert(beatmap);
|
||||
converter.Convert();
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -107,7 +112,7 @@ namespace osu.Game.Tests.Beatmaps
|
||||
}
|
||||
}
|
||||
|
||||
private Beatmap getBeatmap(string name)
|
||||
private IBeatmap getBeatmap(string name)
|
||||
{
|
||||
using (var resStream = openResource($"{resource_namespace}.{name}.osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
@ -125,7 +130,7 @@ namespace osu.Game.Tests.Beatmaps
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<TConvertValue> CreateConvertValue(HitObject hitObject);
|
||||
protected abstract IBeatmapConverter CreateConverter(Beatmap beatmap);
|
||||
protected abstract IBeatmapConverter CreateConverter(IBeatmap beatmap);
|
||||
|
||||
private class ConvertMapping
|
||||
{
|
||||
|
@ -12,8 +12,14 @@ namespace osu.Game.Tests.Beatmaps
|
||||
public class TestBeatmap : Beatmap
|
||||
{
|
||||
public TestBeatmap(RulesetInfo ruleset)
|
||||
: base(createTestBeatmap())
|
||||
{
|
||||
var baseBeatmap = createTestBeatmap();
|
||||
|
||||
BeatmapInfo = baseBeatmap.BeatmapInfo;
|
||||
ControlPointInfo = baseBeatmap.ControlPointInfo;
|
||||
Breaks = baseBeatmap.Breaks;
|
||||
HitObjects = baseBeatmap.HitObjects;
|
||||
|
||||
BeatmapInfo.Ruleset = ruleset;
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,14 @@ namespace osu.Game.Tests.Beatmaps
|
||||
{
|
||||
}
|
||||
|
||||
public TestWorkingBeatmap(Beatmap beatmap)
|
||||
public TestWorkingBeatmap(IBeatmap beatmap)
|
||||
: base(beatmap.BeatmapInfo)
|
||||
{
|
||||
this.beatmap = beatmap;
|
||||
}
|
||||
|
||||
private readonly Beatmap beatmap;
|
||||
protected override Beatmap GetBeatmap() => beatmap;
|
||||
private readonly IBeatmap beatmap;
|
||||
protected override IBeatmap GetBeatmap() => beatmap;
|
||||
protected override Texture GetBackground() => null;
|
||||
|
||||
protected override Track GetTrack()
|
||||
|
@ -259,9 +259,9 @@ namespace osu.Game.Tests.Visual
|
||||
private readonly OsuSpriteText text;
|
||||
|
||||
private readonly Score score;
|
||||
private readonly Beatmap beatmap;
|
||||
private readonly IBeatmap beatmap;
|
||||
|
||||
public PerformanceDisplay(Score score, Beatmap beatmap)
|
||||
public PerformanceDisplay(Score score, IBeatmap beatmap)
|
||||
{
|
||||
this.score = score;
|
||||
this.beatmap = beatmap;
|
||||
|
@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual Beatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo);
|
||||
protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo);
|
||||
|
||||
private Player loadPlayerFor(RulesetInfo ri) => loadPlayerFor(ri.CreateInstance());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user