Compare commits
666 Commits
@@ -145,5 +145,10 @@ jobs:
|
||||
- name: Install .NET Workloads
|
||||
run: dotnet workload install ios
|
||||
|
||||
# https://github.com/dotnet/macios/issues/19157
|
||||
# https://github.com/actions/runner-images/issues/12758
|
||||
- name: Use Xcode 16.4
|
||||
run: sudo xcode-select -switch /Applications/Xcode_16.4.app
|
||||
|
||||
- name: Build
|
||||
run: dotnet build -c Debug osu.iOS.slnf
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.715.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.908.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace osu.Desktop
|
||||
// IMPORTANT DON'T IGNORE: For general sanity, velopack's setup needs to run before anything else.
|
||||
// This has bitten us in the rear before (bricked updater), and although the underlying issue from
|
||||
// last time has been fixed, let's not tempt fate.
|
||||
setupVelopack();
|
||||
setupVelopack(args);
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
@@ -174,8 +174,21 @@ namespace osu.Desktop
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void setupVelopack()
|
||||
private static void setupVelopack(string[] args)
|
||||
{
|
||||
// Arguments being present indicate the user is either starting the game in a special (aka tournament) mode,
|
||||
// or is running with pending imports via file association or otherwise.
|
||||
//
|
||||
// In both these scenarios, we'd hope the game does not attempt to update.
|
||||
//
|
||||
// Special consideration for velopack startup arguments, which must be handled during update.
|
||||
// See https://docs.velopack.io/integrating/hooks#command-line-hooks.
|
||||
if (args.Length > 0 && !args[0].StartsWith("--velo", StringComparison.Ordinal))
|
||||
{
|
||||
Logger.Log("Handling arguments, skipping velopack setup.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (OsuGameDesktop.IsPackageManaged)
|
||||
{
|
||||
Logger.Log("Updates are being managed by an external provider. Skipping Velopack setup.");
|
||||
|
||||
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
@@ -22,8 +22,9 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
var ruleset = new CatchRuleset();
|
||||
var difficulty = new BeatmapDifficulty { ApproachRate = originalApproachRate };
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, []);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, []);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(originalApproachRate));
|
||||
}
|
||||
@@ -33,8 +34,9 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
var ruleset = new CatchRuleset();
|
||||
var difficulty = new BeatmapDifficulty();
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, [new CatchModHalfTime()]);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, [new CatchModHalfTime()]);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(1.67).Within(0.01));
|
||||
}
|
||||
@@ -44,8 +46,9 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
var ruleset = new CatchRuleset();
|
||||
var difficulty = new BeatmapDifficulty();
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, [new CatchModDoubleTime()]);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, [new CatchModDoubleTime()]);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(7.67).Within(0.01));
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
@@ -1,2 +0,0 @@
|
||||
[General]
|
||||
// no version specified means v1
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Extensions.LocalisationExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
@@ -11,6 +12,7 @@ using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets.Catch.Beatmaps;
|
||||
using osu.Game.Rulesets.Catch.Difficulty;
|
||||
using osu.Game.Rulesets.Catch.Edit;
|
||||
@@ -25,6 +27,7 @@ using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Legacy;
|
||||
using osu.Game.Rulesets.Replays.Types;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Scoring.Legacy;
|
||||
@@ -267,9 +270,9 @@ namespace osu.Game.Rulesets.Catch
|
||||
}
|
||||
|
||||
/// <seealso cref="CatchHitObject.ApplyDefaultsToSelf"/>
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapDifficultyInfo difficulty, IReadOnlyCollection<Mod> mods)
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
BeatmapDifficulty adjustedDifficulty = new BeatmapDifficulty(difficulty);
|
||||
BeatmapDifficulty adjustedDifficulty = base.GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
double rate = ModUtils.CalculateRateWithMods(mods);
|
||||
|
||||
double preempt = IBeatmapDifficultyInfo.DifficultyRange(adjustedDifficulty.ApproachRate, CatchHitObject.PREEMPT_MAX, CatchHitObject.PREEMPT_MID, CatchHitObject.PREEMPT_MIN);
|
||||
@@ -279,6 +282,33 @@ namespace osu.Game.Rulesets.Catch
|
||||
return adjustedDifficulty;
|
||||
}
|
||||
|
||||
public override IEnumerable<RulesetBeatmapAttribute> GetBeatmapAttributesForDisplay(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
var originalDifficulty = beatmapInfo.Difficulty;
|
||||
var effectiveDifficulty = GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.CircleSize, @"CS", originalDifficulty.CircleSize, effectiveDifficulty.CircleSize, 10)
|
||||
{
|
||||
Description = "Affects the size of fruits.",
|
||||
AdditionalMetrics =
|
||||
[
|
||||
new RulesetBeatmapAttribute.AdditionalMetric("Hit circle radius", (CatchHitObject.OBJECT_RADIUS * LegacyRulesetExtensions.CalculateScaleFromCircleSize(effectiveDifficulty.CircleSize)).ToLocalisableString("0.#"))
|
||||
]
|
||||
};
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.ApproachRate, @"AR", originalDifficulty.ApproachRate, effectiveDifficulty.ApproachRate, 10)
|
||||
{
|
||||
Description = "Affects how early fruits fade in on the screen.",
|
||||
AdditionalMetrics =
|
||||
[
|
||||
new RulesetBeatmapAttribute.AdditionalMetric("Fade-in time", LocalisableString.Interpolate($@"{IBeatmapDifficultyInfo.DifficultyRange(effectiveDifficulty.ApproachRate, CatchHitObject.PREEMPT_RANGE):#,0.##} ms"))
|
||||
]
|
||||
};
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.HPDrain, @"HP", originalDifficulty.DrainRate, effectiveDifficulty.DrainRate, 10)
|
||||
{
|
||||
Description = "Affects the harshness of health drain and the health penalties for missing."
|
||||
};
|
||||
}
|
||||
|
||||
public override bool EditorShowScrollSpeed => false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Checks
|
||||
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var hitObjects = context.Beatmap.HitObjects;
|
||||
var hitObjects = context.CurrentDifficulty.Playable.HitObjects;
|
||||
(int expectedStartDelta, int expectedEndDelta) = spinner_delta_threshold[context.InterpretedDifficulty];
|
||||
|
||||
for (int i = 0; i < hitObjects.Count - 1; ++i)
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Checks
|
||||
|
||||
public override IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var diff = context.Beatmap.Difficulty;
|
||||
var diff = context.CurrentDifficulty.Playable.Difficulty;
|
||||
Issue? issue;
|
||||
|
||||
if (HasMoreThanOneDecimalPlace("Approach rate", diff.ApproachRate, out issue))
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
|
||||
public override BindableBool ComboBasedSize { get; } = new BindableBool(true);
|
||||
|
||||
public override float DefaultFlashlightSize => 325;
|
||||
public override float DefaultFlashlightSize => 203.125f;
|
||||
|
||||
protected override Flashlight CreateFlashlight() => new CatchFlashlight(this, playfield);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
@@ -16,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
public override string Acronym => "FF";
|
||||
public override LocalisableString Description => "The fruits are... floating?";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override IconUsage? Icon => FontAwesome.Solid.Cloud;
|
||||
public override IconUsage? Icon => OsuIcon.ModFloatingFruits;
|
||||
|
||||
public void ApplyToDrawableRuleset(DrawableRuleset<CatchHitObject> drawableRuleset)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@@ -18,12 +19,12 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
{
|
||||
public partial class CatchModMovingFast : Mod, IApplicableToDrawableRuleset<CatchHitObject>, IApplicableToPlayer
|
||||
{
|
||||
public override string Name => "Moving fast";
|
||||
public override string Name => "Moving Fast";
|
||||
public override string Acronym => "MF";
|
||||
public override LocalisableString Description => "Dashing by default, slow down!";
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override IconUsage? Icon => FontAwesome.Solid.Running;
|
||||
public override IconUsage? Icon => OsuIcon.ModMovingFast;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModRelax) };
|
||||
|
||||
private DrawableCatchRuleset drawableRuleset = null!;
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, PREEMPT_MAX, PREEMPT_MID, PREEMPT_MIN);
|
||||
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, PREEMPT_RANGE);
|
||||
|
||||
Scale = LegacyRulesetExtensions.CalculateScaleFromCircleSize(difficulty.CircleSize);
|
||||
}
|
||||
@@ -203,6 +203,8 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
/// </summary>
|
||||
public const double PREEMPT_MAX = 1800;
|
||||
|
||||
public static readonly DifficultyRange PREEMPT_RANGE = new DifficultyRange(PREEMPT_MAX, PREEMPT_MID, PREEMPT_MIN);
|
||||
|
||||
/// <summary>
|
||||
/// The Y position of the hit object is not used in the normal osu!catch gameplay.
|
||||
/// It is preserved to maximize the backward compatibility with the legacy editor, in which the mappers use the Y position to organize the patterns.
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
|
||||
[TestCase("convert-samples")]
|
||||
[TestCase("mania-samples")]
|
||||
[TestCase("mania-slider")] // e.g. second and fourth notes of https://osu.ppy.sh/beatmapsets/73883#mania/216407
|
||||
[TestCase("slider-convert-samples")]
|
||||
public void Test(string name) => base.Test(name);
|
||||
|
||||
@@ -32,6 +33,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
StartTime = hitObject.StartTime,
|
||||
EndTime = hitObject.GetEndTime(),
|
||||
Column = ((ManiaHitObject)hitObject).Column,
|
||||
PlaySlidingSamples = hitObject is HoldNote holdNote && holdNote.PlaySlidingSamples,
|
||||
Samples = getSampleNames(hitObject.Samples),
|
||||
NodeSamples = getNodeSampleNames((hitObject as HoldNote)?.NodeSamples)
|
||||
};
|
||||
@@ -57,12 +59,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
public double StartTime;
|
||||
public double EndTime;
|
||||
public int Column;
|
||||
public bool PlaySlidingSamples;
|
||||
public IList<string> Samples;
|
||||
public IList<IList<string>> NodeSamples;
|
||||
|
||||
public bool Equals(SampleConvertValue other)
|
||||
=> Precision.AlmostEquals(StartTime, other.StartTime, conversion_lenience)
|
||||
&& Precision.AlmostEquals(EndTime, other.EndTime, conversion_lenience)
|
||||
&& PlaySlidingSamples == other.PlaySlidingSamples
|
||||
&& samplesEqual(Samples, other.Samples)
|
||||
&& nodeSamplesEqual(NodeSamples, other.NodeSamples);
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
}
|
||||
|
||||
[TestCase]
|
||||
public void TestFilterIntersection()
|
||||
public void TestKeysFilterIntersection()
|
||||
{
|
||||
var criteria = new ManiaFilterCriteria();
|
||||
criteria.TryParseCustomKeywordCriteria("keys", Operator.Greater, "4");
|
||||
@@ -175,7 +175,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
}
|
||||
|
||||
[TestCase]
|
||||
public void TestInvalidFilters()
|
||||
public void TestInvalidKeysFilters()
|
||||
{
|
||||
var criteria = new ManiaFilterCriteria();
|
||||
|
||||
@@ -183,5 +183,132 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
Assert.False(criteria.TryParseCustomKeywordCriteria("keys", Operator.NotEqual, "4,some text"));
|
||||
Assert.False(criteria.TryParseCustomKeywordCriteria("keys", Operator.GreaterOrEqual, "4,5,6"));
|
||||
}
|
||||
|
||||
[TestCase]
|
||||
public void TestLnsEqual()
|
||||
{
|
||||
var criteria = new ManiaFilterCriteria();
|
||||
var filterCriteria = new FilterCriteria
|
||||
{
|
||||
Ruleset = new ManiaRuleset().RulesetInfo
|
||||
};
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.Equal, "0");
|
||||
BeatmapInfo beatmapInfo1 = new BeatmapInfo(new ManiaRuleset().RulesetInfo)
|
||||
{
|
||||
TotalObjectCount = 0,
|
||||
EndTimeObjectCount = 0
|
||||
};
|
||||
Assert.True(criteria.Matches(beatmapInfo1, filterCriteria));
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.Equal, "0");
|
||||
BeatmapInfo beatmapInfo2 = new BeatmapInfo(new ManiaRuleset().RulesetInfo)
|
||||
{
|
||||
TotalObjectCount = 100,
|
||||
EndTimeObjectCount = 0
|
||||
};
|
||||
Assert.True(criteria.Matches(beatmapInfo2, filterCriteria));
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.Equal, "100");
|
||||
BeatmapInfo beatmapInfo3 = new BeatmapInfo(new ManiaRuleset().RulesetInfo)
|
||||
{
|
||||
TotalObjectCount = 100,
|
||||
EndTimeObjectCount = 100
|
||||
};
|
||||
Assert.True(criteria.Matches(beatmapInfo3, filterCriteria));
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.Equal, "1");
|
||||
BeatmapInfo beatmapInfo4 = new BeatmapInfo(new ManiaRuleset().RulesetInfo)
|
||||
{
|
||||
TotalObjectCount = 100,
|
||||
EndTimeObjectCount = 1
|
||||
};
|
||||
Assert.True(criteria.Matches(beatmapInfo4, filterCriteria));
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.Equal, "0.1");
|
||||
BeatmapInfo beatmapInfo5 = new BeatmapInfo(new ManiaRuleset().RulesetInfo)
|
||||
{
|
||||
TotalObjectCount = 1000,
|
||||
EndTimeObjectCount = 1
|
||||
};
|
||||
Assert.True(criteria.Matches(beatmapInfo5, filterCriteria));
|
||||
}
|
||||
|
||||
[TestCase]
|
||||
public void TestLnsGreaterOrEqual()
|
||||
{
|
||||
var criteria = new ManiaFilterCriteria();
|
||||
var filterCriteria = new FilterCriteria
|
||||
{
|
||||
Ruleset = new ManiaRuleset().RulesetInfo
|
||||
};
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.GreaterOrEqual, "0");
|
||||
BeatmapInfo beatmapInfo1 = new BeatmapInfo(new ManiaRuleset().RulesetInfo)
|
||||
{
|
||||
TotalObjectCount = 0,
|
||||
EndTimeObjectCount = 0
|
||||
};
|
||||
Assert.True(criteria.Matches(beatmapInfo1, filterCriteria));
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.GreaterOrEqual, "0");
|
||||
BeatmapInfo beatmapInfo2 = new BeatmapInfo(new ManiaRuleset().RulesetInfo)
|
||||
{
|
||||
TotalObjectCount = 100,
|
||||
EndTimeObjectCount = 0
|
||||
};
|
||||
Assert.True(criteria.Matches(beatmapInfo2, filterCriteria));
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.GreaterOrEqual, "100");
|
||||
BeatmapInfo beatmapInfo3 = new BeatmapInfo(new ManiaRuleset().RulesetInfo)
|
||||
{
|
||||
TotalObjectCount = 100,
|
||||
EndTimeObjectCount = 100
|
||||
};
|
||||
Assert.True(criteria.Matches(beatmapInfo3, filterCriteria));
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.GreaterOrEqual, "1");
|
||||
BeatmapInfo beatmapInfo4 = new BeatmapInfo(new ManiaRuleset().RulesetInfo)
|
||||
{
|
||||
TotalObjectCount = 100,
|
||||
EndTimeObjectCount = 1
|
||||
};
|
||||
Assert.True(criteria.Matches(beatmapInfo4, filterCriteria));
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.GreaterOrEqual, "0.1");
|
||||
BeatmapInfo beatmapInfo5 = new BeatmapInfo(new ManiaRuleset().RulesetInfo)
|
||||
{
|
||||
TotalObjectCount = 1000,
|
||||
EndTimeObjectCount = 1
|
||||
};
|
||||
Assert.True(criteria.Matches(beatmapInfo5, filterCriteria));
|
||||
}
|
||||
|
||||
[TestCase]
|
||||
public void TestLnsNotManiaRuleset()
|
||||
{
|
||||
var criteria = new ManiaFilterCriteria();
|
||||
var filterCriteria = new FilterCriteria
|
||||
{
|
||||
Ruleset = new ManiaRuleset().RulesetInfo
|
||||
};
|
||||
|
||||
criteria.TryParseCustomKeywordCriteria("lns", Operator.LessOrEqual, "100");
|
||||
BeatmapInfo beatmapInfo = new BeatmapInfo
|
||||
{
|
||||
TotalObjectCount = 100,
|
||||
EndTimeObjectCount = 50
|
||||
};
|
||||
Assert.False(criteria.Matches(beatmapInfo, filterCriteria));
|
||||
}
|
||||
|
||||
[TestCase]
|
||||
public void TestInvalidLnsFilters()
|
||||
{
|
||||
var criteria = new ManiaFilterCriteria();
|
||||
|
||||
Assert.False(criteria.TryParseCustomKeywordCriteria("lns", Operator.Equal, "some text"));
|
||||
Assert.False(criteria.TryParseCustomKeywordCriteria("lns", Operator.GreaterOrEqual, "1some text"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"StartTime": 1000.0,
|
||||
"EndTime": 2750.0,
|
||||
"Column": 1,
|
||||
"PlaySlidingSamples": true,
|
||||
"NodeSamples": [
|
||||
["Gameplay/normal-hitnormal"],
|
||||
["Gameplay/soft-hitnormal"],
|
||||
@@ -15,6 +16,7 @@
|
||||
"StartTime": 1875.0,
|
||||
"EndTime": 2750.0,
|
||||
"Column": 0,
|
||||
"PlaySlidingSamples": true,
|
||||
"NodeSamples": [
|
||||
["Gameplay/soft-hitnormal"],
|
||||
["Gameplay/drum-hitnormal"]
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"StartTime": 500.0,
|
||||
"EndTime": 1500.0,
|
||||
"Column": 0,
|
||||
"PlaySlidingSamples": false,
|
||||
"NodeSamples": [
|
||||
["Gameplay/normal-hitnormal"],
|
||||
[]
|
||||
@@ -17,6 +18,7 @@
|
||||
"StartTime": 2000.0,
|
||||
"EndTime": 3000.0,
|
||||
"Column": 2,
|
||||
"PlaySlidingSamples": false,
|
||||
"NodeSamples": [
|
||||
["Gameplay/drum-hitnormal"],
|
||||
[]
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"Mappings": [{
|
||||
"StartTime": 500.0,
|
||||
"Objects": [{
|
||||
"StartTime": 500.0,
|
||||
"EndTime": 2500,
|
||||
"Column": 2,
|
||||
"PlaySlidingSamples": true,
|
||||
"NodeSamples": [
|
||||
["Gameplay/soft-hitnormal"],
|
||||
["Gameplay/soft-hitnormal"],
|
||||
["Gameplay/soft-hitnormal"],
|
||||
["Gameplay/soft-hitnormal"]
|
||||
],
|
||||
"Samples": ["Gameplay/soft-hitnormal"]
|
||||
}]
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
osu file format v5
|
||||
|
||||
[General]
|
||||
StackLeniency: 0.7
|
||||
Mode: 3
|
||||
|
||||
[Difficulty]
|
||||
HPDrainRate:2
|
||||
CircleSize:5
|
||||
OverallDifficulty:2
|
||||
SliderMultiplier:1
|
||||
SliderTickRate:2
|
||||
|
||||
[Events]
|
||||
//Background and Video events
|
||||
//Break Periods
|
||||
//Storyboard Layer 0 (Background)
|
||||
//Storyboard Layer 1 (Failing)
|
||||
//Storyboard Layer 2 (Passing)
|
||||
//Storyboard Layer 3 (Foreground)
|
||||
//Storyboard Sound Samples
|
||||
//Background Colour Transformations
|
||||
3,100,163,162,255
|
||||
|
||||
[TimingPoints]
|
||||
355,476.190476190476,4,2,1,60,1,0
|
||||
|
||||
[HitObjects]
|
||||
256,352,500,2,0,L|256:208,3,140
|
||||
@@ -203,7 +203,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
private void toggleTouchControls(bool enabled)
|
||||
{
|
||||
var maniaConfig = (ManiaRulesetConfigManager)RulesetConfigs.GetConfigFor(CreatePlayerRuleset())!;
|
||||
maniaConfig.SetValue(ManiaRulesetSetting.MobileLayout, enabled ? ManiaMobileLayout.LandscapeWithOverlay : ManiaMobileLayout.Portrait);
|
||||
maniaConfig.SetValue(ManiaRulesetSetting.TouchOverlay, enabled);
|
||||
}
|
||||
|
||||
private ManiaTouchInputArea? getTouchOverlay() => this.ChildrenOfType<ManiaTouchInputArea>().SingleOrDefault();
|
||||
|
||||
@@ -47,8 +47,6 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
drawableRuleset = (DrawableManiaRuleset)Ruleset.Value.CreateInstance().CreateDrawableRulesetWith(createTestBeatmap())
|
||||
}
|
||||
};
|
||||
|
||||
drawableRuleset.AllowBackwardsSeeks = true;
|
||||
});
|
||||
AddStep("retrieve config bindable", () =>
|
||||
{
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetColumnCount(LegacyBeatmapConversionDifficultyInfo difficulty, IReadOnlyList<Mod>? mods = null)
|
||||
public static int GetColumnCount(LegacyBeatmapConversionDifficultyInfo difficulty, IReadOnlyCollection<Mod>? mods = null)
|
||||
{
|
||||
var converter = new ManiaBeatmapConverter(null, difficulty, new ManiaRuleset());
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Legacy;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Utils;
|
||||
|
||||
@@ -30,12 +32,18 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
|
||||
if (HitObject is IHasDuration endTimeData)
|
||||
{
|
||||
// despite the beatmap originally being made for mania, if the object is parsed as a slider rather than a hold, sliding samples should still be played.
|
||||
// this is seemingly only possible to achieve by modifying the .osu file directly, but online beatmaps that do that exist
|
||||
// (see second and fourth notes of https://osu.ppy.sh/beatmapsets/73883#mania/216407)
|
||||
bool playSlidingSamples = (HitObject is IHasLegacyHitObjectType hasType && hasType.LegacyType == LegacyHitObjectType.Slider) || HitObject is IHasPath;
|
||||
|
||||
pattern.Add(new HoldNote
|
||||
{
|
||||
StartTime = HitObject.StartTime,
|
||||
Duration = endTimeData.Duration,
|
||||
Column = column,
|
||||
Samples = HitObject.Samples,
|
||||
PlaySlidingSamples = playSlidingSamples,
|
||||
NodeSamples = (HitObject as IHasRepeats)?.NodeSamples ?? HoldNote.CreateDefaultNodeSamples(HitObject)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -521,6 +521,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
Duration = endTime - startTime,
|
||||
Column = column,
|
||||
Samples = HitObject.Samples,
|
||||
PlaySlidingSamples = true,
|
||||
NodeSamples = nodeSamplesAt(startTime)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace osu.Game.Rulesets.Mania.Configuration
|
||||
public ManiaRulesetConfigManager(SettingsStore? settings, RulesetInfo ruleset, int? variant = null)
|
||||
: base(settings, ruleset, variant)
|
||||
{
|
||||
Migrate();
|
||||
}
|
||||
|
||||
protected override void InitialiseDefaults()
|
||||
@@ -24,6 +25,20 @@ namespace osu.Game.Rulesets.Mania.Configuration
|
||||
SetDefault(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down);
|
||||
SetDefault(ManiaRulesetSetting.TimingBasedNoteColouring, false);
|
||||
SetDefault(ManiaRulesetSetting.MobileLayout, ManiaMobileLayout.Portrait);
|
||||
SetDefault(ManiaRulesetSetting.TouchOverlay, false);
|
||||
}
|
||||
|
||||
public void Migrate()
|
||||
{
|
||||
var mobileLayout = GetBindable<ManiaMobileLayout>(ManiaRulesetSetting.MobileLayout);
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (mobileLayout.Value == ManiaMobileLayout.LandscapeWithOverlay)
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
{
|
||||
mobileLayout.Value = ManiaMobileLayout.Landscape;
|
||||
SetValue(ManiaRulesetSetting.TouchOverlay, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override TrackedSettings CreateTrackedSettings() => new TrackedSettings
|
||||
@@ -44,5 +59,6 @@ namespace osu.Game.Rulesets.Mania.Configuration
|
||||
ScrollDirection,
|
||||
TimingBasedNoteColouring,
|
||||
MobileLayout,
|
||||
TouchOverlay,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Checks
|
||||
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var diff = context.Beatmap.Difficulty;
|
||||
var diff = context.CurrentDifficulty.Playable.Difficulty;
|
||||
|
||||
if (diff.CircleSize < 4)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Checks
|
||||
|
||||
public override IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var diff = context.Beatmap.Difficulty;
|
||||
var diff = context.CurrentDifficulty.Playable.Difficulty;
|
||||
Issue? issue;
|
||||
|
||||
if (HasMoreThanOneDecimalPlace("Overall difficulty", diff.OverallDifficulty, out issue))
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Checks
|
||||
{
|
||||
public override IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var hitObjects = context.Beatmap.HitObjects;
|
||||
var hitObjects = context.CurrentDifficulty.Playable.HitObjects;
|
||||
|
||||
for (int i = 0; i < hitObjects.Count - 1; ++i)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
@@ -19,12 +20,16 @@ namespace osu.Game.Rulesets.Mania
|
||||
public class ManiaFilterCriteria : IRulesetFilterCriteria
|
||||
{
|
||||
private readonly HashSet<int> includedKeyCounts = Enumerable.Range(1, LegacyBeatmapDecoder.MAX_MANIA_KEY_COUNT).ToHashSet();
|
||||
private FilterCriteria.OptionalRange<float> longNotePercentage;
|
||||
|
||||
public bool Matches(BeatmapInfo beatmapInfo, FilterCriteria criteria)
|
||||
{
|
||||
int keyCount = ManiaBeatmapConverter.GetColumnCount(LegacyBeatmapConversionDifficultyInfo.FromBeatmapInfo(beatmapInfo), criteria.Mods);
|
||||
|
||||
return includedKeyCounts.Contains(keyCount);
|
||||
bool keyCountMatch = includedKeyCounts.Contains(keyCount);
|
||||
bool longNotePercentageMatch = !longNotePercentage.HasFilter || (!isConvertedBeatmap(beatmapInfo) && longNotePercentage.IsInRange(calculateLongNotePercentage(beatmapInfo)));
|
||||
|
||||
return keyCountMatch && longNotePercentageMatch;
|
||||
}
|
||||
|
||||
public bool TryParseCustomKeywordCriteria(string key, Operator op, string strValues)
|
||||
@@ -84,6 +89,10 @@ namespace osu.Game.Rulesets.Mania
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
case "ln":
|
||||
case "lns":
|
||||
return FilterQueryParser.TryUpdateCriteriaRange(ref longNotePercentage, op, strValues);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -103,5 +112,18 @@ namespace osu.Game.Rulesets.Mania
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool isConvertedBeatmap(BeatmapInfo beatmapInfo)
|
||||
{
|
||||
return !beatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo);
|
||||
}
|
||||
|
||||
private static float calculateLongNotePercentage(BeatmapInfo beatmapInfo)
|
||||
{
|
||||
int holdNotes = beatmapInfo.EndTimeObjectCount;
|
||||
int totalNotes = Math.Max(1, beatmapInfo.TotalObjectCount);
|
||||
|
||||
return holdNotes / (float)totalNotes * 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets.Mania.Configuration;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania
|
||||
{
|
||||
public enum ManiaMobileLayout
|
||||
{
|
||||
[LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.PortraitExpandedColumns))]
|
||||
[LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.Portrait))]
|
||||
Portrait,
|
||||
|
||||
[LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.LandscapeExpandedColumns))]
|
||||
[LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.Landscape))]
|
||||
Landscape,
|
||||
|
||||
[LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.LandscapeTouchOverlay))]
|
||||
[LocalisableDescription(typeof(RulesetSettingsStrings), nameof(RulesetSettingsStrings.LandscapeExpandedColumns))]
|
||||
LandscapeExpandedColumns,
|
||||
|
||||
[Obsolete($"Use {nameof(ManiaRulesetSetting.TouchOverlay)} instead.")] // todo: can be removed 20260211
|
||||
LandscapeWithOverlay,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
@@ -12,6 +13,7 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Overlays.Settings;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
@@ -77,6 +79,7 @@ namespace osu.Game.Rulesets.Mania
|
||||
return new ManiaArgonSkinTransformer(skin, beatmap);
|
||||
|
||||
case DefaultLegacySkin:
|
||||
case RetroSkin:
|
||||
return new ManiaClassicSkinTransformer(skin, beatmap);
|
||||
|
||||
case LegacySkin:
|
||||
@@ -415,9 +418,9 @@ namespace osu.Game.Rulesets.Mania
|
||||
};
|
||||
|
||||
/// <seealso cref="ManiaHitWindows"/>
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapDifficultyInfo difficulty, IReadOnlyCollection<Mod> mods)
|
||||
public override BeatmapDifficulty GetAdjustedDisplayDifficulty(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
BeatmapDifficulty adjustedDifficulty = new BeatmapDifficulty(difficulty);
|
||||
BeatmapDifficulty adjustedDifficulty = base.GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
|
||||
// notably, in mania, hit windows are designed to be independent of track playback rate (see `ManiaHitWindows.SpeedMultiplier`).
|
||||
// *however*, to not make matters *too* simple, mania Hard Rock and Easy differ from all other rulesets
|
||||
@@ -436,10 +439,48 @@ namespace osu.Game.Rulesets.Mania
|
||||
perfectHitWindow /= ManiaModEasy.HIT_WINDOW_DIFFICULTY_MULTIPLIER;
|
||||
|
||||
adjustedDifficulty.OverallDifficulty = (float)IBeatmapDifficultyInfo.InverseDifficultyRange(perfectHitWindow, ManiaHitWindows.PERFECT_WINDOW_RANGE);
|
||||
adjustedDifficulty.CircleSize = ManiaBeatmapConverter.GetColumnCount(LegacyBeatmapConversionDifficultyInfo.FromBeatmapInfo(beatmapInfo), mods);
|
||||
|
||||
return adjustedDifficulty;
|
||||
}
|
||||
|
||||
public override IEnumerable<RulesetBeatmapAttribute> GetBeatmapAttributesForDisplay(IBeatmapInfo beatmapInfo, IReadOnlyCollection<Mod> mods)
|
||||
{
|
||||
// a special touch-up of key count is required to the original difficulty, since key conversion mods are not `IApplicableToDifficulty`
|
||||
var originalDifficulty = new BeatmapDifficulty(beatmapInfo.Difficulty)
|
||||
{
|
||||
CircleSize = ManiaBeatmapConverter.GetColumnCount(LegacyBeatmapConversionDifficultyInfo.FromBeatmapInfo(beatmapInfo), [])
|
||||
};
|
||||
var adjustedDifficulty = GetAdjustedDisplayDifficulty(beatmapInfo, mods);
|
||||
var colours = new OsuColour();
|
||||
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.KeyCount, @"KC", originalDifficulty.CircleSize, adjustedDifficulty.CircleSize, 18)
|
||||
{
|
||||
Description = "Affects the number of key columns on the playfield."
|
||||
};
|
||||
|
||||
var hitWindows = new ManiaHitWindows();
|
||||
hitWindows.SetDifficulty(adjustedDifficulty.OverallDifficulty);
|
||||
hitWindows.IsConvert = !beatmapInfo.Ruleset.Equals(RulesetInfo);
|
||||
hitWindows.ClassicModActive = mods.Any(m => m is ManiaModClassic);
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.Accuracy, @"OD", originalDifficulty.OverallDifficulty, adjustedDifficulty.OverallDifficulty, 10)
|
||||
{
|
||||
Description = "Affects timing requirements for notes.",
|
||||
AdditionalMetrics = hitWindows.GetAllAvailableWindows()
|
||||
.Reverse()
|
||||
.Select(window => new RulesetBeatmapAttribute.AdditionalMetric(
|
||||
$"{window.result.GetDescription().ToUpperInvariant()} hit window",
|
||||
LocalisableString.Interpolate($@"±{hitWindows.WindowFor(window.result):0.##} ms"),
|
||||
colours.ForHitResult(window.result)
|
||||
)).ToArray()
|
||||
};
|
||||
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.HPDrain, @"HP", originalDifficulty.DrainRate, adjustedDifficulty.DrainRate, 10)
|
||||
{
|
||||
Description = "Affects the harshness of health drain and the health penalties for missing."
|
||||
};
|
||||
}
|
||||
|
||||
public override IRulesetFilterCriteria CreateRulesetFilterCriteria()
|
||||
{
|
||||
return new ManiaFilterCriteria();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -48,12 +50,21 @@ namespace osu.Game.Rulesets.Mania
|
||||
},
|
||||
};
|
||||
|
||||
Add(new SettingsCheckbox
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.TouchOverlay,
|
||||
Current = config.GetBindable<bool>(ManiaRulesetSetting.TouchOverlay)
|
||||
});
|
||||
|
||||
if (RuntimeInfo.IsMobile)
|
||||
{
|
||||
Add(new SettingsEnumDropdown<ManiaMobileLayout>
|
||||
{
|
||||
LabelText = RulesetSettingsStrings.MobileLayout,
|
||||
Current = config.GetBindable<ManiaMobileLayout>(ManiaRulesetSetting.MobileLayout),
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
Items = Enum.GetValues<ManiaMobileLayout>().Where(l => l != ManiaMobileLayout.LandscapeWithOverlay),
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@@ -21,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
|
||||
public override LocalisableString Description => "No more tricky speed changes!";
|
||||
|
||||
public override IconUsage? Icon => FontAwesome.Solid.Equals;
|
||||
public override IconUsage? Icon => OsuIcon.ModConstantSpeed;
|
||||
|
||||
public override ModType Type => ModType.Conversion;
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
@@ -14,6 +16,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public override string Name => "Cover";
|
||||
public override string Acronym => "CO";
|
||||
public override IconUsage? Icon => OsuIcon.ModCover;
|
||||
|
||||
public override LocalisableString Description => @"Decrease the playfield's viewing area.";
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
@@ -13,6 +15,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override string Name => "Dual Stages";
|
||||
public override string Acronym => "DS";
|
||||
public override LocalisableString Description => @"Double the stages, double the fun!";
|
||||
public override IconUsage? Icon => OsuIcon.ModDualStages;
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
@@ -12,6 +14,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public override string Name => "Fade In";
|
||||
public override string Acronym => "FI";
|
||||
public override IconUsage? Icon => OsuIcon.ModFadeIn;
|
||||
public override LocalisableString Description => @"Keys appear out of nowhere!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override bool ValidForFreestyleAsRequiredMod => false;
|
||||
|
||||
@@ -9,6 +9,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
@@ -23,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
|
||||
public override LocalisableString Description => @"Replaces all hold notes with normal notes.";
|
||||
|
||||
public override IconUsage? Icon => FontAwesome.Solid.DotCircle;
|
||||
public override IconUsage? Icon => OsuIcon.ModHoldOff;
|
||||
|
||||
public override ModType Type => ModType.Conversion;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@@ -23,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
|
||||
public override LocalisableString Description => "Hold the keys. To the beat.";
|
||||
|
||||
public override IconUsage? Icon => FontAwesome.Solid.YinYang;
|
||||
public override IconUsage? Icon => OsuIcon.ModInvert;
|
||||
|
||||
public override ModType Type => ModType.Conversion;
|
||||
|
||||
@@ -63,6 +64,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
StartTime = locations[i].startTime,
|
||||
Duration = duration,
|
||||
NodeSamples = new List<IList<HitSampleInfo>> { locations[i].samples, Array.Empty<HitSampleInfo>() }
|
||||
// intentionally don't play sliding samples here, it doesn't work in this mod.
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override int KeyCount => 1;
|
||||
public override string Name => "One Key";
|
||||
public override string Acronym => "1K";
|
||||
public override IconUsage? Icon => OsuIcon.ModOneKey;
|
||||
public override LocalisableString Description => @"Play with one key.";
|
||||
public override bool Ranked => false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override int KeyCount => 10;
|
||||
public override string Name => "Ten Keys";
|
||||
public override string Acronym => "10K";
|
||||
public override IconUsage? Icon => OsuIcon.ModTenKeys;
|
||||
public override LocalisableString Description => @"Play with ten keys.";
|
||||
public override bool Ranked => false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override int KeyCount => 2;
|
||||
public override string Name => "Two Keys";
|
||||
public override string Acronym => "2K";
|
||||
public override IconUsage? Icon => OsuIcon.ModTwoKeys;
|
||||
public override LocalisableString Description => @"Play with two keys.";
|
||||
public override bool Ranked => false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override int KeyCount => 3;
|
||||
public override string Name => "Three Keys";
|
||||
public override string Acronym => "3K";
|
||||
public override IconUsage? Icon => OsuIcon.ModThreeKeys;
|
||||
public override LocalisableString Description => @"Play with three keys.";
|
||||
public override bool Ranked => false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override int KeyCount => 4;
|
||||
public override string Name => "Four Keys";
|
||||
public override string Acronym => "4K";
|
||||
public override IconUsage? Icon => OsuIcon.ModFourKeys;
|
||||
public override LocalisableString Description => @"Play with four keys.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override int KeyCount => 5;
|
||||
public override string Name => "Five Keys";
|
||||
public override string Acronym => "5K";
|
||||
public override IconUsage? Icon => OsuIcon.ModFiveKeys;
|
||||
public override LocalisableString Description => @"Play with five keys.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override int KeyCount => 6;
|
||||
public override string Name => "Six Keys";
|
||||
public override string Acronym => "6K";
|
||||
public override IconUsage? Icon => OsuIcon.ModSixKeys;
|
||||
public override LocalisableString Description => @"Play with six keys.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override int KeyCount => 7;
|
||||
public override string Name => "Seven Keys";
|
||||
public override string Acronym => "7K";
|
||||
public override IconUsage? Icon => OsuIcon.ModSevenKeys;
|
||||
public override LocalisableString Description => @"Play with seven keys.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override int KeyCount => 8;
|
||||
public override string Name => "Eight Keys";
|
||||
public override string Acronym => "8K";
|
||||
public override IconUsage? Icon => OsuIcon.ModEightKeys;
|
||||
public override LocalisableString Description => @"Play with eight keys.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
@@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override int KeyCount => 9;
|
||||
public override string Name => "Nine Keys";
|
||||
public override string Acronym => "9K";
|
||||
public override IconUsage? Icon => OsuIcon.ModNineKeys;
|
||||
public override LocalisableString Description => @"Play with nine keys.";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
@@ -26,6 +28,8 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
|
||||
public override double ScoreMultiplier => 0.9;
|
||||
|
||||
public override IconUsage? Icon => OsuIcon.ModNoRelease;
|
||||
|
||||
public override ModType Type => ModType.DifficultyReduction;
|
||||
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ManiaModHoldOff) };
|
||||
@@ -80,7 +84,9 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
StartTime = hold.StartTime;
|
||||
Duration = hold.Duration;
|
||||
Column = hold.Column;
|
||||
Samples = hold.Samples;
|
||||
NodeSamples = hold.NodeSamples;
|
||||
PlaySlidingSamples = hold.PlaySlidingSamples;
|
||||
}
|
||||
|
||||
protected override void CreateNestedHitObjects(CancellationToken cancellationToken)
|
||||
|
||||
@@ -355,7 +355,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
|
||||
private void updateSlidingSample(ValueChangedEvent<bool> tracking)
|
||||
{
|
||||
if (tracking.NewValue)
|
||||
if (tracking.NewValue && HitObject.PlaySlidingSamples)
|
||||
slidingSample?.Play();
|
||||
else
|
||||
slidingSample?.Stop();
|
||||
|
||||
@@ -86,6 +86,11 @@ namespace osu.Game.Rulesets.Mania.Objects
|
||||
/// </summary>
|
||||
public HoldNoteBody Body { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether sliding samples should be played when held.
|
||||
/// </summary>
|
||||
public bool PlaySlidingSamples { get; init; }
|
||||
|
||||
public override double MaximumJudgementOffset => Tail.MaximumJudgementOffset;
|
||||
|
||||
protected override void CreateNestedHitObjects(CancellationToken cancellationToken)
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
public readonly Bindable<Color4> AccentColour = new Bindable<Color4>(Color4.Black);
|
||||
|
||||
private IBindable<ManiaMobileLayout> mobilePlayStyle = null!;
|
||||
private IBindable<bool> touchOverlay = null!;
|
||||
|
||||
private float leftColumnSpacing;
|
||||
private float rightColumnSpacing;
|
||||
@@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
RegisterPool<HoldNoteBody, DrawableHoldNoteBody>(10, 50);
|
||||
|
||||
if (rulesetConfig != null)
|
||||
mobilePlayStyle = rulesetConfig.GetBindable<ManiaMobileLayout>(ManiaRulesetSetting.MobileLayout);
|
||||
touchOverlay = rulesetConfig.GetBindable<bool>(ManiaRulesetSetting.TouchOverlay);
|
||||
}
|
||||
|
||||
private void onSourceChanged()
|
||||
@@ -214,7 +214,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
protected override bool OnTouchDown(TouchDownEvent e)
|
||||
{
|
||||
// if touch overlay is visible, disallow columns from handling touch directly.
|
||||
if (mobilePlayStyle.Value == ManiaMobileLayout.LandscapeWithOverlay)
|
||||
if (touchOverlay.Value)
|
||||
return false;
|
||||
|
||||
maniaInputManager?.KeyBindingContainer.TriggerPressed(Action.Value);
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
float mobileAdjust = 1f;
|
||||
|
||||
if (RuntimeInfo.IsMobile && mobileLayout.Value == ManiaMobileLayout.Landscape)
|
||||
if (RuntimeInfo.IsMobile && mobileLayout.Value == ManiaMobileLayout.LandscapeExpandedColumns)
|
||||
{
|
||||
// GridContainer+CellContainer containing this stage (gets split up for dual stages).
|
||||
Vector2? containingCell = this.FindClosestParent<Stage>()?.Parent?.DrawSize;
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
private readonly Bindable<ManiaScrollingDirection> configDirection = new Bindable<ManiaScrollingDirection>();
|
||||
private readonly BindableDouble configScrollSpeed = new BindableDouble();
|
||||
private readonly Bindable<ManiaMobileLayout> mobileLayout = new Bindable<ManiaMobileLayout>();
|
||||
private readonly Bindable<bool> touchOverlay = new Bindable<bool>();
|
||||
|
||||
public double TargetTimeRange { get; protected set; }
|
||||
|
||||
@@ -122,24 +123,23 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
Config.BindWith(ManiaRulesetSetting.MobileLayout, mobileLayout);
|
||||
mobileLayout.BindValueChanged(_ => updateMobileLayout(), true);
|
||||
|
||||
Config.BindWith(ManiaRulesetSetting.TouchOverlay, touchOverlay);
|
||||
touchOverlay.BindValueChanged(_ => updateMobileLayout(), true);
|
||||
}
|
||||
|
||||
private ManiaTouchInputArea? touchInputArea;
|
||||
|
||||
private void updateMobileLayout()
|
||||
{
|
||||
switch (mobileLayout.Value)
|
||||
if (touchOverlay.Value)
|
||||
KeyBindingInputManager.Add(touchInputArea = new ManiaTouchInputArea(this));
|
||||
else
|
||||
{
|
||||
case ManiaMobileLayout.LandscapeWithOverlay:
|
||||
KeyBindingInputManager.Add(touchInputArea = new ManiaTouchInputArea(this));
|
||||
break;
|
||||
if (touchInputArea != null)
|
||||
KeyBindingInputManager.Remove(touchInputArea, true);
|
||||
|
||||
default:
|
||||
if (touchInputArea != null)
|
||||
KeyBindingInputManager.Remove(touchInputArea, true);
|
||||
|
||||
touchInputArea = null;
|
||||
break;
|
||||
touchInputArea = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,13 +42,22 @@ namespace osu.Game.Rulesets.Mania
|
||||
var bindings = new List<KeyBinding>();
|
||||
|
||||
for (int i = LeftKeys.Length - columns / 2; i < LeftKeys.Length; i++)
|
||||
bindings.Add(new KeyBinding(LeftKeys[i], currentAction++));
|
||||
{
|
||||
bindings.Add(new KeyBinding(LeftKeys[i], currentAction));
|
||||
bindings.Add(new KeyBinding(InputKey.None, currentAction++));
|
||||
}
|
||||
|
||||
if (columns % 2 == 1)
|
||||
bindings.Add(new KeyBinding(SpecialKey, currentAction++));
|
||||
{
|
||||
bindings.Add(new KeyBinding(SpecialKey, currentAction));
|
||||
bindings.Add(new KeyBinding(InputKey.None, currentAction++));
|
||||
}
|
||||
|
||||
for (int i = 0; i < columns / 2; i++)
|
||||
bindings.Add(new KeyBinding(RightKeys[i], currentAction++));
|
||||
{
|
||||
bindings.Add(new KeyBinding(RightKeys[i], currentAction));
|
||||
bindings.Add(new KeyBinding(InputKey.None, currentAction++));
|
||||
}
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Osu.Edit;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
using osu.Game.Tests.Visual;
|
||||
@@ -284,5 +285,70 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
&& Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.01);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGridPlacementCommittedByDragSelection()
|
||||
{
|
||||
AddStep("add circle", () => EditorBeatmap.Add(new HitCircle
|
||||
{
|
||||
Position = new Vector2(64, 64),
|
||||
StartTime = EditorClock.CurrentTime,
|
||||
}));
|
||||
|
||||
AddStep("select circle tool", () => InputManager.Key(Key.Number2));
|
||||
AddStep("select grid tool", () => InputManager.Key(Key.Number5));
|
||||
AddStep("move cursor to centre", () => InputManager.MoveMouseTo(Editor));
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
AddStep("move cursor to (-1, -1)", () =>
|
||||
{
|
||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||
InputManager.MoveMouseTo(composer.ToScreenSpace(new Vector2(-1, -1)));
|
||||
});
|
||||
AddStep("drag to center", () =>
|
||||
{
|
||||
InputManager.PressButton(MouseButton.Left);
|
||||
InputManager.MoveMouseTo(Editor);
|
||||
});
|
||||
AddStep("release left", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||
|
||||
AddAssert("one selection", () => Editor.ChildrenOfType<OsuSelectionHandler>().Single().SelectedBlueprints, () => Has.One.Items);
|
||||
AddAssert("selection is circle", () => Editor.ChildrenOfType<OsuSelectionHandler>().Single().SelectedBlueprints.Single(), Is.TypeOf<HitCircleSelectionBlueprint>);
|
||||
|
||||
AddStep("move cursor to slider", () =>
|
||||
{
|
||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||
InputManager.MoveMouseTo(composer.ToScreenSpace(((Slider)EditorBeatmap.HitObjects.ElementAt(1)).EndPosition + new Vector2(1, 1)));
|
||||
});
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddAssert("one selection", () => Editor.ChildrenOfType<OsuSelectionHandler>().Single().SelectedBlueprints, () => Has.One.Items);
|
||||
AddAssert("selection is slider", () => Editor.ChildrenOfType<OsuSelectionHandler>().Single().SelectedBlueprints.Single(), Is.TypeOf<SliderSelectionBlueprint>);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGridPlacementRevertsToLastTool()
|
||||
{
|
||||
AddStep("select circle tool", () => InputManager.Key(Key.Number2));
|
||||
AddStep("select grid tool", () => InputManager.Key(Key.Number5));
|
||||
AddStep("move cursor to centre", () => InputManager.MoveMouseTo(Editor));
|
||||
AddStep("start grid placement", () => InputManager.Click(MouseButton.Left));
|
||||
AddStep("end grid placement", () => InputManager.Click(MouseButton.Left));
|
||||
AddAssert("tool reverted to circle", () => getComposer().BlueprintContainer.CurrentTool, Is.TypeOf<HitCircleCompositionTool>);
|
||||
|
||||
HitObjectComposer getComposer() => Editor.ChildrenOfType<HitObjectComposer>().Single();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGridPlacementDoesNotOverrideToolChange()
|
||||
{
|
||||
AddStep("select circle tool", () => InputManager.Key(Key.Number2));
|
||||
AddStep("select grid tool", () => InputManager.Key(Key.Number5));
|
||||
AddStep("move cursor to centre", () => InputManager.MoveMouseTo(Editor));
|
||||
AddStep("start grid placement", () => InputManager.Click(MouseButton.Left));
|
||||
AddStep("select circle tool again", () => InputManager.Key(Key.Number2));
|
||||
AddAssert("circle tool selected", () => getComposer().BlueprintContainer.CurrentTool, Is.TypeOf<HitCircleCompositionTool>);
|
||||
|
||||
HitObjectComposer getComposer() => Editor.ChildrenOfType<HitObjectComposer>().Single();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,26 +32,6 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
[Test]
|
||||
public void TestComboBasedSize([Values] bool comboBasedSize) => CreateModTest(new ModTestData { Mod = new OsuModFlashlight { ComboBasedSize = { Value = comboBasedSize } }, PassCondition = () => true });
|
||||
|
||||
[Test]
|
||||
public void TestPlayfieldBasedSize()
|
||||
{
|
||||
OsuModFlashlight flashlight;
|
||||
CreateModTest(new ModTestData
|
||||
{
|
||||
Mods = [flashlight = new OsuModFlashlight(), new OsuModBarrelRoll()],
|
||||
PassCondition = () =>
|
||||
{
|
||||
var flashlightOverlay = Player.DrawableRuleset.Overlays
|
||||
.ChildrenOfType<ModFlashlight<OsuHitObject>.Flashlight>()
|
||||
.First();
|
||||
|
||||
// the combo check is here because the flashlight radius decreases for the first time at 100 combo
|
||||
// and hardcoding it here eliminates the need to meddle in flashlight internals further by e.g. exposing `GetComboScaleFor()`
|
||||
return flashlightOverlay.GetSize() < flashlight.DefaultFlashlightSize && Player.GameplayState.ScoreProcessor.Combo.Value < 100;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSliderDimsOnlyAfterStartTime()
|
||||
{
|
||||
|
||||
@@ -22,8 +22,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
var ruleset = new OsuRuleset();
|
||||
var difficulty = new BeatmapDifficulty { ApproachRate = originalApproachRate };
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, []);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, []);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(originalApproachRate));
|
||||
}
|
||||
@@ -33,8 +34,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
var ruleset = new OsuRuleset();
|
||||
var difficulty = new BeatmapDifficulty { OverallDifficulty = originalOverallDifficulty };
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, []);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, []);
|
||||
|
||||
Assert.That(adjustedDifficulty.OverallDifficulty, Is.EqualTo(originalOverallDifficulty));
|
||||
}
|
||||
@@ -44,8 +46,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
var ruleset = new OsuRuleset();
|
||||
var difficulty = new BeatmapDifficulty();
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, [new OsuModHalfTime()]);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, [new OsuModHalfTime()]);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(1.67).Within(0.01));
|
||||
Assert.That(adjustedDifficulty.OverallDifficulty, Is.EqualTo(2.22).Within(0.01));
|
||||
@@ -56,8 +59,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
var ruleset = new OsuRuleset();
|
||||
var difficulty = new BeatmapDifficulty();
|
||||
var beatmapInfo = new BeatmapInfo { Difficulty = difficulty };
|
||||
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(difficulty, [new OsuModDoubleTime()]);
|
||||
var adjustedDifficulty = ruleset.GetAdjustedDisplayDifficulty(beatmapInfo, [new OsuModDoubleTime()]);
|
||||
|
||||
Assert.That(adjustedDifficulty.ApproachRate, Is.EqualTo(7.67).Within(0.01));
|
||||
Assert.That(adjustedDifficulty.OverallDifficulty, Is.EqualTo(7.77).Within(0.01));
|
||||
|
||||
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |