diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index a44c97c3cf..44a9dd2f1f 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty if (Attributes.ApproachRate > 10.33) approachRateFactor += 0.4 * (Attributes.ApproachRate - 10.33); else if (Attributes.ApproachRate < 8.0) - approachRateFactor += 0.1 * (8.0 - Attributes.ApproachRate); + approachRateFactor += 0.01 * (8.0 - Attributes.ApproachRate); aimValue *= 1.0 + Math.Min(approachRateFactor, approachRateFactor * (totalHits / 1000.0)); diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs index 3d77fb05db..b6db333dc9 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoBeatmapConversionTest.cs @@ -23,6 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Tests [TestCase("sample-to-type-conversions")] [TestCase("slider-conversion-v6")] [TestCase("slider-conversion-v14")] + [TestCase("slider-generating-drumroll-2")] public void Test(string name) => base.Test(name); protected override IEnumerable CreateConvertValue(HitObject hitObject) diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 1214c594aa..b51f096d7d 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -160,7 +160,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps } } - private bool shouldConvertSliderToHits(HitObject obj, IBeatmap beatmap, IHasDistance distanceData, out double taikoDuration, out double tickSpacing) + private bool shouldConvertSliderToHits(HitObject obj, IBeatmap beatmap, IHasDistance distanceData, out int taikoDuration, out double tickSpacing) { // DO NOT CHANGE OR REFACTOR ANYTHING IN HERE WITHOUT TESTING AGAINST _ALL_ BEATMAPS. // Some of these calculations look redundant, but they are not - extremely small floating point errors are introduced to maintain 1:1 compatibility with stable. @@ -185,7 +185,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps // The velocity and duration of the taiko hit object - calculated as the velocity of a drum roll. double taikoVelocity = sliderScoringPointDistance * beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate; - taikoDuration = distance / taikoVelocity * beatLength; + taikoDuration = (int)(distance / taikoVelocity * beatLength); if (isForCurrentRuleset) { @@ -200,7 +200,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps beatLength = timingPoint.BeatLength; // If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat - tickSpacing = Math.Min(beatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, taikoDuration / spans); + tickSpacing = Math.Min(beatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, (double)taikoDuration / spans); return tickSpacing > 0 && distance / osuVelocity * 1000 < 2 * beatLength; diff --git a/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/slider-conversion-v14-expected-conversion.json b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/slider-conversion-v14-expected-conversion.json index 6a6063cb74..b7ad128cab 100644 --- a/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/slider-conversion-v14-expected-conversion.json +++ b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/slider-conversion-v14-expected-conversion.json @@ -1,7 +1,9 @@ { - "Mappings": [{ + "Mappings": [ + { "StartTime": 2000, - "Objects": [{ + "Objects": [ + { "StartTime": 2000, "EndTime": 2000, "IsRim": false, @@ -23,7 +25,8 @@ }, { "StartTime": 4000, - "Objects": [{ + "Objects": [ + { "StartTime": 4000, "EndTime": 4000, "IsRim": false, @@ -45,7 +48,8 @@ }, { "StartTime": 6000, - "Objects": [{ + "Objects": [ + { "StartTime": 6000, "EndTime": 6000, "IsRim": true, @@ -76,300 +80,13 @@ }, { "StartTime": 8000, - "Objects": [{ + "Objects": [ + { "StartTime": 8000, - "EndTime": 8000, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8026, - "EndTime": 8026, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8053, - "EndTime": 8053, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8080, - "EndTime": 8080, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8107, - "EndTime": 8107, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8133, - "EndTime": 8133, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8160, - "EndTime": 8160, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8187, - "EndTime": 8187, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8214, - "EndTime": 8214, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8241, - "EndTime": 8241, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8267, - "EndTime": 8267, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8294, - "EndTime": 8294, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8321, - "EndTime": 8321, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8348, - "EndTime": 8348, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8374, - "EndTime": 8374, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8401, - "EndTime": 8401, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8428, - "EndTime": 8428, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8455, - "EndTime": 8455, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8482, - "EndTime": 8482, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8508, - "EndTime": 8508, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8535, - "EndTime": 8535, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8562, - "EndTime": 8562, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8589, - "EndTime": 8589, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8615, - "EndTime": 8615, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8642, - "EndTime": 8642, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8669, - "EndTime": 8669, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8696, - "EndTime": 8696, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8723, - "EndTime": 8723, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8749, - "EndTime": 8749, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8776, - "EndTime": 8776, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8803, - "EndTime": 8803, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8830, - "EndTime": 8830, - "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, - "IsSwell": false, - "IsStrong": false - }, - { - "StartTime": 8857, "EndTime": 8857, "IsRim": false, - "IsCentre": true, - "IsDrumRoll": false, + "IsCentre": false, + "IsDrumRoll": true, "IsSwell": false, "IsStrong": false } diff --git a/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/slider-generating-drumroll-2-expected-conversion.json b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/slider-generating-drumroll-2-expected-conversion.json new file mode 100644 index 0000000000..b4ee98c86a --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/slider-generating-drumroll-2-expected-conversion.json @@ -0,0 +1,18 @@ +{ + "Mappings": [ + { + "StartTime": 51532, + "Objects": [ + { + "StartTime": 51532, + "EndTime": 52301, + "IsRim": false, + "IsCentre": false, + "IsDrumRoll": true, + "IsSwell": false, + "IsStrong": false + } + ] + } + ] +} \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/slider-generating-drumroll-2.osu b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/slider-generating-drumroll-2.osu new file mode 100644 index 0000000000..d81b09ee26 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Resources/Testing/Beatmaps/slider-generating-drumroll-2.osu @@ -0,0 +1,19 @@ +osu file format v14 + +[General] +Mode: 0 + +[Difficulty] +HPDrainRate:2 +CircleSize:3.2 +OverallDifficulty:2 +ApproachRate:3 +SliderMultiplier:0.999999999999999 +SliderTickRate:1 + +[TimingPoints] +763,384.615384615385,4,2,0,70,1,0 +49993,-90.9090909090909,4,2,0,75,0,1 + +[HitObjects] +51,245,51532,2,0,P|18:150|17:122,2,110.000003356934,0|8|0,0:0|0:0|0:0,0:0:0:0: diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs index 650b4c5412..70b260c84c 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneSetupScreen.cs @@ -2,7 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Game.Tournament.Screens; +using osu.Game.Tournament.Screens.Setup; namespace osu.Game.Tournament.Tests.Screens { diff --git a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs index 6e63b2d799..b422227788 100644 --- a/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs +++ b/osu.Game.Tournament.Tests/Screens/TestSceneStablePathSelectScreen.cs @@ -1,7 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Tournament.Screens; +using osu.Game.Tournament.Screens.Setup; namespace osu.Game.Tournament.Tests.Screens { diff --git a/osu.Game.Tournament/IO/TournamentStorage.cs b/osu.Game.Tournament/IO/TournamentStorage.cs index 2e8a6ce667..2ba1b6be8f 100644 --- a/osu.Game.Tournament/IO/TournamentStorage.cs +++ b/osu.Game.Tournament/IO/TournamentStorage.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.IO; using System.IO; +using System.Collections.Generic; using osu.Game.Tournament.Configuration; namespace osu.Game.Tournament.IO @@ -13,25 +15,39 @@ namespace osu.Game.Tournament.IO { private const string default_tournament = "default"; private readonly Storage storage; + private readonly Storage allTournaments; private readonly TournamentStorageManager storageConfig; + public readonly Bindable CurrentTournament; public TournamentStorage(Storage storage) : base(storage.GetStorageForDirectory("tournaments"), string.Empty) { this.storage = storage; + allTournaments = UnderlyingStorage; storageConfig = new TournamentStorageManager(storage); if (storage.Exists("tournament.ini")) { - ChangeTargetStorage(UnderlyingStorage.GetStorageForDirectory(storageConfig.Get(StorageConfig.CurrentTournament))); + ChangeTargetStorage(allTournaments.GetStorageForDirectory(storageConfig.Get(StorageConfig.CurrentTournament))); } else - Migrate(UnderlyingStorage.GetStorageForDirectory(default_tournament)); + Migrate(allTournaments.GetStorageForDirectory(default_tournament)); + CurrentTournament = storageConfig.GetBindable(StorageConfig.CurrentTournament); Logger.Log("Using tournament storage: " + GetFullPath(string.Empty)); + + CurrentTournament.BindValueChanged(updateTournament); } + private void updateTournament(ValueChangedEvent newTournament) + { + ChangeTargetStorage(allTournaments.GetStorageForDirectory(newTournament.NewValue)); + Logger.Log("Changing tournament storage: " + GetFullPath(string.Empty)); + } + + public IEnumerable ListTournaments() => allTournaments.GetDirectories(string.Empty); + public override void Migrate(Storage newStorage) { // this migration only happens once on moving to the per-tournament storage system. diff --git a/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs b/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs new file mode 100644 index 0000000000..cfdf9c99ae --- /dev/null +++ b/osu.Game.Tournament/Screens/Setup/ActionableInfo.cs @@ -0,0 +1,72 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Graphics.UserInterfaceV2; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tournament.Screens.Setup +{ + internal class ActionableInfo : LabelledDrawable + { + protected OsuButton Button; + + public ActionableInfo() + : base(true) + { + } + + public string ButtonText + { + set => Button.Text = value; + } + + public string Value + { + set => valueText.Text = value; + } + + public bool Failing + { + set => valueText.Colour = value ? Color4.Red : Color4.White; + } + + public Action Action; + + private TournamentSpriteText valueText; + protected FillFlowContainer FlowContainer; + + protected override Drawable CreateComponent() => new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + valueText = new TournamentSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + }, + FlowContainer = new FillFlowContainer + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + Button = new TriangleButton + { + Size = new Vector2(100, 40), + Action = () => Action?.Invoke() + } + } + } + } + }; + } +} diff --git a/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs b/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs new file mode 100644 index 0000000000..4b518ea7c7 --- /dev/null +++ b/osu.Game.Tournament/Screens/Setup/ResolutionSelector.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Tournament.Screens.Setup +{ + internal class ResolutionSelector : ActionableInfo + { + private const int minimum_window_height = 480; + private const int maximum_window_height = 2160; + + public new Action Action; + + private OsuNumberBox numberBox; + + protected override Drawable CreateComponent() + { + var drawable = base.CreateComponent(); + FlowContainer.Insert(-1, numberBox = new OsuNumberBox + { + Text = "1080", + Width = 100 + }); + + base.Action = () => + { + if (string.IsNullOrEmpty(numberBox.Text)) + return; + + // box contains text + if (!int.TryParse(numberBox.Text, out var number)) + { + // at this point, the only reason we can arrive here is if the input number was too big to parse into an int + // so clamp to max allowed value + number = maximum_window_height; + } + else + { + number = Math.Clamp(number, minimum_window_height, maximum_window_height); + } + + // in case number got clamped, reset number in numberBox + numberBox.Text = number.ToString(); + + Action?.Invoke(number); + }; + return drawable; + } + } +} diff --git a/osu.Game.Tournament/Screens/SetupScreen.cs b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs similarity index 60% rename from osu.Game.Tournament/Screens/SetupScreen.cs rename to osu.Game.Tournament/Screens/Setup/SetupScreen.cs index e78d3a9e83..5d8f0405ca 100644 --- a/osu.Game.Tournament/Screens/SetupScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/SetupScreen.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . 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.Drawing; using osu.Framework.Allocation; @@ -17,9 +16,8 @@ using osu.Game.Rulesets; using osu.Game.Tournament.IPC; using osu.Game.Tournament.Models; using osuTK; -using osuTK.Graphics; -namespace osu.Game.Tournament.Screens +namespace osu.Game.Tournament.Screens.Setup { public class SetupScreen : TournamentScreen, IProvideVideo { @@ -64,9 +62,6 @@ namespace osu.Game.Tournament.Screens reload(); } - [Resolved] - private Framework.Game game { get; set; } - private void reload() { var fileBasedIpc = ipc as FileBasedIPC; @@ -111,6 +106,11 @@ namespace osu.Game.Tournament.Screens Items = rulesets.AvailableRulesets, Current = LadderInfo.Ruleset, }, + new TournamentSwitcher + { + Label = "Current tournament", + Description = "Changes the background videos and bracket to match the selected tournament. This requires a restart to apply changes.", + }, resolution = new ResolutionSelector { Label = "Stream area resolution", @@ -151,108 +151,5 @@ namespace osu.Game.Tournament.Screens Width = 0.5f, }; } - - private class ActionableInfo : LabelledDrawable - { - private OsuButton button; - - public ActionableInfo() - : base(true) - { - } - - public string ButtonText - { - set => button.Text = value; - } - - public string Value - { - set => valueText.Text = value; - } - - public bool Failing - { - set => valueText.Colour = value ? Color4.Red : Color4.White; - } - - public Action Action; - - private TournamentSpriteText valueText; - protected FillFlowContainer FlowContainer; - - protected override Drawable CreateComponent() => new Container - { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Children = new Drawable[] - { - valueText = new TournamentSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - }, - FlowContainer = new FillFlowContainer - { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(10, 0), - Children = new Drawable[] - { - button = new TriangleButton - { - Size = new Vector2(100, 40), - Action = () => Action?.Invoke() - } - } - } - } - }; - } - - private class ResolutionSelector : ActionableInfo - { - private const int minimum_window_height = 480; - private const int maximum_window_height = 2160; - - public new Action Action; - - private OsuNumberBox numberBox; - - protected override Drawable CreateComponent() - { - var drawable = base.CreateComponent(); - FlowContainer.Insert(-1, numberBox = new OsuNumberBox - { - Text = "1080", - Width = 100 - }); - - base.Action = () => - { - if (string.IsNullOrEmpty(numberBox.Text)) - return; - - // box contains text - if (!int.TryParse(numberBox.Text, out var number)) - { - // at this point, the only reason we can arrive here is if the input number was too big to parse into an int - // so clamp to max allowed value - number = maximum_window_height; - } - else - { - number = Math.Clamp(number, minimum_window_height, maximum_window_height); - } - - // in case number got clamped, reset number in numberBox - numberBox.Text = number.ToString(); - - Action?.Invoke(number); - }; - return drawable; - } - } } } diff --git a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs similarity index 99% rename from osu.Game.Tournament/Screens/StablePathSelectScreen.cs rename to osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs index 717b43f704..03f79b644f 100644 --- a/osu.Game.Tournament/Screens/StablePathSelectScreen.cs +++ b/osu.Game.Tournament/Screens/Setup/StablePathSelectScreen.cs @@ -13,11 +13,11 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays; -using osu.Game.Tournament.IPC; using osu.Game.Tournament.Components; +using osu.Game.Tournament.IPC; using osuTK; -namespace osu.Game.Tournament.Screens +namespace osu.Game.Tournament.Screens.Setup { public class StablePathSelectScreen : TournamentScreen { diff --git a/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs new file mode 100644 index 0000000000..74c872646c --- /dev/null +++ b/osu.Game.Tournament/Screens/Setup/TournamentSwitcher.cs @@ -0,0 +1,44 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Tournament.IO; + +namespace osu.Game.Tournament.Screens.Setup +{ + internal class TournamentSwitcher : ActionableInfo + { + private OsuDropdown dropdown; + + [Resolved] + private TournamentGameBase game { get; set; } + + [BackgroundDependencyLoader] + private void load(TournamentStorage storage) + { + string startupTournament = storage.CurrentTournament.Value; + + dropdown.Current = storage.CurrentTournament; + dropdown.Items = storage.ListTournaments(); + dropdown.Current.BindValueChanged(v => Button.Enabled.Value = v.NewValue != startupTournament, true); + + Action = () => game.GracefullyExit(); + + ButtonText = "Close osu!"; + } + + protected override Drawable CreateComponent() + { + var drawable = base.CreateComponent(); + + FlowContainer.Insert(-1, dropdown = new OsuDropdown + { + Width = 510 + }); + + return drawable; + } + } +} diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index bc36f27e5b..97c950261b 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -40,6 +40,8 @@ namespace osu.Game.Tournament Resources.AddStore(new DllResourceStore(typeof(TournamentGameBase).Assembly)); dependencies.CacheAs(storage = new TournamentStorage(baseStorage)); + dependencies.CacheAs(storage); + dependencies.Cache(new TournamentVideoResourceStore(storage)); Textures.AddStore(new TextureLoaderStore(new StorageBackedResourceStore(storage))); diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index 870ea466cc..ced1a8ec72 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -19,6 +19,7 @@ using osu.Game.Tournament.Screens.Gameplay; using osu.Game.Tournament.Screens.Ladder; using osu.Game.Tournament.Screens.MapPool; using osu.Game.Tournament.Screens.Schedule; +using osu.Game.Tournament.Screens.Setup; using osu.Game.Tournament.Screens.Showcase; using osu.Game.Tournament.Screens.TeamIntro; using osu.Game.Tournament.Screens.TeamWin; diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 069a25b83d..2fb24c24e0 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -164,12 +164,13 @@ namespace osu.Game.Beatmaps.Formats /// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it. /// DO NOT USE THIS UNLESS 100% SURE. /// - public float BpmMultiplier { get; private set; } + public double BpmMultiplier { get; private set; } public LegacyDifficultyControlPoint(double beatLength) : this() { - BpmMultiplier = beatLength < 0 ? Math.Clamp((float)-beatLength, 10, 10000) / 100f : 1; + // Note: In stable, the division occurs on floats, but with compiler optimisations turned on actually seems to occur on doubles via some .NET black magic (possibly inlining?). + BpmMultiplier = beatLength < 0 ? Math.Clamp((float)-beatLength, 10, 10000) / 100.0 : 1; } public LegacyDifficultyControlPoint() diff --git a/osu.Game/Graphics/UserInterface/DownloadButton.cs b/osu.Game/Graphics/UserInterface/DownloadButton.cs index da6c95299e..5168ff646b 100644 --- a/osu.Game/Graphics/UserInterface/DownloadButton.cs +++ b/osu.Game/Graphics/UserInterface/DownloadButton.cs @@ -73,7 +73,7 @@ namespace osu.Game.Graphics.UserInterface TooltipText = "Downloading..."; break; - case DownloadState.Downloaded: + case DownloadState.Importing: background.FadeColour(colours.Yellow, 500, Easing.InOutExpo); TooltipText = "Importing"; break; diff --git a/osu.Game/Online/DownloadState.cs b/osu.Game/Online/DownloadState.cs index 72efbc286e..a58c40d16a 100644 --- a/osu.Game/Online/DownloadState.cs +++ b/osu.Game/Online/DownloadState.cs @@ -7,7 +7,7 @@ namespace osu.Game.Online { NotDownloaded, Downloading, - Downloaded, + Importing, LocallyAvailable } } diff --git a/osu.Game/Online/DownloadTrackingComposite.cs b/osu.Game/Online/DownloadTrackingComposite.cs index bed95344c6..7a64c9002d 100644 --- a/osu.Game/Online/DownloadTrackingComposite.cs +++ b/osu.Game/Online/DownloadTrackingComposite.cs @@ -106,7 +106,7 @@ namespace osu.Game.Online { if (attachedRequest.Progress == 1) { - State.Value = DownloadState.Downloaded; + State.Value = DownloadState.Importing; Progress.Value = 1; } else @@ -125,7 +125,7 @@ namespace osu.Game.Online } } - private void onRequestSuccess(string _) => Schedule(() => State.Value = DownloadState.Downloaded); + private void onRequestSuccess(string _) => Schedule(() => State.Value = DownloadState.Importing); private void onRequestProgress(float progress) => Schedule(() => Progress.Value = progress); diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 36e3078653..442e8a9401 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -942,18 +942,6 @@ namespace osu.Game return base.OnExiting(); } - /// - /// Use to programatically exit the game as if the user was triggering via alt-f4. - /// Will keep persisting until an exit occurs (exit may be blocked multiple times). - /// - public void GracefullyExit() - { - if (!OnExiting()) - Exit(); - else - Scheduler.AddDelayed(GracefullyExit, 2000); - } - protected override void UpdateAfterChildren() { base.UpdateAfterChildren(); diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index a755fdb379..949e3603c6 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -421,6 +421,18 @@ namespace osu.Game : new OsuConfigManager(Storage); } + /// + /// Use to programatically exit the game as if the user was triggering via alt-f4. + /// Will keep persisting until an exit occurs (exit may be blocked multiple times). + /// + public void GracefullyExit() + { + if (!OnExiting()) + Exit(); + else + Scheduler.AddDelayed(GracefullyExit, 2000); + } + protected override Storage CreateStorage(GameHost host, Storage defaultStorage) => new OsuStorage(host, defaultStorage); private readonly List fileImporters = new List(); diff --git a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs index 001ca801d9..cec1a5ac12 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs @@ -57,7 +57,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels switch (State.Value) { case DownloadState.Downloading: - case DownloadState.Downloaded: + case DownloadState.Importing: shakeContainer.Shake(); break; diff --git a/osu.Game/Overlays/BeatmapListing/Panels/DownloadProgressBar.cs b/osu.Game/Overlays/BeatmapListing/Panels/DownloadProgressBar.cs index 93cf8799b5..6a2f2e4569 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/DownloadProgressBar.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/DownloadProgressBar.cs @@ -50,7 +50,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); break; - case DownloadState.Downloaded: + case DownloadState.Importing: progressBar.FadeIn(400, Easing.OutQuint); progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index 56c0052bfe..cffff86a64 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -126,7 +126,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons }; break; - case DownloadState.Downloaded: + case DownloadState.Importing: textSprites.Children = new Drawable[] { new OsuSpriteText diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 321e496511..c17901bb3f 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -287,7 +287,7 @@ namespace osu.Game.Overlays.BeatmapSet break; case DownloadState.Downloading: - case DownloadState.Downloaded: + case DownloadState.Importing: // temporary to avoid showing two buttons for maps with novideo. will be fixed in new beatmap overlay design. downloadButtonsContainer.Child = new HeaderDownloadButton(BeatmapSet.Value); break; diff --git a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs index d94346cb72..21ac017685 100644 --- a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs +++ b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs @@ -37,6 +37,8 @@ namespace osu.Game.Rulesets.Judgements { JudgementText = new OsuSpriteText { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Text = Result.GetDescription().ToUpperInvariant(), Colour = colours.ForHitResult(Result), Font = OsuFont.Numeric.With(size: 20), diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index e539b315e4..80991569dc 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -241,8 +241,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer void endOperation() { - Debug.Assert(readyClickOperation != null); - readyClickOperation.Dispose(); + readyClickOperation?.Dispose(); readyClickOperation = null; } } @@ -255,9 +254,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer StartPlay(() => new MultiplayerPlayer(SelectedItem.Value, userIds)); - Debug.Assert(readyClickOperation != null); - - readyClickOperation.Dispose(); + readyClickOperation?.Dispose(); readyClickOperation = null; } diff --git a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs index b76842f405..18b8649a59 100644 --- a/osu.Game/Screens/Ranking/ReplayDownloadButton.cs +++ b/osu.Game/Screens/Ranking/ReplayDownloadButton.cs @@ -63,7 +63,7 @@ namespace osu.Game.Screens.Ranking scores.Download(Model.Value); break; - case DownloadState.Downloaded: + case DownloadState.Importing: case DownloadState.Downloading: shakeContainer.Shake(); break;