mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 09:02:58 +08:00
Merge branch 'master' into beatmap-card/download-button
This commit is contained in:
commit
8a1d6757af
@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.EmptyFreeform
|
|||||||
{
|
{
|
||||||
public class EmptyFreeformDifficultyCalculator : DifficultyCalculator
|
public class EmptyFreeformDifficultyCalculator : DifficultyCalculator
|
||||||
{
|
{
|
||||||
public EmptyFreeformDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap)
|
public EmptyFreeformDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ namespace osu.Game.Rulesets.EmptyFreeform
|
|||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) =>
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) =>
|
||||||
new EmptyFreeformBeatmapConverter(beatmap, this);
|
new EmptyFreeformBeatmapConverter(beatmap, this);
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) =>
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) =>
|
||||||
new EmptyFreeformDifficultyCalculator(this, beatmap);
|
new EmptyFreeformDifficultyCalculator(RulesetInfo, beatmap);
|
||||||
|
|
||||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||||
{
|
{
|
||||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Pippidon
|
|||||||
{
|
{
|
||||||
public class PippidonDifficultyCalculator : DifficultyCalculator
|
public class PippidonDifficultyCalculator : DifficultyCalculator
|
||||||
{
|
{
|
||||||
public PippidonDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap)
|
public PippidonDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ namespace osu.Game.Rulesets.Pippidon
|
|||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) =>
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) =>
|
||||||
new PippidonBeatmapConverter(beatmap, this);
|
new PippidonBeatmapConverter(beatmap, this);
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) =>
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) =>
|
||||||
new PippidonDifficultyCalculator(this, beatmap);
|
new PippidonDifficultyCalculator(RulesetInfo, beatmap);
|
||||||
|
|
||||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||||
{
|
{
|
||||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.EmptyScrolling
|
|||||||
{
|
{
|
||||||
public class EmptyScrollingDifficultyCalculator : DifficultyCalculator
|
public class EmptyScrollingDifficultyCalculator : DifficultyCalculator
|
||||||
{
|
{
|
||||||
public EmptyScrollingDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap)
|
public EmptyScrollingDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.EmptyScrolling
|
|||||||
|
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new EmptyScrollingBeatmapConverter(beatmap, this);
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new EmptyScrollingBeatmapConverter(beatmap, this);
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new EmptyScrollingDifficultyCalculator(this, beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new EmptyScrollingDifficultyCalculator(RulesetInfo, beatmap);
|
||||||
|
|
||||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||||
{
|
{
|
||||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Pippidon
|
|||||||
{
|
{
|
||||||
public class PippidonDifficultyCalculator : DifficultyCalculator
|
public class PippidonDifficultyCalculator : DifficultyCalculator
|
||||||
{
|
{
|
||||||
public PippidonDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap)
|
public PippidonDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Pippidon
|
|||||||
|
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new PippidonBeatmapConverter(beatmap, this);
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new PippidonBeatmapConverter(beatmap, this);
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new PippidonDifficultyCalculator(this, beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new PippidonDifficultyCalculator(RulesetInfo, beatmap);
|
||||||
|
|
||||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.1112.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.1112.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.1108.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.1118.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. -->
|
||||||
|
@ -93,6 +93,11 @@ namespace osu.Desktop
|
|||||||
|
|
||||||
protected override UpdateManager CreateUpdateManager()
|
protected override UpdateManager CreateUpdateManager()
|
||||||
{
|
{
|
||||||
|
string packageManaged = Environment.GetEnvironmentVariable("OSU_EXTERNAL_UPDATE_PROVIDER");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(packageManaged))
|
||||||
|
return new NoActionUpdateManager();
|
||||||
|
|
||||||
switch (RuntimeInfo.OS)
|
switch (RuntimeInfo.OS)
|
||||||
{
|
{
|
||||||
case RuntimeInfo.Platform.Windows:
|
case RuntimeInfo.Platform.Windows:
|
||||||
|
@ -183,6 +183,19 @@ namespace osu.Desktop.Updater
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Close()
|
||||||
|
{
|
||||||
|
// cancelling updates is not currently supported by the underlying updater.
|
||||||
|
// only allow dismissing for now.
|
||||||
|
|
||||||
|
switch (State)
|
||||||
|
{
|
||||||
|
case ProgressNotificationState.Cancelled:
|
||||||
|
base.Close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SquirrelLogger : Splat.ILogger, IDisposable
|
private class SquirrelLogger : Splat.ILogger, IDisposable
|
||||||
|
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
public void TestClockRateAdjusted(double expected, string name)
|
public void TestClockRateAdjusted(double expected, string name)
|
||||||
=> Test(expected, name, new CatchModDoubleTime());
|
=> Test(expected, name, new CatchModDoubleTime());
|
||||||
|
|
||||||
protected override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(new CatchRuleset(), beatmap);
|
protected override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new CatchDifficultyCalculator(new CatchRuleset().RulesetInfo, beatmap);
|
||||||
|
|
||||||
protected override Ruleset CreateRuleset() => new CatchRuleset();
|
protected override Ruleset CreateRuleset() => new CatchRuleset();
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
var controlPointInfo = new ControlPointInfo();
|
var controlPointInfo = new ControlPointInfo();
|
||||||
controlPointInfo.Add(0, new TimingControlPoint());
|
controlPointInfo.Add(0, new TimingControlPoint());
|
||||||
|
|
||||||
WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap
|
IWorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap
|
||||||
{
|
{
|
||||||
HitObjects = new List<HitObject> { new Fruit() },
|
HitObjects = new List<HitObject> { new Fruit() },
|
||||||
BeatmapInfo = new BeatmapInfo
|
BeatmapInfo = new BeatmapInfo
|
||||||
|
@ -178,7 +178,7 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
return base.GetDisplayNameForHitResult(result);
|
return base.GetDisplayNameForHitResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new CatchDifficultyCalculator(RulesetInfo, beatmap);
|
||||||
|
|
||||||
public override ISkin CreateLegacySkinProvider(ISkin skin, IBeatmap beatmap) => new CatchLegacySkinTransformer(skin);
|
public override ISkin CreateLegacySkinProvider(ISkin skin, IBeatmap beatmap) => new CatchLegacySkinTransformer(skin);
|
||||||
|
|
||||||
|
@ -1,12 +1,35 @@
|
|||||||
// 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.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Difficulty
|
namespace osu.Game.Rulesets.Catch.Difficulty
|
||||||
{
|
{
|
||||||
public class CatchDifficultyAttributes : DifficultyAttributes
|
public class CatchDifficultyAttributes : DifficultyAttributes
|
||||||
{
|
{
|
||||||
|
[JsonProperty("approach_rate")]
|
||||||
public double ApproachRate { get; set; }
|
public double ApproachRate { get; set; }
|
||||||
|
|
||||||
|
public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes()
|
||||||
|
{
|
||||||
|
foreach (var v in base.ToDatabaseAttributes())
|
||||||
|
yield return v;
|
||||||
|
|
||||||
|
// Todo: osu!catch should not output star rating in the 'aim' attribute.
|
||||||
|
yield return (ATTRIB_ID_AIM, StarRating);
|
||||||
|
yield return (ATTRIB_ID_APPROACH_RATE, ApproachRate);
|
||||||
|
yield return (ATTRIB_ID_MAX_COMBO, MaxCombo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void FromDatabaseAttributes(IReadOnlyDictionary<int, double> values)
|
||||||
|
{
|
||||||
|
base.FromDatabaseAttributes(values);
|
||||||
|
|
||||||
|
StarRating = values[ATTRIB_ID_AIM];
|
||||||
|
ApproachRate = values[ATTRIB_ID_APPROACH_RATE];
|
||||||
|
MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
|
|
||||||
private float halfCatcherWidth;
|
private float halfCatcherWidth;
|
||||||
|
|
||||||
public CatchDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap)
|
public CatchDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
public void TestClockRateAdjusted(double expected, string name)
|
public void TestClockRateAdjusted(double expected, string name)
|
||||||
=> Test(expected, name, new ManiaModDoubleTime());
|
=> Test(expected, name, new ManiaModDoubleTime());
|
||||||
|
|
||||||
protected override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new ManiaDifficultyCalculator(new ManiaRuleset(), beatmap);
|
protected override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new ManiaDifficultyCalculator(new ManiaRuleset().RulesetInfo, beatmap);
|
||||||
|
|
||||||
protected override Ruleset CreateRuleset() => new ManiaRuleset();
|
protected override Ruleset CreateRuleset() => new ManiaRuleset();
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,38 @@
|
|||||||
// 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.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Difficulty
|
namespace osu.Game.Rulesets.Mania.Difficulty
|
||||||
{
|
{
|
||||||
public class ManiaDifficultyAttributes : DifficultyAttributes
|
public class ManiaDifficultyAttributes : DifficultyAttributes
|
||||||
{
|
{
|
||||||
|
[JsonProperty("great_hit_window")]
|
||||||
public double GreatHitWindow { get; set; }
|
public double GreatHitWindow { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("score_multiplier")]
|
||||||
public double ScoreMultiplier { get; set; }
|
public double ScoreMultiplier { get; set; }
|
||||||
|
|
||||||
|
public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes()
|
||||||
|
{
|
||||||
|
foreach (var v in base.ToDatabaseAttributes())
|
||||||
|
yield return v;
|
||||||
|
|
||||||
|
// Todo: osu!mania doesn't output MaxCombo attribute for some reason.
|
||||||
|
yield return (ATTRIB_ID_STRAIN, StarRating);
|
||||||
|
yield return (ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow);
|
||||||
|
yield return (ATTRIB_ID_SCORE_MULTIPLIER, ScoreMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void FromDatabaseAttributes(IReadOnlyDictionary<int, double> values)
|
||||||
|
{
|
||||||
|
base.FromDatabaseAttributes(values);
|
||||||
|
|
||||||
|
StarRating = values[ATTRIB_ID_STRAIN];
|
||||||
|
GreatHitWindow = values[ATTRIB_ID_GREAT_HIT_WINDOW];
|
||||||
|
ScoreMultiplier = values[ATTRIB_ID_SCORE_MULTIPLIER];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||||
using osu.Game.Rulesets.Difficulty.Skills;
|
using osu.Game.Rulesets.Difficulty.Skills;
|
||||||
@ -28,11 +29,11 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
private readonly bool isForCurrentRuleset;
|
private readonly bool isForCurrentRuleset;
|
||||||
private readonly double originalOverallDifficulty;
|
private readonly double originalOverallDifficulty;
|
||||||
|
|
||||||
public ManiaDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap)
|
public ManiaDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.Equals(ruleset.RulesetInfo);
|
isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.MatchesOnlineID(ruleset);
|
||||||
originalOverallDifficulty = beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty;
|
originalOverallDifficulty = beatmap.BeatmapInfo.Difficulty.OverallDifficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
||||||
|
@ -272,7 +272,7 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
|
|
||||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetMania };
|
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetMania };
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new ManiaDifficultyCalculator(this, beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new ManiaDifficultyCalculator(RulesetInfo, beatmap);
|
||||||
|
|
||||||
public int LegacyID => 3;
|
public int LegacyID => 3;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
public void TestClockRateAdjusted(double expected, string name)
|
public void TestClockRateAdjusted(double expected, string name)
|
||||||
=> Test(expected, name, new OsuModDoubleTime());
|
=> Test(expected, name, new OsuModDoubleTime());
|
||||||
|
|
||||||
protected override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(new OsuRuleset(), beatmap);
|
protected override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new OsuDifficultyCalculator(new OsuRuleset().RulesetInfo, beatmap);
|
||||||
|
|
||||||
protected override Ruleset CreateRuleset() => new OsuRuleset();
|
protected override Ruleset CreateRuleset() => new OsuRuleset();
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,77 @@
|
|||||||
// 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Difficulty
|
namespace osu.Game.Rulesets.Osu.Difficulty
|
||||||
{
|
{
|
||||||
public class OsuDifficultyAttributes : DifficultyAttributes
|
public class OsuDifficultyAttributes : DifficultyAttributes
|
||||||
{
|
{
|
||||||
|
[JsonProperty("aim_strain")]
|
||||||
public double AimStrain { get; set; }
|
public double AimStrain { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("speed_strain")]
|
||||||
public double SpeedStrain { get; set; }
|
public double SpeedStrain { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("flashlight_rating")]
|
||||||
public double FlashlightRating { get; set; }
|
public double FlashlightRating { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("slider_factor")]
|
||||||
public double SliderFactor { get; set; }
|
public double SliderFactor { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("approach_rate")]
|
||||||
public double ApproachRate { get; set; }
|
public double ApproachRate { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("overall_difficulty")]
|
||||||
public double OverallDifficulty { get; set; }
|
public double OverallDifficulty { get; set; }
|
||||||
|
|
||||||
public double DrainRate { get; set; }
|
public double DrainRate { get; set; }
|
||||||
|
|
||||||
public int HitCircleCount { get; set; }
|
public int HitCircleCount { get; set; }
|
||||||
|
|
||||||
public int SliderCount { get; set; }
|
public int SliderCount { get; set; }
|
||||||
|
|
||||||
public int SpinnerCount { get; set; }
|
public int SpinnerCount { get; set; }
|
||||||
|
|
||||||
|
public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes()
|
||||||
|
{
|
||||||
|
foreach (var v in base.ToDatabaseAttributes())
|
||||||
|
yield return v;
|
||||||
|
|
||||||
|
yield return (ATTRIB_ID_AIM, AimStrain);
|
||||||
|
yield return (ATTRIB_ID_SPEED, SpeedStrain);
|
||||||
|
yield return (ATTRIB_ID_OVERALL_DIFFICULTY, OverallDifficulty);
|
||||||
|
yield return (ATTRIB_ID_APPROACH_RATE, ApproachRate);
|
||||||
|
yield return (ATTRIB_ID_MAX_COMBO, MaxCombo);
|
||||||
|
yield return (ATTRIB_ID_STRAIN, StarRating);
|
||||||
|
|
||||||
|
if (ShouldSerializeFlashlightRating())
|
||||||
|
yield return (ATTRIB_ID_FLASHLIGHT, FlashlightRating);
|
||||||
|
|
||||||
|
yield return (ATTRIB_ID_SLIDER_FACTOR, SliderFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void FromDatabaseAttributes(IReadOnlyDictionary<int, double> values)
|
||||||
|
{
|
||||||
|
base.FromDatabaseAttributes(values);
|
||||||
|
|
||||||
|
AimStrain = values[ATTRIB_ID_AIM];
|
||||||
|
SpeedStrain = values[ATTRIB_ID_SPEED];
|
||||||
|
OverallDifficulty = values[ATTRIB_ID_OVERALL_DIFFICULTY];
|
||||||
|
ApproachRate = values[ATTRIB_ID_APPROACH_RATE];
|
||||||
|
MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO];
|
||||||
|
StarRating = values[ATTRIB_ID_STRAIN];
|
||||||
|
FlashlightRating = values.GetValueOrDefault(ATTRIB_ID_FLASHLIGHT);
|
||||||
|
SliderFactor = values[ATTRIB_ID_SLIDER_FACTOR];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used implicitly by Newtonsoft.Json to not serialize flashlight property in some cases.
|
||||||
|
[UsedImplicitly]
|
||||||
|
public bool ShouldSerializeFlashlightRating() => Mods.Any(m => m is ModFlashlight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
private const double difficulty_multiplier = 0.0675;
|
private const double difficulty_multiplier = 0.0675;
|
||||||
private double hitWindowGreat;
|
private double hitWindowGreat;
|
||||||
|
|
||||||
public OsuDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap)
|
public OsuDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
|
|
||||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetOsu };
|
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetOsu };
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(this, beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new OsuDifficultyCalculator(RulesetInfo, beatmap);
|
||||||
|
|
||||||
public override PerformanceCalculator CreatePerformanceCalculator(DifficultyAttributes attributes, ScoreInfo score) => new OsuPerformanceCalculator(this, attributes, score);
|
public override PerformanceCalculator CreatePerformanceCalculator(DifficultyAttributes attributes, ScoreInfo score) => new OsuPerformanceCalculator(this, attributes, score);
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
var controlPointInfo = new ControlPointInfo();
|
var controlPointInfo = new ControlPointInfo();
|
||||||
controlPointInfo.Add(0, new TimingControlPoint());
|
controlPointInfo.Add(0, new TimingControlPoint());
|
||||||
|
|
||||||
WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap
|
IWorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap
|
||||||
{
|
{
|
||||||
HitObjects = new List<HitObject> { new Hit { Type = HitType.Centre } },
|
HitObjects = new List<HitObject> { new Hit { Type = HitType.Centre } },
|
||||||
BeatmapInfo = new BeatmapInfo
|
BeatmapInfo = new BeatmapInfo
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
public void TestClockRateAdjusted(double expected, string name)
|
public void TestClockRateAdjusted(double expected, string name)
|
||||||
=> Test(expected, name, new TaikoModDoubleTime());
|
=> Test(expected, name, new TaikoModDoubleTime());
|
||||||
|
|
||||||
protected override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(new TaikoRuleset(), beatmap);
|
protected override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new TaikoDifficultyCalculator(new TaikoRuleset().RulesetInfo, beatmap);
|
||||||
|
|
||||||
protected override Ruleset CreateRuleset() => new TaikoRuleset();
|
protected override Ruleset CreateRuleset() => new TaikoRuleset();
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,46 @@
|
|||||||
// 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.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Difficulty
|
namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||||
{
|
{
|
||||||
public class TaikoDifficultyAttributes : DifficultyAttributes
|
public class TaikoDifficultyAttributes : DifficultyAttributes
|
||||||
{
|
{
|
||||||
|
[JsonProperty("stamina_strain")]
|
||||||
public double StaminaStrain { get; set; }
|
public double StaminaStrain { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("rhythm_strain")]
|
||||||
public double RhythmStrain { get; set; }
|
public double RhythmStrain { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("colour_strain")]
|
||||||
public double ColourStrain { get; set; }
|
public double ColourStrain { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("approach_rate")]
|
||||||
public double ApproachRate { get; set; }
|
public double ApproachRate { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("great_hit_window")]
|
||||||
public double GreatHitWindow { get; set; }
|
public double GreatHitWindow { get; set; }
|
||||||
|
|
||||||
|
public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes()
|
||||||
|
{
|
||||||
|
foreach (var v in base.ToDatabaseAttributes())
|
||||||
|
yield return v;
|
||||||
|
|
||||||
|
yield return (ATTRIB_ID_MAX_COMBO, MaxCombo);
|
||||||
|
yield return (ATTRIB_ID_STRAIN, StarRating);
|
||||||
|
yield return (ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void FromDatabaseAttributes(IReadOnlyDictionary<int, double> values)
|
||||||
|
{
|
||||||
|
base.FromDatabaseAttributes(values);
|
||||||
|
|
||||||
|
MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO];
|
||||||
|
StarRating = values[ATTRIB_ID_STRAIN];
|
||||||
|
GreatHitWindow = values[ATTRIB_ID_GREAT_HIT_WINDOW];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
private const double colour_skill_multiplier = 0.01;
|
private const double colour_skill_multiplier = 0.01;
|
||||||
private const double stamina_skill_multiplier = 0.02;
|
private const double stamina_skill_multiplier = 0.02;
|
||||||
|
|
||||||
public TaikoDifficultyCalculator(Ruleset ruleset, WorkingBeatmap beatmap)
|
public TaikoDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ namespace osu.Game.Rulesets.Taiko
|
|||||||
|
|
||||||
public override HitObjectComposer CreateHitObjectComposer() => new TaikoHitObjectComposer(this);
|
public override HitObjectComposer CreateHitObjectComposer() => new TaikoHitObjectComposer(this);
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(this, beatmap);
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new TaikoDifficultyCalculator(RulesetInfo, beatmap);
|
||||||
|
|
||||||
public override PerformanceCalculator CreatePerformanceCalculator(DifficultyAttributes attributes, ScoreInfo score) => new TaikoPerformanceCalculator(this, attributes, score);
|
public override PerformanceCalculator CreatePerformanceCalculator(DifficultyAttributes attributes, ScoreInfo score) => new TaikoPerformanceCalculator(this, attributes, score);
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ namespace osu.Game.Tests.Mods
|
|||||||
throw new System.NotImplementedException();
|
throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap)
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Extensions;
|
||||||
|
|
||||||
namespace osu.Game.Tests.NonVisual
|
namespace osu.Game.Tests.NonVisual
|
||||||
{
|
{
|
||||||
@ -15,7 +16,8 @@ namespace osu.Game.Tests.NonVisual
|
|||||||
var ourInfo = new BeatmapSetInfo { OnlineID = 123 };
|
var ourInfo = new BeatmapSetInfo { OnlineID = 123 };
|
||||||
var otherInfo = new BeatmapSetInfo { OnlineID = 123 };
|
var otherInfo = new BeatmapSetInfo { OnlineID = 123 };
|
||||||
|
|
||||||
Assert.AreEqual(ourInfo, otherInfo);
|
Assert.AreNotEqual(ourInfo, otherInfo);
|
||||||
|
Assert.IsTrue(ourInfo.MatchesOnlineID(otherInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -33,7 +35,8 @@ namespace osu.Game.Tests.NonVisual
|
|||||||
var ourInfo = new BeatmapSetInfo { ID = 123, OnlineID = 12 };
|
var ourInfo = new BeatmapSetInfo { ID = 123, OnlineID = 12 };
|
||||||
var otherInfo = new BeatmapSetInfo { OnlineID = 12 };
|
var otherInfo = new BeatmapSetInfo { OnlineID = 12 };
|
||||||
|
|
||||||
Assert.AreEqual(ourInfo, otherInfo);
|
Assert.AreNotEqual(ourInfo, otherInfo);
|
||||||
|
Assert.IsTrue(ourInfo.MatchesOnlineID(otherInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -128,7 +128,7 @@ namespace osu.Game.Tests.Online
|
|||||||
|
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException();
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException();
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException();
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => throw new NotImplementedException();
|
||||||
|
|
||||||
public override string Description { get; } = string.Empty;
|
public override string Description { get; } = string.Empty;
|
||||||
public override string ShortName { get; } = string.Empty;
|
public override string ShortName { get; } = string.Empty;
|
||||||
|
@ -90,7 +90,7 @@ namespace osu.Game.Tests.Online
|
|||||||
|
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new System.NotImplementedException();
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new System.NotImplementedException();
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new System.NotImplementedException();
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => throw new System.NotImplementedException();
|
||||||
|
|
||||||
public override string Description { get; } = string.Empty;
|
public override string Description { get; } = string.Empty;
|
||||||
public override string ShortName { get; } = string.Empty;
|
public override string ShortName { get; } = string.Empty;
|
||||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Tests.Skins
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private BeatmapManager beatmaps { get; set; }
|
private BeatmapManager beatmaps { get; set; }
|
||||||
|
|
||||||
private WorkingBeatmap beatmap;
|
private IWorkingBeatmap beatmap;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -79,7 +79,7 @@ namespace osu.Game.Tests.Testing
|
|||||||
public override IEnumerable<Mod> GetModsFor(ModType type) => Array.Empty<Mod>();
|
public override IEnumerable<Mod> GetModsFor(ModType type) => Array.Empty<Mod>();
|
||||||
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => null;
|
public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList<Mod> mods = null) => null;
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null;
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => null;
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => null;
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestRulesetConfigManager : IRulesetConfigManager
|
private class TestRulesetConfigManager : IRulesetConfigManager
|
||||||
|
@ -10,9 +10,13 @@ using osu.Framework.Testing;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Screens.Backgrounds;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||||
|
using osu.Game.Screens.Edit.GameplayTest;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Tests.Beatmaps.IO;
|
using osu.Game.Tests.Beatmaps.IO;
|
||||||
|
using osuTK.Graphics;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Editing
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
@ -58,6 +62,42 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
AddUntilStep("player pushed", () => (editorPlayer = Stack.CurrentScreen as EditorPlayer) != null);
|
AddUntilStep("player pushed", () => (editorPlayer = Stack.CurrentScreen as EditorPlayer) != null);
|
||||||
AddStep("exit player", () => editorPlayer.Exit());
|
AddStep("exit player", () => editorPlayer.Exit());
|
||||||
AddUntilStep("current screen is editor", () => Stack.CurrentScreen is Editor);
|
AddUntilStep("current screen is editor", () => Stack.CurrentScreen is Editor);
|
||||||
|
AddUntilStep("background has correct params", () =>
|
||||||
|
{
|
||||||
|
var background = this.ChildrenOfType<BackgroundScreenBeatmap>().Single();
|
||||||
|
return background.Colour == Color4.DarkGray && background.BlurAmount.Value == 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestGameplayTestWhenTrackRunning()
|
||||||
|
{
|
||||||
|
AddStep("start track", () => EditorClock.Start());
|
||||||
|
AddAssert("sample playback enabled", () => !Editor.SamplePlaybackDisabled.Value);
|
||||||
|
|
||||||
|
AddStep("click test gameplay button", () =>
|
||||||
|
{
|
||||||
|
var button = Editor.ChildrenOfType<TestGameplayButton>().Single();
|
||||||
|
|
||||||
|
InputManager.MoveMouseTo(button);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
EditorPlayer editorPlayer = null;
|
||||||
|
AddUntilStep("player pushed", () => (editorPlayer = Stack.CurrentScreen as EditorPlayer) != null);
|
||||||
|
AddAssert("editor track stopped", () => !EditorClock.IsRunning);
|
||||||
|
AddAssert("sample playback disabled", () => Editor.SamplePlaybackDisabled.Value);
|
||||||
|
|
||||||
|
AddStep("exit player", () => editorPlayer.Exit());
|
||||||
|
AddUntilStep("current screen is editor", () => Stack.CurrentScreen is Editor);
|
||||||
|
AddUntilStep("background has correct params", () =>
|
||||||
|
{
|
||||||
|
var background = this.ChildrenOfType<BackgroundScreenBeatmap>().Single();
|
||||||
|
return background.Colour == Color4.DarkGray && background.BlurAmount.Value == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("start track", () => EditorClock.Start());
|
||||||
|
AddAssert("sample playback re-enabled", () => !Editor.SamplePlaybackDisabled.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -111,6 +151,35 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
AddAssert("track stopped", () => !Beatmap.Value.Track.IsRunning);
|
AddAssert("track stopped", () => !Beatmap.Value.Track.IsRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSharedClockState()
|
||||||
|
{
|
||||||
|
AddStep("seek to 00:01:00", () => EditorClock.Seek(60_000));
|
||||||
|
AddStep("click test gameplay button", () =>
|
||||||
|
{
|
||||||
|
var button = Editor.ChildrenOfType<TestGameplayButton>().Single();
|
||||||
|
|
||||||
|
InputManager.MoveMouseTo(button);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
EditorPlayer editorPlayer = null;
|
||||||
|
AddUntilStep("player pushed", () => (editorPlayer = Stack.CurrentScreen as EditorPlayer) != null);
|
||||||
|
|
||||||
|
GameplayClockContainer gameplayClockContainer = null;
|
||||||
|
AddStep("fetch gameplay clock", () => gameplayClockContainer = editorPlayer.ChildrenOfType<GameplayClockContainer>().First());
|
||||||
|
AddUntilStep("gameplay clock running", () => gameplayClockContainer.IsRunning);
|
||||||
|
AddAssert("gameplay time past 00:01:00", () => gameplayClockContainer.CurrentTime >= 60_000);
|
||||||
|
|
||||||
|
double timeAtPlayerExit = 0;
|
||||||
|
AddWaitStep("wait some", 5);
|
||||||
|
AddStep("store time before exit", () => timeAtPlayerExit = gameplayClockContainer.CurrentTime);
|
||||||
|
|
||||||
|
AddStep("exit player", () => editorPlayer.Exit());
|
||||||
|
AddUntilStep("current screen is editor", () => Stack.CurrentScreen is Editor);
|
||||||
|
AddAssert("time is past player exit", () => EditorClock.CurrentTime >= timeAtPlayerExit);
|
||||||
|
}
|
||||||
|
|
||||||
public override void TearDownSteps()
|
public override void TearDownSteps()
|
||||||
{
|
{
|
||||||
base.TearDownSteps();
|
base.TearDownSteps();
|
||||||
|
@ -81,11 +81,11 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
|
|
||||||
public class EditorBeatmapContainer : Container
|
public class EditorBeatmapContainer : Container
|
||||||
{
|
{
|
||||||
private readonly WorkingBeatmap working;
|
private readonly IWorkingBeatmap working;
|
||||||
|
|
||||||
public EditorBeatmap EditorBeatmap { get; private set; }
|
public EditorBeatmap EditorBeatmap { get; private set; }
|
||||||
|
|
||||||
public EditorBeatmapContainer(WorkingBeatmap working)
|
public EditorBeatmapContainer(IWorkingBeatmap working)
|
||||||
{
|
{
|
||||||
this.working = working;
|
this.working = working;
|
||||||
|
|
||||||
|
@ -0,0 +1,171 @@
|
|||||||
|
// 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 Humanizer;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
|
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||||
|
using osu.Game.Screens.Edit.Timing;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
|
{
|
||||||
|
public class TestSceneHitObjectDifficultyPointAdjustments : EditorTestScene
|
||||||
|
{
|
||||||
|
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||||
|
|
||||||
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||||
|
|
||||||
|
public override void SetUpSteps()
|
||||||
|
{
|
||||||
|
base.SetUpSteps();
|
||||||
|
|
||||||
|
AddStep("add test objects", () =>
|
||||||
|
{
|
||||||
|
EditorBeatmap.Add(new Slider
|
||||||
|
{
|
||||||
|
StartTime = 0,
|
||||||
|
Position = (OsuPlayfield.BASE_SIZE - new Vector2(0, 100)) / 2,
|
||||||
|
Path = new SliderPath
|
||||||
|
{
|
||||||
|
ControlPoints =
|
||||||
|
{
|
||||||
|
new PathControlPoint(new Vector2(0, 0)),
|
||||||
|
new PathControlPoint(new Vector2(0, 100))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
EditorBeatmap.Add(new Slider
|
||||||
|
{
|
||||||
|
StartTime = 500,
|
||||||
|
Position = (OsuPlayfield.BASE_SIZE - new Vector2(100, 0)) / 2,
|
||||||
|
Path = new SliderPath
|
||||||
|
{
|
||||||
|
ControlPoints =
|
||||||
|
{
|
||||||
|
new PathControlPoint(new Vector2(0, 0)),
|
||||||
|
new PathControlPoint(new Vector2(100, 0))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DifficultyControlPoint = new DifficultyControlPoint
|
||||||
|
{
|
||||||
|
SliderVelocity = 2
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSingleSelection()
|
||||||
|
{
|
||||||
|
clickDifficultyPiece(0);
|
||||||
|
velocityPopoverHasSingleValue(1);
|
||||||
|
|
||||||
|
dismissPopover();
|
||||||
|
|
||||||
|
// select first object to ensure that difficulty pieces for unselected objects
|
||||||
|
// work independently from selection state.
|
||||||
|
AddStep("select first object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.First()));
|
||||||
|
|
||||||
|
clickDifficultyPiece(1);
|
||||||
|
velocityPopoverHasSingleValue(2);
|
||||||
|
|
||||||
|
setVelocityViaPopover(5);
|
||||||
|
hitObjectHasVelocity(1, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMultipleSelectionWithSameSliderVelocity()
|
||||||
|
{
|
||||||
|
AddStep("unify slider velocity", () =>
|
||||||
|
{
|
||||||
|
foreach (var h in EditorBeatmap.HitObjects)
|
||||||
|
h.DifficultyControlPoint.SliderVelocity = 1.5;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects));
|
||||||
|
clickDifficultyPiece(0);
|
||||||
|
velocityPopoverHasSingleValue(1.5);
|
||||||
|
|
||||||
|
dismissPopover();
|
||||||
|
|
||||||
|
clickDifficultyPiece(1);
|
||||||
|
velocityPopoverHasSingleValue(1.5);
|
||||||
|
|
||||||
|
setVelocityViaPopover(5);
|
||||||
|
hitObjectHasVelocity(0, 5);
|
||||||
|
hitObjectHasVelocity(1, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMultipleSelectionWithDifferentSliderVelocity()
|
||||||
|
{
|
||||||
|
AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects));
|
||||||
|
clickDifficultyPiece(0);
|
||||||
|
velocityPopoverHasIndeterminateValue();
|
||||||
|
|
||||||
|
dismissPopover();
|
||||||
|
|
||||||
|
clickDifficultyPiece(1);
|
||||||
|
velocityPopoverHasIndeterminateValue();
|
||||||
|
|
||||||
|
setVelocityViaPopover(3);
|
||||||
|
hitObjectHasVelocity(0, 3);
|
||||||
|
hitObjectHasVelocity(1, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clickDifficultyPiece(int objectIndex) => AddStep($"click {objectIndex.ToOrdinalWords()} difficulty piece", () =>
|
||||||
|
{
|
||||||
|
var difficultyPiece = this.ChildrenOfType<DifficultyPointPiece>().Single(piece => piece.HitObject == EditorBeatmap.HitObjects.ElementAt(objectIndex));
|
||||||
|
|
||||||
|
InputManager.MoveMouseTo(difficultyPiece);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
private void velocityPopoverHasSingleValue(double velocity) => AddUntilStep($"velocity popover has {velocity}", () =>
|
||||||
|
{
|
||||||
|
var popover = this.ChildrenOfType<DifficultyPointPiece.DifficultyEditPopover>().SingleOrDefault();
|
||||||
|
var slider = popover?.ChildrenOfType<IndeterminateSliderWithTextBoxInput<double>>().Single();
|
||||||
|
|
||||||
|
return slider?.Current.Value == velocity;
|
||||||
|
});
|
||||||
|
|
||||||
|
private void velocityPopoverHasIndeterminateValue() => AddUntilStep("velocity popover has indeterminate value", () =>
|
||||||
|
{
|
||||||
|
var popover = this.ChildrenOfType<DifficultyPointPiece.DifficultyEditPopover>().SingleOrDefault();
|
||||||
|
var slider = popover?.ChildrenOfType<IndeterminateSliderWithTextBoxInput<double>>().Single();
|
||||||
|
|
||||||
|
return slider != null && slider.Current.Value == null;
|
||||||
|
});
|
||||||
|
|
||||||
|
private void dismissPopover()
|
||||||
|
{
|
||||||
|
AddStep("dismiss popover", () => InputManager.Key(Key.Escape));
|
||||||
|
AddUntilStep("wait for dismiss", () => !this.ChildrenOfType<DifficultyPointPiece.DifficultyEditPopover>().Any(popover => popover.IsPresent));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setVelocityViaPopover(double velocity) => AddStep($"set {velocity} via popover", () =>
|
||||||
|
{
|
||||||
|
var popover = this.ChildrenOfType<DifficultyPointPiece.DifficultyEditPopover>().Single();
|
||||||
|
var slider = popover.ChildrenOfType<IndeterminateSliderWithTextBoxInput<double>>().Single();
|
||||||
|
slider.Current.Value = velocity;
|
||||||
|
});
|
||||||
|
|
||||||
|
private void hitObjectHasVelocity(int objectIndex, double velocity) => AddAssert($"{objectIndex.ToOrdinalWords()} has velocity {velocity}", () =>
|
||||||
|
{
|
||||||
|
var h = EditorBeatmap.HitObjects.ElementAt(objectIndex);
|
||||||
|
return h.DifficultyControlPoint.SliderVelocity == velocity;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,252 @@
|
|||||||
|
// 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 Humanizer;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
|
using osu.Game.Screens.Edit.Compose.Components.Timeline;
|
||||||
|
using osu.Game.Screens.Edit.Timing;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Editing
|
||||||
|
{
|
||||||
|
public class TestSceneHitObjectSamplePointAdjustments : EditorTestScene
|
||||||
|
{
|
||||||
|
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
|
||||||
|
|
||||||
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||||
|
|
||||||
|
public override void SetUpSteps()
|
||||||
|
{
|
||||||
|
base.SetUpSteps();
|
||||||
|
|
||||||
|
AddStep("add test objects", () =>
|
||||||
|
{
|
||||||
|
EditorBeatmap.Add(new HitCircle
|
||||||
|
{
|
||||||
|
StartTime = 0,
|
||||||
|
Position = (OsuPlayfield.BASE_SIZE - new Vector2(100, 0)) / 2,
|
||||||
|
SampleControlPoint = new SampleControlPoint
|
||||||
|
{
|
||||||
|
SampleBank = "normal",
|
||||||
|
SampleVolume = 80
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
EditorBeatmap.Add(new HitCircle
|
||||||
|
{
|
||||||
|
StartTime = 500,
|
||||||
|
Position = (OsuPlayfield.BASE_SIZE + new Vector2(100, 0)) / 2,
|
||||||
|
SampleControlPoint = new SampleControlPoint
|
||||||
|
{
|
||||||
|
SampleBank = "soft",
|
||||||
|
SampleVolume = 60
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSingleSelection()
|
||||||
|
{
|
||||||
|
clickSamplePiece(0);
|
||||||
|
samplePopoverHasSingleBank("normal");
|
||||||
|
samplePopoverHasSingleVolume(80);
|
||||||
|
|
||||||
|
dismissPopover();
|
||||||
|
|
||||||
|
// select first object to ensure that sample pieces for unselected objects
|
||||||
|
// work independently from selection state.
|
||||||
|
AddStep("select first object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.First()));
|
||||||
|
|
||||||
|
clickSamplePiece(1);
|
||||||
|
samplePopoverHasSingleBank("soft");
|
||||||
|
samplePopoverHasSingleVolume(60);
|
||||||
|
|
||||||
|
setVolumeViaPopover(90);
|
||||||
|
hitObjectHasSampleVolume(1, 90);
|
||||||
|
|
||||||
|
setBankViaPopover("drum");
|
||||||
|
hitObjectHasSampleBank(1, "drum");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMultipleSelectionWithSameSampleVolume()
|
||||||
|
{
|
||||||
|
AddStep("unify sample volume", () =>
|
||||||
|
{
|
||||||
|
foreach (var h in EditorBeatmap.HitObjects)
|
||||||
|
h.SampleControlPoint.SampleVolume = 50;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects));
|
||||||
|
clickSamplePiece(0);
|
||||||
|
samplePopoverHasSingleVolume(50);
|
||||||
|
|
||||||
|
dismissPopover();
|
||||||
|
|
||||||
|
clickSamplePiece(1);
|
||||||
|
samplePopoverHasSingleVolume(50);
|
||||||
|
|
||||||
|
setVolumeViaPopover(75);
|
||||||
|
hitObjectHasSampleVolume(0, 75);
|
||||||
|
hitObjectHasSampleVolume(1, 75);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMultipleSelectionWithDifferentSampleVolume()
|
||||||
|
{
|
||||||
|
AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects));
|
||||||
|
clickSamplePiece(0);
|
||||||
|
samplePopoverHasIndeterminateVolume();
|
||||||
|
|
||||||
|
dismissPopover();
|
||||||
|
|
||||||
|
clickSamplePiece(1);
|
||||||
|
samplePopoverHasIndeterminateVolume();
|
||||||
|
|
||||||
|
setVolumeViaPopover(30);
|
||||||
|
hitObjectHasSampleVolume(0, 30);
|
||||||
|
hitObjectHasSampleVolume(1, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMultipleSelectionWithSameSampleBank()
|
||||||
|
{
|
||||||
|
AddStep("unify sample bank", () =>
|
||||||
|
{
|
||||||
|
foreach (var h in EditorBeatmap.HitObjects)
|
||||||
|
h.SampleControlPoint.SampleBank = "soft";
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects));
|
||||||
|
clickSamplePiece(0);
|
||||||
|
samplePopoverHasSingleBank("soft");
|
||||||
|
|
||||||
|
dismissPopover();
|
||||||
|
|
||||||
|
clickSamplePiece(1);
|
||||||
|
samplePopoverHasSingleBank("soft");
|
||||||
|
|
||||||
|
setBankViaPopover(string.Empty);
|
||||||
|
hitObjectHasSampleBank(0, "soft");
|
||||||
|
hitObjectHasSampleBank(1, "soft");
|
||||||
|
samplePopoverHasSingleBank("soft");
|
||||||
|
|
||||||
|
setBankViaPopover("drum");
|
||||||
|
hitObjectHasSampleBank(0, "drum");
|
||||||
|
hitObjectHasSampleBank(1, "drum");
|
||||||
|
samplePopoverHasSingleBank("drum");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMultipleSelectionWithDifferentSampleBank()
|
||||||
|
{
|
||||||
|
AddStep("select both objects", () => EditorBeatmap.SelectedHitObjects.AddRange(EditorBeatmap.HitObjects));
|
||||||
|
clickSamplePiece(0);
|
||||||
|
samplePopoverHasIndeterminateBank();
|
||||||
|
|
||||||
|
dismissPopover();
|
||||||
|
|
||||||
|
clickSamplePiece(1);
|
||||||
|
samplePopoverHasIndeterminateBank();
|
||||||
|
|
||||||
|
setBankViaPopover(string.Empty);
|
||||||
|
hitObjectHasSampleBank(0, "normal");
|
||||||
|
hitObjectHasSampleBank(1, "soft");
|
||||||
|
samplePopoverHasIndeterminateBank();
|
||||||
|
|
||||||
|
setBankViaPopover("normal");
|
||||||
|
hitObjectHasSampleBank(0, "normal");
|
||||||
|
hitObjectHasSampleBank(1, "normal");
|
||||||
|
samplePopoverHasSingleBank("normal");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clickSamplePiece(int objectIndex) => AddStep($"click {objectIndex.ToOrdinalWords()} difficulty piece", () =>
|
||||||
|
{
|
||||||
|
var difficultyPiece = this.ChildrenOfType<SamplePointPiece>().Single(piece => piece.HitObject == EditorBeatmap.HitObjects.ElementAt(objectIndex));
|
||||||
|
|
||||||
|
InputManager.MoveMouseTo(difficultyPiece);
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
private void samplePopoverHasSingleVolume(int volume) => AddUntilStep($"sample popover has volume {volume}", () =>
|
||||||
|
{
|
||||||
|
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
|
||||||
|
var slider = popover?.ChildrenOfType<IndeterminateSliderWithTextBoxInput<int>>().Single();
|
||||||
|
|
||||||
|
return slider?.Current.Value == volume;
|
||||||
|
});
|
||||||
|
|
||||||
|
private void samplePopoverHasIndeterminateVolume() => AddUntilStep("sample popover has indeterminate volume", () =>
|
||||||
|
{
|
||||||
|
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
|
||||||
|
var slider = popover?.ChildrenOfType<IndeterminateSliderWithTextBoxInput<int>>().Single();
|
||||||
|
|
||||||
|
return slider != null && slider.Current.Value == null;
|
||||||
|
});
|
||||||
|
|
||||||
|
private void samplePopoverHasSingleBank(string bank) => AddUntilStep($"sample popover has bank {bank}", () =>
|
||||||
|
{
|
||||||
|
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
|
||||||
|
var textBox = popover?.ChildrenOfType<OsuTextBox>().First();
|
||||||
|
|
||||||
|
return textBox?.Current.Value == bank && string.IsNullOrEmpty(textBox?.PlaceholderText.ToString());
|
||||||
|
});
|
||||||
|
|
||||||
|
private void samplePopoverHasIndeterminateBank() => AddUntilStep("sample popover has indeterminate bank", () =>
|
||||||
|
{
|
||||||
|
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().SingleOrDefault();
|
||||||
|
var textBox = popover?.ChildrenOfType<OsuTextBox>().First();
|
||||||
|
|
||||||
|
return textBox != null && string.IsNullOrEmpty(textBox.Current.Value) && !string.IsNullOrEmpty(textBox.PlaceholderText.ToString());
|
||||||
|
});
|
||||||
|
|
||||||
|
private void dismissPopover()
|
||||||
|
{
|
||||||
|
AddStep("dismiss popover", () => InputManager.Key(Key.Escape));
|
||||||
|
AddUntilStep("wait for dismiss", () => !this.ChildrenOfType<DifficultyPointPiece.DifficultyEditPopover>().Any(popover => popover.IsPresent));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setVolumeViaPopover(int volume) => AddStep($"set volume {volume} via popover", () =>
|
||||||
|
{
|
||||||
|
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().Single();
|
||||||
|
var slider = popover.ChildrenOfType<IndeterminateSliderWithTextBoxInput<int>>().Single();
|
||||||
|
slider.Current.Value = volume;
|
||||||
|
});
|
||||||
|
|
||||||
|
private void hitObjectHasSampleVolume(int objectIndex, int volume) => AddAssert($"{objectIndex.ToOrdinalWords()} has volume {volume}", () =>
|
||||||
|
{
|
||||||
|
var h = EditorBeatmap.HitObjects.ElementAt(objectIndex);
|
||||||
|
return h.SampleControlPoint.SampleVolume == volume;
|
||||||
|
});
|
||||||
|
|
||||||
|
private void setBankViaPopover(string bank) => AddStep($"set bank {bank} via popover", () =>
|
||||||
|
{
|
||||||
|
var popover = this.ChildrenOfType<SamplePointPiece.SampleEditPopover>().Single();
|
||||||
|
var textBox = popover.ChildrenOfType<LabelledTextBox>().First();
|
||||||
|
textBox.Current.Value = bank;
|
||||||
|
// force a commit via keyboard.
|
||||||
|
// this is needed when testing attempting to set empty bank - which should revert to the previous value, but only on commit.
|
||||||
|
InputManager.ChangeFocus(textBox);
|
||||||
|
InputManager.Key(Key.Enter);
|
||||||
|
});
|
||||||
|
|
||||||
|
private void hitObjectHasSampleBank(int objectIndex, string bank) => AddAssert($"{objectIndex.ToOrdinalWords()} has bank {bank}", () =>
|
||||||
|
{
|
||||||
|
var h = EditorBeatmap.HitObjects.ElementAt(objectIndex);
|
||||||
|
return h.SampleControlPoint.SampleBank == bank;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class TestSceneWaveform : OsuTestScene
|
public class TestSceneWaveform : OsuTestScene
|
||||||
{
|
{
|
||||||
private WorkingBeatmap waveformBeatmap;
|
private IWorkingBeatmap waveformBeatmap;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(AudioManager audio)
|
private void load(AudioManager audio)
|
||||||
|
@ -293,7 +293,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap, null);
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap, null);
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException();
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => throw new NotImplementedException();
|
||||||
|
|
||||||
public override string Description { get; } = string.Empty;
|
public override string Description { get; } = string.Empty;
|
||||||
|
|
||||||
|
@ -31,12 +31,18 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
AddUntilStep("wait for fail", () => Player.HasFailed);
|
AddUntilStep("wait for fail", () => Player.HasFailed);
|
||||||
AddUntilStep("wait for fail overlay", () => ((FailPlayer)Player).FailOverlay.State.Value == Visibility.Visible);
|
AddUntilStep("wait for fail overlay", () => ((FailPlayer)Player).FailOverlay.State.Value == Visibility.Visible);
|
||||||
|
|
||||||
|
// The pause screen and fail animation both ramp frequency.
|
||||||
|
// This tests to ensure that it doesn't reset during that handoff.
|
||||||
|
AddAssert("frequency only ever decreased", () => !((FailPlayer)Player).FrequencyIncreased);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FailPlayer : TestPlayer
|
private class FailPlayer : TestPlayer
|
||||||
{
|
{
|
||||||
public new FailOverlay FailOverlay => base.FailOverlay;
|
public new FailOverlay FailOverlay => base.FailOverlay;
|
||||||
|
|
||||||
|
public bool FrequencyIncreased { get; private set; }
|
||||||
|
|
||||||
public FailPlayer()
|
public FailPlayer()
|
||||||
: base(false, false)
|
: base(false, false)
|
||||||
{
|
{
|
||||||
@ -47,6 +53,19 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
HealthProcessor.FailConditions += (_, __) => true;
|
HealthProcessor.FailConditions += (_, __) => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double lastFrequency = double.MaxValue;
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
double freq = Beatmap.Value.Track.AggregateFrequency.Value;
|
||||||
|
|
||||||
|
FrequencyIncreased |= freq > lastFrequency;
|
||||||
|
|
||||||
|
lastFrequency = freq;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) =>
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) =>
|
||||||
throw new System.NotImplementedException();
|
throw new System.NotImplementedException();
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) =>
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) =>
|
||||||
throw new System.NotImplementedException();
|
throw new System.NotImplementedException();
|
||||||
|
|
||||||
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0)
|
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0)
|
||||||
@ -83,6 +83,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<TestAction> e)
|
public bool OnPressed(KeyBindingPressEvent<TestAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
ReceivedAction = e.Action == TestAction.Down;
|
ReceivedAction = e.Action == TestAction.Down;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -95,8 +95,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
private void prepareBeatmap()
|
private void prepareBeatmap()
|
||||||
{
|
{
|
||||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
var workingBeatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||||
Beatmap.Value.BeatmapInfo.EpilepsyWarning = epilepsyWarning;
|
workingBeatmap.BeatmapInfo.EpilepsyWarning = epilepsyWarning;
|
||||||
|
Beatmap.Value = workingBeatmap;
|
||||||
|
|
||||||
foreach (var mod in SelectedMods.Value.OfType<IApplicableToTrack>())
|
foreach (var mod in SelectedMods.Value.OfType<IApplicableToTrack>())
|
||||||
mod.ApplyToTrack(Beatmap.Value.Track);
|
mod.ApplyToTrack(Beatmap.Value.Track);
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
public class TestScenePlayerReferenceLeaking : TestSceneAllRulesetPlayers
|
public class TestScenePlayerReferenceLeaking : TestSceneAllRulesetPlayers
|
||||||
{
|
{
|
||||||
private readonly WeakList<WorkingBeatmap> workingWeakReferences = new WeakList<WorkingBeatmap>();
|
private readonly WeakList<IWorkingBeatmap> workingWeakReferences = new WeakList<IWorkingBeatmap>();
|
||||||
|
|
||||||
private readonly WeakList<Player> playerWeakReferences = new WeakList<Player>();
|
private readonly WeakList<Player> playerWeakReferences = new WeakList<Player>();
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap, this);
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new TestBeatmapConverter(beatmap, this);
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException();
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => throw new NotImplementedException();
|
||||||
|
|
||||||
public override string Description { get; } = string.Empty;
|
public override string Description { get; } = string.Empty;
|
||||||
|
|
||||||
|
@ -231,6 +231,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<TestAction> e)
|
public bool OnPressed(KeyBindingPressEvent<TestAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
box.Colour = Color4.White;
|
box.Colour = Color4.White;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<TestAction> e)
|
public bool OnPressed(KeyBindingPressEvent<TestAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
box.Colour = Color4.White;
|
box.Colour = Color4.White;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -283,6 +283,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<TestAction> e)
|
public bool OnPressed(KeyBindingPressEvent<TestAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
box.Colour = Color4.White;
|
box.Colour = Color4.White;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
track.Start();
|
track.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadStoryboard(WorkingBeatmap working)
|
private void loadStoryboard(IWorkingBeatmap working)
|
||||||
{
|
{
|
||||||
if (storyboard != null)
|
if (storyboard != null)
|
||||||
storyboardContainer.Remove(storyboard);
|
storyboardContainer.Remove(storyboard);
|
||||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
public void TestMusicNavigationActions()
|
public void TestMusicNavigationActions()
|
||||||
{
|
{
|
||||||
int importId = 0;
|
int importId = 0;
|
||||||
Queue<(WorkingBeatmap working, TrackChangeDirection changeDirection)> trackChangeQueue = null;
|
Queue<(IWorkingBeatmap working, TrackChangeDirection changeDirection)> trackChangeQueue = null;
|
||||||
|
|
||||||
// ensure we have at least two beatmaps available to identify the direction the music controller navigated to.
|
// ensure we have at least two beatmaps available to identify the direction the music controller navigated to.
|
||||||
AddRepeatStep("import beatmap", () => Game.BeatmapManager.Import(new BeatmapSetInfo
|
AddRepeatStep("import beatmap", () => Game.BeatmapManager.Import(new BeatmapSetInfo
|
||||||
@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
|
|
||||||
AddStep("bind to track change", () =>
|
AddStep("bind to track change", () =>
|
||||||
{
|
{
|
||||||
trackChangeQueue = new Queue<(WorkingBeatmap, TrackChangeDirection)>();
|
trackChangeQueue = new Queue<(IWorkingBeatmap, TrackChangeDirection)>();
|
||||||
Game.MusicController.TrackChanged += (working, changeDirection) => trackChangeQueue.Enqueue((working, changeDirection));
|
Game.MusicController.TrackChanged += (working, changeDirection) => trackChangeQueue.Enqueue((working, changeDirection));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -67,6 +67,19 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
AddAssert("no item selected", () => playlist.SelectedItem.Value == null);
|
AddAssert("no item selected", () => playlist.SelectedItem.Value == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMarkInvalid()
|
||||||
|
{
|
||||||
|
createPlaylist(true, true);
|
||||||
|
|
||||||
|
AddStep("mark item 0 as invalid", () => playlist.Items[0].MarkInvalid());
|
||||||
|
|
||||||
|
moveToItem(0);
|
||||||
|
|
||||||
|
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||||
|
AddAssert("no item selected", () => playlist.SelectedItem.Value == null);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSelectable()
|
public void TestSelectable()
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mania;
|
using osu.Game.Rulesets.Mania;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
@ -139,7 +140,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
AddStep("present beatmap", () => Game.PresentBeatmap(getImport()));
|
AddStep("present beatmap", () => Game.PresentBeatmap(getImport()));
|
||||||
|
|
||||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect);
|
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect);
|
||||||
AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapSetInfo.ID == getImport().ID);
|
AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapSetInfo.MatchesOnlineID(getImport()));
|
||||||
AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Beatmaps.First().Ruleset.ID);
|
AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Beatmaps.First().Ruleset.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
Player player = null;
|
Player player = null;
|
||||||
ResultsScreen results = null;
|
ResultsScreen results = null;
|
||||||
|
|
||||||
WorkingBeatmap beatmap() => Game.Beatmap.Value;
|
IWorkingBeatmap beatmap() => Game.Beatmap.Value;
|
||||||
|
|
||||||
PushAndConfirm(() => new TestPlaySongSelect());
|
PushAndConfirm(() => new TestPlaySongSelect());
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
{
|
{
|
||||||
Player player = null;
|
Player player = null;
|
||||||
|
|
||||||
WorkingBeatmap beatmap() => Game.Beatmap.Value;
|
IWorkingBeatmap beatmap() => Game.Beatmap.Value;
|
||||||
|
|
||||||
PushAndConfirm(() => new TestPlaySongSelect());
|
PushAndConfirm(() => new TestPlaySongSelect());
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
RoomManager.CreateRequested = r =>
|
RoomManager.CreateRequested = r =>
|
||||||
{
|
{
|
||||||
createdRoom = r;
|
createdRoom = r;
|
||||||
return true;
|
return string.Empty;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -82,28 +82,58 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
AddAssert("has correct duration", () => createdRoom.Duration.Value == expectedDuration);
|
AddAssert("has correct duration", () => createdRoom.Duration.Value == expectedDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestInvalidBeatmapError()
|
||||||
|
{
|
||||||
|
const string not_found_prefix = "beatmaps not found:";
|
||||||
|
|
||||||
|
string errorMesage = null;
|
||||||
|
|
||||||
|
AddStep("setup", () =>
|
||||||
|
{
|
||||||
|
var beatmap = CreateBeatmap(Ruleset.Value).BeatmapInfo;
|
||||||
|
|
||||||
|
SelectedRoom.Value.Name.Value = "Test Room";
|
||||||
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = beatmap } });
|
||||||
|
|
||||||
|
errorMesage = $"{not_found_prefix} {beatmap.OnlineID}";
|
||||||
|
|
||||||
|
RoomManager.CreateRequested = _ => errorMesage;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("error not displayed", () => !settings.ErrorText.IsPresent);
|
||||||
|
AddAssert("playlist item valid", () => SelectedRoom.Value.Playlist[0].Valid.Value);
|
||||||
|
|
||||||
|
AddStep("create room", () => settings.ApplyButton.Action.Invoke());
|
||||||
|
|
||||||
|
AddAssert("error displayed", () => settings.ErrorText.IsPresent);
|
||||||
|
AddAssert("error has custom text", () => settings.ErrorText.Text != errorMesage);
|
||||||
|
AddAssert("playlist item marked invalid", () => !SelectedRoom.Value.Playlist[0].Valid.Value);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCreationFailureDisplaysError()
|
public void TestCreationFailureDisplaysError()
|
||||||
{
|
{
|
||||||
bool fail;
|
const string error_message = "failed";
|
||||||
|
|
||||||
|
string failText = error_message;
|
||||||
|
|
||||||
AddStep("setup", () =>
|
AddStep("setup", () =>
|
||||||
{
|
{
|
||||||
SelectedRoom.Value.Name.Value = "Test Room";
|
SelectedRoom.Value.Name.Value = "Test Room";
|
||||||
SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } });
|
SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } });
|
||||||
|
|
||||||
fail = true;
|
RoomManager.CreateRequested = _ => failText;
|
||||||
RoomManager.CreateRequested = _ => !fail;
|
|
||||||
});
|
});
|
||||||
AddAssert("error not displayed", () => !settings.ErrorText.IsPresent);
|
AddAssert("error not displayed", () => !settings.ErrorText.IsPresent);
|
||||||
|
|
||||||
AddStep("create room", () => settings.ApplyButton.Action.Invoke());
|
AddStep("create room", () => settings.ApplyButton.Action.Invoke());
|
||||||
AddAssert("error displayed", () => settings.ErrorText.IsPresent);
|
AddAssert("error displayed", () => settings.ErrorText.IsPresent);
|
||||||
AddAssert("error has correct text", () => settings.ErrorText.Text == TestRoomManager.FAILED_TEXT);
|
AddAssert("error has correct text", () => settings.ErrorText.Text == error_message);
|
||||||
|
|
||||||
AddStep("create room no fail", () =>
|
AddStep("create room no fail", () =>
|
||||||
{
|
{
|
||||||
fail = false;
|
failText = string.Empty;
|
||||||
settings.ApplyButton.Action.Invoke();
|
settings.ApplyButton.Action.Invoke();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -132,9 +162,7 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
|
|
||||||
protected class TestRoomManager : IRoomManager
|
protected class TestRoomManager : IRoomManager
|
||||||
{
|
{
|
||||||
public const string FAILED_TEXT = "failed";
|
public Func<Room, string> CreateRequested;
|
||||||
|
|
||||||
public Func<Room, bool> CreateRequested;
|
|
||||||
|
|
||||||
public event Action RoomsUpdated
|
public event Action RoomsUpdated
|
||||||
{
|
{
|
||||||
@ -157,8 +185,10 @@ namespace osu.Game.Tests.Visual.Playlists
|
|||||||
if (CreateRequested == null)
|
if (CreateRequested == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!CreateRequested.Invoke(room))
|
string error = CreateRequested.Invoke(room);
|
||||||
onError?.Invoke(FAILED_TEXT);
|
|
||||||
|
if (!string.IsNullOrEmpty(error))
|
||||||
|
onError?.Invoke(error);
|
||||||
else
|
else
|
||||||
onSuccess?.Invoke(room);
|
onSuccess?.Invoke(room);
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMetadataForBeatmap(Func<WorkingBeatmap> getBeatmap)
|
private void showMetadataForBeatmap(Func<IWorkingBeatmap> getBeatmap)
|
||||||
{
|
{
|
||||||
AddStep("setup display", () =>
|
AddStep("setup display", () =>
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
@ -102,8 +103,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
{
|
{
|
||||||
BeatmapSetInfo catchSet = null, mixedSet = null;
|
BeatmapSetInfo catchSet = null, mixedSet = null;
|
||||||
|
|
||||||
AddStep("create catch beatmapset", () => catchSet = importBeatmapSet(0, new[] { new CatchRuleset().RulesetInfo }));
|
AddStep("create catch beatmapset", () => catchSet = importBeatmapSet(1, new[] { new CatchRuleset().RulesetInfo }));
|
||||||
AddStep("create mixed beatmapset", () => mixedSet = importBeatmapSet(1,
|
AddStep("create mixed beatmapset", () => mixedSet = importBeatmapSet(2,
|
||||||
new[] { new TaikoRuleset().RulesetInfo, new CatchRuleset().RulesetInfo, new ManiaRuleset().RulesetInfo }));
|
new[] { new TaikoRuleset().RulesetInfo, new CatchRuleset().RulesetInfo, new ManiaRuleset().RulesetInfo }));
|
||||||
|
|
||||||
AddAssert("all sets imported", () => ensureAllBeatmapSetsImported(new[] { catchSet, mixedSet }));
|
AddAssert("all sets imported", () => ensureAllBeatmapSetsImported(new[] { catchSet, mixedSet }));
|
||||||
@ -120,8 +121,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
{
|
{
|
||||||
BeatmapSetInfo osuSet = null, mixedSet = null;
|
BeatmapSetInfo osuSet = null, mixedSet = null;
|
||||||
|
|
||||||
AddStep("create osu! beatmapset", () => osuSet = importBeatmapSet(0, new[] { new OsuRuleset().RulesetInfo }));
|
AddStep("create osu! beatmapset", () => osuSet = importBeatmapSet(1, new[] { new OsuRuleset().RulesetInfo }));
|
||||||
AddStep("create mixed beatmapset", () => mixedSet = importBeatmapSet(1,
|
AddStep("create mixed beatmapset", () => mixedSet = importBeatmapSet(2,
|
||||||
new[] { new TaikoRuleset().RulesetInfo, new CatchRuleset().RulesetInfo, new ManiaRuleset().RulesetInfo }));
|
new[] { new TaikoRuleset().RulesetInfo, new CatchRuleset().RulesetInfo, new ManiaRuleset().RulesetInfo }));
|
||||||
|
|
||||||
AddAssert("all sets imported", () => ensureAllBeatmapSetsImported(new[] { osuSet, mixedSet }));
|
AddAssert("all sets imported", () => ensureAllBeatmapSetsImported(new[] { osuSet, mixedSet }));
|
||||||
@ -138,8 +139,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
{
|
{
|
||||||
BeatmapSetInfo osuSet = null, mixedSet = null;
|
BeatmapSetInfo osuSet = null, mixedSet = null;
|
||||||
|
|
||||||
AddStep("create osu! beatmapset", () => osuSet = importBeatmapSet(0, new[] { new OsuRuleset().RulesetInfo }));
|
AddStep("create osu! beatmapset", () => osuSet = importBeatmapSet(1, new[] { new OsuRuleset().RulesetInfo }));
|
||||||
AddStep("create mixed beatmapset", () => mixedSet = importBeatmapSet(1,
|
AddStep("create mixed beatmapset", () => mixedSet = importBeatmapSet(2,
|
||||||
new[] { new TaikoRuleset().RulesetInfo, new CatchRuleset().RulesetInfo, new TaikoRuleset().RulesetInfo }));
|
new[] { new TaikoRuleset().RulesetInfo, new CatchRuleset().RulesetInfo, new TaikoRuleset().RulesetInfo }));
|
||||||
|
|
||||||
AddAssert("all sets imported", () => ensureAllBeatmapSetsImported(new[] { osuSet, mixedSet }));
|
AddAssert("all sets imported", () => ensureAllBeatmapSetsImported(new[] { osuSet, mixedSet }));
|
||||||
@ -156,8 +157,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
{
|
{
|
||||||
BeatmapSetInfo osuSet = null, maniaSet = null;
|
BeatmapSetInfo osuSet = null, maniaSet = null;
|
||||||
|
|
||||||
AddStep("create osu! beatmapset", () => osuSet = importBeatmapSet(0, new[] { new OsuRuleset().RulesetInfo }));
|
AddStep("create osu! beatmapset", () => osuSet = importBeatmapSet(1, new[] { new OsuRuleset().RulesetInfo }));
|
||||||
AddStep("create mania beatmapset", () => maniaSet = importBeatmapSet(1, Enumerable.Repeat(new ManiaRuleset().RulesetInfo, 10)));
|
AddStep("create mania beatmapset", () => maniaSet = importBeatmapSet(2, Enumerable.Repeat(new ManiaRuleset().RulesetInfo, 10)));
|
||||||
|
|
||||||
AddAssert("all sets imported", () => ensureAllBeatmapSetsImported(new[] { osuSet, maniaSet }));
|
AddAssert("all sets imported", () => ensureAllBeatmapSetsImported(new[] { osuSet, maniaSet }));
|
||||||
|
|
||||||
@ -203,11 +204,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
AddStep("present beatmap", () => Game.PresentBeatmap(getImport()));
|
AddStep("present beatmap", () => Game.PresentBeatmap(getImport()));
|
||||||
|
|
||||||
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect);
|
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect);
|
||||||
AddUntilStep("recommended beatmap displayed", () =>
|
AddUntilStep("recommended beatmap displayed", () => Game.Beatmap.Value.BeatmapInfo.MatchesOnlineID(getImport().Beatmaps[expectedDiff - 1]));
|
||||||
{
|
|
||||||
int? expectedID = getImport().Beatmaps[expectedDiff - 1].OnlineID;
|
|
||||||
return Game.Beatmap.Value.BeatmapInfo.OnlineID == expectedID;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ using osu.Framework.Screens;
|
|||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
@ -360,7 +361,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmapInfo.Equals(target));
|
AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmapInfo.Equals(target));
|
||||||
|
|
||||||
// this is an important check, to make sure updateComponentFromBeatmap() was actually run
|
// this is an important check, to make sure updateComponentFromBeatmap() was actually run
|
||||||
AddUntilStep("selection shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap.BeatmapInfo.Equals(target));
|
AddUntilStep("selection shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap.BeatmapInfo.MatchesOnlineID(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -392,7 +393,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
AddUntilStep("has correct ruleset", () => Ruleset.Value.ID == 0);
|
AddUntilStep("has correct ruleset", () => Ruleset.Value.ID == 0);
|
||||||
|
|
||||||
// this is an important check, to make sure updateComponentFromBeatmap() was actually run
|
// this is an important check, to make sure updateComponentFromBeatmap() was actually run
|
||||||
AddUntilStep("selection shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap.BeatmapInfo.Equals(target));
|
AddUntilStep("selection shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap.BeatmapInfo.MatchesOnlineID(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -507,13 +508,13 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
i.IsFiltered || i.Item.BeatmapInfo.Ruleset.ID == targetRuleset || i.Item.BeatmapInfo.Ruleset.ID == 0);
|
i.IsFiltered || i.Item.BeatmapInfo.Ruleset.ID == targetRuleset || i.Item.BeatmapInfo.Ruleset.ID == 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmapInfo?.OnlineID == target.OnlineID);
|
AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmapInfo?.MatchesOnlineID(target) == true);
|
||||||
AddUntilStep("game has correct", () => Beatmap.Value.BeatmapInfo.OnlineID == target.OnlineID);
|
AddUntilStep("game has correct", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(target));
|
||||||
|
|
||||||
AddStep("reset filter text", () => songSelect.FilterControl.ChildrenOfType<SearchTextBox>().First().Text = string.Empty);
|
AddStep("reset filter text", () => songSelect.FilterControl.ChildrenOfType<SearchTextBox>().First().Text = string.Empty);
|
||||||
|
|
||||||
AddAssert("game still correct", () => Beatmap.Value?.BeatmapInfo.OnlineID == target.OnlineID);
|
AddAssert("game still correct", () => Beatmap.Value?.BeatmapInfo.MatchesOnlineID(target) == true);
|
||||||
AddAssert("carousel still correct", () => songSelect.Carousel.SelectedBeatmapInfo.OnlineID == target.OnlineID);
|
AddAssert("carousel still correct", () => songSelect.Carousel.SelectedBeatmapInfo.MatchesOnlineID(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -544,8 +545,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
|
|
||||||
AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmapInfo != null);
|
AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmapInfo != null);
|
||||||
|
|
||||||
AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmapInfo?.OnlineID == target.OnlineID);
|
AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmapInfo?.MatchesOnlineID(target) == true);
|
||||||
AddUntilStep("game has correct", () => Beatmap.Value.BeatmapInfo.OnlineID == target.OnlineID);
|
AddUntilStep("game has correct", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(target));
|
||||||
|
|
||||||
AddStep("set filter text", () => songSelect.FilterControl.ChildrenOfType<SearchTextBox>().First().Text = "nononoo");
|
AddStep("set filter text", () => songSelect.FilterControl.ChildrenOfType<SearchTextBox>().First().Text = "nononoo");
|
||||||
|
|
||||||
@ -672,7 +673,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
|
|
||||||
AddUntilStep("wait for selection", () => !Beatmap.IsDefault);
|
AddUntilStep("wait for selection", () => !Beatmap.IsDefault);
|
||||||
|
|
||||||
AddStep("record set ID", () => previousSetID = Beatmap.Value.BeatmapSetInfo.ID);
|
AddStep("record set ID", () => previousSetID = ((IBeatmapSetInfo)Beatmap.Value.BeatmapSetInfo).OnlineID);
|
||||||
AddAssert("selection changed once", () => changeCount == 1);
|
AddAssert("selection changed once", () => changeCount == 1);
|
||||||
|
|
||||||
AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0);
|
AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0);
|
||||||
@ -683,8 +684,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
|
|
||||||
AddUntilStep("selection changed", () => changeCount > 1);
|
AddUntilStep("selection changed", () => changeCount > 1);
|
||||||
|
|
||||||
AddAssert("Selected beatmap still same set", () => Beatmap.Value.BeatmapSetInfo.ID == previousSetID);
|
AddAssert("Selected beatmap still same set", () => Beatmap.Value.BeatmapSetInfo.OnlineID == previousSetID);
|
||||||
AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.ID == 3);
|
AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.OnlineID == 3);
|
||||||
|
|
||||||
AddAssert("selection changed only fired twice", () => changeCount == 2);
|
AddAssert("selection changed only fired twice", () => changeCount == 2);
|
||||||
|
|
||||||
@ -727,7 +728,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
|
|
||||||
int previousSetID = 0;
|
int previousSetID = 0;
|
||||||
|
|
||||||
AddStep("record set ID", () => previousSetID = Beatmap.Value.BeatmapSetInfo.ID);
|
AddStep("record set ID", () => previousSetID = ((IBeatmapSetInfo)Beatmap.Value.BeatmapSetInfo).OnlineID);
|
||||||
|
|
||||||
AddStep("Click on a difficulty", () =>
|
AddStep("Click on a difficulty", () =>
|
||||||
{
|
{
|
||||||
@ -738,8 +739,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
|
|
||||||
AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3);
|
AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3);
|
||||||
|
|
||||||
AddAssert("Selected beatmap still same set", () => songSelect.Carousel.SelectedBeatmapInfo.BeatmapSet.ID == previousSetID);
|
AddAssert("Selected beatmap still same set", () => songSelect.Carousel.SelectedBeatmapInfo.BeatmapSet.OnlineID == previousSetID);
|
||||||
AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.ID == 3);
|
AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.OnlineID == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -784,7 +785,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
|
|
||||||
AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3);
|
AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3);
|
||||||
|
|
||||||
AddAssert("Check first item in group selected", () => Beatmap.Value.BeatmapInfo.Equals(groupIcon.Items.First().BeatmapInfo));
|
AddAssert("Check first item in group selected", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(groupIcon.Items.First().BeatmapInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -815,7 +816,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
|
|
||||||
AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen());
|
AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen());
|
||||||
|
|
||||||
AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.Equals(getPresentBeatmap()));
|
AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(getPresentBeatmap()));
|
||||||
AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0);
|
AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,7 +848,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
|
|
||||||
AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen());
|
AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen());
|
||||||
|
|
||||||
AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.Equals(getPresentBeatmap()));
|
AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(getPresentBeatmap()));
|
||||||
AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0);
|
AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -960,7 +961,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
public new FilterControl FilterControl => base.FilterControl;
|
public new FilterControl FilterControl => base.FilterControl;
|
||||||
|
|
||||||
public WorkingBeatmap CurrentBeatmap => Beatmap.Value;
|
public WorkingBeatmap CurrentBeatmap => Beatmap.Value;
|
||||||
public WorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap;
|
public IWorkingBeatmap CurrentBeatmapDetailsBeatmap => BeatmapDetails.Beatmap;
|
||||||
public new BeatmapCarousel Carousel => base.Carousel;
|
public new BeatmapCarousel Carousel => base.Carousel;
|
||||||
|
|
||||||
public new void PresentScore(ScoreInfo score) => base.PresentScore(score);
|
public new void PresentScore(ScoreInfo score) => base.PresentScore(score);
|
||||||
|
@ -199,7 +199,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException();
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => throw new NotImplementedException();
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => throw new NotImplementedException();
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => throw new NotImplementedException();
|
||||||
|
|
||||||
public override string Description { get; } = "test";
|
public override string Description { get; } = "test";
|
||||||
public override string ShortName { get; } = "tst";
|
public override string ShortName { get; } = "tst";
|
||||||
|
@ -151,7 +151,7 @@ namespace osu.Game.Beatmaps
|
|||||||
}, token, TaskCreationOptions.HideScheduler | TaskCreationOptions.RunContinuationsAsynchronously, updateScheduler);
|
}, token, TaskCreationOptions.HideScheduler | TaskCreationOptions.RunContinuationsAsynchronously, updateScheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<TimedDifficultyAttributes>> GetTimedDifficultyAttributesAsync(WorkingBeatmap beatmap, Ruleset ruleset, Mod[] mods, CancellationToken token = default)
|
public Task<List<TimedDifficultyAttributes>> GetTimedDifficultyAttributesAsync(IWorkingBeatmap beatmap, Ruleset ruleset, Mod[] mods, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
return Task.Factory.StartNew(() => ruleset.CreateDifficultyCalculator(beatmap).CalculateTimed(mods),
|
return Task.Factory.StartNew(() => ruleset.CreateDifficultyCalculator(beatmap).CalculateTimed(mods),
|
||||||
token,
|
token,
|
||||||
|
@ -154,14 +154,17 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public bool Equals(BeatmapInfo other)
|
public bool Equals(BeatmapInfo other)
|
||||||
{
|
{
|
||||||
if (ID == 0 || other?.ID == 0)
|
if (ReferenceEquals(this, other)) return true;
|
||||||
// one of the two BeatmapInfos we are comparing isn't sourced from a database.
|
if (other == null) return false;
|
||||||
// fall back to reference equality.
|
|
||||||
return ReferenceEquals(this, other);
|
|
||||||
|
|
||||||
return ID == other?.ID;
|
if (ID != 0 && other.ID != 0)
|
||||||
|
return ID == other.ID;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Equals(IBeatmapInfo other) => other is BeatmapInfo b && Equals(b);
|
||||||
|
|
||||||
public bool AudioEquals(BeatmapInfo other) => other != null && BeatmapSet != null && other.BeatmapSet != null &&
|
public bool AudioEquals(BeatmapInfo other) => other != null && BeatmapSet != null && other.BeatmapSet != null &&
|
||||||
BeatmapSet.Hash == other.BeatmapSet.Hash &&
|
BeatmapSet.Hash == other.BeatmapSet.Hash &&
|
||||||
(Metadata ?? BeatmapSet.Metadata).AudioFile == (other.Metadata ?? other.BeatmapSet.Metadata).AudioFile;
|
(Metadata ?? BeatmapSet.Metadata).AudioFile == (other.Metadata ?? other.BeatmapSet.Metadata).AudioFile;
|
||||||
|
@ -179,7 +179,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
|
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public WorkingBeatmap DefaultBeatmap => workingBeatmapCache.DefaultBeatmap;
|
public IWorkingBeatmap DefaultBeatmap => workingBeatmapCache.DefaultBeatmap;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired when a notification should be presented to the user.
|
/// Fired when a notification should be presented to the user.
|
||||||
|
@ -69,21 +69,17 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public bool Equals(BeatmapSetInfo other)
|
public bool Equals(BeatmapSetInfo other)
|
||||||
{
|
{
|
||||||
if (other == null)
|
if (ReferenceEquals(this, other)) return true;
|
||||||
return false;
|
if (other == null) return false;
|
||||||
|
|
||||||
if (ID != 0 && other.ID != 0)
|
if (ID != 0 && other.ID != 0)
|
||||||
return ID == other.ID;
|
return ID == other.ID;
|
||||||
|
|
||||||
if (OnlineID.HasValue && other.OnlineID.HasValue)
|
return false;
|
||||||
return OnlineID == other.OnlineID;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Hash) && !string.IsNullOrEmpty(other.Hash))
|
|
||||||
return Hash == other.Hash;
|
|
||||||
|
|
||||||
return ReferenceEquals(this, other);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Equals(IBeatmapSetInfo other) => other is BeatmapSetInfo b && Equals(b);
|
||||||
|
|
||||||
#region Implementation of IHasOnlineID
|
#region Implementation of IHasOnlineID
|
||||||
|
|
||||||
int IHasOnlineID<int>.OnlineID => OnlineID ?? -1;
|
int IHasOnlineID<int>.OnlineID => OnlineID ?? -1;
|
||||||
|
@ -9,9 +9,9 @@ namespace osu.Game.Beatmaps.Drawables
|
|||||||
{
|
{
|
||||||
public class BeatmapBackgroundSprite : Sprite
|
public class BeatmapBackgroundSprite : Sprite
|
||||||
{
|
{
|
||||||
private readonly WorkingBeatmap working;
|
private readonly IWorkingBeatmap working;
|
||||||
|
|
||||||
public BeatmapBackgroundSprite(WorkingBeatmap working)
|
public BeatmapBackgroundSprite(IWorkingBeatmap working)
|
||||||
{
|
{
|
||||||
if (working == null)
|
if (working == null)
|
||||||
throw new ArgumentNullException(nameof(working));
|
throw new ArgumentNullException(nameof(working));
|
||||||
|
@ -69,7 +69,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new DummyBeatmapConverter { Beatmap = beatmap };
|
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new DummyBeatmapConverter { Beatmap = beatmap };
|
||||||
|
|
||||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => null;
|
public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => null;
|
||||||
|
|
||||||
public override string Description => "dummy";
|
public override string Description => "dummy";
|
||||||
|
|
||||||
|
@ -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 osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A single beatmap difficulty.
|
/// A single beatmap difficulty.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBeatmapInfo : IHasOnlineID<int>
|
public interface IBeatmapInfo : IHasOnlineID<int>, IEquatable<IBeatmapInfo>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The user-specified name given to this beatmap.
|
/// The user-specified name given to this beatmap.
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A representation of a collection of beatmap difficulties, generally packaged as an ".osz" archive.
|
/// A representation of a collection of beatmap difficulties, generally packaged as an ".osz" archive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBeatmapSetInfo : IHasOnlineID<int>
|
public interface IBeatmapSetInfo : IHasOnlineID<int>, IEquatable<IBeatmapSetInfo>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The date when this beatmap was imported.
|
/// The date when this beatmap was imported.
|
||||||
|
@ -17,33 +17,69 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
public interface IWorkingBeatmap
|
public interface IWorkingBeatmap
|
||||||
{
|
{
|
||||||
|
IBeatmapInfo BeatmapInfo { get; }
|
||||||
|
|
||||||
|
IBeatmapSetInfo BeatmapSetInfo { get; }
|
||||||
|
|
||||||
|
IBeatmapMetadataInfo Metadata { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the <see cref="IBeatmap"/> which this <see cref="WorkingBeatmap"/> represents.
|
/// Whether the Beatmap has finished loading.
|
||||||
|
///</summary>
|
||||||
|
public bool BeatmapLoaded { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the Background has finished loading.
|
||||||
|
///</summary>
|
||||||
|
public bool BackgroundLoaded { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the Waveform has finished loading.
|
||||||
|
///</summary>
|
||||||
|
public bool WaveformLoaded { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the Storyboard has finished loading.
|
||||||
|
///</summary>
|
||||||
|
public bool StoryboardLoaded { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the Skin has finished loading.
|
||||||
|
///</summary>
|
||||||
|
public bool SkinLoaded { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the Track has finished loading.
|
||||||
|
///</summary>
|
||||||
|
public bool TrackLoaded { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the <see cref="IBeatmap"/> which this <see cref="IWorkingBeatmap"/> represents.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IBeatmap Beatmap { get; }
|
IBeatmap Beatmap { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the background for this <see cref="WorkingBeatmap"/>.
|
/// Retrieves the background for this <see cref="IWorkingBeatmap"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Texture Background { get; }
|
Texture Background { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the <see cref="Waveform"/> for the <see cref="Track"/> of this <see cref="WorkingBeatmap"/>.
|
/// Retrieves the <see cref="Waveform"/> for the <see cref="Track"/> of this <see cref="IWorkingBeatmap"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Waveform Waveform { get; }
|
Waveform Waveform { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the <see cref="Storyboard"/> which this <see cref="WorkingBeatmap"/> provides.
|
/// Retrieves the <see cref="Storyboard"/> which this <see cref="IWorkingBeatmap"/> provides.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Storyboard Storyboard { get; }
|
Storyboard Storyboard { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the <see cref="Skin"/> which this <see cref="WorkingBeatmap"/> provides.
|
/// Retrieves the <see cref="Skin"/> which this <see cref="IWorkingBeatmap"/> provides.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISkin Skin { get; }
|
ISkin Skin { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the <see cref="Track"/> which this <see cref="WorkingBeatmap"/> has loaded.
|
/// Retrieves the <see cref="Track"/> which this <see cref="IWorkingBeatmap"/> has loaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Track Track { get; }
|
Track Track { get; }
|
||||||
|
|
||||||
@ -59,7 +95,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <param name="timeout">The maximum length in milliseconds to wait for load to complete. Defaults to 10,000ms.</param>
|
/// <param name="timeout">The maximum length in milliseconds to wait for load to complete. Defaults to 10,000ms.</param>
|
||||||
/// <returns>The converted <see cref="IBeatmap"/>.</returns>
|
/// <returns>The converted <see cref="IBeatmap"/>.</returns>
|
||||||
/// <exception cref="BeatmapInvalidForRulesetException">If <see cref="Beatmap"/> could not be converted to <paramref name="ruleset"/>.</exception>
|
/// <exception cref="BeatmapInvalidForRulesetException">If <see cref="Beatmap"/> could not be converted to <paramref name="ruleset"/>.</exception>
|
||||||
IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null, TimeSpan? timeout = null);
|
IBeatmap GetPlayableBeatmap(IRulesetInfo ruleset, IReadOnlyList<Mod> mods = null, TimeSpan? timeout = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load a new audio track instance for this beatmap. This should be called once before accessing <see cref="Track"/>.
|
/// Load a new audio track instance for this beatmap. This should be called once before accessing <see cref="Track"/>.
|
||||||
@ -67,7 +103,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// In a standard game context, the loading of the track is managed solely by MusicController, which will
|
/// In a standard game context, the loading of the track is managed solely by MusicController, which will
|
||||||
/// automatically load the track of the current global IBindable WorkingBeatmap.
|
/// automatically load the track of the current global IBindable IWorkingBeatmap.
|
||||||
/// As such, this method should only be called in very special scenarios, such as external tests or apps which are
|
/// As such, this method should only be called in very special scenarios, such as external tests or apps which are
|
||||||
/// outside of the game context.
|
/// outside of the game context.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
@ -79,5 +115,20 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="storagePath">The storage path to the file.</param>
|
/// <param name="storagePath">The storage path to the file.</param>
|
||||||
Stream GetStream(string storagePath);
|
Stream GetStream(string storagePath);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Beings loading the contents of this <see cref="IWorkingBeatmap"/> asynchronously.
|
||||||
|
/// </summary>
|
||||||
|
public void BeginAsyncLoad();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancels the asynchronous loading of the contents of this <see cref="IWorkingBeatmap"/>.
|
||||||
|
/// </summary>
|
||||||
|
public void CancelAsyncLoad();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the correct track restart point from beatmap metadata and sets looping to enabled.
|
||||||
|
/// </summary>
|
||||||
|
void PrepareTrackForPreviewLooping();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,7 @@ namespace osu.Game.Beatmaps
|
|||||||
public abstract class WorkingBeatmap : IWorkingBeatmap
|
public abstract class WorkingBeatmap : IWorkingBeatmap
|
||||||
{
|
{
|
||||||
public readonly BeatmapInfo BeatmapInfo;
|
public readonly BeatmapInfo BeatmapInfo;
|
||||||
|
|
||||||
public readonly BeatmapSetInfo BeatmapSetInfo;
|
public readonly BeatmapSetInfo BeatmapSetInfo;
|
||||||
|
|
||||||
public readonly BeatmapMetadata Metadata;
|
public readonly BeatmapMetadata Metadata;
|
||||||
|
|
||||||
protected AudioManager AudioManager { get; }
|
protected AudioManager AudioManager { get; }
|
||||||
@ -81,7 +79,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <returns>The applicable <see cref="IBeatmapConverter"/>.</returns>
|
/// <returns>The applicable <see cref="IBeatmapConverter"/>.</returns>
|
||||||
protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap);
|
protected virtual IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) => ruleset.CreateBeatmapConverter(beatmap);
|
||||||
|
|
||||||
public virtual IBeatmap GetPlayableBeatmap(RulesetInfo ruleset, IReadOnlyList<Mod> mods = null, TimeSpan? timeout = null)
|
public virtual IBeatmap GetPlayableBeatmap(IRulesetInfo ruleset, IReadOnlyList<Mod> mods = null, TimeSpan? timeout = null)
|
||||||
{
|
{
|
||||||
using (var cancellationSource = createCancellationTokenSource(timeout))
|
using (var cancellationSource = createCancellationTokenSource(timeout))
|
||||||
{
|
{
|
||||||
@ -89,6 +87,9 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
var rulesetInstance = ruleset.CreateInstance();
|
var rulesetInstance = ruleset.CreateInstance();
|
||||||
|
|
||||||
|
if (rulesetInstance == null)
|
||||||
|
throw new RulesetLoadException("Creating ruleset instance failed when attempting to create playable beatmap.");
|
||||||
|
|
||||||
IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance);
|
IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance);
|
||||||
|
|
||||||
// Check if the beatmap can be converted
|
// Check if the beatmap can be converted
|
||||||
@ -176,17 +177,8 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
private CancellationTokenSource loadCancellation = new CancellationTokenSource();
|
private CancellationTokenSource loadCancellation = new CancellationTokenSource();
|
||||||
|
|
||||||
/// <summary>
|
public void BeginAsyncLoad() => loadBeatmapAsync();
|
||||||
/// Beings loading the contents of this <see cref="WorkingBeatmap"/> asynchronously.
|
|
||||||
/// </summary>
|
|
||||||
public void BeginAsyncLoad()
|
|
||||||
{
|
|
||||||
loadBeatmapAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cancels the asynchronous loading of the contents of this <see cref="WorkingBeatmap"/>.
|
|
||||||
/// </summary>
|
|
||||||
public void CancelAsyncLoad()
|
public void CancelAsyncLoad()
|
||||||
{
|
{
|
||||||
lock (beatmapFetchLock)
|
lock (beatmapFetchLock)
|
||||||
@ -234,6 +226,10 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public virtual bool BeatmapLoaded => beatmapLoadTask?.IsCompleted ?? false;
|
public virtual bool BeatmapLoaded => beatmapLoadTask?.IsCompleted ?? false;
|
||||||
|
|
||||||
|
IBeatmapInfo IWorkingBeatmap.BeatmapInfo => BeatmapInfo;
|
||||||
|
IBeatmapMetadataInfo IWorkingBeatmap.Metadata => Metadata;
|
||||||
|
IBeatmapSetInfo IWorkingBeatmap.BeatmapSetInfo => BeatmapSetInfo;
|
||||||
|
|
||||||
public IBeatmap Beatmap
|
public IBeatmap Beatmap
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -273,9 +269,6 @@ namespace osu.Game.Beatmaps
|
|||||||
[NotNull]
|
[NotNull]
|
||||||
public Track LoadTrack() => loadedTrack = GetBeatmapTrack() ?? GetVirtualTrack(1000);
|
public Track LoadTrack() => loadedTrack = GetBeatmapTrack() ?? GetVirtualTrack(1000);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reads the correct track restart point from beatmap metadata and sets looping to enabled.
|
|
||||||
/// </summary>
|
|
||||||
public void PrepareTrackForPreviewLooping()
|
public void PrepareTrackForPreviewLooping()
|
||||||
{
|
{
|
||||||
Track.Looping = true;
|
Track.Looping = true;
|
||||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Collections
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The beatmaps contained by the collection.
|
/// The beatmaps contained by the collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly BindableList<BeatmapInfo> Beatmaps = new BindableList<BeatmapInfo>();
|
public readonly BindableList<IBeatmapInfo> Beatmaps = new BindableList<IBeatmapInfo>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The date when this collection was last modified.
|
/// The date when this collection was last modified.
|
||||||
|
@ -39,7 +39,7 @@ namespace osu.Game.Collections
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly IBindableList<BeatmapCollection> collections = new BindableList<BeatmapCollection>();
|
private readonly IBindableList<BeatmapCollection> collections = new BindableList<BeatmapCollection>();
|
||||||
private readonly IBindableList<BeatmapInfo> beatmaps = new BindableList<BeatmapInfo>();
|
private readonly IBindableList<IBeatmapInfo> beatmaps = new BindableList<IBeatmapInfo>();
|
||||||
private readonly BindableList<CollectionFilterMenuItem> filters = new BindableList<CollectionFilterMenuItem>();
|
private readonly BindableList<CollectionFilterMenuItem> filters = new BindableList<CollectionFilterMenuItem>();
|
||||||
|
|
||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
@ -200,7 +200,7 @@ namespace osu.Game.Collections
|
|||||||
private IBindable<WorkingBeatmap> beatmap { get; set; }
|
private IBindable<WorkingBeatmap> beatmap { get; set; }
|
||||||
|
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
private readonly BindableList<BeatmapInfo> collectionBeatmaps;
|
private readonly BindableList<IBeatmapInfo> collectionBeatmaps;
|
||||||
|
|
||||||
[NotNull]
|
[NotNull]
|
||||||
private readonly Bindable<string> collectionName;
|
private readonly Bindable<string> collectionName;
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
// 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;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
namespace osu.Game.Database
|
namespace osu.Game.Database
|
||||||
{
|
{
|
||||||
public interface IHasOnlineID<out T>
|
public interface IHasOnlineID<out T>
|
||||||
|
where T : IEquatable<T>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The server-side ID representing this instance, if one exists. Any value 0 or less denotes a missing ID (except in special cases where autoincrement is not used, like rulesets).
|
/// The server-side ID representing this instance, if one exists. Any value 0 or less denotes a missing ID (except in special cases where autoincrement is not used, like rulesets).
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
// 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 osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input.Bindings;
|
|
||||||
using osu.Framework.Threading;
|
|
||||||
using osu.Game.Screens.Play.HUD;
|
using osu.Game.Screens.Play.HUD;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -14,30 +11,6 @@ namespace osu.Game.Extensions
|
|||||||
{
|
{
|
||||||
public static class DrawableExtensions
|
public static class DrawableExtensions
|
||||||
{
|
{
|
||||||
public const double REPEAT_INTERVAL = 70;
|
|
||||||
public const double INITIAL_DELAY = 250;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Helper method that is used while <see cref="IKeyBindingHandler"/> doesn't support repetitions of <see cref="IKeyBindingHandler{T}.OnPressed"/>.
|
|
||||||
/// Simulates repetitions by continually invoking a delegate according to the default key repeat rate.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// The returned delegate can be cancelled to stop repeat events from firing (usually in <see cref="IKeyBindingHandler{T}.OnReleased"/>).
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="handler">The <see cref="IKeyBindingHandler{T}"/> which is handling the repeat.</param>
|
|
||||||
/// <param name="scheduler">The <see cref="Scheduler"/> to schedule repetitions on.</param>
|
|
||||||
/// <param name="action">The <see cref="Action"/> to be invoked once immediately and with every repetition.</param>
|
|
||||||
/// <param name="initialRepeatDelay">The delay imposed on the first repeat. Defaults to <see cref="INITIAL_DELAY"/>.</param>
|
|
||||||
/// <returns>A <see cref="ScheduledDelegate"/> which can be cancelled to stop the repeat events from firing.</returns>
|
|
||||||
public static ScheduledDelegate BeginKeyRepeat(this IKeyBindingHandler handler, Scheduler scheduler, Action action, double initialRepeatDelay = INITIAL_DELAY)
|
|
||||||
{
|
|
||||||
action();
|
|
||||||
|
|
||||||
ScheduledDelegate repeatDelegate = new ScheduledDelegate(action, handler.Time.Current + initialRepeatDelay, REPEAT_INTERVAL);
|
|
||||||
scheduler.Add(repeatDelegate);
|
|
||||||
return repeatDelegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shakes this drawable.
|
/// Shakes this drawable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
// 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 osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace osu.Game.Extensions
|
namespace osu.Game.Extensions
|
||||||
{
|
{
|
||||||
public static class ModelExtensions
|
public static class ModelExtensions
|
||||||
@ -22,9 +26,9 @@ namespace osu.Game.Extensions
|
|||||||
/// extension method type inference rules cause this method to call itself and cause a stack overflow.
|
/// extension method type inference rules cause this method to call itself and cause a stack overflow.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static string GetDisplayString(this object model)
|
public static string GetDisplayString(this object? model)
|
||||||
{
|
{
|
||||||
string result = null;
|
string? result = null;
|
||||||
|
|
||||||
switch (model)
|
switch (model)
|
||||||
{
|
{
|
||||||
@ -57,5 +61,59 @@ namespace osu.Game.Extensions
|
|||||||
result ??= model?.ToString() ?? @"null";
|
result ??= model?.ToString() ?? @"null";
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check whether the online ID of two <see cref="IBeatmapSetInfo"/>s match.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="instance">The instance to compare.</param>
|
||||||
|
/// <param name="other">The other instance to compare against.</param>
|
||||||
|
/// <returns>Whether online IDs match. If either instance is missing an online ID, this will return false.</returns>
|
||||||
|
public static bool MatchesOnlineID(this IBeatmapSetInfo? instance, IBeatmapSetInfo? other) => matchesOnlineID(instance, other);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check whether the online ID of two <see cref="IBeatmapInfo"/>s match.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="instance">The instance to compare.</param>
|
||||||
|
/// <param name="other">The other instance to compare against.</param>
|
||||||
|
/// <returns>Whether online IDs match. If either instance is missing an online ID, this will return false.</returns>
|
||||||
|
public static bool MatchesOnlineID(this IBeatmapInfo? instance, IBeatmapInfo? other) => matchesOnlineID(instance, other);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check whether the online ID of two <see cref="IRulesetInfo"/>s match.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="instance">The instance to compare.</param>
|
||||||
|
/// <param name="other">The other instance to compare against.</param>
|
||||||
|
/// <returns>Whether online IDs match. If either instance is missing an online ID, this will return false.</returns>
|
||||||
|
public static bool MatchesOnlineID(this IRulesetInfo? instance, IRulesetInfo? other) => matchesOnlineID(instance, other);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check whether the online ID of two <see cref="APIUser"/>s match.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="instance">The instance to compare.</param>
|
||||||
|
/// <param name="other">The other instance to compare against.</param>
|
||||||
|
/// <returns>Whether online IDs match. If either instance is missing an online ID, this will return false.</returns>
|
||||||
|
public static bool MatchesOnlineID(this APIUser? instance, APIUser? other) => matchesOnlineID(instance, other);
|
||||||
|
|
||||||
|
private static bool matchesOnlineID(this IHasOnlineID<long>? instance, IHasOnlineID<long>? other)
|
||||||
|
{
|
||||||
|
if (instance == null || other == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (instance.OnlineID < 0 || other.OnlineID < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return instance.OnlineID.Equals(other.OnlineID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool matchesOnlineID(this IHasOnlineID<int>? instance, IHasOnlineID<int>? other)
|
||||||
|
{
|
||||||
|
if (instance == null || other == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (instance.OnlineID < 0 || other.OnlineID < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return instance.OnlineID.Equals(other.OnlineID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,9 @@ namespace osu.Game.Graphics.Containers
|
|||||||
|
|
||||||
public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
case GlobalAction.Back:
|
case GlobalAction.Back:
|
||||||
|
@ -60,6 +60,9 @@ namespace osu.Game.Graphics
|
|||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
case GlobalAction.TakeScreenshot:
|
case GlobalAction.TakeScreenshot:
|
||||||
|
@ -64,6 +64,9 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
case GlobalAction.Back:
|
case GlobalAction.Back:
|
||||||
|
@ -75,6 +75,9 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
public virtual bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!HasFocus) return false;
|
if (!HasFocus) return false;
|
||||||
|
|
||||||
if (e.Action == GlobalAction.Back)
|
if (e.Action == GlobalAction.Back)
|
||||||
|
@ -19,6 +19,7 @@ using osu.Framework.Input.Events;
|
|||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Utils;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.UserInterface
|
namespace osu.Game.Graphics.UserInterface
|
||||||
{
|
{
|
||||||
@ -219,7 +220,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
decimal decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits);
|
decimal decimalPrecision = normalise(CurrentNumber.Precision.ToDecimal(NumberFormatInfo.InvariantInfo), max_decimal_digits);
|
||||||
|
|
||||||
// Find the number of significant digits (we could have less than 5 after normalize())
|
// Find the number of significant digits (we could have less than 5 after normalize())
|
||||||
int significantDigits = findPrecision(decimalPrecision);
|
int significantDigits = FormatUtils.FindPrecision(decimalPrecision);
|
||||||
|
|
||||||
TooltipText = floatValue.ToString($"N{significantDigits}");
|
TooltipText = floatValue.ToString($"N{significantDigits}");
|
||||||
}
|
}
|
||||||
@ -248,23 +249,5 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
/// <returns>The normalised decimal.</returns>
|
/// <returns>The normalised decimal.</returns>
|
||||||
private decimal normalise(decimal d, int sd)
|
private decimal normalise(decimal d, int sd)
|
||||||
=> decimal.Parse(Math.Round(d, sd).ToString(string.Concat("0.", new string('#', sd)), CultureInfo.InvariantCulture), CultureInfo.InvariantCulture);
|
=> decimal.Parse(Math.Round(d, sd).ToString(string.Concat("0.", new string('#', sd)), CultureInfo.InvariantCulture), CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds the number of digits after the decimal.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="d">The value to find the number of decimal digits for.</param>
|
|
||||||
/// <returns>The number decimal digits.</returns>
|
|
||||||
private int findPrecision(decimal d)
|
|
||||||
{
|
|
||||||
int precision = 0;
|
|
||||||
|
|
||||||
while (d != Math.Round(d))
|
|
||||||
{
|
|
||||||
d *= 10;
|
|
||||||
precision++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return precision;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,9 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (State.Value == Visibility.Hidden)
|
if (State.Value == Visibility.Hidden)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Models
|
|||||||
[ExcludeFromDynamicCompile]
|
[ExcludeFromDynamicCompile]
|
||||||
[Serializable]
|
[Serializable]
|
||||||
[MapTo("Beatmap")]
|
[MapTo("Beatmap")]
|
||||||
public class RealmBeatmap : RealmObject, IHasGuidPrimaryKey, IBeatmapInfo
|
public class RealmBeatmap : RealmObject, IHasGuidPrimaryKey, IBeatmapInfo, IEquatable<RealmBeatmap>
|
||||||
{
|
{
|
||||||
[PrimaryKey]
|
[PrimaryKey]
|
||||||
public Guid ID { get; set; } = Guid.NewGuid();
|
public Guid ID { get; set; } = Guid.NewGuid();
|
||||||
@ -98,6 +98,16 @@ namespace osu.Game.Models
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public bool Equals(RealmBeatmap? other)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(this, other)) return true;
|
||||||
|
if (other == null) return false;
|
||||||
|
|
||||||
|
return ID == other.ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(IBeatmapInfo? other) => other is RealmBeatmap b && Equals(b);
|
||||||
|
|
||||||
public bool AudioEquals(RealmBeatmap? other) => other != null
|
public bool AudioEquals(RealmBeatmap? other) => other != null
|
||||||
&& BeatmapSet != null
|
&& BeatmapSet != null
|
||||||
&& other.BeatmapSet != null
|
&& other.BeatmapSet != null
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using Realms;
|
using Realms;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
@ -53,25 +54,18 @@ namespace osu.Game.Models
|
|||||||
/// <param name="filename">The name of the file to get the storage path of.</param>
|
/// <param name="filename">The name of the file to get the storage path of.</param>
|
||||||
public string? GetPathForFile(string filename) => Files.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.File.StoragePath;
|
public string? GetPathForFile(string filename) => Files.SingleOrDefault(f => string.Equals(f.Filename, filename, StringComparison.OrdinalIgnoreCase))?.File.StoragePath;
|
||||||
|
|
||||||
public override string ToString() => Metadata?.ToString() ?? base.ToString();
|
|
||||||
|
|
||||||
public bool Equals(RealmBeatmapSet? other)
|
public bool Equals(RealmBeatmapSet? other)
|
||||||
{
|
{
|
||||||
if (other == null)
|
if (ReferenceEquals(this, other)) return true;
|
||||||
return false;
|
if (other == null) return false;
|
||||||
|
|
||||||
if (IsManaged && other.IsManaged)
|
return ID == other.ID;
|
||||||
return ID == other.ID;
|
|
||||||
|
|
||||||
if (OnlineID > 0 && other.OnlineID > 0)
|
|
||||||
return OnlineID == other.OnlineID;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Hash) && !string.IsNullOrEmpty(other.Hash))
|
|
||||||
return Hash == other.Hash;
|
|
||||||
|
|
||||||
return ReferenceEquals(this, other);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString() => Metadata?.GetDisplayString() ?? base.ToString();
|
||||||
|
|
||||||
|
public bool Equals(IBeatmapSetInfo? other) => other is RealmBeatmapSet b && Equals(b);
|
||||||
|
|
||||||
IEnumerable<IBeatmapInfo> IBeatmapSetInfo.Beatmaps => Beatmaps;
|
IEnumerable<IBeatmapInfo> IBeatmapSetInfo.Beatmaps => Beatmaps;
|
||||||
|
|
||||||
IEnumerable<INamedFileUsage> IBeatmapSetInfo.Files => Files;
|
IEnumerable<INamedFileUsage> IBeatmapSetInfo.Files => Files;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
@ -103,5 +104,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
public string Hash => throw new NotImplementedException();
|
public string Hash => throw new NotImplementedException();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public bool Equals(IBeatmapInfo? other) => other is APIBeatmap b && this.MatchesOnlineID(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Extensions;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
@ -141,5 +142,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
double IBeatmapSetInfo.MaxBPM => BPM;
|
double IBeatmapSetInfo.MaxBPM => BPM;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public bool Equals(IBeatmapSetInfo? other) => other is APIBeatmapSet b && this.MatchesOnlineID(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests.Responses
|
namespace osu.Game.Online.API.Requests.Responses
|
||||||
@ -240,6 +241,6 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
|
|
||||||
public int OnlineID => Id;
|
public int OnlineID => Id;
|
||||||
|
|
||||||
public bool Equals(APIUser other) => OnlineID == other?.OnlineID;
|
public bool Equals(APIUser other) => this.MatchesOnlineID(other);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Online.Chat
|
|||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
string verb;
|
string verb;
|
||||||
BeatmapInfo beatmapInfo;
|
IBeatmapInfo beatmapInfo;
|
||||||
|
|
||||||
switch (api.Activity.Value)
|
switch (api.Activity.Value)
|
||||||
{
|
{
|
||||||
@ -57,7 +57,7 @@ namespace osu.Game.Online.Chat
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
string beatmapString = beatmapInfo.OnlineID.HasValue ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineID} {beatmapInfo}]" : beatmapInfo.ToString();
|
string beatmapString = beatmapInfo.OnlineID > 0 ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineID} {beatmapInfo}]" : beatmapInfo.ToString();
|
||||||
|
|
||||||
channelManager.PostMessage($"is {verb} {beatmapString}", true, target);
|
channelManager.PostMessage($"is {verb} {beatmapString}", true, target);
|
||||||
Expire();
|
Expire();
|
||||||
|
@ -41,8 +41,10 @@ namespace osu.Game.Online.Chat
|
|||||||
/// <param name="postingTextbox">Whether a textbox for posting new messages should be displayed.</param>
|
/// <param name="postingTextbox">Whether a textbox for posting new messages should be displayed.</param>
|
||||||
public StandAloneChatDisplay(bool postingTextbox = false)
|
public StandAloneChatDisplay(bool postingTextbox = false)
|
||||||
{
|
{
|
||||||
|
const float corner_radius = 10;
|
||||||
|
|
||||||
this.postingTextbox = postingTextbox;
|
this.postingTextbox = postingTextbox;
|
||||||
CornerRadius = 10;
|
CornerRadius = corner_radius;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
@ -62,6 +64,7 @@ namespace osu.Game.Online.Chat
|
|||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = textbox_height,
|
Height = textbox_height,
|
||||||
PlaceholderText = "type your message",
|
PlaceholderText = "type your message",
|
||||||
|
CornerRadius = corner_radius,
|
||||||
ReleaseFocusOnCommit = false,
|
ReleaseFocusOnCommit = false,
|
||||||
HoldFocus = true,
|
HoldFocus = true,
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
|
@ -10,6 +10,7 @@ using Newtonsoft.Json.Converters;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -62,7 +63,7 @@ namespace osu.Game.Online.Rooms
|
|||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
public MultiplayerScoresAround ScoresAround { get; set; }
|
public MultiplayerScoresAround ScoresAround { get; set; }
|
||||||
|
|
||||||
public ScoreInfo CreateScoreInfo(PlaylistItem playlistItem, [NotNull] BeatmapInfo beatmap)
|
public ScoreInfo CreateScoreInfo(RulesetStore rulesets, PlaylistItem playlistItem, [NotNull] BeatmapInfo beatmap)
|
||||||
{
|
{
|
||||||
var rulesetInstance = playlistItem.Ruleset.Value.CreateInstance();
|
var rulesetInstance = playlistItem.Ruleset.Value.CreateInstance();
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ namespace osu.Game.Online.Rooms
|
|||||||
MaxCombo = MaxCombo,
|
MaxCombo = MaxCombo,
|
||||||
BeatmapInfo = beatmap,
|
BeatmapInfo = beatmap,
|
||||||
BeatmapInfoID = playlistItem.BeatmapID,
|
BeatmapInfoID = playlistItem.BeatmapID,
|
||||||
Ruleset = playlistItem.Ruleset.Value,
|
Ruleset = rulesets.GetRuleset(playlistItem.RulesetID),
|
||||||
RulesetID = playlistItem.RulesetID,
|
RulesetID = playlistItem.RulesetID,
|
||||||
Statistics = Statistics,
|
Statistics = Statistics,
|
||||||
User = User,
|
User = User,
|
||||||
|
@ -30,11 +30,16 @@ namespace osu.Game.Online.Rooms
|
|||||||
[JsonProperty("expired")]
|
[JsonProperty("expired")]
|
||||||
public bool Expired { get; set; }
|
public bool Expired { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public IBindable<bool> Valid => valid;
|
||||||
|
|
||||||
|
private readonly Bindable<bool> valid = new BindableBool(true);
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public readonly Bindable<IBeatmapInfo> Beatmap = new Bindable<IBeatmapInfo>();
|
public readonly Bindable<IBeatmapInfo> Beatmap = new Bindable<IBeatmapInfo>();
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
public readonly Bindable<IRulesetInfo> Ruleset = new Bindable<IRulesetInfo>();
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public readonly BindableList<Mod> AllowedMods = new BindableList<Mod>();
|
public readonly BindableList<Mod> AllowedMods = new BindableList<Mod>();
|
||||||
@ -66,9 +71,11 @@ namespace osu.Game.Online.Rooms
|
|||||||
public PlaylistItem()
|
public PlaylistItem()
|
||||||
{
|
{
|
||||||
Beatmap.BindValueChanged(beatmap => BeatmapID = beatmap.NewValue?.OnlineID ?? -1);
|
Beatmap.BindValueChanged(beatmap => BeatmapID = beatmap.NewValue?.OnlineID ?? -1);
|
||||||
Ruleset.BindValueChanged(ruleset => RulesetID = ruleset.NewValue?.ID ?? 0);
|
Ruleset.BindValueChanged(ruleset => RulesetID = ruleset.NewValue?.OnlineID ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void MarkInvalid() => valid.Value = false;
|
||||||
|
|
||||||
public void MapObjects(RulesetStore rulesets)
|
public void MapObjects(RulesetStore rulesets)
|
||||||
{
|
{
|
||||||
Beatmap.Value ??= apiBeatmap;
|
Beatmap.Value ??= apiBeatmap;
|
||||||
|
@ -1007,6 +1007,9 @@ namespace osu.Game
|
|||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (introScreen == null) return false;
|
if (introScreen == null) return false;
|
||||||
|
|
||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
|
@ -8,6 +8,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online;
|
using osu.Game.Online;
|
||||||
@ -80,7 +81,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels
|
|||||||
case DownloadState.LocallyAvailable:
|
case DownloadState.LocallyAvailable:
|
||||||
Predicate<BeatmapInfo> findPredicate = null;
|
Predicate<BeatmapInfo> findPredicate = null;
|
||||||
if (SelectedBeatmap.Value != null)
|
if (SelectedBeatmap.Value != null)
|
||||||
findPredicate = b => b.OnlineID == SelectedBeatmap.Value.OnlineID;
|
findPredicate = b => b.MatchesOnlineID(SelectedBeatmap.Value);
|
||||||
|
|
||||||
game?.PresentBeatmap(beatmapSet, findPredicate);
|
game?.PresentBeatmap(beatmapSet, findPredicate);
|
||||||
break;
|
break;
|
||||||
|
@ -14,6 +14,7 @@ using osu.Framework.Graphics.Sprites;
|
|||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.Drawables;
|
using osu.Game.Beatmaps.Drawables;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
@ -166,7 +167,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
if (BeatmapSet != null)
|
if (BeatmapSet != null)
|
||||||
{
|
{
|
||||||
Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps
|
Difficulties.ChildrenEnumerable = BeatmapSet.Beatmaps
|
||||||
.Where(b => b.Ruleset.OnlineID == ruleset.Value?.OnlineID)
|
.Where(b => b.Ruleset.MatchesOnlineID(ruleset.Value))
|
||||||
.OrderBy(b => b.StarRating)
|
.OrderBy(b => b.StarRating)
|
||||||
.Select(b => new DifficultySelectorButton(b)
|
.Select(b => new DifficultySelectorButton(b)
|
||||||
{
|
{
|
||||||
|
@ -7,6 +7,7 @@ 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.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
@ -64,7 +65,7 @@ namespace osu.Game.Overlays.BeatmapSet
|
|||||||
|
|
||||||
BeatmapSet.BindValueChanged(setInfo =>
|
BeatmapSet.BindValueChanged(setInfo =>
|
||||||
{
|
{
|
||||||
int beatmapsCount = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.OnlineID == Value.OnlineID) ?? 0;
|
int beatmapsCount = setInfo.NewValue?.Beatmaps.Count(b => b.Ruleset.MatchesOnlineID(Value)) ?? 0;
|
||||||
|
|
||||||
count.Text = beatmapsCount.ToString();
|
count.Text = beatmapsCount.ToString();
|
||||||
countContainer.FadeTo(beatmapsCount > 0 ? 1 : 0);
|
countContainer.FadeTo(beatmapsCount > 0 ? 1 : 0);
|
||||||
|
@ -94,6 +94,9 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
case GlobalAction.Back:
|
case GlobalAction.Back:
|
||||||
|
@ -102,6 +102,9 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
public override bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
case GlobalAction.Select:
|
case GlobalAction.Select:
|
||||||
|
@ -32,6 +32,9 @@ namespace osu.Game.Overlays.Music
|
|||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
|
if (e.Repeat)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (beatmap.Disabled)
|
if (beatmap.Disabled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Music
|
|||||||
var items = (SearchContainer<RearrangeableListItem<BeatmapSetInfo>>)ListContainer;
|
var items = (SearchContainer<RearrangeableListItem<BeatmapSetInfo>>)ListContainer;
|
||||||
|
|
||||||
foreach (var item in items.OfType<PlaylistItem>())
|
foreach (var item in items.OfType<PlaylistItem>())
|
||||||
item.InSelectedCollection = criteria.Collection?.Beatmaps.Any(b => b.BeatmapSet.Equals(item.Model)) ?? true;
|
item.InSelectedCollection = criteria.Collection?.Beatmaps.Any(b => item.Model.Equals(b.BeatmapSet)) ?? true;
|
||||||
|
|
||||||
items.SearchTerm = criteria.SearchText;
|
items.SearchTerm = criteria.SearchText;
|
||||||
}
|
}
|
||||||
|
@ -5,22 +5,23 @@ using System;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Cursor;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
using osu.Game.Resources.Localisation.Web;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile.Header.Components
|
namespace osu.Game.Overlays.Profile.Header.Components
|
||||||
{
|
{
|
||||||
public class SupporterIcon : CompositeDrawable, IHasTooltip
|
public class SupporterIcon : OsuClickableContainer
|
||||||
{
|
{
|
||||||
private readonly Box background;
|
private readonly Box background;
|
||||||
private readonly FillFlowContainer iconContainer;
|
private readonly FillFlowContainer iconContainer;
|
||||||
private readonly CircularContainer content;
|
private readonly CircularContainer content;
|
||||||
|
|
||||||
public LocalisableString TooltipText => UsersStrings.ShowIsSupporter;
|
public override LocalisableString TooltipText => UsersStrings.ShowIsSupporter;
|
||||||
|
|
||||||
public int SupportLevel
|
public int SupportLevel
|
||||||
{
|
{
|
||||||
@ -56,7 +57,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
|
|||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.X;
|
AutoSizeAxes = Axes.X;
|
||||||
|
|
||||||
InternalChild = content = new CircularContainer
|
Child = content = new CircularContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
AutoSizeAxes = Axes.X,
|
AutoSizeAxes = Axes.X,
|
||||||
@ -78,10 +79,27 @@ namespace osu.Game.Overlays.Profile.Header.Components
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[Resolved]
|
||||||
private void load(OsuColour colours)
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader(true)]
|
||||||
|
private void load(OsuGame game)
|
||||||
{
|
{
|
||||||
background.Colour = colours.Pink;
|
background.Colour = colours.Pink;
|
||||||
|
|
||||||
|
Action = () => game?.OpenUrlExternally(@"/home/support");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
background.FadeColour(colours.PinkLight, 500, Easing.OutQuint);
|
||||||
|
return base.OnHover(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
|
{
|
||||||
|
background.FadeColour(colours.Pink, 500, Easing.OutQuint);
|
||||||
|
base.OnHoverLost(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,6 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Threading;
|
|
||||||
using osu.Game.Extensions;
|
|
||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Volume
|
namespace osu.Game.Overlays.Volume
|
||||||
@ -17,18 +15,12 @@ namespace osu.Game.Overlays.Volume
|
|||||||
public Func<GlobalAction, bool> ActionRequested;
|
public Func<GlobalAction, bool> ActionRequested;
|
||||||
public Func<GlobalAction, float, bool, bool> ScrollActionRequested;
|
public Func<GlobalAction, float, bool, bool> ScrollActionRequested;
|
||||||
|
|
||||||
private ScheduledDelegate keyRepeat;
|
|
||||||
|
|
||||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
case GlobalAction.DecreaseVolume:
|
case GlobalAction.DecreaseVolume:
|
||||||
case GlobalAction.IncreaseVolume:
|
case GlobalAction.IncreaseVolume:
|
||||||
keyRepeat?.Cancel();
|
|
||||||
keyRepeat = this.BeginKeyRepeat(Scheduler, () => ActionRequested?.Invoke(e.Action), 150);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case GlobalAction.ToggleMute:
|
case GlobalAction.ToggleMute:
|
||||||
case GlobalAction.NextVolumeMeter:
|
case GlobalAction.NextVolumeMeter:
|
||||||
case GlobalAction.PreviousVolumeMeter:
|
case GlobalAction.PreviousVolumeMeter:
|
||||||
@ -41,7 +33,6 @@ namespace osu.Game.Overlays.Volume
|
|||||||
|
|
||||||
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
keyRepeat?.Cancel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnScroll(ScrollEvent e)
|
protected override bool OnScroll(ScrollEvent e)
|
||||||
|
@ -1,28 +1,87 @@
|
|||||||
// 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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Rulesets.Difficulty.Skills;
|
using osu.Game.Rulesets.Difficulty.Skills;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Difficulty
|
namespace osu.Game.Rulesets.Difficulty
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the difficulty of a beatmap, as output by a <see cref="DifficultyCalculator"/>.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn)]
|
||||||
public class DifficultyAttributes
|
public class DifficultyAttributes
|
||||||
{
|
{
|
||||||
|
protected const int ATTRIB_ID_AIM = 1;
|
||||||
|
protected const int ATTRIB_ID_SPEED = 3;
|
||||||
|
protected const int ATTRIB_ID_OVERALL_DIFFICULTY = 5;
|
||||||
|
protected const int ATTRIB_ID_APPROACH_RATE = 7;
|
||||||
|
protected const int ATTRIB_ID_MAX_COMBO = 9;
|
||||||
|
protected const int ATTRIB_ID_STRAIN = 11;
|
||||||
|
protected const int ATTRIB_ID_GREAT_HIT_WINDOW = 13;
|
||||||
|
protected const int ATTRIB_ID_SCORE_MULTIPLIER = 15;
|
||||||
|
protected const int ATTRIB_ID_FLASHLIGHT = 17;
|
||||||
|
protected const int ATTRIB_ID_SLIDER_FACTOR = 19;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The mods which were applied to the beatmap.
|
||||||
|
/// </summary>
|
||||||
public Mod[] Mods { get; set; }
|
public Mod[] Mods { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The skills resulting from the difficulty calculation.
|
||||||
|
/// </summary>
|
||||||
public Skill[] Skills { get; set; }
|
public Skill[] Skills { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The combined star rating of all skill.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("star_rating", Order = -3)]
|
||||||
public double StarRating { get; set; }
|
public double StarRating { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum achievable combo.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty("max_combo", Order = -2)]
|
||||||
public int MaxCombo { get; set; }
|
public int MaxCombo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates new <see cref="DifficultyAttributes"/>.
|
||||||
|
/// </summary>
|
||||||
public DifficultyAttributes()
|
public DifficultyAttributes()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates new <see cref="DifficultyAttributes"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mods">The mods which were applied to the beatmap.</param>
|
||||||
|
/// <param name="skills">The skills resulting from the difficulty calculation.</param>
|
||||||
|
/// <param name="starRating">The combined star rating of all skills.</param>
|
||||||
public DifficultyAttributes(Mod[] mods, Skill[] skills, double starRating)
|
public DifficultyAttributes(Mod[] mods, Skill[] skills, double starRating)
|
||||||
{
|
{
|
||||||
Mods = mods;
|
Mods = mods;
|
||||||
Skills = skills;
|
Skills = skills;
|
||||||
StarRating = starRating;
|
StarRating = starRating;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts this <see cref="DifficultyAttributes"/> to osu-web compatible database attribute mappings.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// See: osu_difficulty_attribs table.
|
||||||
|
/// </remarks>
|
||||||
|
public virtual IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() => Enumerable.Empty<(int, object)>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads osu-web database attribute mappings into this <see cref="DifficultyAttributes"/> object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="values">The attribute mappings.</param>
|
||||||
|
public virtual void FromDatabaseAttributes(IReadOnlyDictionary<int, double> values)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user