diff --git a/LICENCE b/LICENCE index 797be26fff..a11a7ce75b 100644 --- a/LICENCE +++ b/LICENCE @@ -1,4 +1,4 @@ -Copyright (c) 2007-2017 ppy Pty Ltd . +Copyright (c) 2007-2018 ppy Pty Ltd . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/osu.Desktop.Deploy/App.config b/osu.Desktop.Deploy/App.config index 8218f31a68..f6673fef1a 100644 --- a/osu.Desktop.Deploy/App.config +++ b/osu.Desktop.Deploy/App.config @@ -1,6 +1,6 @@  diff --git a/osu.Desktop.Deploy/GitHubObject.cs b/osu.Desktop.Deploy/GitHubObject.cs index a91e7273a4..59c15f8015 100644 --- a/osu.Desktop.Deploy/GitHubObject.cs +++ b/osu.Desktop.Deploy/GitHubObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Newtonsoft.Json; @@ -13,4 +13,4 @@ namespace osu.Desktop.Deploy [JsonProperty(@"name")] public string Name; } -} \ No newline at end of file +} diff --git a/osu.Desktop.Deploy/GitHubRelease.cs b/osu.Desktop.Deploy/GitHubRelease.cs index fe372a7825..22820b047a 100644 --- a/osu.Desktop.Deploy/GitHubRelease.cs +++ b/osu.Desktop.Deploy/GitHubRelease.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Newtonsoft.Json; @@ -25,4 +25,4 @@ namespace osu.Desktop.Deploy [JsonProperty(@"upload_url")] public string UploadUrl; } -} \ No newline at end of file +} diff --git a/osu.Desktop.Deploy/Program.cs b/osu.Desktop.Deploy/Program.cs index 48cc9c7581..88d6ffbca7 100644 --- a/osu.Desktop.Deploy/Program.cs +++ b/osu.Desktop.Deploy/Program.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index f2906f043c..22ef8f1a34 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -43,7 +43,7 @@ namespace osu.Desktop { protected override string LocateBasePath() { - Func checkExists = p => Directory.Exists(Path.Combine(p, "Songs")); + bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")); string stableInstallPath; diff --git a/osu.Desktop/OsuTestBrowser.cs b/osu.Desktop/OsuTestBrowser.cs index 23617de1c0..7aae2604af 100644 --- a/osu.Desktop/OsuTestBrowser.cs +++ b/osu.Desktop/OsuTestBrowser.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Platform; @@ -27,4 +27,4 @@ namespace osu.Desktop host.Window.CursorState |= CursorState.Hidden; } } -} \ No newline at end of file +} diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index 4bf0b76814..357cd49a5c 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Diagnostics; @@ -37,7 +37,8 @@ namespace osu.Desktop.Overlays private OsuConfigManager config; private OsuGameBase game; - public override bool HandleInput => false; + public override bool HandleKeyboardInput => false; + public override bool HandleMouseInput => false; [BackgroundDependencyLoader] private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index b7ecefe1ce..a91e728ce7 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -46,7 +46,6 @@ namespace osu.Desktop host.Run(new OsuGameDesktop(args)); break; } - } return 0; } diff --git a/osu.Desktop/osu.nuspec b/osu.Desktop/osu.nuspec index 4c529f57e5..bb7d382cee 100644 --- a/osu.Desktop/osu.nuspec +++ b/osu.Desktop/osu.nuspec @@ -12,12 +12,12 @@ click the circles. to the beat. click the circles. testing - Copyright ppy Pty Ltd 2007-2017 + Copyright ppy Pty Ltd 2007-2018 en-AU - + diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 6b9ec8b9a4..01aa7abb9f 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; @@ -11,7 +11,7 @@ using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Catch.Beatmaps { - internal class CatchBeatmapConverter : BeatmapConverter + public class CatchBeatmapConverter : BeatmapConverter { protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; @@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps var curveData = obj as IHasCurve; var positionData = obj as IHasXPosition; var comboData = obj as IHasCombo; + var endTime = obj as IHasEndTime; if (positionData == null) yield break; @@ -42,6 +43,19 @@ namespace osu.Game.Rulesets.Catch.Beatmaps yield break; } + if (endTime != null) + { + yield return new BananaShower + { + StartTime = obj.StartTime, + Samples = obj.Samples, + Duration = endTime.Duration, + NewCombo = comboData?.NewCombo ?? false + }; + + yield break; + } + yield return new Fruit { StartTime = obj.StartTime, diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs index 9901dbde18..d3012b1981 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -12,14 +12,14 @@ using OpenTK; namespace osu.Game.Rulesets.Catch.Beatmaps { - internal class CatchBeatmapProcessor : BeatmapProcessor + public class CatchBeatmapProcessor : BeatmapProcessor { public override void PostProcess(Beatmap beatmap) { if (beatmap.ComboColors.Count == 0) return; - int comboIndex = 0; + int index = 0; int colourIndex = 0; CatchHitObject lastObj = null; @@ -31,12 +31,10 @@ namespace osu.Game.Rulesets.Catch.Beatmaps if (obj.NewCombo) { if (lastObj != null) lastObj.LastInCombo = true; - - comboIndex = 0; colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count; } - obj.ComboIndex = comboIndex++; + obj.IndexInBeatmap = index++; obj.ComboColour = beatmap.ComboColors[colourIndex]; lastObj = obj; diff --git a/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs index e9524a867d..917a076426 100644 --- a/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Catch/CatchInputManager.cs b/osu.Game.Rulesets.Catch/CatchInputManager.cs index 47e9b9905a..fa8958687c 100644 --- a/osu.Game.Rulesets.Catch/CatchInputManager.cs +++ b/osu.Game.Rulesets.Catch/CatchInputManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; @@ -22,6 +22,6 @@ namespace osu.Game.Rulesets.Catch [Description("Move right")] MoveRight, [Description("Engage dash")] - Dash + Dash, } } diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index cb46c75583..5e70239c7c 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; @@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Catch { Mods = new Mod[] { - new ModAutoplay(), + new CatchModAutoplay(), new ModCinema(), }, }, @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Catch public override int LegacyID => 2; - public CatchRuleset(RulesetInfo rulesetInfo) + public CatchRuleset(RulesetInfo rulesetInfo = null) : base(rulesetInfo) { } diff --git a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index cc5b1eaaf4..d0e22bb04e 100644 --- a/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchMod.cs b/osu.Game.Rulesets.Catch/Mods/CatchMod.cs deleted file mode 100644 index 66261b0f0f..0000000000 --- a/osu.Game.Rulesets.Catch/Mods/CatchMod.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Mods; - -namespace osu.Game.Rulesets.Catch.Mods -{ - public class CatchModNoFail : ModNoFail - { - - } - - public class CatchModEasy : ModEasy - { - - } - - public class CatchModHidden : ModHidden - { - public override string Description => @"Play with fading notes for a slight score advantage."; - public override double ScoreMultiplier => 1.06; - } - - public class CatchModHardRock : ModHardRock - { - public override double ScoreMultiplier => 1.12; - public override bool Ranked => true; - } - - public class CatchModSuddenDeath : ModSuddenDeath - { - - } - - public class CatchModDaycore : ModDaycore - { - public override double ScoreMultiplier => 0.5; - } - - public class CatchModDoubleTime : ModDoubleTime - { - public override double ScoreMultiplier => 1.06; - } - - public class CatchModRelax : ModRelax - { - public override string Description => @"Use the mouse to control the catcher."; - } - - public class CatchModHalfTime : ModHalfTime - { - public override double ScoreMultiplier => 0.5; - } - - public class CatchModNightcore : ModNightcore - { - public override double ScoreMultiplier => 1.06; - } - - public class CatchModFlashlight : ModFlashlight - { - public override double ScoreMultiplier => 1.12; - } - - public class CatchModPerfect : ModPerfect - { - - } -} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs new file mode 100644 index 0000000000..8ff08ab825 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Replays; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModAutoplay : ModAutoplay + { + protected override Score CreateReplayScore(Beatmap beatmap) + { + return new Score + { + User = new User { Username = "osu!salad!" }, + Replay = new CatchAutoGenerator(beatmap).Generate(), + }; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs new file mode 100644 index 0000000000..124af06d56 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDaycore.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModDaycore : ModDaycore + { + public override double ScoreMultiplier => 0.5; + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs b/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs new file mode 100644 index 0000000000..7a7eeed719 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModDoubleTime.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModDoubleTime : ModDoubleTime + { + public override double ScoreMultiplier => 1.06; + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs b/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs new file mode 100644 index 0000000000..5c025bdea0 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModEasy.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModEasy : ModEasy + { + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs new file mode 100644 index 0000000000..424f14ad02 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModFlashlight : ModFlashlight + { + public override double ScoreMultiplier => 1.12; + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs new file mode 100644 index 0000000000..303fa6011d --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHalfTime.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModHalfTime : ModHalfTime + { + public override double ScoreMultiplier => 0.5; + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs new file mode 100644 index 0000000000..ed33bf7124 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModHardRock : ModHardRock + { + public override double ScoreMultiplier => 1.12; + public override bool Ranked => true; + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs b/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs new file mode 100644 index 0000000000..981ebda9eb --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModHidden : ModHidden + { + public override string Description => @"Play with fading notes for a slight score advantage."; + public override double ScoreMultiplier => 1.06; + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs b/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs new file mode 100644 index 0000000000..b53cac0d7c --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModNightcore.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModNightcore : ModNightcore + { + public override double ScoreMultiplier => 1.06; + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs b/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs new file mode 100644 index 0000000000..afb2d83720 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModNoFail.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModNoFail : ModNoFail + { + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs b/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs new file mode 100644 index 0000000000..bc0dd10f6c --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModPerfect.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModPerfect : ModPerfect + { + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs new file mode 100644 index 0000000000..de0b6bc614 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModRelax.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModRelax : ModRelax + { + public override string Description => @"Use the mouse to control the catcher."; + } +} diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs b/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs new file mode 100644 index 0000000000..1e778e5305 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Mods/CatchModSuddenDeath.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Catch.Mods +{ + public class CatchModSuddenDeath : ModSuddenDeath + { + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs new file mode 100644 index 0000000000..89bd73f8fb --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -0,0 +1,63 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Objects.Types; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Objects +{ + public class BananaShower : CatchHitObject, IHasEndTime + { + public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana; + + public override bool LastInCombo => true; + + protected override void CreateNestedHitObjects() + { + base.CreateNestedHitObjects(); + createBananas(); + } + + private void createBananas() + { + double spacing = Duration; + while (spacing > 100) + spacing /= 2; + + if (spacing <= 0) + return; + + for (double i = StartTime; i <= EndTime; i += spacing) + AddNested(new Banana + { + Samples = Samples, + ComboColour = getNextComboColour(), + StartTime = i, + X = RNG.NextSingle() + }); + } + + private Color4 getNextComboColour() + { + switch (RNG.Next(0, 3)) + { + default: + return new Color4(255, 240, 0, 255); + case 1: + return new Color4(255, 192, 0, 255); + case 2: + return new Color4(214, 221, 28, 255); + } + } + + public double EndTime => StartTime + Duration; + + public double Duration { get; set; } + + public class Banana : Fruit + { + public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index 9952e85c70..559bf47842 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; @@ -15,8 +15,11 @@ namespace osu.Game.Rulesets.Catch.Objects public float X { get; set; } - public Color4 ComboColour { get; set; } = Color4.Gray; - public int ComboIndex { get; set; } + public Color4 ComboColour { get; set; } + + public int IndexInBeatmap { get; set; } + + public virtual FruitVisualRepresentation VisualRepresentation => (FruitVisualRepresentation)(IndexInBeatmap % 4); public virtual bool NewCombo { get; set; } @@ -44,4 +47,13 @@ namespace osu.Game.Rulesets.Catch.Objects Scale = 1.0f - 0.7f * (difficulty.CircleSize - 5) / 5; } } + + public enum FruitVisualRepresentation + { + Pear, + Grape, + Raspberry, + Pineapple, + Banana // banananananannaanana + } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs new file mode 100644 index 0000000000..7b0370ef88 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBananaShower.cs @@ -0,0 +1,44 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Catch.Objects.Drawable +{ + public class DrawableBananaShower : DrawableCatchHitObject + { + private readonly Container bananaContainer; + + public DrawableBananaShower(BananaShower s, Func> getVisualRepresentation = null) + : base(s) + { + RelativeSizeAxes = Axes.X; + Origin = Anchor.BottomLeft; + X = 0; + + Child = bananaContainer = new Container { RelativeSizeAxes = Axes.Both }; + + foreach (var b in s.NestedHitObjects.Cast()) + AddNested(getVisualRepresentation?.Invoke(b)); + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (timeOffset >= 0) + AddJudgement(new Judgement { Result = NestedHitObjects.Cast().Any(n => n.Judgements.Any(j => j.IsHit)) ? HitResult.Perfect : HitResult.Miss }); + } + + protected override void AddNested(DrawableHitObject h) + { + ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; + bananaContainer.Add(h); + base.AddNested(h); + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index a617b65676..8d56fc1081 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -1,15 +1,28 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; using OpenTK; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Catch.Objects.Drawable { + public abstract class PalpableCatchHitObject : DrawableCatchHitObject + where TObject : CatchHitObject + { + public override bool CanBePlated => true; + + protected PalpableCatchHitObject(TObject hitObject) + : base(hitObject) + { + Scale = new Vector2(HitObject.Scale); + } + } + public abstract class DrawableCatchHitObject : DrawableCatchHitObject where TObject : CatchHitObject { @@ -19,27 +32,29 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable : base(hitObject) { HitObject = hitObject; - - Scale = new Vector2(HitObject.Scale); + Anchor = Anchor.BottomLeft; } } - public abstract class DrawableCatchHitObject : DrawableScrollingHitObject + public abstract class DrawableCatchHitObject : DrawableHitObject { + public virtual bool CanBePlated => false; + protected DrawableCatchHitObject(CatchHitObject hitObject) : base(hitObject) { - RelativePositionAxes = Axes.Both; + RelativePositionAxes = Axes.X; X = hitObject.X; - Y = (float)HitObject.StartTime; } public Func CheckPosition; protected override void CheckForJudgements(bool userTriggered, double timeOffset) { - if (timeOffset > 0) - AddJudgement(new Judgement { Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Perfect : HitResult.Miss }); + if (CheckPosition == null) return; + + if (timeOffset >= 0) + AddJudgement(new Judgement { Result = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss }); } private const float preempt = 1000; @@ -47,17 +62,21 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable protected override void UpdateState(ArmedState state) { using (BeginAbsoluteSequence(HitObject.StartTime - preempt)) - { - // animation this.FadeIn(200); - } - switch (state) + var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + + using (BeginAbsoluteSequence(endTime, true)) { - case ArmedState.Miss: - using (BeginAbsoluteSequence(HitObject.StartTime, true)) - this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out); - break; + switch (state) + { + case ArmedState.Miss: + this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out).Expire(); + break; + case ArmedState.Hit: + this.FadeOut().Expire(); + break; + } } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs index 2b2a8e7f8d..c2b0552ab3 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -8,15 +8,13 @@ using OpenTK; namespace osu.Game.Rulesets.Catch.Objects.Drawable { - public class DrawableDroplet : DrawableCatchHitObject + public class DrawableDroplet : PalpableCatchHitObject { public DrawableDroplet(Droplet h) : base(h) { Origin = Anchor.Centre; - - Size = new Vector2(Pulp.PULP_SIZE); - + Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS) / 4; AccentColour = h.ComboColour; Masking = false; } @@ -27,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable Child = new Pulp { AccentColour = AccentColour, - Scale = new Vector2(0.8f), + Size = Size }; } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 9f46bbd3a4..93a1483f6f 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -1,9 +1,12 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces; using OpenTK; @@ -11,14 +14,16 @@ using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable { - public class DrawableFruit : DrawableCatchHitObject + public class DrawableFruit : PalpableCatchHitObject { + private Circle border; + public DrawableFruit(Fruit h) : base(h) { Origin = Anchor.Centre; - Size = new Vector2(Pulp.PULP_SIZE * 2.2f, Pulp.PULP_SIZE * 2.8f); + Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS); AccentColour = HitObject.ComboColour; Masking = false; @@ -28,48 +33,34 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable [BackgroundDependencyLoader] private void load() { - Children = new Framework.Graphics.Drawable[] + Children = new[] { - //todo: share this more - new BufferedContainer + createPulp(HitObject.VisualRepresentation), + border = new Circle { - RelativeSizeAxes = Axes.Both, - CacheDrawnFrameBuffer = true, + EdgeEffect = new EdgeEffectParameters + { + Hollow = !HitObject.HyperDash, + Type = EdgeEffectType.Glow, + Radius = 4, + Colour = HitObject.HyperDash ? Color4.Red : AccentColour.Darken(1).Opacity(0.6f) + }, + Size = new Vector2(Height * 1.5f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + BorderColour = Color4.White, + BorderThickness = 4f, Children = new Framework.Graphics.Drawable[] { - new Pulp + new Box { - RelativePositionAxes = Axes.Both, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AccentColour = AccentColour, - Scale = new Vector2(0.6f), - }, - new Pulp - { - RelativePositionAxes = Axes.Both, - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - AccentColour = AccentColour, - Y = -0.08f - }, - new Pulp - { - RelativePositionAxes = Axes.Both, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - AccentColour = AccentColour, - Y = -0.08f - }, - new Pulp - { - RelativePositionAxes = Axes.Both, - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - AccentColour = AccentColour, - }, + AlwaysPresent = true, + Colour = AccentColour, + Alpha = 0, + RelativeSizeAxes = Axes.Both + } } - } + }, }; if (HitObject.HyperDash) @@ -82,9 +73,205 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable AccentColour = Color4.Red, Blending = BlendingMode.Additive, Alpha = 0.5f, - Scale = new Vector2(2) + Scale = new Vector2(1.333f) }); } } + + private Framework.Graphics.Drawable createPulp(FruitVisualRepresentation representation) + { + const float large_pulp_3 = 13f; + const float distance_from_centre_3 = 0.23f; + + const float large_pulp_4 = large_pulp_3 * 0.925f; + const float distance_from_centre_4 = distance_from_centre_3 / 0.925f; + + const float small_pulp = large_pulp_3 / 2; + + Vector2 positionAt(float angle, float distance) => new Vector2( + distance * (float)Math.Sin(angle * Math.PI / 180), + distance * (float)Math.Cos(angle * Math.PI / 180)); + + switch (representation) + { + default: + return new Container(); + case FruitVisualRepresentation.Raspberry: + return new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Framework.Graphics.Drawable[] + { + new Pulp + { + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + AccentColour = AccentColour, + Size = new Vector2(small_pulp), + Y = 0.05f, + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_4), + Position = positionAt(0, distance_from_centre_4), + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_4), + Position = positionAt(90, distance_from_centre_4), + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_4), + Position = positionAt(180, distance_from_centre_4), + }, + new Pulp + { + Size = new Vector2(large_pulp_4), + AccentColour = AccentColour, + Position = positionAt(270, distance_from_centre_4), + }, + } + }; + case FruitVisualRepresentation.Pineapple: + return new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Framework.Graphics.Drawable[] + { + new Pulp + { + Anchor = Anchor.TopCentre, + Origin = Anchor.BottomCentre, + AccentColour = AccentColour, + Size = new Vector2(small_pulp), + Y = 0.1f, + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_4), + Position = positionAt(45, distance_from_centre_4), + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_4), + Position = positionAt(135, distance_from_centre_4), + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_4), + Position = positionAt(225, distance_from_centre_4), + }, + new Pulp + { + Size = new Vector2(large_pulp_4), + AccentColour = AccentColour, + Position = positionAt(315, distance_from_centre_4), + }, + } + }; + case FruitVisualRepresentation.Pear: + return new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Framework.Graphics.Drawable[] + { + new Pulp + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AccentColour = AccentColour, + Size = new Vector2(small_pulp), + Y = -0.1f, + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_3), + Position = positionAt(60, distance_from_centre_3), + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_3), + Position = positionAt(180, distance_from_centre_3), + }, + new Pulp + { + Size = new Vector2(large_pulp_3), + AccentColour = AccentColour, + Position = positionAt(300, distance_from_centre_3), + }, + } + }; + case FruitVisualRepresentation.Grape: + return new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Framework.Graphics.Drawable[] + { + new Pulp + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AccentColour = AccentColour, + Size = new Vector2(small_pulp), + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_3), + Position = positionAt(0, distance_from_centre_3), + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_3), + Position = positionAt(120, distance_from_centre_3), + }, + new Pulp + { + Size = new Vector2(large_pulp_3), + AccentColour = AccentColour, + Position = positionAt(240, distance_from_centre_3), + }, + } + }; + case FruitVisualRepresentation.Banana: + return new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Framework.Graphics.Drawable[] + { + new Pulp + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AccentColour = AccentColour, + Size = new Vector2(small_pulp), + Y = -0.15f + }, + new Pulp + { + AccentColour = AccentColour, + Size = new Vector2(large_pulp_4 * 1.2f, large_pulp_4 * 3), + }, + } + }; + } + } + + protected override void Update() + { + base.Update(); + + border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1); + } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index db0632a07d..965ca62674 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using OpenTK; using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Catch.Objects.Drawable @@ -13,41 +13,28 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { private readonly Container dropletContainer; - public DrawableJuiceStream(JuiceStream s) : base(s) + public DrawableJuiceStream(JuiceStream s, Func> getVisualRepresentation = null) + : base(s) { RelativeSizeAxes = Axes.Both; - Height = (float)HitObject.Duration; + Origin = Anchor.BottomLeft; X = 0; - Child = dropletContainer = new Container - { - RelativeSizeAxes = Axes.Both, - RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), - RelativeChildSize = new Vector2(1, (float)HitObject.Duration) - }; + Child = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }; - foreach (CatchHitObject tick in s.NestedHitObjects.OfType()) - { - TinyDroplet tiny = tick as TinyDroplet; - if (tiny != null) - { - AddNested(new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) }); - continue; - } - - Droplet droplet = tick as Droplet; - if (droplet != null) - AddNested(new DrawableDroplet(droplet)); - - Fruit fruit = tick as Fruit; - if (fruit != null) - AddNested(new DrawableFruit(fruit)); - } + foreach (var o in s.NestedHitObjects.Cast()) + AddNested(getVisualRepresentation?.Invoke(o)); } - protected override void AddNested(DrawableHitObject h) + protected override bool ProvidesJudgement => false; + + protected override void AddNested(DrawableHitObject h) { - ((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; + var catchObject = (DrawableCatchHitObject)h; + + catchObject.CheckPosition = o => CheckPosition?.Invoke(o) ?? false; + catchObject.AccentColour = HitObject.ComboColour; + dropletContainer.Add(h); base.AddNested(h); } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs index 2de266b3f0..80520ea846 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; @@ -6,18 +6,17 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using OpenTK; using OpenTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces { public class Pulp : Circle, IHasAccentColour { - public const float PULP_SIZE = (float)CatchHitObject.OBJECT_RADIUS / 2.2f; - public Pulp() { - Size = new Vector2(PULP_SIZE); + RelativePositionAxes = Axes.Both; + Anchor = Anchor.Centre; + Origin = Anchor.Centre; Blending = BlendingMode.Additive; Colour = Color4.White.Opacity(0.9f); @@ -34,8 +33,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, - Radius = 5, - Colour = accentColour.Lighten(100), + Radius = 8, + Colour = accentColour.Darken(0.2f).Opacity(0.75f) }; } } diff --git a/osu.Game.Rulesets.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs index a2bdf830e5..4f9636e110 100644 --- a/osu.Game.Rulesets.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Catch.Objects diff --git a/osu.Game.Rulesets.Catch/Objects/Fruit.cs b/osu.Game.Rulesets.Catch/Objects/Fruit.cs index 5f1060fb51..c738984667 100644 --- a/osu.Game.Rulesets.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Catch.Objects diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 7d0d80a0ce..be1e360fce 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -21,9 +21,7 @@ namespace osu.Game.Rulesets.Catch.Objects /// private const float base_scoring_distance = 100; - public readonly SliderCurve Curve = new SliderCurve(); - - public int RepeatCount { get; set; } = 1; + public int RepeatCount { get; set; } public double Velocity; public double TickDistance; @@ -55,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Objects var length = Curve.Distance; var tickDistance = Math.Min(TickDistance, length); - var repeatDuration = length / Velocity; + var spanDuration = length / Velocity; var minDistanceFromEnd = Velocity * 0.01; @@ -67,10 +65,10 @@ namespace osu.Game.Rulesets.Catch.Objects X = X }); - for (var repeat = 0; repeat < RepeatCount; repeat++) + for (var span = 0; span < this.SpanCount(); span++) { - var repeatStartTime = StartTime + repeat * repeatDuration; - var reversed = repeat % 2 == 1; + var spanStartTime = StartTime + span * spanDuration; + var reversed = span % 2 == 1; for (var d = tickDistance; d <= length; d += tickDistance) { @@ -80,7 +78,7 @@ namespace osu.Game.Rulesets.Catch.Objects var timeProgress = d / length; var distanceProgress = reversed ? 1 - timeProgress : timeProgress; - var lastTickTime = repeatStartTime + timeProgress * repeatDuration; + var lastTickTime = spanStartTime + timeProgress * spanDuration; AddNested(new Droplet { StartTime = lastTickTime, @@ -95,17 +93,17 @@ namespace osu.Game.Rulesets.Catch.Objects }); } - double tinyTickInterval = tickDistance / length * repeatDuration; + double tinyTickInterval = tickDistance / length * spanDuration; while (tinyTickInterval > 100) tinyTickInterval /= 2; - for (double t = 0; t < repeatDuration; t += tinyTickInterval) + for (double t = 0; t < spanDuration; t += tinyTickInterval) { - double progress = reversed ? 1 - t / repeatDuration : t / repeatDuration; + double progress = reversed ? 1 - t / spanDuration : t / spanDuration; AddNested(new TinyDroplet { - StartTime = repeatStartTime + t, + StartTime = spanStartTime + t, ComboColour = ComboColour, X = Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH, Samples = new List(Samples.Select(s => new SampleInfo @@ -121,17 +119,15 @@ namespace osu.Game.Rulesets.Catch.Objects { Samples = Samples, ComboColour = ComboColour, - StartTime = repeatStartTime + repeatDuration, + StartTime = spanStartTime + spanDuration, X = Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH }); } - } + public double EndTime => StartTime + this.SpanCount() * Curve.Distance / Velocity; - public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity; - - public float EndX => Curve.PositionAt(ProgressAt(1)).X / CatchPlayfield.BASE_WIDTH; + public float EndX => Curve.PositionAt(this.ProgressAt(1)).X / CatchPlayfield.BASE_WIDTH; public double Duration => EndTime - StartTime; @@ -141,6 +137,8 @@ namespace osu.Game.Rulesets.Catch.Objects set { Curve.Distance = value; } } + public SliderCurve Curve { get; } = new SliderCurve(); + public List ControlPoints { get { return Curve.ControlPoints; } @@ -154,17 +152,5 @@ namespace osu.Game.Rulesets.Catch.Objects get { return Curve.CurveType; } set { Curve.CurveType = value; } } - - public Vector2 PositionAt(double progress) => Curve.PositionAt(ProgressAt(progress)); - - public double ProgressAt(double progress) - { - double p = progress * RepeatCount % 1; - if (RepeatAt(progress) % 2 == 1) - p = 1 - p; - return p; - } - - public int RepeatAt(double progress) => (int)(progress * RepeatCount); } } diff --git a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs index 231f3d5361..23b8a7e02f 100644 --- a/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Catch.Objects diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs new file mode 100644 index 0000000000..f8ca75fae9 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -0,0 +1,120 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Framework.MathUtils; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Replays; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Catch.Replays +{ + internal class CatchAutoGenerator : AutoGenerator + { + public const double RELEASE_DELAY = 20; + + public CatchAutoGenerator(Beatmap beatmap) + : base(beatmap) + { + Replay = new Replay { User = new User { Username = @"Autoplay" } }; + } + + protected Replay Replay; + + public override Replay Generate() + { + // todo: add support for HT DT + const double dash_speed = CatcherArea.Catcher.BASE_SPEED; + const double movement_speed = dash_speed / 2; + float lastPosition = 0.5f; + double lastTime = 0; + + // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled + Replay.Frames.Add(new CatchReplayFrame(-100000, lastPosition)); + + void moveToNext(CatchHitObject h) + { + float positionChange = Math.Abs(lastPosition - h.X); + double timeAvailable = h.StartTime - lastTime; + + //So we can either make it there without a dash or not. + double speedRequired = positionChange / timeAvailable; + + bool dashRequired = speedRequired > movement_speed && h.StartTime != 0; + + // todo: get correct catcher size, based on difficulty CS. + const float catcher_width_half = CatcherArea.CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * 0.3f * 0.5f; + + if (lastPosition - catcher_width_half < h.X && lastPosition + catcher_width_half > h.X) + { + //we are already in the correct range. + lastTime = h.StartTime; + Replay.Frames.Add(new CatchReplayFrame(h.StartTime, lastPosition)); + return; + } + + if (h is BananaShower.Banana) + { + // auto bananas unrealistically warp to catch 100% combo. + Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + } + else if (h.HyperDash) + { + Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable, lastPosition, ReplayButtonState.Right1)); + Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + } + else if (dashRequired) + { + //we do a movement in two parts - the dash part then the normal part... + double timeAtNormalSpeed = positionChange / movement_speed; + double timeWeNeedToSave = timeAtNormalSpeed - timeAvailable; + double timeAtDashSpeed = timeWeNeedToSave / 2; + + float midPosition = (float)Interpolation.Lerp(lastPosition, h.X, (float)timeAtDashSpeed / timeAvailable); + + //dash movement + Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable + 1, lastPosition, ReplayButtonState.Left1)); + Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable + timeAtDashSpeed, midPosition)); + Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + } + else + { + double timeBefore = positionChange / movement_speed; + + Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeBefore, lastPosition, ReplayButtonState.Right1)); + Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + } + + lastTime = h.StartTime; + lastPosition = h.X; + } + + foreach (var obj in Beatmap.HitObjects) + { + switch (obj) + { + case Fruit _: + moveToNext(obj); + break; + } + + foreach (var nestedObj in obj.NestedHitObjects.Cast()) + { + switch (nestedObj) + { + case BananaShower.Banana _: + case TinyDroplet _: + case Droplet _: + moveToNext(nestedObj); + break; + } + } + } + + return Replay; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs new file mode 100644 index 0000000000..2f296a2504 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -0,0 +1,46 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Input; +using osu.Game.Rulesets.Replays; + +namespace osu.Game.Rulesets.Catch.Replays +{ + public class CatchFramedReplayInputHandler : FramedReplayInputHandler + { + public CatchFramedReplayInputHandler(Replay replay) + : base(replay) + { + } + + public override List GetPendingStates() + { + if (!Position.HasValue) return new List(); + + var action = new List(); + + if (CurrentFrame.ButtonState == ReplayButtonState.Left1) + action.Add(CatchAction.Dash); + + if (Position.Value.X > CurrentFrame.Position.X) + action.Add(CatchAction.MoveRight); + else if (Position.Value.X < CurrentFrame.Position.X) + action.Add(CatchAction.MoveLeft); + + return new List + { + new CatchReplayState + { + PressedActions = action, + CatcherX = Position.Value.X + }, + }; + } + + public class CatchReplayState : ReplayState + { + public float? CatcherX { get; set; } + } + } +} diff --git a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs new file mode 100644 index 0000000000..0194fc93a4 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Replays; + +namespace osu.Game.Rulesets.Catch.Replays +{ + public class CatchReplayFrame : ReplayFrame + { + public override bool IsImportant => MouseX > 0; + + public CatchReplayFrame(double time, float? x = null, ReplayButtonState button = ReplayButtonState.None) + : base(time, x ?? -1, null, button) + { + } + } +} diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 3b9eacde9c..0a8a53c6f1 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; @@ -10,7 +10,7 @@ using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Catch.Scoring { - internal class CatchScoreProcessor : ScoreProcessor + public class CatchScoreProcessor : ScoreProcessor { public CatchScoreProcessor(RulesetContainer rulesetContainer) : base(rulesetContainer) @@ -21,23 +21,21 @@ namespace osu.Game.Rulesets.Catch.Scoring { foreach (var obj in beatmap.HitObjects) { - var stream = obj as JuiceStream; - - if (stream != null) + switch (obj) { - AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); - AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); - - foreach (var unused in stream.NestedHitObjects.OfType()) + case JuiceStream stream: + foreach (var _ in stream.NestedHitObjects.Cast()) + AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); + break; + case BananaShower shower: + foreach (var _ in shower.NestedHitObjects.Cast()) + AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); - - continue; + break; + case Fruit _: + AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); + break; } - - var fruit = obj as Fruit; - - if (fruit != null) - AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); } base.SimulateAutoplay(beatmap); diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs new file mode 100644 index 0000000000..e23e7633ca --- /dev/null +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseBananaShower.cs @@ -0,0 +1,50 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Objects.Drawable; +using osu.Game.Rulesets.Catch.UI; + +namespace osu.Game.Rulesets.Catch.Tests +{ + [TestFixture] + [Ignore("getting CI working")] + public class TestCaseBananaShower : Game.Tests.Visual.TestCasePlayer + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(BananaShower), + typeof(DrawableBananaShower), + + typeof(CatchRuleset), + typeof(CatchRulesetContainer), + }; + + public TestCaseBananaShower() + : base(new CatchRuleset()) + { + } + + protected override Beatmap CreateBeatmap() + { + var beatmap = new Beatmap + { + BeatmapInfo = new BeatmapInfo + { + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 6, + } + } + }; + + beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 5000, NewCombo = true }); + + return beatmap; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs index cc434b3080..dbd5e5b36c 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchPlayer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch.Tests [Ignore("getting CI working")] public class TestCaseCatchPlayer : Game.Tests.Visual.TestCasePlayer { - public TestCaseCatchPlayer() : base(typeof(CatchRuleset)) + public TestCaseCatchPlayer() : base(new CatchRuleset()) { } } diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchStacker.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchStacker.cs index 586de17f15..b9fa38f74e 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseCatchStacker.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseCatchStacker.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Catch.Tests public class TestCaseCatchStacker : Game.Tests.Visual.TestCasePlayer { public TestCaseCatchStacker() - : base(typeof(CatchRuleset)) + : base(new CatchRuleset()) { } diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseCatcherArea.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseCatcherArea.cs index 8217265e3d..a2d18520d7 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseCatcherArea.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseCatcherArea.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseFruitObjects.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseFruitObjects.cs new file mode 100644 index 0000000000..d406231cc9 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseFruitObjects.cs @@ -0,0 +1,104 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Objects.Drawable; +using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces; +using osu.Game.Tests.Visual; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Tests +{ + [Ignore("getting CI working")] + public class TestCaseFruitObjects : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(CatchHitObject), + typeof(Fruit), + typeof(Droplet), + typeof(DrawableCatchHitObject), + typeof(DrawableFruit), + typeof(DrawableDroplet), + typeof(Pulp), + }; + + public TestCaseFruitObjects() + { + Add(new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + createDrawable(0), + createDrawable(1), + createDrawable(2), + }, + new Drawable[] + { + createDrawable(3), + createDrawable(4), + createDrawable(5), + }, + } + }); + } + + private DrawableFruit createDrawable(int index) + { + var fruit = new Fruit + { + StartTime = 1000000000000, + IndexInBeatmap = index, + Scale = 1.5f, + }; + + fruit.ComboColour = colourForRrepesentation(fruit.VisualRepresentation); + + return new DrawableFruit(fruit) + { + Anchor = Anchor.Centre, + RelativePositionAxes = Axes.Both, + Position = Vector2.Zero, + Alpha = 1, + LifetimeStart = double.NegativeInfinity, + LifetimeEnd = double.PositiveInfinity, + }; + } + + private Color4 colourForRrepesentation(FruitVisualRepresentation representation) + { + switch (representation) + { + default: + case FruitVisualRepresentation.Pear: + return new Color4(17, 136, 170, 255); + case FruitVisualRepresentation.Grape: + return new Color4(204, 102, 0, 255); + case FruitVisualRepresentation.Raspberry: + return new Color4(121, 9, 13, 255); + case FruitVisualRepresentation.Pineapple: + return new Color4(102, 136, 0, 255); + case FruitVisualRepresentation.Banana: + switch (RNG.Next(0, 3)) + { + default: + return new Color4(255, 240, 0, 255); + case 1: + return new Color4(255, 192, 0, 255); + case 2: + return new Color4(214, 221, 28, 255); + } + } + } + } +} diff --git a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs index ce3f79bae2..59659b3d0d 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCaseHyperdash.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Catch.Tests public class TestCaseHyperdash : Game.Tests.Visual.TestCasePlayer { public TestCaseHyperdash() - : base(typeof(CatchRuleset)) + : base(new CatchRuleset()) { } diff --git a/osu.Game.Rulesets.Catch/Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Catch/Tests/TestCasePerformancePoints.cs index 0d2dc14160..725eb5cf76 100644 --- a/osu.Game.Rulesets.Catch/Tests/TestCasePerformancePoints.cs +++ b/osu.Game.Rulesets.Catch/Tests/TestCasePerformancePoints.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch.Tests public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints { public TestCasePerformancePoints() - : base(new CatchRuleset(new RulesetInfo())) + : base(new CatchRuleset()) { } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 76dbfa77c6..39b7ffb387 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -1,15 +1,15 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Graphics; -using osu.Game.Rulesets.UI; -using OpenTK; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Catch.UI { @@ -22,33 +22,35 @@ namespace osu.Game.Rulesets.Catch.UI private readonly CatcherArea catcherArea; - public CatchPlayfield(BeatmapDifficulty difficulty) - : base(Axes.Y) + public CatchPlayfield(BeatmapDifficulty difficulty, Func> getVisualRepresentation) + : base(ScrollingDirection.Down, BASE_WIDTH) { Container explodingFruitContainer; - Reversed.Value = true; - Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; - InternalChildren = new Drawable[] + ScaledContent.Anchor = Anchor.BottomLeft; + ScaledContent.Origin = Anchor.BottomLeft; + + ScaledContent.AddRange(new Drawable[] { - content = new Container - { - RelativeSizeAxes = Axes.Both, - }, explodingFruitContainer = new Container { RelativeSizeAxes = Axes.Both, }, catcherArea = new CatcherArea(difficulty) { + GetVisualRepresentation = getVisualRepresentation, ExplodingFruitTarget = explodingFruitContainer, Anchor = Anchor.BottomLeft, Origin = Anchor.TopLeft, - } - }; + }, + content = new Container + { + RelativeSizeAxes = Axes.Both, + }, + }); } public bool CheckIfWeCanCatch(CatchHitObject obj) => catcherArea.AttemptCatch(obj); @@ -56,6 +58,7 @@ namespace osu.Game.Rulesets.Catch.UI public override void Add(DrawableHitObject h) { h.Depth = (float)h.HitObject.StartTime; + h.OnJudgement += onJudgement; base.Add(h); @@ -63,18 +66,6 @@ namespace osu.Game.Rulesets.Catch.UI fruit.CheckPosition = CheckIfWeCanCatch; } - public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) - { - if (judgement.IsHit) - { - Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre; - - // todo: don't do this - (judgedObject.Parent as Container)?.Remove(judgedObject); - (judgedObject.Parent as Container)?.Remove(judgedObject); - - catcherArea.Add(judgedObject, screenPosition); - } - } + private void onJudgement(DrawableHitObject judgedObject, Judgement judgement) => catcherArea.OnJudgement((DrawableCatchHitObject)judgedObject, judgement); } } diff --git a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs index 3ed9090098..956a524121 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchRulesetContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Input; @@ -6,10 +6,14 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawable; +using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; namespace osu.Game.Rulesets.Catch.UI { @@ -22,23 +26,31 @@ namespace osu.Game.Rulesets.Catch.UI public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this); + protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay); + protected override BeatmapProcessor CreateBeatmapProcessor() => new CatchBeatmapProcessor(); protected override BeatmapConverter CreateBeatmapConverter() => new CatchBeatmapConverter(); - protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty); + protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, GetVisualRepresentation); public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); protected override DrawableHitObject GetVisualRepresentation(CatchHitObject h) { - var fruit = h as Fruit; - if (fruit != null) - return new DrawableFruit(fruit); - - var stream = h as JuiceStream; - if (stream != null) - return new DrawableJuiceStream(stream); + switch (h) + { + case Fruit fruit: + return new DrawableFruit(fruit); + case JuiceStream stream: + return new DrawableJuiceStream(stream, GetVisualRepresentation); + case BananaShower banana: + return new DrawableBananaShower(banana, GetVisualRepresentation); + case TinyDroplet tiny: + return new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) }; + case Droplet droplet: + return new DrawableDroplet(droplet); + } return null; } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 2bb0f3cd18..7c548f70d4 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -12,6 +12,9 @@ using osu.Framework.Input.Bindings; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Objects.Drawable; +using osu.Game.Rulesets.Catch.Replays; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; using OpenTK.Graphics; @@ -24,6 +27,8 @@ namespace osu.Game.Rulesets.Catch.UI protected readonly Catcher MovableCatcher; + public Func> GetVisualRepresentation; + public Container ExplodingFruitTarget { set { MovableCatcher.ExplodingFruitTarget = value; } @@ -39,19 +44,58 @@ namespace osu.Game.Rulesets.Catch.UI }; } - public void Add(DrawableHitObject fruit, Vector2 absolutePosition) + private DrawableCatchHitObject lastPlateableFruit; + + public void OnJudgement(DrawableCatchHitObject fruit, Judgement judgement) { - fruit.RelativePositionAxes = Axes.None; - fruit.Position = new Vector2(MovableCatcher.ToLocalSpace(absolutePosition).X - MovableCatcher.DrawSize.X / 2, 0); + if (judgement.IsHit && fruit.CanBePlated) + { + var caughtFruit = (DrawableCatchHitObject)GetVisualRepresentation?.Invoke(fruit.HitObject); - fruit.Anchor = Anchor.TopCentre; - fruit.Origin = Anchor.BottomCentre; - fruit.Scale *= 0.7f; - fruit.LifetimeEnd = double.MaxValue; + if (caughtFruit == null) return; - MovableCatcher.Add(fruit); + caughtFruit.AccentColour = fruit.AccentColour; + caughtFruit.RelativePositionAxes = Axes.None; + caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0); + + caughtFruit.Anchor = Anchor.TopCentre; + caughtFruit.Origin = Anchor.Centre; + caughtFruit.Scale *= 0.7f; + caughtFruit.LifetimeEnd = double.MaxValue; + + MovableCatcher.Add(caughtFruit); + + lastPlateableFruit = caughtFruit; + } + + if (fruit.HitObject.LastInCombo) + { + if (judgement.IsHit) + { + // this is required to make this run after the last caught fruit runs UpdateState at least once. + // TODO: find a better alternative + if (lastPlateableFruit.IsLoaded) + MovableCatcher.Explode(); + else + lastPlateableFruit.OnLoadComplete = _ => { MovableCatcher.Explode(); }; + } + else + MovableCatcher.Drop(); + } } + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + var state = GetContainingInputManager().CurrentState as CatchFramedReplayInputHandler.CatchReplayState; + + if (state?.CatcherX != null) + MovableCatcher.X = state.CatcherX.Value; + } + + public bool OnReleased(CatchAction action) => false; + public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj); public class Catcher : Container, IKeyBindingHandler @@ -84,12 +128,12 @@ namespace osu.Game.Rulesets.Catch.UI Children = new Drawable[] { - createCatcherSprite(), caughtFruit = new Container { Anchor = Anchor.TopCentre, Origin = Anchor.BottomCentre, - } + }, + createCatcherSprite(), }; } @@ -167,20 +211,23 @@ namespace osu.Game.Rulesets.Catch.UI /// The fruit that was caught. public void Add(DrawableHitObject fruit) { - float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; + float ourRadius = fruit.DrawSize.X / 2 * fruit.Scale.X; + float theirRadius = 0; - while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) + const float allowance = 6; + + while (caughtFruit.Any(f => + f.LifetimeEnd == double.MaxValue && + Vector2Extensions.Distance(f.Position, fruit.Position) < (ourRadius + (theirRadius = f.DrawSize.X / 2 * f.Scale.X)) / (allowance / 2))) { - fruit.X += RNG.Next(-5, 5); - fruit.Y -= RNG.Next(0, 5); + float diff = (ourRadius + theirRadius) / allowance; + fruit.X += (RNG.NextSingle() - 0.5f) * 2 * diff; + fruit.Y -= RNG.NextSingle() * diff; } + fruit.X = MathHelper.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2); + caughtFruit.Add(fruit); - - var catchObject = (CatchHitObject)fruit.HitObject; - - if (catchObject.LastInCombo) - explode(); } /// @@ -190,15 +237,15 @@ namespace osu.Game.Rulesets.Catch.UI /// Whether the catch is possible. public bool AttemptCatch(CatchHitObject fruit) { - const double relative_catcher_width = CATCHER_SIZE / 2; + double halfCatcherWidth = CATCHER_SIZE * Math.Abs(Scale.X) * 0.5f; // this stuff wil disappear once we move fruit to non-relative coordinate space in the future. var catchObjectPosition = fruit.X * CatchPlayfield.BASE_WIDTH; var catcherPosition = Position.X * CatchPlayfield.BASE_WIDTH; var validCatch = - catchObjectPosition >= catcherPosition - relative_catcher_width / 2 && - catchObjectPosition <= catcherPosition + relative_catcher_width / 2; + catchObjectPosition >= catcherPosition - halfCatcherWidth && + catchObjectPosition <= catcherPosition + halfCatcherWidth; if (validCatch && fruit.HyperDash) { @@ -309,7 +356,35 @@ namespace osu.Game.Rulesets.Catch.UI X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * BASE_SPEED * dashModifier, 0, 1); } - private void explode() + /// + /// Drop any fruit off the plate. + /// + public void Drop() + { + var fruit = caughtFruit.ToArray(); + + foreach (var f in fruit) + { + if (ExplodingFruitTarget != null) + { + f.Anchor = Anchor.TopLeft; + f.Position = caughtFruit.ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget); + + caughtFruit.Remove(f); + + ExplodingFruitTarget.Add(f); + } + + f.MoveToY(f.Y + 75, 750, Easing.InSine); + f.FadeOut(750); + f.Expire(); + } + } + + /// + /// Explode any fruit off the plate. + /// + public void Explode() { var fruit = caughtFruit.ToArray(); diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs new file mode 100644 index 0000000000..0a248658a8 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmap.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.UI; + +namespace osu.Game.Rulesets.Mania.Beatmaps +{ + public class ManiaBeatmap : Beatmap + { + /// + /// The definitions for each stage in a . + /// + public List Stages = new List(); + + /// + /// Total number of columns represented by all stages in this . + /// + public int TotalColumns => Stages.Sum(g => g.Columns); + + /// + /// Creates a new . + /// + /// The initial stages. + public ManiaBeatmap(StageDefinition defaultStage) + { + Stages.Add(defaultStage); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 407d4db143..9922d4c8ad 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Mania.Objects; using System; +using System.Linq; using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; @@ -24,25 +25,39 @@ namespace osu.Game.Rulesets.Mania.Beatmaps protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; + public int TargetColumns; + public readonly bool IsForCurrentRuleset; + private Pattern lastPattern = new Pattern(); private FastRandom random; - private Beatmap beatmap; - private readonly int availableColumns; - private readonly bool isForCurrentRuleset; + private ManiaBeatmap beatmap; - public ManiaBeatmapConverter(bool isForCurrentRuleset, int availableColumns) + public ManiaBeatmapConverter(bool isForCurrentRuleset, Beatmap original) { - if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns)); + IsForCurrentRuleset = isForCurrentRuleset; - this.isForCurrentRuleset = isForCurrentRuleset; - this.availableColumns = availableColumns; + var roundedCircleSize = Math.Round(original.BeatmapInfo.BaseDifficulty.CircleSize); + var roundedOverallDifficulty = Math.Round(original.BeatmapInfo.BaseDifficulty.OverallDifficulty); + + if (isForCurrentRuleset) + TargetColumns = (int)Math.Max(1, roundedCircleSize); + else + { + float percentSliderOrSpinner = (float)original.HitObjects.Count(h => h is IHasEndTime) / original.HitObjects.Count; + if (percentSliderOrSpinner < 0.2) + TargetColumns = 7; + else if (percentSliderOrSpinner < 0.3 || roundedCircleSize >= 5) + TargetColumns = roundedOverallDifficulty > 5 ? 7 : 6; + else if (percentSliderOrSpinner > 0.6) + TargetColumns = roundedOverallDifficulty > 4 ? 5 : 4; + else + TargetColumns = Math.Max(4, Math.Min((int)roundedOverallDifficulty + 1, 7)); + } } protected override Beatmap ConvertBeatmap(Beatmap original) { - beatmap = original; - BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty; int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate); @@ -51,6 +66,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps return base.ConvertBeatmap(original); } + protected override Beatmap CreateBeatmap() => beatmap = new ManiaBeatmap(new StageDefinition { Columns = TargetColumns }); + protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) { var maniaOriginal = original as ManiaHitObject; @@ -60,7 +77,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps yield break; } - var objects = isForCurrentRuleset ? generateSpecific(original) : generateConverted(original); + var objects = IsForCurrentRuleset ? generateSpecific(original) : generateConverted(original); if (objects == null) yield break; @@ -96,7 +113,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// The hit objects generated. private IEnumerable generateSpecific(HitObject original) { - var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, availableColumns, lastPattern); + var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern); Pattern newPattern = generator.Generate(); lastPattern = newPattern; @@ -120,14 +137,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps Patterns.PatternGenerator conversion = null; if (distanceData != null) - conversion = new DistanceObjectPatternGenerator(random, original, beatmap, availableColumns, lastPattern); + conversion = new DistanceObjectPatternGenerator(random, original, beatmap, lastPattern); else if (endTimeData != null) - conversion = new EndTimeObjectPatternGenerator(random, original, beatmap, availableColumns); + conversion = new EndTimeObjectPatternGenerator(random, original, beatmap); else if (positionData != null) { computeDensity(original.StartTime); - conversion = new HitObjectPatternGenerator(random, original, beatmap, availableColumns, lastPattern, lastTime, lastPosition, density, lastStair); + conversion = new HitObjectPatternGenerator(random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair); recordNote(original.StartTime, positionData.Position); } @@ -149,8 +166,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps /// private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator { - public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) - : base(random, hitObject, beatmap, availableColumns, previousPattern) + public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern) + : base(random, hitObject, beatmap, previousPattern) { } @@ -199,7 +216,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps if (curveData == null) return HitObject.Samples; - double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.RepeatCount; + double segmentTime = (curveData.EndTime - HitObject.StartTime) / curveData.SpanCount(); int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); return curveData.RepeatSamples[index]; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs index 8251dea5f7..a102781e70 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; using System.Linq; using osu.Game.Audio; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -26,12 +25,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy private readonly double endTime; private readonly double segmentDuration; - private readonly int repeatCount; + private readonly int spanCount; private PatternType convertType; - public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) - : base(random, hitObject, beatmap, availableColumns, previousPattern) + public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern) + : base(random, hitObject, beatmap, previousPattern) { convertType = PatternType.None; if (Beatmap.ControlPointInfo.EffectPointAt(hitObject.StartTime).KiaiMode) @@ -40,25 +39,25 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var distanceData = hitObject as IHasDistance; var repeatsData = hitObject as IHasRepeats; - repeatCount = repeatsData?.RepeatCount ?? 1; + spanCount = repeatsData?.SpanCount() ?? 1; TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime); DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(hitObject.StartTime); // The true distance, accounting for any repeats - double distance = (distanceData?.Distance ?? 0) * repeatCount; + double distance = (distanceData?.Distance ?? 0) * spanCount; // The velocity of the osu! hit object - calculated as the velocity of a slider double osuVelocity = osu_base_scoring_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier / timingPoint.BeatLength; // The duration of the osu! hit object double osuDuration = distance / osuVelocity; endTime = hitObject.StartTime + osuDuration; - segmentDuration = (endTime - HitObject.StartTime) / repeatCount; + segmentDuration = (endTime - HitObject.StartTime) / spanCount; } public override Pattern Generate() { - if (repeatCount > 1) + if (spanCount > 1) { if (segmentDuration <= 90) return generateRandomHoldNotes(HitObject.StartTime, 1); @@ -66,7 +65,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (segmentDuration <= 120) { convertType |= PatternType.ForceNotStack; - return generateRandomNotes(HitObject.StartTime, repeatCount + 1); + return generateRandomNotes(HitObject.StartTime, spanCount + 1); } if (segmentDuration <= 160) @@ -79,7 +78,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (duration >= 4000) return generateNRandomNotes(HitObject.StartTime, 0.23, 0, 0); - if (segmentDuration > 400 && repeatCount < AvailableColumns - 1 - RandomStart) + if (segmentDuration > 400 && spanCount < TotalColumns - 1 - RandomStart) return generateTiledHoldNotes(HitObject.StartTime); return generateHoldAndNormalNotes(HitObject.StartTime); @@ -87,7 +86,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (segmentDuration <= 110) { - if (PreviousPattern.ColumnWithObjects < AvailableColumns) + if (PreviousPattern.ColumnWithObjects < TotalColumns) convertType |= PatternType.ForceNotStack; else convertType &= ~PatternType.ForceNotStack; @@ -135,12 +134,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); - int usableColumns = AvailableColumns - RandomStart - PreviousPattern.ColumnWithObjects; - int nextColumn = Random.Next(RandomStart, AvailableColumns); + int usableColumns = TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects; + int nextColumn = Random.Next(RandomStart, TotalColumns); for (int i = 0; i < Math.Min(usableColumns, noteCount); i++) { while (pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn)) //find available column - nextColumn = Random.Next(RandomStart, AvailableColumns); + nextColumn = Random.Next(RandomStart, TotalColumns); addToPattern(pattern, nextColumn, startTime, endTime); } @@ -148,7 +147,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy for (int i = 0; i < noteCount - usableColumns; i++) { while (pattern.ColumnHasObject(nextColumn)) - nextColumn = Random.Next(RandomStart, AvailableColumns); + nextColumn = Random.Next(RandomStart, TotalColumns); addToPattern(pattern, nextColumn, startTime, endTime); } @@ -172,10 +171,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); - if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < AvailableColumns) + if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns) { while (PreviousPattern.ColumnHasObject(nextColumn)) - nextColumn = Random.Next(RandomStart, AvailableColumns); + nextColumn = Random.Next(RandomStart, TotalColumns); } int lastColumn = nextColumn; @@ -183,7 +182,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { addToPattern(pattern, nextColumn, startTime, startTime); while (nextColumn == lastColumn) - nextColumn = Random.Next(RandomStart, AvailableColumns); + nextColumn = Random.Next(RandomStart, TotalColumns); lastColumn = nextColumn; startTime += segmentDuration; @@ -213,7 +212,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int column = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); bool increasing = Random.NextDouble() > 0.5; - for (int i = 0; i <= repeatCount; i++) + for (int i = 0; i <= spanCount; i++) { addToPattern(pattern, column, startTime, startTime); startTime += segmentDuration; @@ -221,7 +220,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy // Check if we're at the borders of the stage, and invert the pattern if so if (increasing) { - if (column >= AvailableColumns - 1) + if (column >= TotalColumns - 1) { increasing = false; column--; @@ -259,24 +258,24 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); - bool legacy = AvailableColumns >= 4 && AvailableColumns <= 8; - int interval = Random.Next(1, AvailableColumns - (legacy ? 1 : 0)); + bool legacy = TotalColumns >= 4 && TotalColumns <= 8; + int interval = Random.Next(1, TotalColumns - (legacy ? 1 : 0)); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); - for (int i = 0; i <= repeatCount; i++) + for (int i = 0; i <= spanCount; i++) { addToPattern(pattern, nextColumn, startTime, startTime); nextColumn += interval; - if (nextColumn >= AvailableColumns - RandomStart) - nextColumn = nextColumn - AvailableColumns - RandomStart + (legacy ? 1 : 0); + if (nextColumn >= TotalColumns - RandomStart) + nextColumn = nextColumn - TotalColumns - RandomStart + (legacy ? 1 : 0); nextColumn += RandomStart; // If we're in 2K, let's not add many consecutive doubles - if (AvailableColumns > 2) + if (TotalColumns > 2) addToPattern(pattern, nextColumn, startTime, startTime); - nextColumn = Random.Next(RandomStart, AvailableColumns); + nextColumn = Random.Next(RandomStart, TotalColumns); startTime += segmentDuration; } @@ -298,7 +297,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy // □ - □ □ // ■ - ■ ■ - switch (AvailableColumns) + switch (TotalColumns) { case 2: p2 = 0; @@ -322,7 +321,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy break; } - Func isDoubleSample = sample => sample.Name == SampleInfo.HIT_CLAP && sample.Name == SampleInfo.HIT_FINISH; + bool isDoubleSample(SampleInfo sample) => sample.Name == SampleInfo.HIT_CLAP && sample.Name == SampleInfo.HIT_FINISH; bool canGenerateTwoNotes = (convertType & PatternType.LowProbability) == 0; canGenerateTwoNotes &= HitObject.Samples.Any(isDoubleSample) || sampleInfoListAt(HitObject.StartTime).Any(isDoubleSample); @@ -351,19 +350,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); - int columnRepeat = Math.Min(repeatCount, AvailableColumns); + int columnRepeat = Math.Min(spanCount, TotalColumns); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); - if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < AvailableColumns) + if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns) { while (PreviousPattern.ColumnHasObject(nextColumn)) - nextColumn = Random.Next(RandomStart, AvailableColumns); + nextColumn = Random.Next(RandomStart, TotalColumns); } for (int i = 0; i < columnRepeat; i++) { while (pattern.ColumnHasObject(nextColumn)) - nextColumn = Random.Next(RandomStart, AvailableColumns); + nextColumn = Random.Next(RandomStart, TotalColumns); addToPattern(pattern, nextColumn, startTime, endTime); startTime += segmentDuration; @@ -388,10 +387,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); int holdColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); - if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < AvailableColumns) + if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns) { while (PreviousPattern.ColumnHasObject(holdColumn)) - holdColumn = Random.Next(RandomStart, AvailableColumns); + holdColumn = Random.Next(RandomStart, TotalColumns); } // Create the hold note @@ -401,23 +400,23 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (ConversionDifficulty > 6.5) noteCount = GetRandomNoteCount(0.63, 0); else if (ConversionDifficulty > 4) - noteCount = GetRandomNoteCount(AvailableColumns < 6 ? 0.12 : 0.45, 0); + noteCount = GetRandomNoteCount(TotalColumns < 6 ? 0.12 : 0.45, 0); else if (ConversionDifficulty > 2.5) - noteCount = GetRandomNoteCount(AvailableColumns < 6 ? 0 : 0.24, 0); - noteCount = Math.Min(AvailableColumns - 1, noteCount); + noteCount = GetRandomNoteCount(TotalColumns < 6 ? 0 : 0.24, 0); + noteCount = Math.Min(TotalColumns - 1, noteCount); bool ignoreHead = !sampleInfoListAt(startTime).Any(s => s.Name == SampleInfo.HIT_WHISTLE || s.Name == SampleInfo.HIT_FINISH || s.Name == SampleInfo.HIT_CLAP); - int nextColumn = Random.Next(RandomStart, AvailableColumns); + int nextColumn = Random.Next(RandomStart, TotalColumns); var rowPattern = new Pattern(); - for (int i = 0; i <= repeatCount; i++) + for (int i = 0; i <= spanCount; i++) { if (!(ignoreHead && startTime == HitObject.StartTime)) { for (int j = 0; j < noteCount; j++) { while (rowPattern.ColumnHasObject(nextColumn) || nextColumn == holdColumn) - nextColumn = Random.Next(RandomStart, AvailableColumns); + nextColumn = Random.Next(RandomStart, TotalColumns); addToPattern(rowPattern, nextColumn, startTime, startTime); } } @@ -443,7 +442,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if (curveData == null) return HitObject.Samples; - double segmentTime = (endTime - HitObject.StartTime) / repeatCount; + double segmentTime = (endTime - HitObject.StartTime) / spanCount; int index = (int)(segmentTime == 0 ? 0 : (time - HitObject.StartTime) / segmentTime); return curveData.RepeatSamples[index]; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs index 8e832960df..278a4c4aab 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs @@ -1,8 +1,7 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -16,8 +15,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy { private readonly double endTime; - public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns) - : base(random, hitObject, beatmap, availableColumns, new Pattern()) + public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap) + : base(random, hitObject, beatmap, new Pattern()) { var endtimeData = HitObject as IHasEndTime; @@ -30,14 +29,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy bool generateHold = endTime - HitObject.StartTime >= 100; - if (AvailableColumns == 8) + if (TotalColumns == 8) { if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000) addToPattern(pattern, 0, generateHold); else addToPattern(pattern, getNextRandomColumn(RandomStart), generateHold); } - else if (AvailableColumns > 0) + else if (TotalColumns > 0) addToPattern(pattern, getNextRandomColumn(0), generateHold); return pattern; @@ -50,10 +49,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// A random column after . private int getNextRandomColumn(int start) { - int nextColumn = Random.Next(start, AvailableColumns); + int nextColumn = Random.Next(start, TotalColumns); while (PreviousPattern.ColumnHasObject(nextColumn)) - nextColumn = Random.Next(start, AvailableColumns); + nextColumn = Random.Next(start, TotalColumns); return nextColumn; } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs index 077b926635..c4ef23a982 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/HitObjectPatternGenerator.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Linq; using OpenTK; using osu.Game.Audio; -using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Mania.Objects; @@ -20,8 +19,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy private readonly PatternType convertType; - public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair) - : base(random, hitObject, beatmap, availableColumns, previousPattern) + public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair) + : base(random, hitObject, beatmap, previousPattern) { if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime)); if (density < 0) throw new ArgumentOutOfRangeException(nameof(density)); @@ -88,23 +87,23 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy // Generate a new pattern by copying the last hit objects in reverse-column order var pattern = new Pattern(); - for (int i = RandomStart; i < AvailableColumns; i++) + for (int i = RandomStart; i < TotalColumns; i++) if (PreviousPattern.ColumnHasObject(i)) - addToPattern(pattern, RandomStart + AvailableColumns - i - 1); + addToPattern(pattern, RandomStart + TotalColumns - i - 1); return pattern; } if ((convertType & PatternType.Cycle) > 0 && PreviousPattern.HitObjects.Count() == 1 // If we convert to 7K + 1, let's not overload the special key - && (AvailableColumns != 8 || lastColumn != 0) + && (TotalColumns != 8 || lastColumn != 0) // Make sure the last column was not the centre column - && (AvailableColumns % 2 == 0 || lastColumn != AvailableColumns / 2)) + && (TotalColumns % 2 == 0 || lastColumn != TotalColumns / 2)) { // Generate a new pattern by cycling backwards (similar to Reverse but for only one hit object) var pattern = new Pattern(); - int column = RandomStart + AvailableColumns - lastColumn - 1; + int column = RandomStart + TotalColumns - lastColumn - 1; addToPattern(pattern, column); return pattern; @@ -115,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy // Generate a new pattern by placing on the already filled columns var pattern = new Pattern(); - for (int i = RandomStart; i < AvailableColumns; i++) + for (int i = RandomStart; i < TotalColumns; i++) if (PreviousPattern.ColumnHasObject(i)) addToPattern(pattern, i); @@ -128,7 +127,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy var pattern = new Pattern(); int targetColumn = lastColumn + 1; - if (targetColumn == AvailableColumns) + if (targetColumn == TotalColumns) { targetColumn = RandomStart; StairType = PatternType.ReverseStair; @@ -146,7 +145,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy int targetColumn = lastColumn - 1; if (targetColumn == RandomStart - 1) { - targetColumn = AvailableColumns - 1; + targetColumn = TotalColumns - 1; StairType = PatternType.Stair; } @@ -206,7 +205,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy bool allowStacking = (convertType & PatternType.ForceNotStack) == 0; if (!allowStacking) - noteCount = Math.Min(noteCount, AvailableColumns - RandomStart - PreviousPattern.ColumnWithObjects); + noteCount = Math.Min(noteCount, TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); for (int i = 0; i < noteCount; i++) @@ -216,11 +215,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if ((convertType & PatternType.Gathered) > 0) { nextColumn++; - if (nextColumn == AvailableColumns) + if (nextColumn == TotalColumns) nextColumn = RandomStart; } else - nextColumn = Random.Next(RandomStart, AvailableColumns); + nextColumn = Random.Next(RandomStart, TotalColumns); } addToPattern(pattern, nextColumn); @@ -268,7 +267,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy bool addToCentre; int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out addToCentre); - int columnLimit = (AvailableColumns % 2 == 0 ? AvailableColumns : AvailableColumns - 1) / 2; + int columnLimit = (TotalColumns % 2 == 0 ? TotalColumns : TotalColumns - 1) / 2; int nextColumn = Random.Next(RandomStart, columnLimit); for (int i = 0; i < noteCount; i++) { @@ -278,11 +277,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy // Add normal note addToPattern(pattern, nextColumn); // Add mirrored note - addToPattern(pattern, RandomStart + AvailableColumns - nextColumn - 1); + addToPattern(pattern, RandomStart + TotalColumns - nextColumn - 1); } if (addToCentre) - addToPattern(pattern, AvailableColumns / 2); + addToPattern(pattern, TotalColumns / 2); if (RandomStart > 0 && hasSpecialColumn) addToPattern(pattern, 0); @@ -300,7 +299,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// The amount of notes to be generated. private int getRandomNoteCount(double p2, double p3, double p4, double p5) { - switch (AvailableColumns) + switch (TotalColumns) { case 2: p2 = 0; @@ -348,7 +347,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy if ((convertType & PatternType.ForceNotStack) > 0) return getRandomNoteCount(p2 / 2, p2, (p2 + p3) / 2, p3); - switch (AvailableColumns) + switch (TotalColumns) { case 2: centreProbability = 0; @@ -379,7 +378,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy double centreVal = Random.NextDouble(); int noteCount = GetRandomNoteCount(p2, p3); - addToCentre = AvailableColumns % 2 != 0 && noteCount != 3 && centreVal > 1 - centreProbability; + addToCentre = TotalColumns % 2 != 0 && noteCount != 3 && centreVal > 1 - centreProbability; return noteCount; } diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index c38680c3a5..5f98749f0c 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -25,16 +25,15 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// protected readonly FastRandom Random; - protected PatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) - : base(hitObject, beatmap, availableColumns, previousPattern) + protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern) + : base(hitObject, beatmap, previousPattern) { if (random == null) throw new ArgumentNullException(nameof(random)); if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); - if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns)); if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern)); Random = random; - RandomStart = AvailableColumns == 8 ? 1 : 0; + RandomStart = TotalColumns == 8 ? 1 : 0; } /// @@ -45,14 +44,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy /// The column. protected int GetColumn(float position, bool allowSpecial = false) { - if (allowSpecial && AvailableColumns == 8) + if (allowSpecial && TotalColumns == 8) { const float local_x_divisor = 512f / 7; return MathHelper.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; } - float localXDivisor = 512f / AvailableColumns; - return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, AvailableColumns - 1); + float localXDivisor = 512f / TotalColumns; + return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1); } /// diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs index d645882511..2ead37e136 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternType.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs index 15d31406e9..d4b0eafa64 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Pattern.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index ef321232c8..6862fd57c1 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -1,8 +1,7 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns @@ -12,11 +11,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// internal abstract class PatternGenerator { - /// - /// The number of columns available to create the pattern. - /// - protected readonly int AvailableColumns; - /// /// The last pattern. /// @@ -30,19 +24,21 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// /// The beatmap which is a part of. /// - protected readonly Beatmap Beatmap; + protected readonly ManiaBeatmap Beatmap; - protected PatternGenerator(HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) + protected readonly int TotalColumns; + + protected PatternGenerator(HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern) { if (hitObject == null) throw new ArgumentNullException(nameof(hitObject)); if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); - if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns)); if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern)); HitObject = hitObject; Beatmap = beatmap; - AvailableColumns = availableColumns; PreviousPattern = previousPattern; + + TotalColumns = Beatmap.TotalColumns; } /// diff --git a/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs b/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs new file mode 100644 index 0000000000..aeefc2f396 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Beatmaps/StageDefinition.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mania.UI; + +namespace osu.Game.Rulesets.Mania.Beatmaps +{ + /// + /// Defines properties for each stage in a . + /// + public struct StageDefinition + { + /// + /// The number of s which this stage contains. + /// + public int Columns; + } +} diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs new file mode 100644 index 0000000000..a4de360870 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaConfigManager.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration.Tracking; +using osu.Game.Configuration; +using osu.Game.Rulesets.Configuration; + +namespace osu.Game.Rulesets.Mania.Configuration +{ + public class ManiaConfigManager : RulesetConfigManager + { + public ManiaConfigManager(SettingsStore settings, RulesetInfo ruleset, int variant) + : base(settings, ruleset, variant) + { + } + + protected override void InitialiseDefaults() + { + base.InitialiseDefaults(); + + Set(ManiaSetting.ScrollTime, 1500.0, 50.0, 10000.0, 50.0); + } + + public override TrackedSettings CreateTrackedSettings() => new TrackedSettings + { + new TrackedSetting(ManiaSetting.ScrollTime, v => new SettingDescription(v, "Scroll Time", $"{v}ms")) + }; + } + + public enum ManiaSetting + { + ScrollTime + } +} diff --git a/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs b/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs deleted file mode 100644 index ded1bc17af..0000000000 --- a/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Scoring; - -namespace osu.Game.Rulesets.Mania.Judgements -{ - public class HitWindows - { - #region Constants - - /// - /// PERFECT hit window at OD = 10. - /// - private const double perfect_min = 27.8; - /// - /// PERFECT hit window at OD = 5. - /// - private const double perfect_mid = 38.8; - /// - /// PERFECT hit window at OD = 0. - /// - private const double perfect_max = 44.8; - - /// - /// GREAT hit window at OD = 10. - /// - private const double great_min = 68; - /// - /// GREAT hit window at OD = 5. - /// - private const double great_mid = 98; - /// - /// GREAT hit window at OD = 0. - /// - private const double great_max = 128; - - /// - /// GOOD hit window at OD = 10. - /// - private const double good_min = 134; - /// - /// GOOD hit window at OD = 5. - /// - private const double good_mid = 164; - /// - /// GOOD hit window at OD = 0. - /// - private const double good_max = 194; - - /// - /// OK hit window at OD = 10. - /// - private const double ok_min = 194; - /// - /// OK hit window at OD = 5. - /// - private const double ok_mid = 224; - /// - /// OK hit window at OD = 0. - /// - private const double ok_max = 254; - - /// - /// BAD hit window at OD = 10. - /// - private const double bad_min = 242; - /// - /// BAD hit window at OD = 5. - /// - private const double bad_mid = 272; - /// - /// BAD hit window at OD = 0. - /// - private const double bad_max = 302; - - /// - /// MISS hit window at OD = 10. - /// - private const double miss_min = 316; - /// - /// MISS hit window at OD = 5. - /// - private const double miss_mid = 346; - /// - /// MISS hit window at OD = 0. - /// - private const double miss_max = 376; - - #endregion - - /// - /// Hit window for a PERFECT hit. - /// - public double Perfect = perfect_mid; - - /// - /// Hit window for a GREAT hit. - /// - public double Great = great_mid; - - /// - /// Hit window for a GOOD hit. - /// - public double Good = good_mid; - - /// - /// Hit window for an OK hit. - /// - public double Ok = ok_mid; - - /// - /// Hit window for a BAD hit. - /// - public double Bad = bad_mid; - - /// - /// Hit window for a MISS hit. - /// - public double Miss = miss_mid; - - /// - /// Constructs default hit windows. - /// - public HitWindows() - { - } - - /// - /// Constructs hit windows by fitting a parameter to a 2-part piecewise linear function for each hit window. - /// - /// The parameter. - public HitWindows(double difficulty) - { - Perfect = BeatmapDifficulty.DifficultyRange(difficulty, perfect_max, perfect_mid, perfect_min); - Great = BeatmapDifficulty.DifficultyRange(difficulty, great_max, great_mid, great_min); - Good = BeatmapDifficulty.DifficultyRange(difficulty, good_max, good_mid, good_min); - Ok = BeatmapDifficulty.DifficultyRange(difficulty, ok_max, ok_mid, ok_min); - Bad = BeatmapDifficulty.DifficultyRange(difficulty, bad_max, bad_mid, bad_min); - Miss = BeatmapDifficulty.DifficultyRange(difficulty, miss_max, miss_mid, miss_min); - } - - /// - /// Retrieves the hit result for a time offset. - /// - /// The time offset. - /// The hit result, or null if the time offset results in a miss. - public HitResult? ResultFor(double hitOffset) - { - if (hitOffset <= Perfect / 2) - return HitResult.Perfect; - if (hitOffset <= Great / 2) - return HitResult.Great; - if (hitOffset <= Good / 2) - return HitResult.Good; - if (hitOffset <= Ok / 2) - return HitResult.Ok; - if (hitOffset <= Bad / 2) - return HitResult.Meh; - return null; - } - - /// - /// Constructs new hit windows which have been multiplied by a value. - /// - /// The original hit windows. - /// The value to multiply each hit window by. - public static HitWindows operator *(HitWindows windows, double value) - { - return new HitWindows - { - Perfect = windows.Perfect * value, - Great = windows.Great * value, - Good = windows.Good * value, - Ok = windows.Ok * value, - Bad = windows.Bad * value, - Miss = windows.Miss * value - }; - } - - /// - /// Constructs new hit windows which have been divided by a value. - /// - /// The original hit windows. - /// The value to divide each hit window by. - public static HitWindows operator /(HitWindows windows, double value) - { - return new HitWindows - { - Perfect = windows.Perfect / value, - Great = windows.Great / value, - Good = windows.Good / value, - Ok = windows.Ok / value, - Bad = windows.Bad / value, - Miss = windows.Miss / value - }; - } - } -} diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs index e369df6ae1..361923266c 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index 4787a4977b..62df4a30cc 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index 4762a98c40..dae89bf88d 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs index e0763284a6..75a8543548 100644 --- a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using System.Collections.Generic; -using System; namespace osu.Game.Rulesets.Mania { @@ -18,6 +17,6 @@ namespace osu.Game.Rulesets.Mania public override double Calculate(Dictionary categoryDifficulty = null) => 0; - protected override BeatmapConverter CreateBeatmapConverter(Beatmap beatmap) => new ManiaBeatmapConverter(true, (int)Math.Max(1, Math.Round(beatmap.BeatmapInfo.BaseDifficulty.CircleSize))); + protected override BeatmapConverter CreateBeatmapConverter(Beatmap beatmap) => new ManiaBeatmapConverter(true, beatmap); } } diff --git a/osu.Game.Rulesets.Mania/ManiaInputManager.cs b/osu.Game.Rulesets.Mania/ManiaInputManager.cs index a574bc75ec..01e2821540 100644 --- a/osu.Game.Rulesets.Mania/ManiaInputManager.cs +++ b/osu.Game.Rulesets.Mania/ManiaInputManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; @@ -17,8 +17,13 @@ namespace osu.Game.Rulesets.Mania public enum ManiaAction { - [Description("Special")] - Special, + [Description("Special 1")] + Special1 = 1, + [Description("Special 2")] + Special2, + + // This offsets the start value of normal keys in-case we add more special keys + // above at a later time, without breaking replays/configs. [Description("Key 1")] Key1 = 10, [Description("Key 2")] @@ -36,6 +41,24 @@ namespace osu.Game.Rulesets.Mania [Description("Key 8")] Key8, [Description("Key 9")] - Key9 + Key9, + [Description("Key 10")] + Key10, + [Description("Key 11")] + Key11, + [Description("Key 12")] + Key12, + [Description("Key 13")] + Key13, + [Description("Key 14")] + Key14, + [Description("Key 15")] + Key15, + [Description("Key 16")] + Key16, + [Description("Key 17")] + Key17, + [Description("Key 18")] + Key18, } } diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 070c7b09d1..3bfb4d3e44 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -1,12 +1,14 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Game.Beatmaps; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Game.Graphics; @@ -86,7 +88,7 @@ namespace osu.Game.Rulesets.Mania }, }, new ManiaModRandom(), - new ManiaModKeyCoop(), + new ManiaModDualStages(), new MultiMod { Mods = new Mod[] @@ -95,7 +97,6 @@ namespace osu.Game.Rulesets.Mania new ModCinema(), }, }, - new ManiaModGravity() }; default: @@ -113,47 +114,194 @@ namespace osu.Game.Rulesets.Mania public override int LegacyID => 3; - public ManiaRuleset(RulesetInfo rulesetInfo) + public ManiaRuleset(RulesetInfo rulesetInfo = null) : base(rulesetInfo) { } - public override IEnumerable AvailableVariants => new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + public override IEnumerable AvailableVariants + { + get + { + for (int i = 1; i <= 9; i++) + yield return (int)PlayfieldType.Single + i; + for (int i = 2; i <= 18; i += 2) + yield return (int)PlayfieldType.Dual + i; + } + } public override IEnumerable GetDefaultKeyBindings(int variant = 0) { - var leftKeys = new[] + switch (getPlayfieldType(variant)) { - InputKey.A, - InputKey.S, - InputKey.D, - InputKey.F - }; + case PlayfieldType.Single: + return new VariantMappingGenerator + { + LeftKeys = new[] + { + InputKey.A, + InputKey.S, + InputKey.D, + InputKey.F + }, + RightKeys = new[] + { + InputKey.J, + InputKey.K, + InputKey.L, + InputKey.Semicolon + }, + SpecialKey = InputKey.Space, + SpecialAction = ManiaAction.Special1, + NormalActionStart = ManiaAction.Key1, + }.GenerateKeyBindingsFor(variant, out _); + case PlayfieldType.Dual: + int keys = getDualStageKeyCount(variant); - var rightKeys = new[] - { - InputKey.J, - InputKey.K, - InputKey.L, - InputKey.Semicolon - }; + var stage1Bindings = new VariantMappingGenerator + { + LeftKeys = new[] + { + InputKey.Number1, + InputKey.Number2, + InputKey.Number3, + InputKey.Number4, + }, + RightKeys = new[] + { + InputKey.Z, + InputKey.X, + InputKey.C, + InputKey.V + }, + SpecialKey = InputKey.Tilde, + SpecialAction = ManiaAction.Special1, + NormalActionStart = ManiaAction.Key1 + }.GenerateKeyBindingsFor(keys, out var nextNormal); - ManiaAction currentKey = ManiaAction.Key1; + var stage2Bindings = new VariantMappingGenerator + { + LeftKeys = new[] + { + InputKey.Number7, + InputKey.Number8, + InputKey.Number9, + InputKey.Number0 + }, + RightKeys = new[] + { + InputKey.O, + InputKey.P, + InputKey.BracketLeft, + InputKey.BracketRight + }, + SpecialKey = InputKey.BackSlash, + SpecialAction = ManiaAction.Special2, + NormalActionStart = nextNormal + }.GenerateKeyBindingsFor(keys, out _); - var bindings = new List(); + return stage1Bindings.Concat(stage2Bindings); + } - for (int i = leftKeys.Length - variant / 2; i < leftKeys.Length; i++) - bindings.Add(new KeyBinding(leftKeys[i], currentKey++)); - - for (int i = 0; i < variant / 2; i++) - bindings.Add(new KeyBinding(rightKeys[i], currentKey++)); - - if (variant % 2 == 1) - bindings.Add(new KeyBinding(InputKey.Space, ManiaAction.Special)); - - return bindings; + return new KeyBinding[0]; } - public override string GetVariantName(int variant) => $"{variant}K"; + public override string GetVariantName(int variant) + { + switch (getPlayfieldType(variant)) + { + default: + return $"{variant}K"; + case PlayfieldType.Dual: + { + var keys = getDualStageKeyCount(variant); + return $"{keys}K + {keys}K"; + } + } + } + + /// + /// Finds the number of keys for each stage in a variant. + /// + /// The variant. + private int getDualStageKeyCount(int variant) => (variant - (int)PlayfieldType.Dual) / 2; + + /// + /// Finds the that corresponds to a variant value. + /// + /// The variant value. + /// The that corresponds to . + private PlayfieldType getPlayfieldType(int variant) + { + return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast().OrderByDescending(i => i).First(v => variant >= v); + } + + private class VariantMappingGenerator + { + /// + /// All the s available to the left hand. + /// + public InputKey[] LeftKeys; + + /// + /// All the s available to the right hand. + /// + public InputKey[] RightKeys; + + /// + /// The for the special key. + /// + public InputKey SpecialKey; + + /// + /// The at which the normal columns should begin. + /// + public ManiaAction NormalActionStart; + + /// + /// The for the special column. + /// + public ManiaAction SpecialAction; + + /// + /// Generates a list of s for a specific number of columns. + /// + /// The number of columns that need to be bound. + /// The next to use for normal columns. + /// The keybindings. + public IEnumerable GenerateKeyBindingsFor(int columns, out ManiaAction nextNormalAction) + { + ManiaAction currentNormalAction = NormalActionStart; + + var bindings = new List(); + + for (int i = LeftKeys.Length - columns / 2; i < LeftKeys.Length; i++) + bindings.Add(new KeyBinding(LeftKeys[i], currentNormalAction++)); + + for (int i = 0; i < columns / 2; i++) + bindings.Add(new KeyBinding(RightKeys[i], currentNormalAction++)); + + if (columns % 2 == 1) + bindings.Add(new KeyBinding(SpecialKey, SpecialAction)); + + nextNormalAction = currentNormalAction; + return bindings; + } + } + } + + public enum PlayfieldType + { + /// + /// Columns are grouped into a single stage. + /// Number of columns in this stage lies at (item - Single). + /// + Single = 0, + /// + /// Columns are grouped into two stages. + /// Overall number of columns lies at (item - Dual), further computation is required for + /// number of columns in each individual stage. + /// + Dual = 1000, } } diff --git a/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs b/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs index f31873d1c8..e14473c478 100644 --- a/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs +++ b/osu.Game.Rulesets.Mania/MathUtils/FastRandom.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs b/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs deleted file mode 100644 index 954ee3f481..0000000000 --- a/osu.Game.Rulesets.Mania/Mods/IGenerateSpeedAdjustments.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.Mania.Mods -{ - /// - /// A type of mod which generates speed adjustments that scroll the hit objects and bar lines. - /// - internal interface IGenerateSpeedAdjustments - { - /// - /// Applies this mod to a hit renderer. - /// - /// The hit renderer to apply to. - /// The per-column list of speed adjustments for hit objects. - /// The list of speed adjustments for bar lines. - void ApplyToRulesetContainer(ManiaRulesetContainer rulesetContainer, ref List[] hitObjectTimingChanges, ref List barlineTimingChanges); - } -} diff --git a/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs b/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs new file mode 100644 index 0000000000..93d98b5d83 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/IPlayfieldTypeMod.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public interface IPlayfieldTypeMod : IApplicableMod + { + /// + /// The which this requires. + /// + PlayfieldType PlayfieldType { get; } + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs new file mode 100644 index 0000000000..aafebb61ec --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter + { + public override string ShortenedName => Name; + public abstract int KeyCount { get; } + public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier + public override bool Ranked => true; + + public void ApplyToBeatmapConverter(BeatmapConverter beatmapConverter) + { + var mbc = (ManiaBeatmapConverter)beatmapConverter; + + // Although this can work, for now let's not allow keymods for mania-specific beatmaps + if (mbc.IsForCurrentRuleset) + return; + + mbc.TargetColumns = KeyCount; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaMod.cs b/osu.Game.Rulesets.Mania/Mods/ManiaMod.cs deleted file mode 100644 index 61e11f7610..0000000000 --- a/osu.Game.Rulesets.Mania/Mods/ManiaMod.cs +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Graphics; -using osu.Game.Rulesets.Mods; -using System; -using System.Linq; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.MathUtils; -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.Replays; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Scoring; -using osu.Game.Users; -using osu.Game.Rulesets.UI; - -namespace osu.Game.Rulesets.Mania.Mods -{ - public class ManiaModNoFail : ModNoFail - { - - } - - public class ManiaModEasy : ModEasy - { - - } - - public class ManiaModHidden : ModHidden - { - public override string Description => @"The notes fade out before you hit them!"; - public override double ScoreMultiplier => 1.0; - public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) }; - } - - public class ManiaModHardRock : ModHardRock - { - public override double ScoreMultiplier => 1.0; - } - - public class ManiaModSuddenDeath : ModSuddenDeath - { - - } - - public class ManiaModDaycore : ModDaycore - { - public override double ScoreMultiplier => 0.3; - } - - public class ManiaModDoubleTime : ModDoubleTime - { - public override double ScoreMultiplier => 1.0; - } - - public class ManiaModHalfTime : ModHalfTime - { - public override double ScoreMultiplier => 0.3; - } - - public class ManiaModNightcore : ModNightcore - { - public override double ScoreMultiplier => 1.0; - } - - public class ManiaModFlashlight : ModFlashlight - { - public override double ScoreMultiplier => 1.0; - public override Type[] IncompatibleMods => new[] { typeof(ModHidden) }; - } - - public class ManiaModPerfect : ModPerfect - { - - } - - public class ManiaModFadeIn : Mod - { - public override string Name => "FadeIn"; - public override string ShortenedName => "FI"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden; - public override ModType Type => ModType.DifficultyIncrease; - public override double ScoreMultiplier => 1; - public override bool Ranked => true; - public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) }; - } - - public class ManiaModRandom : Mod, IApplicableToRulesetContainer - { - public override string Name => "Random"; - public override string ShortenedName => "RD"; - public override FontAwesome Icon => FontAwesome.fa_osu_dice; - public override string Description => @"Shuffle around the notes!"; - public override double ScoreMultiplier => 1; - - public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) - { - int availableColumns = ((ManiaRulesetContainer)rulesetContainer).AvailableColumns; - var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => RNG.Next()).ToList(); - - rulesetContainer.Objects.OfType().ForEach(h => h.Column = shuffledColumns[h.Column]); - } - } - - public abstract class ManiaKeyMod : Mod - { - // TODO: implement using the IApplicable interface. Haven't done so yet because KeyCount isn't even hooked up at the moment. - - public override string ShortenedName => Name; - public abstract int KeyCount { get; } - public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier - public override bool Ranked => true; - } - - public class ManiaModKey1 : ManiaKeyMod - { - public override int KeyCount => 1; - public override string Name => "1K"; - } - - public class ManiaModKey2 : ManiaKeyMod - { - public override int KeyCount => 2; - public override string Name => "2K"; - } - - public class ManiaModKey3 : ManiaKeyMod - { - public override int KeyCount => 3; - public override string Name => "3K"; - } - - public class ManiaModKey4 : ManiaKeyMod - { - public override int KeyCount => 4; - public override string Name => "4K"; - } - - public class ManiaModKey5 : ManiaKeyMod - { - public override int KeyCount => 5; - public override string Name => "5K"; - } - - public class ManiaModKey6 : ManiaKeyMod - { - public override int KeyCount => 6; - public override string Name => "6K"; - } - - public class ManiaModKey7 : ManiaKeyMod - { - public override int KeyCount => 7; - public override string Name => "7K"; - } - - public class ManiaModKey8 : ManiaKeyMod - { - public override int KeyCount => 8; - public override string Name => "8K"; - } - - public class ManiaModKey9 : ManiaKeyMod - { - public override int KeyCount => 9; - public override string Name => "9K"; - } - - public class ManiaModKeyCoop : Mod - { - public override string Name => "KeyCoop"; - public override string ShortenedName => "2P"; - public override string Description => @"Double the key amount, double the fun!"; - public override double ScoreMultiplier => 1; - public override bool Ranked => true; - } - - public class ManiaModAutoplay : ModAutoplay - { - protected override Score CreateReplayScore(Beatmap beatmap) => new Score - { - User = new User { Username = "osu!topus!" }, - Replay = new ManiaAutoGenerator(beatmap).Generate(), - }; - } -} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs new file mode 100644 index 0000000000..3c5179cef0 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Replays; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModAutoplay : ModAutoplay + { + protected override Score CreateReplayScore(Beatmap beatmap) + { + return new Score + { + User = new User { Username = "osu!topus!" }, + Replay = new ManiaAutoGenerator(beatmap).Generate(), + }; + } + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs new file mode 100644 index 0000000000..7c7dc5e4f7 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDaycore.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModDaycore : ModDaycore + { + public override double ScoreMultiplier => 0.3; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs new file mode 100644 index 0000000000..64ce86e748 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModDoubleTime : ModDoubleTime + { + public override double ScoreMultiplier => 1.0; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs new file mode 100644 index 0000000000..3330d87e88 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs @@ -0,0 +1,53 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter, IApplicableToRulesetContainer + { + public override string Name => "Dual Stages"; + public override string ShortenedName => "DS"; + public override string Description => @"Double the stages, double the fun!"; + public override double ScoreMultiplier => 1; + public override bool Ranked => false; + + public void ApplyToBeatmapConverter(BeatmapConverter beatmapConverter) + { + var mbc = (ManiaBeatmapConverter)beatmapConverter; + + // Although this can work, for now let's not allow keymods for mania-specific beatmaps + if (mbc.IsForCurrentRuleset) + return; + + mbc.TargetColumns *= 2; + } + + public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + { + var mrc = (ManiaRulesetContainer)rulesetContainer; + + // Although this can work, for now let's not allow keymods for mania-specific beatmaps + if (mrc.IsForCurrentRuleset) + return; + + var newDefinitions = new List(); + foreach (var existing in mrc.Beatmap.Stages) + { + newDefinitions.Add(new StageDefinition { Columns = existing.Columns / 2 }); + newDefinitions.Add(new StageDefinition { Columns = existing.Columns / 2 }); + } + + mrc.Beatmap.Stages = newDefinitions; + } + + public PlayfieldType PlayfieldType => PlayfieldType.Dual; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs new file mode 100644 index 0000000000..1faed5e1c0 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModEasy.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModEasy : ModEasy + { + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs new file mode 100644 index 0000000000..03442507d6 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModFadeIn : Mod + { + public override string Name => "FadeIn"; + public override string ShortenedName => "FI"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden; + public override ModType Type => ModType.DifficultyIncrease; + public override double ScoreMultiplier => 1; + public override bool Ranked => true; + public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) }; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs new file mode 100644 index 0000000000..89eb02268e --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModFlashlight : ModFlashlight + { + public override double ScoreMultiplier => 1.0; + public override Type[] IncompatibleMods => new[] { typeof(ModHidden) }; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs deleted file mode 100644 index 70270af6c9..0000000000 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModGravity.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Collections.Generic; -using System.Linq; -using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Mods; -using osu.Game.Graphics; -using osu.Game.Rulesets.Mania.Timing; -using osu.Game.Rulesets.Timing; -using osu.Game.Rulesets.Mania.Objects.Drawables; - -namespace osu.Game.Rulesets.Mania.Mods -{ - public class ManiaModGravity : Mod, IGenerateSpeedAdjustments - { - public override string Name => "Gravity"; - public override string ShortenedName => "GR"; - - public override double ScoreMultiplier => 0; - - public override FontAwesome Icon => FontAwesome.fa_sort_desc; - - public void ApplyToRulesetContainer(ManiaRulesetContainer rulesetContainer, ref List[] hitObjectTimingChanges, ref List barlineTimingChanges) - { - // We have to generate one speed adjustment per hit object for gravity - foreach (ManiaHitObject obj in rulesetContainer.Objects.OfType()) - { - MultiplierControlPoint controlPoint = rulesetContainer.CreateControlPointAt(obj.StartTime); - // Beat length has too large of an effect for gravity, so we'll force it to a constant value for now - controlPoint.TimingPoint.BeatLength = 1000; - - hitObjectTimingChanges[obj.Column].Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity)); - } - - // Like with hit objects, we need to generate one speed adjustment per bar line - foreach (DrawableBarLine barLine in rulesetContainer.BarLines) - { - var controlPoint = rulesetContainer.CreateControlPointAt(barLine.HitObject.StartTime); - // Beat length has too large of an effect for gravity, so we'll force it to a constant value for now - controlPoint.TimingPoint.BeatLength = 1000; - - barlineTimingChanges.Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity)); - } - } - } -} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs new file mode 100644 index 0000000000..2f8404609f --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHalfTime.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModHalfTime : ModHalfTime + { + public override double ScoreMultiplier => 0.3; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs new file mode 100644 index 0000000000..91edbaf0cf --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModHardRock : ModHardRock + { + public override double ScoreMultiplier => 1.0; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs new file mode 100644 index 0000000000..c2fc07da89 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModHidden : ModHidden + { + public override string Description => @"The notes fade out before you hit them!"; + public override double ScoreMultiplier => 1.0; + public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) }; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs new file mode 100644 index 0000000000..8a6943d99b --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey1.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModKey1 : ManiaKeyMod + { + public override int KeyCount => 1; + public override string Name => "1K"; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs new file mode 100644 index 0000000000..553827ac1c --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey2.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModKey2 : ManiaKeyMod + { + public override int KeyCount => 2; + public override string Name => "2K"; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs new file mode 100644 index 0000000000..ef048c848e --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey3.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModKey3 : ManiaKeyMod + { + public override int KeyCount => 3; + public override string Name => "3K"; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs new file mode 100644 index 0000000000..9c713d920f --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey4.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModKey4 : ManiaKeyMod + { + public override int KeyCount => 4; + public override string Name => "4K"; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs new file mode 100644 index 0000000000..a83faf4627 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey5.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModKey5 : ManiaKeyMod + { + public override int KeyCount => 5; + public override string Name => "5K"; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs new file mode 100644 index 0000000000..d7df901048 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey6.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModKey6 : ManiaKeyMod + { + public override int KeyCount => 6; + public override string Name => "6K"; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs new file mode 100644 index 0000000000..4a3f9857e5 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey7.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModKey7 : ManiaKeyMod + { + public override int KeyCount => 7; + public override string Name => "7K"; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs new file mode 100644 index 0000000000..22c301fb7a --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey8.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModKey8 : ManiaKeyMod + { + public override int KeyCount => 8; + public override string Name => "8K"; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs new file mode 100644 index 0000000000..b2a0bc4ddf --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModKey9.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModKey9 : ManiaKeyMod + { + public override int KeyCount => 9; + public override string Name => "9K"; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs new file mode 100644 index 0000000000..a977eef5e3 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModNightcore : ModNightcore + { + public override double ScoreMultiplier => 1.0; + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs new file mode 100644 index 0000000000..c9c50f9919 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModNoFail.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModNoFail : ModNoFail + { + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs new file mode 100644 index 0000000000..2c0bd5f8c3 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModPerfect.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModPerfect : ModPerfect + { + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs new file mode 100644 index 0000000000..a6cbad44d7 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModRandom.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.MathUtils; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModRandom : Mod, IApplicableToRulesetContainer + { + public override string Name => "Random"; + public override string ShortenedName => "RD"; + public override FontAwesome Icon => FontAwesome.fa_osu_dice; + public override string Description => @"Shuffle around the notes!"; + public override double ScoreMultiplier => 1; + + public void ApplyToRulesetContainer(RulesetContainer rulesetContainer) + { + var availableColumns = ((ManiaRulesetContainer)rulesetContainer).Beatmap.TotalColumns; + var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => RNG.Next()).ToList(); + + rulesetContainer.Objects.OfType().ForEach(h => h.Column = shuffledColumns[h.Column]); + } + } +} diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModSuddenDeath.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModSuddenDeath.cs new file mode 100644 index 0000000000..9edf131195 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModSuddenDeath.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Mania.Mods +{ + public class ManiaModSuddenDeath : ModSuddenDeath + { + } +} diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs index 76a3d3920d..e5cba161a2 100644 --- a/osu.Game.Rulesets.Mania/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/BarLine.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps.ControlPoints; @@ -18,4 +18,4 @@ namespace osu.Game.Rulesets.Mania.Objects /// public int BeatIndex; } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index fc5ea4e116..91c83a62f0 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -71,4 +71,4 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs index 41d817a746..5a9ff592bc 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs @@ -1,13 +1,11 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Linq; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using OpenTK.Graphics; -using OpenTK; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Mania.Judgements; using osu.Framework.Extensions.IEnumerableExtensions; @@ -42,8 +40,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables public DrawableHoldNote(HoldNote hitObject, ManiaAction action) : base(hitObject, action) { - RelativeSizeAxes = Axes.Both; - Height = (float)HitObject.Duration; + RelativeSizeAxes = Axes.X; AddRange(new Drawable[] { @@ -60,12 +57,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, }, - tickContainer = new Container - { - RelativeSizeAxes = Axes.Both, - RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime), - RelativeChildSize = new Vector2(1, (float)HitObject.Duration) - }, + tickContainer = new Container { RelativeSizeAxes = Axes.Both }, head = new DrawableHeadNote(this, action) { Anchor = Anchor.TopCentre, @@ -73,7 +65,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }, tail = new DrawableTailNote(this, action) { - Anchor = Anchor.BottomCentre, + Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre } }); @@ -157,7 +149,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables holdStartTime = null; // If the key has been released too early, the user should not receive full score for the release - if (!tail.AllJudged) + if (!tail.IsHit) hasBroken = true; return true; @@ -175,13 +167,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { this.holdNote = holdNote; - RelativePositionAxes = Axes.None; - Y = 0; - - // Life time managed by the parent DrawableHoldNote - LifetimeStart = double.MinValue; - LifetimeEnd = double.MaxValue; - GlowPiece.Alpha = 0; } @@ -200,6 +185,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return true; } + + protected override void UpdateState(ArmedState state) + { + // The holdnote keeps scrolling through for now, so having the head disappear looks weird + } } /// @@ -214,13 +204,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { this.holdNote = holdNote; - RelativePositionAxes = Axes.None; - Y = 0; - - // Life time managed by the parent DrawableHoldNote - LifetimeStart = double.MinValue; - LifetimeEnd = double.MaxValue; - GlowPiece.Alpha = 0; } @@ -228,7 +211,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { if (!userTriggered) { - if (timeOffset > HitObject.HitWindows.Bad / 2) + if (!HitObject.HitWindows.CanBeHit(timeOffset)) { AddJudgement(new HoldNoteTailJudgement { @@ -240,18 +223,22 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables return; } - double offset = Math.Abs(timeOffset); - - if (offset > HitObject.HitWindows.Miss / 2) + var result = HitObject.HitWindows.ResultFor(timeOffset); + if (result == HitResult.None) return; AddJudgement(new HoldNoteTailJudgement { - Result = HitObject.HitWindows.ResultFor(offset) ?? HitResult.Miss, + Result = result, HasBroken = holdNote.hasBroken }); } + protected override void UpdateState(ArmedState state) + { + // The holdnote keeps scrolling through, so having the tail disappear looks weird + } + public override bool OnPressed(ManiaAction action) => false; // Tail doesn't handle key down public override bool OnReleased(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 8ed5d2b924..f9c0b96d37 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -32,15 +32,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Anchor = Anchor.TopCentre; Origin = Anchor.TopCentre; - Y = (float)HitObject.StartTime; - RelativeSizeAxes = Axes.X; Size = new Vector2(1); - // Life time managed by the parent DrawableHoldNote - LifetimeStart = double.MinValue; - LifetimeEnd = double.MaxValue; - Children = new[] { glowContainer = new CircularContainer diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index 6354c6ff77..0a1624b464 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Mania.Objects.Drawables { - public abstract class DrawableManiaHitObject : DrawableScrollingHitObject + public abstract class DrawableManiaHitObject : DrawableHitObject where TObject : ManiaHitObject { /// @@ -20,7 +20,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables protected DrawableManiaHitObject(TObject hitObject, ManiaAction? action = null) : base(hitObject) { - RelativePositionAxes = Axes.Y; + Anchor = Anchor.TopCentre; + Origin = Anchor.TopCentre; + HitObject = hitObject; if (action != null) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index aabfcafa85..8944978bdd 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -1,7 +1,6 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; @@ -63,21 +62,27 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables { if (!userTriggered) { - if (timeOffset > HitObject.HitWindows.Bad / 2) + if (!HitObject.HitWindows.CanBeHit(timeOffset)) AddJudgement(new ManiaJudgement { Result = HitResult.Miss }); return; } - double offset = Math.Abs(timeOffset); - - if (offset > HitObject.HitWindows.Miss / 2) + var result = HitObject.HitWindows.ResultFor(timeOffset); + if (result == HitResult.None) return; - AddJudgement(new ManiaJudgement { Result = HitObject.HitWindows.ResultFor(offset) ?? HitResult.Miss }); + AddJudgement(new ManiaJudgement { Result = result }); } protected override void UpdateState(ArmedState state) { + switch (state) + { + case ArmedState.Hit: + case ArmedState.Miss: + this.FadeOut(100).Expire(); + break; + } } public virtual bool OnPressed(ManiaAction action) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs index fe40532e42..d2e6547be4 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/BodyPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs index 6f022f452f..5f4a4a6ace 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/GlowPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs index 6d4ac2fb61..ee83bc93d0 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/LaneGlowPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index 3df085c346..e8a3377689 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index f72bed3142..728c79b9cf 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; @@ -93,7 +93,6 @@ namespace osu.Game.Rulesets.Mania.Objects Column = Column }); } - } /// diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs index 6c4cf127f3..ec502a803d 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNoteTick.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Mania.Objects @@ -9,4 +9,4 @@ namespace osu.Game.Rulesets.Mania.Objects public class HoldNoteTick : ManiaHitObject { } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs index 7beb21f9e3..be93471bcd 100644 --- a/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaHitObject.cs @@ -1,6 +1,8 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Mania.Objects.Types; using osu.Game.Rulesets.Objects; @@ -9,5 +11,13 @@ namespace osu.Game.Rulesets.Mania.Objects public abstract class ManiaHitObject : HitObject, IHasColumn { public virtual int Column { get; set; } + + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) + { + base.ApplyDefaultsToSelf(controlPointInfo, difficulty); + + HitWindows.AllowsPerfect = true; + HitWindows.AllowsOk = true; + } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 51a9a18afa..438116b363 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -1,11 +1,6 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using Newtonsoft.Json; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Mania.Judgements; - namespace osu.Game.Rulesets.Mania.Objects { /// @@ -13,17 +8,5 @@ namespace osu.Game.Rulesets.Mania.Objects /// public class Note : ManiaHitObject { - /// - /// The key-press hit window for this note. - /// - [JsonIgnore] - public HitWindows HitWindows { get; protected set; } = new HitWindows(); - - protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) - { - base.ApplyDefaultsToSelf(controlPointInfo, difficulty); - - HitWindows = new HitWindows(difficulty.OverallDifficulty); - } } } diff --git a/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs b/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs index 8281d0d9e4..cdff2b0827 100644 --- a/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs +++ b/osu.Game.Rulesets.Mania/Objects/Types/IHasColumn.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Mania.Objects.Types diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 153fee3ab6..6f6217f540 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs index 12534d6eb4..fd084f138f 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaFramedReplayInputHandler.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index d1bc7da911..e5c5ac9eeb 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Replays; diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 140bab2225..c3b840b9f0 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game.Rulesets.Mania/Tests/TestCaseAutoGeneration.cs b/osu.Game.Rulesets.Mania/Tests/TestCaseAutoGeneration.cs index 805553eafc..81c6c5c9d5 100644 --- a/osu.Game.Rulesets.Mania/Tests/TestCaseAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania/Tests/TestCaseAutoGeneration.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; diff --git a/osu.Game.Rulesets.Mania/Tests/TestCaseManiaHitObjects.cs b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaHitObjects.cs index 03886f5784..0e6d40dc67 100644 --- a/osu.Game.Rulesets.Mania/Tests/TestCaseManiaHitObjects.cs +++ b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaHitObjects.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; @@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Mania.Tests RelativeChildSize = new Vector2(1, 10000), Children = new[] { - new DrawableHoldNote(new HoldNote(), ManiaAction.Key1) + new DrawableHoldNote(new HoldNote { Duration = 1000 } , ManiaAction.Key1) { Y = 5000, Height = 1000, diff --git a/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs index b5890b289f..7d35ab2f4d 100644 --- a/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs @@ -1,20 +1,19 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Timing; +using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Timing; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests @@ -34,24 +33,52 @@ namespace osu.Game.Rulesets.Mania.Tests { var rng = new Random(1337); - AddStep("1 column", () => createPlayfield(1, SpecialColumnPosition.Normal)); - AddStep("4 columns", () => createPlayfield(4, SpecialColumnPosition.Normal)); - AddStep("Left special style", () => createPlayfield(4, SpecialColumnPosition.Left)); - AddStep("Right special style", () => createPlayfield(4, SpecialColumnPosition.Right)); - AddStep("5 columns", () => createPlayfield(5, SpecialColumnPosition.Normal)); - AddStep("8 columns", () => createPlayfield(8, SpecialColumnPosition.Normal)); - AddStep("Left special style", () => createPlayfield(8, SpecialColumnPosition.Left)); - AddStep("Right special style", () => createPlayfield(8, SpecialColumnPosition.Right)); - AddStep("Reversed", () => createPlayfield(4, SpecialColumnPosition.Normal, true)); + AddStep("1 column", () => createPlayfield(1)); + AddStep("4 columns", () => createPlayfield(4)); + AddStep("5 columns", () => createPlayfield(5)); + AddStep("8 columns", () => createPlayfield(8)); + AddStep("4 + 4 columns", () => + { + var stages = new List + { + new StageDefinition { Columns = 4 }, + new StageDefinition { Columns = 4 }, + }; + createPlayfield(stages); + }); - AddStep("Notes with input", () => createPlayfieldWithNotes(false)); - AddStep("Notes with input (reversed)", () => createPlayfieldWithNotes(false, true)); - AddStep("Notes with gravity", () => createPlayfieldWithNotes(true)); - AddStep("Notes with gravity (reversed)", () => createPlayfieldWithNotes(true, true)); + AddStep("2 + 4 + 2 columns", () => + { + var stages = new List + { + new StageDefinition { Columns = 2 }, + new StageDefinition { Columns = 4 }, + new StageDefinition { Columns = 2 }, + }; + createPlayfield(stages); + }); + + AddStep("1 + 8 + 1 columns", () => + { + var stages = new List + { + new StageDefinition { Columns = 1 }, + new StageDefinition { Columns = 8 }, + new StageDefinition { Columns = 1 }, + }; + createPlayfield(stages); + }); + + AddStep("Reversed", () => createPlayfield(4, true)); + + AddStep("Notes with input", () => createPlayfieldWithNotes()); + AddStep("Notes with input (reversed)", () => createPlayfieldWithNotes(true)); + AddStep("Notes with gravity", () => createPlayfieldWithNotes()); + AddStep("Notes with gravity (reversed)", () => createPlayfieldWithNotes(true)); AddStep("Hit explosion", () => { - var playfield = createPlayfield(4, SpecialColumnPosition.Normal); + var playfield = createPlayfield(4); int col = rng.Next(0, 4); @@ -61,6 +88,7 @@ namespace osu.Game.Rulesets.Mania.Tests }; playfield.OnJudgement(note, new ManiaJudgement { Result = HitResult.Perfect }); + playfield.Columns[col].OnJudgement(note, new ManiaJudgement { Result = HitResult.Perfect }); }); } @@ -70,24 +98,29 @@ namespace osu.Game.Rulesets.Mania.Tests maniaRuleset = rulesets.GetRuleset(3); } - private SpeedAdjustmentContainer createTimingChange(double time, bool gravity) => new ManiaSpeedAdjustmentContainer(new MultiplierControlPoint(time) + private ManiaPlayfield createPlayfield(int cols, bool inverted = false) { - TimingPoint = { BeatLength = 1000 } - }, gravity ? ScrollingAlgorithm.Gravity : ScrollingAlgorithm.Basic); + var stages = new List + { + new StageDefinition { Columns = cols }, + }; - private ManiaPlayfield createPlayfield(int cols, SpecialColumnPosition specialPos, bool inverted = false) + return createPlayfield(stages, inverted); + } + + private ManiaPlayfield createPlayfield(List stages, bool inverted = false) { Clear(); - var inputManager = new ManiaInputManager(maniaRuleset, cols) { RelativeSizeAxes = Axes.Both }; + var inputManager = new ManiaInputManager(maniaRuleset, stages.Sum(g => g.Columns)) { RelativeSizeAxes = Axes.Both }; Add(inputManager); ManiaPlayfield playfield; - inputManager.Add(playfield = new ManiaPlayfield(cols) + + inputManager.Add(playfield = new ManiaPlayfield(stages) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - SpecialColumnPosition = specialPos }); playfield.Inverted.Value = inverted; @@ -95,7 +128,7 @@ namespace osu.Game.Rulesets.Mania.Tests return playfield; } - private void createPlayfieldWithNotes(bool gravity, bool inverted = false) + private void createPlayfieldWithNotes(bool inverted = false) { Clear(); @@ -105,7 +138,12 @@ namespace osu.Game.Rulesets.Mania.Tests Add(inputManager); ManiaPlayfield playfield; - inputManager.Add(playfield = new ManiaPlayfield(4) + var stages = new List + { + new StageDefinition { Columns = 4 }, + }; + + inputManager.Add(playfield = new ManiaPlayfield(stages) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -114,23 +152,14 @@ namespace osu.Game.Rulesets.Mania.Tests playfield.Inverted.Value = inverted; - if (!gravity) - playfield.Columns.ForEach(c => c.Add(createTimingChange(0, false))); - for (double t = start_time; t <= start_time + duration; t += 100) { - if (gravity) - playfield.Columns.ElementAt(0).Add(createTimingChange(t, true)); - playfield.Add(new DrawableNote(new Note { StartTime = t, Column = 0 }, ManiaAction.Key1)); - if (gravity) - playfield.Columns.ElementAt(3).Add(createTimingChange(t, true)); - playfield.Add(new DrawableNote(new Note { StartTime = t, @@ -138,9 +167,6 @@ namespace osu.Game.Rulesets.Mania.Tests }, ManiaAction.Key4)); } - if (gravity) - playfield.Columns.ElementAt(1).Add(createTimingChange(start_time, true)); - playfield.Add(new DrawableHoldNote(new HoldNote { StartTime = start_time, @@ -148,9 +174,6 @@ namespace osu.Game.Rulesets.Mania.Tests Column = 1 }, ManiaAction.Key2)); - if (gravity) - playfield.Columns.ElementAt(2).Add(createTimingChange(start_time, true)); - playfield.Add(new DrawableHoldNote(new HoldNote { StartTime = start_time, diff --git a/osu.Game.Rulesets.Mania/Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Mania/Tests/TestCasePerformancePoints.cs index 8aa8c6b799..c76816db6a 100644 --- a/osu.Game.Rulesets.Mania/Tests/TestCasePerformancePoints.cs +++ b/osu.Game.Rulesets.Mania/Tests/TestCasePerformancePoints.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Mania.Tests public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints { public TestCasePerformancePoints() - : base(new ManiaRuleset(new RulesetInfo())) + : base(new ManiaRuleset()) { } } diff --git a/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs b/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs deleted file mode 100644 index 699acc477b..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/GravityScrollingContainer.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.Mania.Timing -{ - /// - /// A that emulates a form of gravity where hit objects speed up over time. - /// - internal class GravityScrollingContainer : ScrollingContainer - { - private readonly MultiplierControlPoint controlPoint; - - public GravityScrollingContainer(MultiplierControlPoint controlPoint) - { - this.controlPoint = controlPoint; - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - // The gravity-adjusted start position - float startPos = (float)computeGravityTime(controlPoint.StartTime); - // The gravity-adjusted end position - float endPos = (float)computeGravityTime(controlPoint.StartTime + RelativeChildSize.Y); - - Y = startPos; - Height = endPos - startPos; - } - - /// - /// Applies gravity to a time value based on the current time. - /// - /// The time value gravity should be applied to. - /// The time after gravity is applied to . - private double computeGravityTime(double time) - { - double relativeTime = relativeTimeAt(time); - - // The sign of the relative time, this is used to apply backwards acceleration leading into startTime - double sign = relativeTime < 0 ? -1 : 1; - - return VisibleTimeRange - acceleration * relativeTime * relativeTime * sign; - } - - /// - /// The acceleration due to "gravity" of the content of this container. - /// - private double acceleration => 1 / VisibleTimeRange; - - /// - /// Computes the current time relative to , accounting for . - /// - /// The non-offset time. - /// The current time relative to - . - private double relativeTimeAt(double time) => Time.Current - time + VisibleTimeRange; - } -} diff --git a/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs b/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs deleted file mode 100644 index 321b4ee92b..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/ManiaSpeedAdjustmentContainer.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.Mania.Timing -{ - public class ManiaSpeedAdjustmentContainer : SpeedAdjustmentContainer - { - private readonly ScrollingAlgorithm scrollingAlgorithm; - - public ManiaSpeedAdjustmentContainer(MultiplierControlPoint timingSection, ScrollingAlgorithm scrollingAlgorithm) - : base(timingSection) - { - this.scrollingAlgorithm = scrollingAlgorithm; - } - - protected override ScrollingContainer CreateScrollingContainer() - { - switch (scrollingAlgorithm) - { - default: - return base.CreateScrollingContainer(); - case ScrollingAlgorithm.Gravity: - return new GravityScrollingContainer(ControlPoint); - } - } - } -} \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs b/osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs deleted file mode 100644 index 72e096f5aa..0000000000 --- a/osu.Game.Rulesets.Mania/Timing/ScrollingAlgorithm.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Rulesets.Mania.Timing -{ - public enum ScrollingAlgorithm - { - /// - /// Basic scrolling algorithm based on the timing section time. This is the default algorithm. - /// - Basic, - /// - /// Emulating a form of gravity where hit objects speed up over time. - /// - Gravity - } -} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 2d553f8639..21f00c003b 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -11,13 +11,14 @@ using osu.Framework.Graphics.Colour; using osu.Game.Graphics; using osu.Game.Rulesets.Objects.Drawables; using System; +using System.Linq; using osu.Framework.Input.Bindings; -using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { - public class Column : ScrollingPlayfield, IHasAccentColour + public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { private const float key_icon_size = 10; private const float key_icon_corner_radius = 3; @@ -45,8 +46,9 @@ namespace osu.Game.Rulesets.Mania.UI private const float opacity_pressed = 0.25f; public Column() - : base(Axes.Y) + : base(ScrollingDirection.Up) { + RelativeSizeAxes = Axes.Y; Width = column_width; InternalChildren = new Drawable[] @@ -61,7 +63,7 @@ namespace osu.Game.Rulesets.Mania.UI { Name = "Hit target + hit objects", RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = ManiaPlayfield.HIT_TARGET_POSITION }, + Padding = new MarginPadding { Top = ManiaStage.HIT_TARGET_POSITION }, Children = new Drawable[] { new Container @@ -115,7 +117,7 @@ namespace osu.Game.Rulesets.Mania.UI { Name = "Key", RelativeSizeAxes = Axes.X, - Height = ManiaPlayfield.HIT_TARGET_POSITION, + Height = ManiaStage.HIT_TARGET_POSITION, Children = new Drawable[] { new Box @@ -204,12 +206,13 @@ namespace osu.Game.Rulesets.Mania.UI public override void Add(DrawableHitObject hitObject) { hitObject.Depth = (float)hitObject.HitObject.StartTime; - hitObject.AccentColour = AccentColour; + hitObject.OnJudgement += OnJudgement; + HitObjects.Add(hitObject); } - public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) + internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { if (!judgement.IsHit) return; @@ -257,5 +260,26 @@ namespace osu.Game.Rulesets.Mania.UI public bool OnPressed(ManiaAction action) => Pressed?.Invoke(action) ?? false; public bool OnReleased(ManiaAction action) => Released?.Invoke(action) ?? false; } + + public bool OnPressed(ManiaAction action) + { + // Play the sounds of the next hitobject + if (HitObjects.AliveObjects.Any()) + { + // If there are alive hitobjects, we can abuse the fact that AliveObjects are sorted by time (see: Add()) + HitObjects.AliveObjects.First().PlaySamples(); + } + else + { + // If not, we do a slow search - we might want to do a BinarySearch here if this becomes problematic + // We fallback to LastOrDefault() if we're beyond the last note in the map + var hitObject = HitObjects.Objects.FirstOrDefault(h => h.HitObject.StartTime > Time.Current) ?? HitObjects.Objects.LastOrDefault(); + hitObject?.PlaySamples(); + } + + return false; + } + + public bool OnReleased(ManiaAction action) => false; } } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs index 08478cef33..8a03f5a785 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Mania.UI internal class DrawableManiaJudgement : DrawableJudgement { public DrawableManiaJudgement(Judgement judgement) - : base(judgement) + : base(judgement) { JudgementText.TextSize = 25; } diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index 433c518929..dcf54f0819 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 6c164a34f0..c3cbf81af1 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -1,238 +1,94 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.UI; -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Graphics.Containers; using System; -using osu.Game.Graphics; -using osu.Framework.Allocation; -using System.Linq; using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Configuration; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Mania.Configuration; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Mania.UI { public class ManiaPlayfield : ScrollingPlayfield { - public const float HIT_TARGET_POSITION = 50; - - private SpecialColumnPosition specialColumnPosition; - /// - /// The style to use for the special column. - /// - public SpecialColumnPosition SpecialColumnPosition - { - get { return specialColumnPosition; } - set - { - if (IsLoaded) - throw new InvalidOperationException($"Setting {nameof(SpecialColumnPosition)} after the playfield is loaded requires re-creating the playfield."); - specialColumnPosition = value; - } - } - /// /// Whether this playfield should be inverted. This flips everything inside the playfield. /// public readonly Bindable Inverted = new Bindable(true); - private readonly FlowContainer columns; - public IEnumerable Columns => columns.Children; + public List Columns => stages.SelectMany(x => x.Columns).ToList(); + private readonly List stages = new List(); - protected override Container Content => content; - private readonly Container content; - - private List normalColumnColours = new List(); - private Color4 specialColumnColour; - - private readonly Container judgements; - - private readonly int columnCount; - - public ManiaPlayfield(int columnCount) - : base(Axes.Y) + public ManiaPlayfield(List stageDefinitions) + : base(ScrollingDirection.Up) { - this.columnCount = columnCount; + if (stageDefinitions == null) + throw new ArgumentNullException(nameof(stageDefinitions)); - if (columnCount <= 0) - throw new ArgumentException("Can't have zero or fewer columns."); + if (stageDefinitions.Count <= 0) + throw new ArgumentException("Can't have zero or fewer stages."); Inverted.Value = true; - Container topLevelContainer; - InternalChildren = new Drawable[] + GridContainer playfieldGrid; + InternalChild = playfieldGrid = new GridContainer { - new Container - { - Name = "Playfield elements", - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Children = new Drawable[] - { - new Container - { - Name = "Columns mask", - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Masking = true, - Children = new Drawable[] - { - new Box - { - Name = "Background", - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black - }, - columns = new FillFlowContainer - { - Name = "Columns", - RelativeSizeAxes = Axes.Y, - AutoSizeAxes = Axes.X, - Direction = FillDirection.Horizontal, - Padding = new MarginPadding { Left = 1, Right = 1 }, - Spacing = new Vector2(1, 0) - }, - } - }, - new Container - { - Name = "Barlines mask", - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Y, - Width = 1366, // Bar lines should only be masked on the vertical axis - BypassAutoSizeAxes = Axes.Both, - Masking = true, - Child = content = new Container - { - Name = "Bar lines", - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.Y, - Padding = new MarginPadding { Top = HIT_TARGET_POSITION } - } - }, - judgements = new Container - { - Anchor = Anchor.TopCentre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Y = HIT_TARGET_POSITION + 150, - BypassAutoSizeAxes = Axes.Both - }, - topLevelContainer = new Container { RelativeSizeAxes = Axes.Both } - } - } + RelativeSizeAxes = Axes.Both, + Content = new[] { new Drawable[stageDefinitions.Count] } }; - var currentAction = ManiaAction.Key1; - for (int i = 0; i < columnCount; i++) + var normalColumnAction = ManiaAction.Key1; + var specialColumnAction = ManiaAction.Special1; + int firstColumnIndex = 0; + for (int i = 0; i < stageDefinitions.Count; i++) { - var c = new Column(); - c.VisibleTimeRange.BindTo(VisibleTimeRange); + var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction); + newStage.VisibleTimeRange.BindTo(VisibleTimeRange); + newStage.Inverted.BindTo(Inverted); - c.IsSpecial = isSpecialColumn(i); - c.Action = c.IsSpecial ? ManiaAction.Special : currentAction++; + playfieldGrid.Content[0][i] = newStage; - topLevelContainer.Add(c.TopLevelContainer.CreateProxy()); + stages.Add(newStage); + AddNested(newStage); - columns.Add(c); - AddNested(c); + firstColumnIndex += newStage.Columns.Count; } - - Inverted.ValueChanged += invertedChanged; - Inverted.TriggerChange(); } - private void invertedChanged(bool newValue) + public override void Add(DrawableHitObject h) => getStageByColumn(((ManiaHitObject)h.HitObject).Column).Add(h); + + public void Add(BarLine barline) => stages.ForEach(s => s.Add(barline)); + + private ManiaStage getStageByColumn(int column) { - Scale = new Vector2(1, newValue ? -1 : 1); - judgements.Scale = Scale; + int sum = 0; + foreach (var stage in stages) + { + sum = sum + stage.Columns.Count; + if (sum > column) + return stage; + } + + return null; } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(ManiaConfigManager maniaConfig) { - normalColumnColours = new List - { - colours.RedDark, - colours.GreenDark - }; - - specialColumnColour = colours.BlueDark; - - // Set the special column + colour + key - foreach (var column in Columns) - { - if (!column.IsSpecial) - continue; - - column.AccentColour = specialColumnColour; - } - - var nonSpecialColumns = Columns.Where(c => !c.IsSpecial).ToList(); - - // We'll set the colours of the non-special columns in a separate loop, because the non-special - // column colours are mirrored across their centre and special styles mess with this - for (int i = 0; i < Math.Ceiling(nonSpecialColumns.Count / 2f); i++) - { - Color4 colour = normalColumnColours[i % normalColumnColours.Count]; - nonSpecialColumns[i].AccentColour = colour; - nonSpecialColumns[nonSpecialColumns.Count - 1 - i].AccentColour = colour; - } + maniaConfig.BindWith(ManiaSetting.ScrollTime, VisibleTimeRange); } - public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) + internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { - var maniaObject = (ManiaHitObject)judgedObject.HitObject; - columns[maniaObject.Column].OnJudgement(judgedObject, judgement); - - judgements.Clear(); - judgements.Add(new DrawableManiaJudgement(judgement) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }); - } - - /// - /// Whether the column index is a special column for this playfield. - /// - /// The 0-based column index. - /// Whether the column is a special column. - private bool isSpecialColumn(int column) - { - switch (SpecialColumnPosition) - { - default: - case SpecialColumnPosition.Normal: - return columnCount % 2 == 1 && column == columnCount / 2; - case SpecialColumnPosition.Left: - return column == 0; - case SpecialColumnPosition.Right: - return column == columnCount - 1; - } - } - - public override void Add(DrawableHitObject h) => Columns.ElementAt(((ManiaHitObject)h.HitObject).Column).Add(h); - - public void Add(DrawableBarLine barline) => HitObjects.Add(barline); - - protected override void Update() - { - // Due to masking differences, it is not possible to get the width of the columns container automatically - // While masking on effectively only the Y-axis, so we need to set the width of the bar line container manually - content.Width = columns.Width; + getStageByColumn(((ManiaHitObject)judgedObject.HitObject).Column).OnJudgement(judgedObject, judgement); } } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs index 61446a31b6..436d5c1ea6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaRulesetContainer.cs @@ -1,10 +1,8 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; using System.Linq; -using OpenTK; using osu.Framework.Allocation; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; @@ -12,30 +10,30 @@ using osu.Framework.Input; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Configuration; +using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Scoring; -using osu.Game.Rulesets.Mania.Timing; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Timing; using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; namespace osu.Game.Rulesets.Mania.UI { public class ManiaRulesetContainer : ScrollingRulesetContainer { - /// - /// The number of columns which the should display, and which - /// the beatmap converter will attempt to convert beatmaps to use. - /// - public int AvailableColumns { get; private set; } + public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap; - public IEnumerable BarLines; + public IEnumerable BarLines; public ManiaRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset) : base(ruleset, beatmap, isForCurrentRuleset) @@ -44,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; var timingPoints = Beatmap.ControlPointInfo.TimingPoints; - var barLines = new List(); + var barLines = new List(); for (int i = 0; i < timingPoints.Count; i++) { @@ -56,12 +54,12 @@ namespace osu.Game.Rulesets.Mania.UI int index = 0; for (double t = timingPoints[i].Time; Precision.DefinitelyBigger(endTime, t); t += point.BeatLength, index++) { - barLines.Add(new DrawableBarLine(new BarLine + barLines.Add(new BarLine { StartTime = t, ControlPoint = point, BeatIndex = index - })); + }); } } @@ -74,7 +72,7 @@ namespace osu.Game.Rulesets.Mania.UI BarLines.ForEach(Playfield.Add); } - protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(AvailableColumns) + protected sealed override Playfield CreatePlayfield() => new ManiaPlayfield(Beatmap.Stages) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -82,27 +80,11 @@ namespace osu.Game.Rulesets.Mania.UI public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); - public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, AvailableColumns); + public override int Variant => (int)(Mods.OfType().FirstOrDefault()?.PlayfieldType ?? PlayfieldType.Single) + Beatmap.TotalColumns; - protected override BeatmapConverter CreateBeatmapConverter() - { - if (IsForCurrentRuleset) - AvailableColumns = (int)Math.Max(1, Math.Round(WorkingBeatmap.BeatmapInfo.BaseDifficulty.CircleSize)); - else - { - float percentSliderOrSpinner = (float)WorkingBeatmap.Beatmap.HitObjects.Count(h => h is IHasEndTime) / WorkingBeatmap.Beatmap.HitObjects.Count; - if (percentSliderOrSpinner < 0.2) - AvailableColumns = 7; - else if (percentSliderOrSpinner < 0.3 || Math.Round(WorkingBeatmap.BeatmapInfo.BaseDifficulty.CircleSize) >= 5) - AvailableColumns = Math.Round(WorkingBeatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty) > 5 ? 7 : 6; - else if (percentSliderOrSpinner > 0.6) - AvailableColumns = Math.Round(WorkingBeatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty) > 4 ? 5 : 4; - else - AvailableColumns = Math.Max(4, Math.Min((int)Math.Round(WorkingBeatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty) + 1, 7)); - } + public override PassThroughInputManager CreateInputManager() => new ManiaInputManager(Ruleset.RulesetInfo, Variant); - return new ManiaBeatmapConverter(IsForCurrentRuleset, AvailableColumns); - } + protected override BeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(IsForCurrentRuleset, WorkingBeatmap.Beatmap); protected override DrawableHitObject GetVisualRepresentation(ManiaHitObject h) { @@ -121,8 +103,8 @@ namespace osu.Game.Rulesets.Mania.UI protected override Vector2 GetPlayfieldAspectAdjust() => new Vector2(1, 0.8f); - protected override SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) => new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Basic); - protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay, this); + + protected override IRulesetConfigManager CreateConfig(Ruleset ruleset, SettingsStore settings) => new ManiaConfigManager(settings, Ruleset.RulesetInfo, Variant); } } diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs new file mode 100644 index 0000000000..ebd73d7dca --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -0,0 +1,229 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.UI.Scrolling; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Rulesets.Mania.UI +{ + /// + /// A collection of s. + /// + internal class ManiaStage : ScrollingPlayfield + { + public const float HIT_TARGET_POSITION = 50; + + /// + /// Whether this playfield should be inverted. This flips everything inside the playfield. + /// + public readonly Bindable Inverted = new Bindable(true); + + public IReadOnlyList Columns => columnFlow.Children; + private readonly FillFlowContainer columnFlow; + + protected override Container Content => content; + private readonly Container content; + + public Container Judgements => judgements; + private readonly Container judgements; + + private readonly Container topLevelContainer; + + private List normalColumnColours = new List(); + private Color4 specialColumnColour; + + private readonly int firstColumnIndex; + private readonly StageDefinition definition; + + public ManiaStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction) + : base(ScrollingDirection.Up) + { + this.firstColumnIndex = firstColumnIndex; + this.definition = definition; + + Name = "Stage"; + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + RelativeSizeAxes = Axes.Y; + AutoSizeAxes = Axes.X; + + InternalChildren = new Drawable[] + { + new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Children = new Drawable[] + { + new Container + { + Name = "Columns mask", + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Masking = true, + Children = new Drawable[] + { + new Box + { + Name = "Background", + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black + }, + columnFlow = new FillFlowContainer + { + Name = "Columns", + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding { Left = 1, Right = 1 }, + Spacing = new Vector2(1, 0) + }, + } + }, + new Container + { + Name = "Barlines mask", + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Y, + Width = 1366, // Bar lines should only be masked on the vertical axis + BypassAutoSizeAxes = Axes.Both, + Masking = true, + Child = content = new Container + { + Name = "Bar lines", + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.Y, + Padding = new MarginPadding { Top = HIT_TARGET_POSITION } + } + }, + judgements = new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Y = HIT_TARGET_POSITION + 150, + BypassAutoSizeAxes = Axes.Both + }, + topLevelContainer = new Container { RelativeSizeAxes = Axes.Both } + } + } + }; + + for (int i = 0; i < definition.Columns; i++) + { + var isSpecial = isSpecialColumn(i); + var column = new Column + { + IsSpecial = isSpecial, + Action = isSpecial ? specialColumnStartAction++ : normalColumnStartAction++ + }; + + AddColumn(column); + } + + Inverted.ValueChanged += invertedChanged; + Inverted.TriggerChange(); + } + + private void invertedChanged(bool newValue) + { + Scale = new Vector2(1, newValue ? -1 : 1); + Judgements.Scale = Scale; + } + + public void AddColumn(Column c) + { + c.VisibleTimeRange.BindTo(VisibleTimeRange); + + topLevelContainer.Add(c.TopLevelContainer.CreateProxy()); + columnFlow.Add(c); + AddNested(c); + } + + /// + /// Whether the column index is a special column for this playfield. + /// + /// The 0-based column index. + /// Whether the column is a special column. + private bool isSpecialColumn(int column) => definition.Columns % 2 == 1 && column == definition.Columns / 2; + + public override void Add(DrawableHitObject h) + { + var maniaObject = (ManiaHitObject)h.HitObject; + int columnIndex = maniaObject.Column - firstColumnIndex; + Columns.ElementAt(columnIndex).Add(h); + h.OnJudgement += OnJudgement; + } + + public void Add(BarLine barline) => base.Add(new DrawableBarLine(barline)); + + internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) + { + judgements.Clear(); + judgements.Add(new DrawableManiaJudgement(judgement) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + normalColumnColours = new List + { + colours.RedDark, + colours.GreenDark + }; + + specialColumnColour = colours.BlueDark; + + // Set the special column + colour + key + foreach (var column in Columns) + { + if (!column.IsSpecial) + continue; + + column.AccentColour = specialColumnColour; + } + + var nonSpecialColumns = Columns.Where(c => !c.IsSpecial).ToList(); + + // We'll set the colours of the non-special columns in a separate loop, because the non-special + // column colours are mirrored across their centre and special styles mess with this + for (int i = 0; i < Math.Ceiling(nonSpecialColumns.Count / 2f); i++) + { + Color4 colour = normalColumnColours[i % normalColumnColours.Count]; + nonSpecialColumns[i].AccentColour = colour; + nonSpecialColumns[nonSpecialColumns.Count - 1 - i].AccentColour = colour; + } + } + + protected override void Update() + { + // Due to masking differences, it is not possible to get the width of the columns container automatically + // While masking on effectively only the Y-axis, so we need to set the width of the bar line container manually + content.Width = columnFlow.Width; + } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/SpecialColumnPosition.cs b/osu.Game.Rulesets.Mania/UI/SpecialColumnPosition.cs deleted file mode 100644 index 7fd30e7d0d..0000000000 --- a/osu.Game.Rulesets.Mania/UI/SpecialColumnPosition.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Rulesets.Mania.UI -{ - public enum SpecialColumnPosition - { - /// - /// The special column will lie in the center of the columns. - /// - Normal, - /// - /// The special column will lie to the left of the columns. - /// - Left, - /// - /// The special column will lie to the right of the columns. - /// - Right - } -} diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 919ed04d5f..37cb47a83e 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index 31b374f71d..3dad5b508c 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Beatmaps { @@ -29,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count; } - obj.ComboIndex = comboIndex++; + obj.IndexInCurrentCombo = comboIndex++; obj.ComboColour = beatmap.ComboColors[colourIndex]; } } @@ -37,7 +36,6 @@ namespace osu.Game.Rulesets.Osu.Beatmaps private void applyStacking(Beatmap beatmap) { const int stack_distance = 3; - float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; // Reset stacking for (int i = 0; i <= beatmap.HitObjects.Count - 1; i++) @@ -58,6 +56,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps continue; double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime; + double stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; if (objectN.StartTime - endTime > stackThreshold) //We are no longer within stacking range of the next object. @@ -100,6 +99,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps OsuHitObject objectI = beatmap.HitObjects[i]; if (objectI.StackHeight != 0 || objectI is Spinner) continue; + double stackThreshold = objectI.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; + /* If this object is a hitcircle, then we enter this "special" case. * It either ends with a stack of hitcircles only, or a stack of hitcircles that are underneath a slider. * Any other case is handled by the "is Slider" code below this. diff --git a/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs b/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs index 0d7fa6c334..5f232b1889 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuEditPlayfield.cs @@ -1,15 +1,12 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Graphics.Cursor; using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Rulesets.Osu.Edit { public class OsuEditPlayfield : OsuPlayfield { - protected override CursorContainer CreateCursor() => null; - protected override bool ProxyApproachCircles => false; } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs b/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs index 1e9e4b4686..56efc25fa5 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuEditRulesetContainer.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Graphics.Cursor; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.UI; @@ -15,5 +16,7 @@ namespace osu.Game.Rulesets.Osu.Edit } protected override Playfield CreatePlayfield() => new OsuEditPlayfield(); + + protected override CursorContainer CreateCursor() => null; } } diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index ec3aa4661c..6652a5fde2 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index cd9c3888df..b2d9844613 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs new file mode 100644 index 0000000000..a6e67ea979 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Osu.Judgements +{ + public class OsuSliderTailJudgement : OsuJudgement + { + public override bool AffectsCombo => false; + protected override int NumericResultFor(HitResult result) => 0; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs deleted file mode 100644 index 7b1f80f439..0000000000 --- a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Rulesets.Osu.Replays; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Osu.Objects; -using System; -using System.Collections.Generic; -using System.Linq; -using osu.Game.Rulesets.Osu.UI; -using osu.Game.Rulesets.Scoring; -using OpenTK; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Framework.Graphics; -using osu.Game.Rulesets.Objects.Types; - -namespace osu.Game.Rulesets.Osu.Mods -{ - public class OsuModNoFail : ModNoFail - { - public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); - } - - public class OsuModEasy : ModEasy - { - } - - public class OsuModHidden : ModHidden, IApplicableToDrawableHitObjects - { - public override string Description => @"Play with no approach circles and fading notes for a slight score advantage."; - public override double ScoreMultiplier => 1.06; - - private const double fade_in_duration_multiplier = 0.4; - private const double fade_out_duration_multiplier = 0.3; - - private float preEmpt => DrawableOsuHitObject.TIME_PREEMPT; - - public void ApplyToDrawableHitObjects(IEnumerable drawables) - { - foreach (var d in drawables.OfType()) - { - d.ApplyCustomUpdateState += ApplyHiddenState; - d.FadeInDuration = preEmpt * fade_in_duration_multiplier; - } - } - - protected void ApplyHiddenState(DrawableHitObject drawable, ArmedState state) - { - if (!(drawable is DrawableOsuHitObject d)) - return; - - var fadeOutStartTime = d.HitObject.StartTime - preEmpt + d.FadeInDuration; - var fadeOutDuration = preEmpt * fade_out_duration_multiplier; - - // new duration from completed fade in to end (before fading out) - var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime; - - switch (drawable) - { - case DrawableHitCircle circle: - // we don't want to see the approach circle - circle.ApproachCircle.Hide(); - - // fade out immediately after fade in. - using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true)) - circle.FadeOut(fadeOutDuration); - break; - case DrawableSlider slider: - using (slider.BeginAbsoluteSequence(fadeOutStartTime, true)) - { - slider.Body.FadeOut(longFadeDuration, Easing.Out); - - // delay a bit less to let the sliderball fade out peacefully instead of having a hard cut - using (slider.BeginDelayedSequence(longFadeDuration - fadeOutDuration, true)) - slider.Ball.FadeOut(fadeOutDuration); - } - - break; - case DrawableSpinner spinner: - // hide elements we don't care about. - spinner.Disc.Hide(); - spinner.Ticks.Hide(); - spinner.Background.Hide(); - - using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true)) - { - spinner.FadeOut(fadeOutDuration); - - // speed up the end sequence accordingly - switch (state) - { - case ArmedState.Hit: - spinner.ScaleTo(spinner.Scale * 1.2f, fadeOutDuration * 2, Easing.Out); - break; - case ArmedState.Miss: - spinner.ScaleTo(spinner.Scale * 0.8f, fadeOutDuration * 2, Easing.In); - break; - } - - spinner.Expire(); - } - - break; - } - } - } - - public class OsuModHardRock : ModHardRock, IApplicableToHitObject - { - public override double ScoreMultiplier => 1.06; - public override bool Ranked => true; - - public void ApplyToHitObject(OsuHitObject hitObject) - { - hitObject.Position = new Vector2(hitObject.Position.X, OsuPlayfield.BASE_SIZE.Y - hitObject.Y); - - var slider = hitObject as Slider; - if (slider == null) - return; - - var newControlPoints = new List(); - slider.ControlPoints.ForEach(c => newControlPoints.Add(new Vector2(c.X, OsuPlayfield.BASE_SIZE.Y - c.Y))); - - slider.ControlPoints = newControlPoints; - slider.Curve?.Calculate(); // Recalculate the slider curve - } - } - - public class OsuModSuddenDeath : ModSuddenDeath - { - public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); - } - - public class OsuModDaycore : ModDaycore - { - public override double ScoreMultiplier => 0.5; - } - - public class OsuModDoubleTime : ModDoubleTime - { - public override double ScoreMultiplier => 1.12; - } - - public class OsuModRelax : ModRelax - { - public override string Description => "You don't need to click.\nGive your clicking/tapping finger a break from the heat of things."; - public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); - } - - public class OsuModHalfTime : ModHalfTime - { - public override double ScoreMultiplier => 0.5; - } - - public class OsuModNightcore : ModNightcore - { - public override double ScoreMultiplier => 1.12; - } - - public class OsuModFlashlight : ModFlashlight - { - public override double ScoreMultiplier => 1.12; - } - - public class OsuModPerfect : ModPerfect - { - } - - public class OsuModSpunOut : Mod - { - public override string Name => "Spun Out"; - public override string ShortenedName => "SO"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout; - public override string Description => @"Spinners will be automatically completed"; - public override double ScoreMultiplier => 0.9; - public override bool Ranked => true; - public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot) }; - } - - public class OsuModAutopilot : Mod - { - public override string Name => "Autopilot"; - public override string ShortenedName => "AP"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot; - public override string Description => @"Automatic cursor movement - just follow the rhythm."; - public override double ScoreMultiplier => 0; - public override bool Ranked => false; - public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) }; - } - - public class OsuModAutoplay : ModAutoplay - { - public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray(); - - protected override Score CreateReplayScore(Beatmap beatmap) => new Score - { - Replay = new OsuAutoGenerator(beatmap).Generate() - }; - } - - public class OsuModTarget : Mod - { - public override string Name => "Target"; - public override string ShortenedName => "TP"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_target; - public override string Description => @""; - public override double ScoreMultiplier => 1; - } -} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs new file mode 100644 index 0000000000..0c842143e4 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModAutopilot : Mod + { + public override string Name => "Autopilot"; + public override string ShortenedName => "AP"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot; + public override string Description => @"Automatic cursor movement - just follow the rhythm."; + public override double ScoreMultiplier => 0; + public override bool Ranked => false; + public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) }; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs new file mode 100644 index 0000000000..42fe95356d --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Replays; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModAutoplay : ModAutoplay + { + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray(); + + protected override Score CreateReplayScore(Beatmap beatmap) + { + return new Score + { + Replay = new OsuAutoGenerator(beatmap).Generate() + }; + } + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs new file mode 100644 index 0000000000..eb90338e2f --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDaycore.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModDaycore : ModDaycore + { + public override double ScoreMultiplier => 0.5; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs b/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs new file mode 100644 index 0000000000..5a835aac75 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModDoubleTime.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModDoubleTime : ModDoubleTime + { + public override double ScoreMultiplier => 1.12; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs b/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs new file mode 100644 index 0000000000..80c83bf5d8 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModEasy.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModEasy : ModEasy + { + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs new file mode 100644 index 0000000000..342c53b41f --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModFlashlight : ModFlashlight + { + public override double ScoreMultiplier => 1.12; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs new file mode 100644 index 0000000000..7d009b0344 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHalfTime.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModHalfTime : ModHalfTime + { + public override double ScoreMultiplier => 0.5; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs new file mode 100644 index 0000000000..dfbe9ad021 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.UI; +using OpenTK; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModHardRock : ModHardRock, IApplicableToHitObject + { + public override double ScoreMultiplier => 1.06; + public override bool Ranked => true; + + public void ApplyToHitObject(OsuHitObject hitObject) + { + hitObject.Position = new Vector2(hitObject.Position.X, OsuPlayfield.BASE_SIZE.Y - hitObject.Y); + + var slider = hitObject as Slider; + if (slider == null) + return; + + var newControlPoints = new List(); + slider.ControlPoints.ForEach(c => newControlPoints.Add(new Vector2(c.X, OsuPlayfield.BASE_SIZE.Y - c.Y))); + + slider.ControlPoints = newControlPoints; + slider.Curve?.Calculate(); // Recalculate the slider curve + } + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs new file mode 100644 index 0000000000..b4dd08eadb --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -0,0 +1,77 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects.Drawables; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModHidden : ModHidden, IApplicableToDrawableHitObjects + { + public override string Description => @"Play with no approach circles and fading notes for a slight score advantage."; + public override double ScoreMultiplier => 1.06; + + private const double fade_in_duration_multiplier = 0.4; + private const double fade_out_duration_multiplier = 0.3; + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (var d in drawables.OfType()) + { + d.ApplyCustomUpdateState += ApplyHiddenState; + d.HitObject.TimeFadein = d.HitObject.TimePreempt * fade_in_duration_multiplier; + } + } + + protected void ApplyHiddenState(DrawableHitObject drawable, ArmedState state) + { + if (!(drawable is DrawableOsuHitObject d)) + return; + + var fadeOutStartTime = d.HitObject.StartTime - d.HitObject.TimePreempt + d.HitObject.TimeFadein; + var fadeOutDuration = d.HitObject.TimePreempt * fade_out_duration_multiplier; + + // new duration from completed fade in to end (before fading out) + var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime; + + switch (drawable) + { + case DrawableHitCircle circle: + // we don't want to see the approach circle + circle.ApproachCircle.Hide(); + + // fade out immediately after fade in. + using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true)) + { + circle.FadeOut(fadeOutDuration); + } + + break; + case DrawableSlider slider: + using (slider.BeginAbsoluteSequence(fadeOutStartTime, true)) + { + slider.Body.FadeOut(longFadeDuration, Easing.Out); + } + + break; + case DrawableSpinner spinner: + // hide elements we don't care about. + spinner.Disc.Hide(); + spinner.Ticks.Hide(); + spinner.Background.Hide(); + + using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true)) + { + spinner.FadeOut(fadeOutDuration); + } + + break; + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs new file mode 100644 index 0000000000..aa0acff68d --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNightcore.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModNightcore : ModNightcore + { + public override double ScoreMultiplier => 1.12; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs b/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs new file mode 100644 index 0000000000..f94ee484fc --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModNoFail.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModNoFail : ModNoFail + { + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs b/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs new file mode 100644 index 0000000000..886048cd30 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModPerfect.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModPerfect : ModPerfect + { + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs new file mode 100644 index 0000000000..057916c04b --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModRelax : ModRelax + { + public override string Description => "You don't need to click.\nGive your clicking/tapping finger a break from the heat of things."; + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs new file mode 100644 index 0000000000..18b212f781 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModSpunOut : Mod + { + public override string Name => "Spun Out"; + public override string ShortenedName => "SO"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout; + public override string Description => @"Spinners will be automatically completed"; + public override double ScoreMultiplier => 0.9; + public override bool Ranked => true; + public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot) }; + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs b/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs new file mode 100644 index 0000000000..797e0af0ad --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModSuddenDeath.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Linq; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModSuddenDeath : ModSuddenDeath + { + public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); + } +} diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs new file mode 100644 index 0000000000..b2b5130be3 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTarget.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Osu.Mods +{ + public class OsuModTarget : Mod + { + public override string Name => "Target"; + public override string ShortenedName => "TP"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_target; + public override string Description => @""; + public override double ScoreMultiplier => 1; + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs index 192ab0536e..c7dd12cb0c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index ee0b5e6c50..8a93f7151f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index fca9187047..d501df492d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -96,12 +96,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections using (fp.BeginAbsoluteSequence(fadeInTime)) { - fp.FadeIn(DrawableOsuHitObject.TIME_FADEIN); - fp.ScaleTo(1, DrawableOsuHitObject.TIME_FADEIN, Easing.Out); + fp.FadeIn(currHitObject.TimeFadein); + fp.ScaleTo(1, currHitObject.TimeFadein, Easing.Out); - fp.MoveTo(pointEndPosition, DrawableOsuHitObject.TIME_FADEIN, Easing.Out); + fp.MoveTo(pointEndPosition, currHitObject.TimeFadein, Easing.Out); - fp.Delay(fadeOutTime - fadeInTime).FadeOut(DrawableOsuHitObject.TIME_FADEIN); + fp.Delay(fadeOutTime - fadeInTime).FadeOut(currHitObject.TimeFadein); } fp.Expire(true); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 72ca9b37a8..959c87bbba 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }, number = new NumberPiece { - Text = (HitObject.ComboIndex + 1).ToString(), + Text = (HitObject.IndexInCurrentCombo + 1).ToString(), }, ring = new RingPiece(), flash = new FlashPiece(), @@ -72,14 +72,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { if (!userTriggered) { - if (timeOffset > HitObject.HitWindowFor(HitResult.Meh)) + if (!HitObject.HitWindows.CanBeHit(timeOffset)) AddJudgement(new OsuJudgement { Result = HitResult.Miss }); return; } + var result = HitObject.HitWindows.ResultFor(timeOffset); + if (result == HitResult.None) + return; + AddJudgement(new OsuJudgement { - Result = HitObject.ScoreResultForOffset(Math.Abs(timeOffset)), + Result = result, PositionOffset = Vector2.Zero //todo: set to correct value }); } @@ -88,8 +92,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdatePreemptState(); - ApproachCircle.FadeIn(Math.Min(FadeInDuration * 2, TIME_PREEMPT)); - ApproachCircle.ScaleTo(1.1f, TIME_PREEMPT); + ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadein * 2, HitObject.TimePreempt)); + ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt); } protected override void UpdateCurrentState(ArmedState state) @@ -99,12 +103,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (state) { case ArmedState.Idle: - this.Delay(TIME_PREEMPT).FadeOut(500); + this.Delay(HitObject.TimePreempt).FadeOut(500); Expire(true); // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. - LifetimeEnd = HitObject.StartTime + HitObject.HitWindowFor(HitResult.Miss); + LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss); break; case ArmedState.Miss: ApproachCircle.FadeOut(50); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index f5f0300ae1..c8e42fa44f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; @@ -10,15 +10,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuHitObject : DrawableHitObject { - public const float TIME_PREEMPT = 600; - public const float TIME_FADEIN = 400; - - /// - /// The number of milliseconds used to fade in. - /// - public virtual double FadeInDuration { get; set; } = TIME_FADEIN; - - public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - TIME_PREEMPT; + public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - HitObject.TimePreempt; protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) @@ -29,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected sealed override void UpdateState(ArmedState state) { - double transformTime = HitObject.StartTime - TIME_PREEMPT; + double transformTime = HitObject.StartTime - HitObject.TimePreempt; base.ApplyTransformsAt(transformTime, true); base.ClearTransformsAfter(transformTime, true); @@ -38,12 +30,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { UpdatePreemptState(); - using (BeginDelayedSequence(TIME_PREEMPT + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true)) + using (BeginDelayedSequence(HitObject.TimePreempt + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true)) UpdateCurrentState(state); } } - protected virtual void UpdatePreemptState() => this.FadeIn(FadeInDuration); + protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadein); protected virtual void UpdateCurrentState(ArmedState state) { diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index f16a41519e..716f4b629b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 477ced01c6..79a4714e33 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; @@ -11,13 +12,12 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableRepeatPoint : DrawableOsuHitObject + public class DrawableRepeatPoint : DrawableOsuHitObject, ITrackSnaking { private readonly RepeatPoint repeatPoint; private readonly DrawableSlider drawableSlider; - public double FadeInTime; - public double FadeOutTime; + private double animDuration; public DrawableRepeatPoint(RepeatPoint repeatPoint, DrawableSlider drawableSlider) : base(repeatPoint) @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables this.repeatPoint = repeatPoint; this.drawableSlider = drawableSlider; - Size = new Vector2(32 * repeatPoint.Scale); + Size = new Vector2(45 * repeatPoint.Scale); Blending = BlendingMode.Additive; Origin = Anchor.Centre; @@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables new SpriteIcon { RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.fa_eercast + Icon = FontAwesome.fa_chevron_right } }; } @@ -48,11 +48,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdatePreemptState() { - var animIn = Math.Min(150, repeatPoint.StartTime - FadeInTime); + animDuration = Math.Min(150, repeatPoint.SpanDuration / 2); - this.FadeIn(animIn).ScaleTo(1.2f, animIn) - .Then() - .ScaleTo(1, 150, Easing.Out); + this.Animate( + d => d.FadeIn(animDuration), + d => d.ScaleTo(0.5f).ScaleTo(1f, animDuration * 4, Easing.OutElasticHalf) + ); } protected override void UpdateCurrentState(ArmedState state) @@ -60,16 +61,40 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (state) { case ArmedState.Idle: - this.Delay(FadeOutTime - repeatPoint.StartTime).FadeOut(); + this.Delay(HitObject.TimePreempt).FadeOut(); break; case ArmedState.Miss: - this.FadeOut(160); + this.FadeOut(animDuration); break; case ArmedState.Hit: - this.FadeOut(120, Easing.OutQuint) - .ScaleTo(Scale * 1.5f, 120, Easing.OutQuint); + this.FadeOut(animDuration, Easing.OutQuint) + .ScaleTo(Scale * 1.5f, animDuration, Easing.Out); break; } } + + public void UpdateSnakingPosition(Vector2 start, Vector2 end) + { + bool isRepeatAtEnd = repeatPoint.RepeatIndex % 2 == 0; + List curve = drawableSlider.Body.CurrentCurve; + + Position = isRepeatAtEnd ? end : start; + + if (curve.Count < 2) + return; + + int searchStart = isRepeatAtEnd ? curve.Count - 1 : 0; + int direction = isRepeatAtEnd ? -1 : 1; + + // find the next vector2 in the curve which is not equal to our current position to infer a rotation. + for (int i = searchStart; i >= 0 && i < curve.Count; i += direction) + { + if (curve[i] == Position) + continue; + + Rotation = MathHelper.RadiansToDegrees((float)Math.Atan2(curve[i].Y - Position.Y, curve[i].X - Position.X)); + break; + } + } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index f32a027f2e..5795bb8405 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -10,6 +10,7 @@ using System.Linq; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Osu.Judgements; using osu.Framework.Graphics.Primitives; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects.Drawables @@ -17,14 +18,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { private readonly Slider slider; + private readonly List components = new List(); - public readonly DrawableHitCircle InitialCircle; - - private readonly List components = new List(); - - private readonly Container ticks; - private readonly Container repeatPoints; - + public readonly DrawableHitCircle HeadCircle; public readonly SliderBody Body; public readonly SliderBall Ball; @@ -33,6 +29,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { slider = s; + DrawableSliderTail tail; + Container ticks; + Container repeatPoints; + Children = new Drawable[] { Body = new SliderBody(s) @@ -50,68 +50,46 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AlwaysPresent = true, Alpha = 0 }, - InitialCircle = new DrawableHitCircle(new HitCircle - { - StartTime = s.StartTime, - Position = s.StackedPosition, - ComboIndex = s.ComboIndex, - Scale = s.Scale, - ComboColour = s.ComboColour, - Samples = s.Samples, - SampleControlPoint = s.SampleControlPoint - }) + HeadCircle = new DrawableHitCircle(s.HeadCircle), + tail = new DrawableSliderTail(s.TailCircle) }; components.Add(Body); components.Add(Ball); - AddNested(InitialCircle); + AddNested(HeadCircle); + + AddNested(tail); + components.Add(tail); - var repeatDuration = s.Curve.Distance / s.Velocity; foreach (var tick in s.NestedHitObjects.OfType()) { - var repeatStartTime = s.StartTime + tick.RepeatIndex * repeatDuration; - var fadeInTime = repeatStartTime + (tick.StartTime - repeatStartTime) / 2 - (tick.RepeatIndex == 0 ? FadeInDuration : FadeInDuration / 2); - var fadeOutTime = repeatStartTime + repeatDuration; - var drawableTick = new DrawableSliderTick(tick) { - FadeInTime = fadeInTime, - FadeOutTime = fadeOutTime, - Position = tick.Position, + Position = tick.Position }; ticks.Add(drawableTick); + components.Add(drawableTick); AddNested(drawableTick); } foreach (var repeatPoint in s.NestedHitObjects.OfType()) { - var repeatStartTime = s.StartTime + repeatPoint.RepeatIndex * repeatDuration; - var fadeInTime = repeatStartTime + (repeatPoint.StartTime - repeatStartTime) / 2 - (repeatPoint.RepeatIndex == 0 ? FadeInDuration : FadeInDuration / 2); - var fadeOutTime = repeatStartTime + repeatDuration; - var drawableRepeatPoint = new DrawableRepeatPoint(repeatPoint, this) { - FadeInTime = fadeInTime, - FadeOutTime = fadeOutTime, - Position = repeatPoint.Position, + Position = repeatPoint.Position }; repeatPoints.Add(drawableRepeatPoint); + components.Add(drawableRepeatPoint); AddNested(drawableRepeatPoint); } } - private int currentRepeat; + private int currentSpan; public bool Tracking; - public override double FadeInDuration - { - get { return base.FadeInDuration; } - set { InitialCircle.FadeInDuration = base.FadeInDuration = value; } - } - protected override void Update() { base.Update(); @@ -120,33 +98,32 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1); - int repeat = slider.RepeatAt(progress); + int span = slider.SpanAt(progress); progress = slider.ProgressAt(progress); - if (repeat > currentRepeat) - currentRepeat = repeat; + if (span > currentSpan) + currentSpan = span; //todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. - if (!InitialCircle.Judgements.Any(j => j.IsHit)) - InitialCircle.Position = slider.Curve.PositionAt(progress); + if (!HeadCircle.IsHit) + HeadCircle.Position = slider.Curve.PositionAt(progress); - foreach (var c in components) c.UpdateProgress(progress, repeat); - foreach (var t in ticks.Children) t.Tracking = Ball.Tracking; + foreach (var c in components.OfType()) c.UpdateProgress(progress, span); + foreach (var c in components.OfType()) c.UpdateSnakingPosition(slider.Curve.PositionAt(Body.SnakedStart ?? 0), slider.Curve.PositionAt(Body.SnakedEnd ?? 0)); + foreach (var t in components.OfType()) t.Tracking = Ball.Tracking; } protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (!userTriggered && Time.Current >= slider.EndTime) { - var judgementsCount = ticks.Children.Count + repeatPoints.Children.Count + 1; - var judgementsHit = ticks.Children.Count(t => t.Judgements.Any(j => j.IsHit)) + repeatPoints.Children.Count(t => t.Judgements.Any(j => j.IsHit)); - if (InitialCircle.Judgements.Any(j => j.IsHit)) - judgementsHit++; + var judgementsCount = NestedHitObjects.Count; + var judgementsHit = NestedHitObjects.Count(h => h.IsHit); var hitFraction = (double)judgementsHit / judgementsCount; - if (hitFraction == 1 && InitialCircle.Judgements.Any(j => j.Result == HitResult.Great)) + if (hitFraction == 1 && HeadCircle.Judgements.Any(j => j.Result == HitResult.Great)) AddJudgement(new OsuJudgement { Result = HitResult.Great }); - else if (hitFraction >= 0.5 && InitialCircle.Judgements.Any(j => j.Result >= HitResult.Good)) + else if (hitFraction >= 0.5 && HeadCircle.Judgements.Any(j => j.Result >= HitResult.Good)) AddJudgement(new OsuJudgement { Result = HitResult.Good }); else if (hitFraction > 0) AddJudgement(new OsuJudgement { Result = HitResult.Meh }); @@ -178,7 +155,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - public Drawable ProxiedLayer => InitialCircle.ApproachCircle; + public Drawable ProxiedLayer => HeadCircle.ApproachCircle; public override Vector2 SelectionPoint => ToScreenSpace(Body.Position); public override Quad SelectionQuad => Body.PathDrawQuad; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs new file mode 100644 index 0000000000..8835fc2b29 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTail.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables +{ + public class DrawableSliderTail : DrawableOsuHitObject, IRequireTracking + { + /// + /// The judgement text is provided by the . + /// + public override bool DisplayJudgement => false; + + public bool Tracking { get; set; } + + public DrawableSliderTail(HitCircle hitCircle) + : base(hitCircle) + { + AlwaysPresent = true; + RelativeSizeAxes = Axes.Both; + } + + protected override void CheckForJudgements(bool userTriggered, double timeOffset) + { + if (!userTriggered && timeOffset >= 0) + AddJudgement(new OsuSliderTailJudgement { Result = Tracking ? HitResult.Great : HitResult.Miss }); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index bce7ef6141..41d73a745a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -1,7 +1,6 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; @@ -12,21 +11,16 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects.Drawables { - public class DrawableSliderTick : DrawableOsuHitObject + public class DrawableSliderTick : DrawableOsuHitObject, IRequireTracking { - private readonly SliderTick sliderTick; + private const double anim_duration = 150; - public double FadeInTime; - public double FadeOutTime; - - public bool Tracking; + public bool Tracking { get; set; } public override bool DisplayJudgement => false; public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) { - this.sliderTick = sliderTick; - Size = new Vector2(16) * sliderTick.Scale; Masking = true; @@ -56,13 +50,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdatePreemptState() { - var animIn = Math.Min(150, sliderTick.StartTime - FadeInTime); - this.Animate( - d => d.FadeIn(animIn), - d => d.ScaleTo(0.5f).ScaleTo(1.2f, animIn) - ).Then( - d => d.ScaleTo(1, 150, Easing.Out) + d => d.FadeIn(anim_duration), + d => d.ScaleTo(0.5f).ScaleTo(1f, anim_duration * 4, Easing.OutElasticHalf) ); } @@ -71,15 +61,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (state) { case ArmedState.Idle: - this.Delay(FadeOutTime - sliderTick.StartTime).FadeOut(); + this.Delay(HitObject.TimePreempt).FadeOut(); break; case ArmedState.Miss: - this.FadeOut(160) - .FadeColour(Color4.Red, 80); + this.FadeOut(anim_duration) + .FadeColour(Color4.Red, anim_duration / 2); break; case ArmedState.Hit: - this.FadeOut(120, Easing.OutQuint) - .ScaleTo(Scale * 1.5f, 120, Easing.OutQuint); + this.FadeOut(anim_duration, Easing.OutQuint) + .ScaleTo(Scale * 1.5f, anim_duration, Easing.Out); break; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index bbe6b3a0a0..722ab4c6d5 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { Disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton); if (!spmCounter.IsPresent && Disc.Tracking) - spmCounter.FadeIn(FadeInDuration); + spmCounter.FadeIn(HitObject.TimeFadein); base.Update(); } @@ -191,14 +191,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.UpdatePreemptState(); circleContainer.ScaleTo(Spinner.Scale * 0.3f); - circleContainer.ScaleTo(Spinner.Scale, TIME_PREEMPT / 1.4f, Easing.OutQuint); + circleContainer.ScaleTo(Spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint); Disc.RotateTo(-720); symbol.RotateTo(-720); mainContainer .ScaleTo(0) - .ScaleTo(Spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, TIME_PREEMPT - 150, Easing.OutQuint) + .ScaleTo(Spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, HitObject.TimePreempt - 150, Easing.OutQuint) .Then() .ScaleTo(1, 500, Easing.OutQuint); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs new file mode 100644 index 0000000000..98fc686dd3 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/IRequireTracking.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Osu.Objects.Drawables +{ + public interface IRequireTracking + { + /// + /// Whether the is currently being tracked by the user. + /// + bool Tracking { get; set; } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs new file mode 100644 index 0000000000..b5fd87f60b --- /dev/null +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/ITrackSnaking.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; + +namespace osu.Game.Rulesets.Osu.Objects.Drawables +{ + /// + /// A component which tracks the current end snaking position of a slider. + /// + public interface ITrackSnaking + { + void UpdateSnakingPosition(Vector2 start, Vector2 end); + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs index 323f5fb297..61e9027157 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -32,4 +32,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces approachCircle.Texture = textures.Get(@"Play/osu/approachcircle"); } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index a7384b8f8e..286df14056 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -63,4 +63,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public bool OnReleased(OsuAction action) => false; } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs index 7912108901..9be951e29c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -30,4 +30,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces }; } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs index a80d163246..56faa335b1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -32,4 +32,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces }; } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs index 0adfed2710..9a1208f998 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -36,4 +36,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces layer.Texture = textures.Get(@"Play/osu/ring-glow"); } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs index 28e54c3b4e..afbf00f320 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; @@ -56,4 +56,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces }; } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs index f66099e1c3..2347927f2e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -35,4 +35,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces }; } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 46b4353f9a..2fda299389 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; @@ -139,7 +139,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } - public void UpdateProgress(double progress, int repeat) + public void UpdateProgress(double progress, int span) { Position = slider.Curve.PositionAt(progress); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 75c2c15084..901d1c568d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -15,6 +15,7 @@ using OpenTK; using OpenTK.Graphics.ES30; using OpenTK.Graphics; using osu.Framework.Graphics.Primitives; +using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { @@ -88,7 +89,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces // We want the container to have the same size as the slider, // and to be positioned such that the slider head is at (0,0). container.Size = path.Size; - container.Position = -path.PositionInBoundingBox(slider.Curve.PositionAt(0) - currentCurve[0]); + container.Position = -path.PositionInBoundingBox(slider.Curve.PositionAt(0) - CurrentCurve[0]); container.ForceRedraw(); } @@ -147,7 +148,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces path.Texture = texture; } - private readonly List currentCurve = new List(); + public readonly List CurrentCurve = new List(); private bool updateSnaking(double p0, double p1) { if (SnakedStart == p0 && SnakedEnd == p1) return false; @@ -155,23 +156,23 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces SnakedStart = p0; SnakedEnd = p1; - slider.Curve.GetPathToProgress(currentCurve, p0, p1); + slider.Curve.GetPathToProgress(CurrentCurve, p0, p1); path.ClearVertices(); - foreach (Vector2 p in currentCurve) - path.AddVertex(p - currentCurve[0]); + foreach (Vector2 p in CurrentCurve) + path.AddVertex(p - CurrentCurve[0]); return true; } - public void UpdateProgress(double progress, int repeat) + public void UpdateProgress(double progress, int span) { double start = 0; - double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - DrawableOsuHitObject.TIME_PREEMPT)) / DrawableOsuHitObject.TIME_FADEIN, 0, 1) : 1; + double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadein, 0, 1) : 1; - if (repeat >= slider.RepeatCount - 1) + if (span >= slider.SpanCount() - 1) { - if (Math.Min(repeat, slider.RepeatCount - 1) % 2 == 1) + if (Math.Min(span, slider.SpanCount() - 1) % 2 == 1) { start = 0; end = snakingOut ? progress : 1; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs index bdd5b71211..c44d7594ad 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; @@ -11,7 +11,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class SpinnerBackground : CircularContainer, IHasAccentColour { - public override bool HandleInput => false; + public override bool HandleKeyboardInput => false; + public override bool HandleMouseInput => false; protected Box Disc; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index 9f54ce3fa3..971914ca13 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs index 774511313a..182cc9d56a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs index fc0d436788..135fbbd8db 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerTicks.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -54,4 +54,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces } } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs index ea3ddb5051..4d3397de3e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics.Backgrounds; @@ -23,4 +23,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces base.Update(); } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs index be969f1e18..9f6041cb70 100644 --- a/osu.Game.Rulesets.Osu/Objects/HitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Osu.Objects diff --git a/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs b/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs index cb0d177a60..54f783b664 100644 --- a/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs +++ b/osu.Game.Rulesets.Osu/Objects/ISliderProgress.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Osu.Objects { public interface ISliderProgress { - void UpdateProgress(double progress, int repeat); + void UpdateProgress(double progress, int span); } } diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index a3a6527b31..9b9d88f0f6 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; @@ -7,7 +7,6 @@ using OpenTK; using osu.Game.Rulesets.Objects.Types; using OpenTK.Graphics; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects { @@ -15,10 +14,8 @@ namespace osu.Game.Rulesets.Osu.Objects { public const double OBJECT_RADIUS = 64; - private const double hittable_range = 300; - private const double hit_window_50 = 150; - private const double hit_window_100 = 80; - private const double hit_window_300 = 30; + public double TimePreempt = 600; + public double TimeFadein = 400; public Vector2 Position { get; set; } public float X => Position.X; @@ -40,38 +37,15 @@ namespace osu.Game.Rulesets.Osu.Objects public Color4 ComboColour { get; set; } = Color4.Gray; public virtual bool NewCombo { get; set; } - public int ComboIndex { get; set; } - - public double HitWindowFor(HitResult result) - { - switch (result) - { - default: - return 300; - case HitResult.Meh: - return 150; - case HitResult.Good: - return 80; - case HitResult.Great: - return 30; - } - } - - public HitResult ScoreResultForOffset(double offset) - { - if (offset < HitWindowFor(HitResult.Great)) - return HitResult.Great; - if (offset < HitWindowFor(HitResult.Good)) - return HitResult.Good; - if (offset < HitWindowFor(HitResult.Meh)) - return HitResult.Meh; - return HitResult.Miss; - } + public int IndexInCurrentCombo { get; set; } protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); + TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450); + TimeFadein = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1200, 800, 300); + Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2; } } diff --git a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs index c113b7cd7a..eaaa8d7a7e 100644 --- a/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/RepeatPoint.cs @@ -1,10 +1,25 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; + namespace osu.Game.Rulesets.Osu.Objects { public class RepeatPoint : OsuHitObject { public int RepeatIndex { get; set; } + public double SpanDuration { get; set; } + + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) + { + base.ApplyDefaultsToSelf(controlPointInfo, difficulty); + + // We want to show the first RepeatPoint as the TimePreempt dictates but on short (and possibly fast) sliders + // we may need to cut down this time on following RepeatPoints to only show up to two RepeatPoints at any given time. + if (RepeatIndex > 0) + TimePreempt = Math.Min(SpanDuration * 2, TimePreempt); + } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index ec51a10345..5dd3d7aa89 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -20,12 +20,13 @@ namespace osu.Game.Rulesets.Osu.Objects /// private const float base_scoring_distance = 100; - public readonly SliderCurve Curve = new SliderCurve(); - - public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity; + public double EndTime => StartTime + this.SpanCount() * Curve.Distance / Velocity; public double Duration => EndTime - StartTime; - public override Vector2 EndPosition => PositionAt(1); + public Vector2 StackedPositionAt(double t) => this.PositionAt(t) + StackOffset; + public override Vector2 EndPosition => this.PositionAt(1); + + public SliderCurve Curve { get; } = new SliderCurve(); public List ControlPoints { @@ -58,9 +59,15 @@ namespace osu.Game.Rulesets.Osu.Objects internal float LazyTravelDistance; public List> RepeatSamples { get; set; } = new List>(); - public int RepeatCount { get; set; } = 1; + public int RepeatCount { get; set; } + + /// + /// The length of one span of this . + /// + public double SpanDuration => Duration / this.SpanCount(); private int stackHeight; + public override int StackHeight { get { return stackHeight; } @@ -74,6 +81,9 @@ namespace osu.Game.Rulesets.Osu.Objects public double Velocity; public double TickDistance; + public HitCircle HeadCircle; + public HitCircle TailCircle; + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); @@ -87,40 +97,52 @@ namespace osu.Game.Rulesets.Osu.Objects TickDistance = scoringDistance / difficulty.SliderTickRate; } - public Vector2 PositionAt(double progress) => Curve.PositionAt(ProgressAt(progress)); - - public double ProgressAt(double progress) - { - double p = progress * RepeatCount % 1; - if (RepeatAt(progress) % 2 == 1) - p = 1 - p; - return p; - } - - public int RepeatAt(double progress) => (int)(progress * RepeatCount); - protected override void CreateNestedHitObjects() { base.CreateNestedHitObjects(); + createSliderEnds(); createTicks(); createRepeatPoints(); } + private void createSliderEnds() + { + HeadCircle = new HitCircle + { + StartTime = StartTime, + Position = StackedPosition, + IndexInCurrentCombo = IndexInCurrentCombo, + ComboColour = ComboColour, + Samples = Samples, + SampleControlPoint = SampleControlPoint + }; + + TailCircle = new HitCircle + { + StartTime = EndTime, + Position = StackedEndPosition, + IndexInCurrentCombo = IndexInCurrentCombo, + ComboColour = ComboColour + }; + + AddNested(HeadCircle); + AddNested(TailCircle); + } + private void createTicks() { if (TickDistance == 0) return; var length = Curve.Distance; var tickDistance = Math.Min(TickDistance, length); - var repeatDuration = length / Velocity; var minDistanceFromEnd = Velocity * 0.01; - for (var repeat = 0; repeat < RepeatCount; repeat++) + for (var span = 0; span < this.SpanCount(); span++) { - var repeatStartTime = StartTime + repeat * repeatDuration; - var reversed = repeat % 2 == 1; + var spanStartTime = StartTime + span * SpanDuration; + var reversed = span % 2 == 1; for (var d = tickDistance; d <= length; d += tickDistance) { @@ -130,20 +152,27 @@ namespace osu.Game.Rulesets.Osu.Objects var distanceProgress = d / length; var timeProgress = reversed ? 1 - distanceProgress : distanceProgress; + var firstSample = Samples.FirstOrDefault(s => s.Name == SampleInfo.HIT_NORMAL) ?? Samples.FirstOrDefault(); // TODO: remove this when guaranteed sort is present for samples (https://github.com/ppy/osu/issues/1933) + var sampleList = new List(); + + if (firstSample != null) + sampleList.Add(new SampleInfo + { + Bank = firstSample.Bank, + Volume = firstSample.Volume, + Name = @"slidertick", + }); + AddNested(new SliderTick { - RepeatIndex = repeat, - StartTime = repeatStartTime + timeProgress * repeatDuration, + SpanIndex = span, + SpanStartTime = spanStartTime, + StartTime = spanStartTime + timeProgress * SpanDuration, Position = Curve.PositionAt(distanceProgress), StackHeight = StackHeight, Scale = Scale, ComboColour = ComboColour, - Samples = new List(Samples.Select(s => new SampleInfo - { - Bank = s.Bank, - Name = @"slidertick", - Volume = s.Volume - })) + Samples = sampleList }); } } @@ -151,21 +180,18 @@ namespace osu.Game.Rulesets.Osu.Objects private void createRepeatPoints() { - var repeatDuration = Distance / Velocity; - - for (var repeat = 1; repeat < RepeatCount; repeat++) + for (int repeatIndex = 0, repeat = 1; repeatIndex < RepeatCount; repeatIndex++, repeat++) { - var repeatStartTime = StartTime + repeat * repeatDuration; - AddNested(new RepeatPoint { - RepeatIndex = repeat, - StartTime = repeatStartTime, + RepeatIndex = repeatIndex, + SpanDuration = SpanDuration, + StartTime = StartTime + repeat * SpanDuration, Position = Curve.PositionAt(repeat % 2), StackHeight = StackHeight, Scale = Scale, ComboColour = ComboColour, - Samples = new List(RepeatSamples[repeat]) + Samples = new List(RepeatSamples[repeatIndex]) }); } } diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 7112a39f97..966db73eb9 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -1,10 +1,30 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; + namespace osu.Game.Rulesets.Osu.Objects { public class SliderTick : OsuHitObject { - public int RepeatIndex { get; set; } + public int SpanIndex { get; set; } + public double SpanStartTime { get; set; } + + protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) + { + base.ApplyDefaultsToSelf(controlPointInfo, difficulty); + + double offset; + + if (SpanIndex > 0) + // Adding 200 to include the offset stable used. + // This is so on repeats ticks don't appear too late to be visually processed by the player. + offset = 200; + else + offset = TimeFadein * 0.66f; + + TimePreempt = (StartTime - SpanStartTime) / 2 + offset; + } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 7d1bd9239d..2f238bb74b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs index 3d185ab694..fb5acbb643 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/OsuDifficultyCalculator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -29,8 +29,7 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty protected override void PreprocessHitObjects() { - foreach (OsuHitObject h in Beatmap.HitObjects) - (h as Slider)?.Curve?.Calculate(); + new OsuBeatmapProcessor().PostProcess(Beatmap); } public override double Calculate(Dictionary categoryDifficulty = null) diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs index f8e9423e29..a1a2687cea 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyBeatmap.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections; diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs index 11c0df0c8c..c817cd0ff3 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Preprocessing/OsuDifficultyHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing var computeVertex = new Action(t => { // ReSharper disable once PossibleInvalidOperationException (bugged in current r# version) - var diff = slider.PositionAt(t) - slider.LazyEndPosition.Value; + var diff = slider.StackedPositionAt(t) - slider.LazyEndPosition.Value; float dist = diff.Length; if (dist > approxFollowCircleRadius) diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Aim.cs index aad53f6fe8..361b31c7bd 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Aim.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Skill.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Skill.cs index b9632e18e2..db9658087b 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Skill.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Skill.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Speed.cs index 6c43c53e35..b85904acf9 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Skills/Speed.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing; diff --git a/osu.Game.Rulesets.Osu/OsuDifficulty/Utils/History.cs b/osu.Game.Rulesets.Osu/OsuDifficulty/Utils/History.cs index d2c2e1d774..9f07248abf 100644 --- a/osu.Game.Rulesets.Osu/OsuDifficulty/Utils/History.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficulty/Utils/History.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/OsuInputManager.cs b/osu.Game.Rulesets.Osu/OsuInputManager.cs index 56990d1351..1a7f00ea51 100644 --- a/osu.Game.Rulesets.Osu/OsuInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuInputManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 19d60c9046..b38f95694f 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; @@ -145,7 +145,7 @@ namespace osu.Game.Rulesets.Osu public override int LegacyID => 0; - public OsuRuleset(RulesetInfo rulesetInfo) + public OsuRuleset(RulesetInfo rulesetInfo = null) : base(rulesetInfo) { } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index ba774e887f..a22ac6aed1 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Rulesets.Osu.Objects; -using osu.Game.Rulesets.Osu.Objects.Drawables; using System; using System.Diagnostics; using osu.Framework.Graphics; @@ -90,20 +89,20 @@ namespace osu.Game.Rulesets.Osu.Replays double endTime = (prev as IHasEndTime)?.EndTime ?? prev.StartTime; // Make the cursor stay at a hitObject as long as possible (mainly for autopilot). - if (h.StartTime - h.HitWindowFor(HitResult.Miss) > endTime + h.HitWindowFor(HitResult.Meh) + 50) + if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Miss) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50) { - if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None)); - if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(HitResult.Miss), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None)); + if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None)); + if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None)); } - else if (h.StartTime - h.HitWindowFor(HitResult.Meh) > endTime + h.HitWindowFor(HitResult.Meh) + 50) + else if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50) { - if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None)); - if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(HitResult.Meh), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None)); + if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None)); + if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None)); } - else if (h.StartTime - h.HitWindowFor(HitResult.Good) > endTime + h.HitWindowFor(HitResult.Good) + 50) + else if (h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh) > endTime + h.HitWindows.HalfWindowFor(HitResult.Meh) + 50) { - if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(HitResult.Good), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None)); - if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(HitResult.Good), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None)); + if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindows.HalfWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None)); + if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindows.HalfWindowFor(HitResult.Meh), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None)); } } @@ -133,7 +132,7 @@ namespace osu.Game.Rulesets.Osu.Replays // Do some nice easing for cursor movements if (Frames.Count > 0) { - moveToHitObject(h.StartTime, startPosition, h.Radius, easing); + moveToHitObject(h, startPosition, easing); } // Add frames to click the hitobject @@ -191,12 +190,12 @@ namespace osu.Game.Rulesets.Osu.Replays } } - private void moveToHitObject(double targetTime, Vector2 targetPos, double hitObjectRadius, Easing easing) + private void moveToHitObject(OsuHitObject h, Vector2 targetPos, Easing easing) { ReplayFrame lastFrame = Frames[Frames.Count - 1]; // Wait until Auto could "see and react" to the next note. - double waitTime = targetTime - Math.Max(0.0, DrawableOsuHitObject.TIME_PREEMPT - reactionTime); + double waitTime = h.StartTime - Math.Max(0.0, h.TimePreempt - reactionTime); if (waitTime > lastFrame.Time) { lastFrame = new ReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState); @@ -205,17 +204,17 @@ namespace osu.Game.Rulesets.Osu.Replays Vector2 lastPosition = lastFrame.Position; - double timeDifference = ApplyModsToTime(targetTime - lastFrame.Time); + double timeDifference = ApplyModsToTime(h.StartTime - lastFrame.Time); // Only "snap" to hitcircles if they are far enough apart. As the time between hitcircles gets shorter the snapping threshold goes up. if (timeDifference > 0 && // Sanity checks - ((lastPosition - targetPos).Length > hitObjectRadius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough + ((lastPosition - targetPos).Length > h.Radius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough timeDifference >= 266)) // ... or the beats are slow enough to tap anyway. { // Perform eased movement - for (double time = lastFrame.Time + FrameDelay; time < targetTime; time += FrameDelay) + for (double time = lastFrame.Time + FrameDelay; time < h.StartTime; time += FrameDelay) { - Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPos, lastFrame.Time, targetTime, easing); + Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPos, lastFrame.Time, h.StartTime, easing); AddFrameToReplay(new ReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState)); } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs index 65ed9530f2..b2adeda73b 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGeneratorBase.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs index 0811a68392..63c9111190 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayInputHandler.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs index 38c602bc42..25d88a38f3 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuPerformanceCalculator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 7520e1801c..67b96f1fd9 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseHitCircle.cs b/osu.Game.Rulesets.Osu/Tests/TestCaseHitCircle.cs index f307ff7c70..77c70c68cd 100644 --- a/osu.Game.Rulesets.Osu/Tests/TestCaseHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Tests/TestCaseHitCircle.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseHitCircleHidden.cs b/osu.Game.Rulesets.Osu/Tests/TestCaseHitCircleHidden.cs index 7cc0c343a2..1f64de496d 100644 --- a/osu.Game.Rulesets.Osu/Tests/TestCaseHitCircleHidden.cs +++ b/osu.Game.Rulesets.Osu/Tests/TestCaseHitCircleHidden.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Osu/Tests/TestCasePerformancePoints.cs index 25a6110459..500347c874 100644 --- a/osu.Game.Rulesets.Osu/Tests/TestCasePerformancePoints.cs +++ b/osu.Game.Rulesets.Osu/Tests/TestCasePerformancePoints.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Osu.Tests public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints { public TestCasePerformancePoints() - : base(new OsuRuleset(new RulesetInfo())) + : base(new OsuRuleset()) { } } diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseSlider.cs b/osu.Game.Rulesets.Osu/Tests/TestCaseSlider.cs index 1238572484..93085df975 100644 --- a/osu.Game.Rulesets.Osu/Tests/TestCaseSlider.cs +++ b/osu.Game.Rulesets.Osu/Tests/TestCaseSlider.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -16,6 +16,10 @@ using OpenTK; using OpenTK.Graphics; using osu.Game.Rulesets.Mods; using System.Linq; +using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; namespace osu.Game.Rulesets.Osu.Tests @@ -27,7 +31,9 @@ namespace osu.Game.Rulesets.Osu.Tests { typeof(SliderBall), typeof(SliderBody), + typeof(SliderTick), typeof(DrawableSlider), + typeof(DrawableSliderTick), typeof(DrawableRepeatPoint), typeof(DrawableOsuHitObject) }; @@ -63,9 +69,27 @@ namespace osu.Game.Rulesets.Osu.Tests AddStep("Fast Short Slider", () => testShortHighSpeed()); AddStep("Fast Short Slider 1 Repeat", () => testShortHighSpeed(1)); AddStep("Fast Short Slider 2 Repeats", () => testShortHighSpeed(2)); + AddStep("Fast Short Slider 6 Repeats", () => testShortHighSpeed(6)); - AddStep("Perfect Curve", testCurve); - // TODO more curve types? + AddStep("Perfect Curve", () => testPerfect()); + AddStep("Perfect Curve 1 Repeat", () => testPerfect(1)); + AddStep("Perfect Curve 2 Repeats", () => testPerfect(2)); + + AddStep("Linear Slider", () => testLinear()); + AddStep("Linear Slider 1 Repeat", () => testLinear(1)); + AddStep("Linear Slider 2 Repeats", () => testLinear(2)); + + AddStep("Bezier Slider", () => testBezier()); + AddStep("Bezier Slider 1 Repeat", () => testBezier(1)); + AddStep("Bezier Slider 2 Repeats", () => testBezier(2)); + + AddStep("Linear Overlapping", () => testLinearOverlapping()); + AddStep("Linear Overlapping 1 Repeat", () => testLinearOverlapping(1)); + AddStep("Linear Overlapping 2 Repeats", () => testLinearOverlapping(2)); + + AddStep("Catmull Slider", () => testCatmull()); + AddStep("Catmull Slider 1 Repeat", () => testCatmull(1)); + AddStep("Catmull Slider 2 Repeats", () => testCatmull(2)); } private void testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats); @@ -84,15 +108,6 @@ namespace osu.Game.Rulesets.Osu.Tests private void createSlider(float circleSize = 2, float distance = 400, int repeats = 0, double speedMultiplier = 2) { - repeats++; // The first run through the slider is considered a repeat - - var repeatSamples = new List>(); - if (repeats > 1) - { - for (int i = 0; i < repeats; i++) - repeatSamples.Add(new List()); - } - var slider = new Slider { StartTime = Time.Current + 1000, @@ -105,13 +120,13 @@ namespace osu.Game.Rulesets.Osu.Tests }, Distance = distance, RepeatCount = repeats, - RepeatSamples = repeatSamples + RepeatSamples = createEmptySamples(repeats) }; addSlider(slider, circleSize, speedMultiplier); } - private void testCurve() + private void testPerfect(int repeats = 0) { var slider = new Slider { @@ -124,18 +139,137 @@ namespace osu.Game.Rulesets.Osu.Tests new Vector2(0, 200), new Vector2(200, 0) }, - Distance = 600 + Distance = 600, + RepeatCount = repeats, + RepeatSamples = createEmptySamples(repeats) }; addSlider(slider, 2, 3); } + private void testLinear(int repeats = 0) => createLinear(repeats); + + private void createLinear(int repeats) + { + var slider = new Slider + { + CurveType = CurveType.Linear, + StartTime = Time.Current + 1000, + Position = new Vector2(-200, 0), + ComboColour = Color4.LightSeaGreen, + ControlPoints = new List + { + new Vector2(-200, 0), + new Vector2(-50, 75), + new Vector2(0, 100), + new Vector2(100, -200), + new Vector2(200, 0), + new Vector2(230, 0) + }, + Distance = 793.4417, + RepeatCount = repeats, + RepeatSamples = createEmptySamples(repeats) + }; + + addSlider(slider, 2, 3); + } + + private void testBezier(int repeats = 0) => createBezier(repeats); + + private void createBezier(int repeats) + { + var slider = new Slider + { + CurveType = CurveType.Bezier, + StartTime = Time.Current + 1000, + Position = new Vector2(-200, 0), + ComboColour = Color4.LightSeaGreen, + ControlPoints = new List + { + new Vector2(-200, 0), + new Vector2(-50, 75), + new Vector2(0, 100), + new Vector2(100, -200), + new Vector2(230, 0) + }, + Distance = 480, + RepeatCount = repeats, + RepeatSamples = createEmptySamples(repeats) + }; + + addSlider(slider, 2, 3); + } + + private void testLinearOverlapping(int repeats = 0) => createOverlapping(repeats); + + private void createOverlapping(int repeats) + { + var slider = new Slider + { + CurveType = CurveType.Linear, + StartTime = Time.Current + 1000, + Position = new Vector2(0, 0), + ComboColour = Color4.LightSeaGreen, + ControlPoints = new List + { + new Vector2(0, 0), + new Vector2(-200, 0), + new Vector2(0, 0), + new Vector2(0, -200), + new Vector2(-200, -200), + new Vector2(0, -200) + }, + Distance = 1000, + RepeatCount = repeats, + RepeatSamples = createEmptySamples(repeats) + }; + + addSlider(slider, 2, 3); + } + + private void testCatmull(int repeats = 0) => createCatmull(repeats); + + private void createCatmull(int repeats = 0) + { + var repeatSamples = new List>(); + for (int i = 0; i < repeats; i++) + repeatSamples.Add(new List()); + + var slider = new Slider + { + StartTime = Time.Current + 1000, + Position = new Vector2(-100, 0), + ComboColour = Color4.LightSeaGreen, + CurveType = CurveType.Catmull, + ControlPoints = new List + { + new Vector2(-100, 0), + new Vector2(-50, -50), + new Vector2(50, 50), + new Vector2(100, 0) + }, + Distance = 300, + RepeatCount = repeats, + RepeatSamples = repeatSamples + }; + + addSlider(slider, 3, 1); + } + + private List> createEmptySamples(int repeats) + { + var repeatSamples = new List>(); + for (int i = 0; i < repeats; i++) + repeatSamples.Add(new List()); + return repeatSamples; + } + private void addSlider(Slider slider, float circleSize, double speedMultiplier) { var cpi = new ControlPointInfo(); cpi.DifficultyPoints.Add(new DifficultyControlPoint { SpeedMultiplier = speedMultiplier }); - slider.ApplyDefaults(cpi, new BeatmapDifficulty { CircleSize = circleSize }); + slider.ApplyDefaults(cpi, new BeatmapDifficulty { CircleSize = circleSize, SliderTickRate = 3 }); var drawable = new DrawableSlider(slider) { @@ -146,7 +280,34 @@ namespace osu.Game.Rulesets.Osu.Tests foreach (var mod in Mods.OfType()) mod.ApplyToDrawableHitObjects(new[] { drawable }); + drawable.OnJudgement += onJudgement; + Add(drawable); } + + private float judgementOffsetDirection = 1; + private void onJudgement(DrawableHitObject judgedObject, Judgement judgement) + { + var osuObject = judgedObject as DrawableOsuHitObject; + if (osuObject == null) + return; + + OsuSpriteText text; + Add(text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = judgement.IsHit ? "Hit!" : "Miss!", + Colour = judgement.IsHit ? Color4.Green : Color4.Red, + TextSize = 30, + Position = osuObject.HitObject.StackedEndPosition + judgementOffsetDirection * new Vector2(0, 45) + }); + + text.Delay(150) + .Then().FadeOut(200) + .Then().Expire(); + + judgementOffsetDirection *= -1; + } } } diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseSliderHidden.cs b/osu.Game.Rulesets.Osu/Tests/TestCaseSliderHidden.cs index 016909ad73..bd4be1675b 100644 --- a/osu.Game.Rulesets.Osu/Tests/TestCaseSliderHidden.cs +++ b/osu.Game.Rulesets.Osu/Tests/TestCaseSliderHidden.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseSpinner.cs b/osu.Game.Rulesets.Osu/Tests/TestCaseSpinner.cs index 752574018c..f2d031633b 100644 --- a/osu.Game.Rulesets.Osu/Tests/TestCaseSpinner.cs +++ b/osu.Game.Rulesets.Osu/Tests/TestCaseSpinner.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/Tests/TestCaseSpinnerHidden.cs b/osu.Game.Rulesets.Osu/Tests/TestCaseSpinnerHidden.cs index 9ef94b308f..7764f3d4af 100644 --- a/osu.Game.Rulesets.Osu/Tests/TestCaseSpinnerHidden.cs +++ b/osu.Game.Rulesets.Osu/Tests/TestCaseSpinnerHidden.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index cb8b13ef27..8be55f7b4b 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs index d8dd6c7323..0aeb14514d 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/GameplayCursor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -159,5 +159,17 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor return false; } + + protected override void PopIn() + { + ActiveCursor.FadeTo(1, 250, Easing.OutQuint); + ActiveCursor.ScaleTo(1, 400, Easing.OutQuint); + } + + protected override void PopOut() + { + ActiveCursor.FadeTo(0, 250, Easing.OutQuint); + ActiveCursor.ScaleTo(0.6f, 250, Easing.In); + } } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 0dc6feee75..17521f8992 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -12,8 +12,6 @@ using osu.Game.Rulesets.UI; using System.Linq; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; -using osu.Game.Rulesets.Osu.UI.Cursor; -using osu.Framework.Graphics.Cursor; namespace osu.Game.Rulesets.Osu.UI { @@ -23,8 +21,6 @@ namespace osu.Game.Rulesets.Osu.UI private readonly Container judgementLayer; private readonly ConnectionRenderer connectionLayer; - public override bool ProvidingUserCursor => true; - // Todo: This should not be a thing, but is currently required for the editor // https://github.com/ppy/osu-framework/issues/1283 protected virtual bool ProxyApproachCircles => true; @@ -70,19 +66,12 @@ namespace osu.Game.Rulesets.Osu.UI }); } - protected override void LoadComplete() - { - base.LoadComplete(); - - var cursor = CreateCursor(); - if (cursor != null) - AddInternal(cursor); - } - public override void Add(DrawableHitObject h) { h.Depth = (float)h.HitObject.StartTime; + h.OnJudgement += onJudgement; + var c = h as IDrawableHitObjectWithProxiedApproach; if (c != null && ProxyApproachCircles) approachCircles.Add(c.ProxiedLayer.CreateProxy()); @@ -97,7 +86,7 @@ namespace osu.Game.Rulesets.Osu.UI .OrderBy(h => h.StartTime).OfType(); } - public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) + private void onJudgement(DrawableHitObject judgedObject, Judgement judgement) { var osuJudgement = (OsuJudgement)judgement; var osuObject = (OsuHitObject)judgedObject.HitObject; @@ -113,7 +102,5 @@ namespace osu.Game.Rulesets.Osu.UI judgementLayer.Add(explosion); } - - protected virtual CursorContainer CreateCursor() => new GameplayCursor(); } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs index f37b87e533..526348062f 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuRulesetContainer.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Graphics.Cursor; using osu.Framework.Input; using OpenTK; using osu.Game.Beatmaps; @@ -10,6 +11,7 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Replays; @@ -49,5 +51,7 @@ namespace osu.Game.Rulesets.Osu.UI protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new OsuReplayInputHandler(replay); protected override Vector2 GetPlayfieldAspectAdjust() => new Vector2(0.75f); + + protected override CursorContainer CreateCursor() => new GameplayCursor(); } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuSettings.cs b/osu.Game.Rulesets.Osu/UI/OsuSettings.cs index b820f33b39..d8f0aa9ebf 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuSettings.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs index 982b339d3a..5493a5029b 100644 --- a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs +++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 690b80b12c..e5fe288f20 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; @@ -84,7 +84,8 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps if (distanceData != null) { - int repeats = repeatsData?.RepeatCount ?? 1; + // Number of spans of the object - one for the initial length and for each repeat + int spans = repeatsData?.SpanCount() ?? 1; TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime); DifficultyControlPoint difficultyPoint = beatmap.ControlPointInfo.DifficultyPointAt(obj.StartTime); @@ -93,7 +94,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps double speedAdjustedBeatLength = timingPoint.BeatLength / speedAdjustment; // The true distance, accounting for any repeats. This ends up being the drum roll distance later - double distance = distanceData.Distance * repeats * legacy_velocity_multiplier; + double distance = distanceData.Distance * spans * legacy_velocity_multiplier; // The velocity of the taiko hit object - calculated as the velocity of a drum roll double taikoVelocity = taiko_base_distance * beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier * legacy_velocity_multiplier / speedAdjustedBeatLength; @@ -111,7 +112,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps double osuDuration = distance / osuVelocity; // If the drum roll is to be split into hit circles, assume the ticks are 1/8 spaced within the duration of one beat - double tickSpacing = Math.Min(speedAdjustedBeatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, taikoDuration / repeats); + double tickSpacing = Math.Min(speedAdjustedBeatLength / beatmap.BeatmapInfo.BaseDifficulty.SliderTickRate, taikoDuration / spans); if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) { diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index ce5be8d148..a713b8ba8c 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Scoring; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index 70cdd1fe0e..f3dc45d78e 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs index e1fe19212b..c477851335 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Taiko.Judgements diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoMod.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoMod.cs deleted file mode 100644 index abaa8c1bc1..0000000000 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoMod.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Objects; -using osu.Game.Rulesets.Taiko.Replays; -using osu.Game.Users; - -namespace osu.Game.Rulesets.Taiko.Mods -{ - public class TaikoModNoFail : ModNoFail - { - - } - - public class TaikoModEasy : ModEasy - { - - } - - public class TaikoModHidden : ModHidden - { - public override string Description => @"The notes fade out before you hit them!"; - public override double ScoreMultiplier => 1.06; - } - - public class TaikoModHardRock : ModHardRock - { - public override double ScoreMultiplier => 1.06; - public override bool Ranked => true; - } - - public class TaikoModSuddenDeath : ModSuddenDeath - { - - } - - public class TaikoModDaycore : ModDaycore - { - public override double ScoreMultiplier => 0.5; - } - - public class TaikoModDoubleTime : ModDoubleTime - { - public override double ScoreMultiplier => 1.12; - } - - public class TaikoModRelax : ModRelax - { - public override string Description => @"Relax! You will no longer get dizzyfied by ninja-like spinners, demanding drumrolls or unexpected katu's."; - } - - public class TaikoModHalfTime : ModHalfTime - { - public override double ScoreMultiplier => 0.5; - } - - public class TaikoModNightcore : ModNightcore - { - public override double ScoreMultiplier => 1.12; - } - - public class TaikoModFlashlight : ModFlashlight - { - public override double ScoreMultiplier => 1.12; - } - - public class TaikoModPerfect : ModPerfect - { - - } - - public class TaikoModAutoplay : ModAutoplay - { - protected override Score CreateReplayScore(Beatmap beatmap) => new Score - { - User = new User { Username = "mekkadosu!" }, - Replay = new TaikoAutoGenerator(beatmap).Generate(), - }; - } -} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs new file mode 100644 index 0000000000..239f0d5a6b --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Replays; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModAutoplay : ModAutoplay + { + protected override Score CreateReplayScore(Beatmap beatmap) + { + return new Score + { + User = new User { Username = "mekkadosu!" }, + Replay = new TaikoAutoGenerator(beatmap).Generate(), + }; + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs new file mode 100644 index 0000000000..c50878c6a3 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDaycore.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModDaycore : ModDaycore + { + public override double ScoreMultiplier => 0.5; + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs new file mode 100644 index 0000000000..2ae52b4549 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDoubleTime.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModDoubleTime : ModDoubleTime + { + public override double ScoreMultiplier => 1.12; + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs new file mode 100644 index 0000000000..1c5e43f411 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModEasy.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModEasy : ModEasy + { + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs new file mode 100644 index 0000000000..a2c6d7f9e0 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModFlashlight : ModFlashlight + { + public override double ScoreMultiplier => 1.12; + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs new file mode 100644 index 0000000000..9813f8b78e --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHalfTime.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModHalfTime : ModHalfTime + { + public override double ScoreMultiplier => 0.5; + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs new file mode 100644 index 0000000000..ba304c41d8 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModHardRock : ModHardRock + { + public override double ScoreMultiplier => 1.06; + public override bool Ranked => true; + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs new file mode 100644 index 0000000000..b0ad43b851 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModHidden : ModHidden + { + public override string Description => @"The notes fade out before you hit them!"; + public override double ScoreMultiplier => 1.06; + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs new file mode 100644 index 0000000000..0504b7c5b6 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModNightcore.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModNightcore : ModNightcore + { + public override double ScoreMultiplier => 1.12; + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs new file mode 100644 index 0000000000..3e10f58bbd --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModNoFail.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModNoFail : ModNoFail + { + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs new file mode 100644 index 0000000000..7388283d41 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModPerfect.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModPerfect : ModPerfect + { + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs new file mode 100644 index 0000000000..ec2385bfba --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModRelax.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModRelax : ModRelax + { + public override string Description => @"Relax! You will no longer get dizzyfied by ninja-like spinners, demanding drumrolls or unexpected katu's."; + } +} diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs new file mode 100644 index 0000000000..129d181616 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModSuddenDeath.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Mods; + +namespace osu.Game.Rulesets.Taiko.Mods +{ + public class TaikoModSuddenDeath : ModSuddenDeath + { + } +} diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs index 0e6ff9f758..efd7d57ed7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/CentreHit.cs b/osu.Game.Rulesets.Taiko/Objects/CentreHit.cs index f82058fe01..ff7c36a8ad 100644 --- a/osu.Game.Rulesets.Taiko/Objects/CentreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/CentreHit.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index b30b3a1aca..cf6aa7d895 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// A line that scrolls alongside hit objects in the playfield and visualises control points. /// - public class DrawableBarLine : DrawableScrollingHitObject + public class DrawableBarLine : DrawableHitObject { /// /// The width of the line tracker. diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs index 7a4cf1f1f7..23c34e9863 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs index 26aa20f1af..56a0976ddb 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs index 1dbab408de..c0bfaba5f5 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index f5bafefd0b..29d464f614 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; @@ -34,15 +34,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public DrawableDrumRoll(DrumRoll drumRoll) : base(drumRoll) { - Width = (float)HitObject.Duration; + RelativeSizeAxes = Axes.Y; Container tickContainer; - MainPiece.Add(tickContainer = new Container - { - RelativeSizeAxes = Axes.Both, - RelativeChildOffset = new Vector2((float)HitObject.StartTime, 0), - RelativeChildSize = new Vector2((float)HitObject.Duration, 1) - }); + MainPiece.Add(tickContainer = new Container { RelativeSizeAxes = Axes.Both }); foreach (var tick in drumRoll.NestedHitObjects.OfType()) { @@ -86,7 +81,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables if (timeOffset < 0) return; - int countHit = NestedHitObjects.Count(o => o.AllJudged); + int countHit = NestedHitObjects.Count(o => o.IsHit); if (countHit > HitObject.RequiredGoodHits) { @@ -100,6 +95,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void UpdateState(ArmedState state) { + switch (state) + { + case ArmedState.Hit: + case ArmedState.Miss: + this.FadeOut(100).Expire(); + break; + } } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index a741e35963..bc5abce245 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -15,23 +15,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables public DrawableDrumRollTick(DrumRollTick tick) : base(tick) { - // Because ticks aren't added by the ScrollingPlayfield, we need to set the following properties ourselves - RelativePositionAxes = Axes.X; - X = (float)tick.StartTime; - FillMode = FillMode.Fit; } public override bool DisplayJudgement => false; - protected override void LoadComplete() - { - base.LoadComplete(); - - // We need to set this here because RelativeSizeAxes won't/can't set our size by default with a different RelativeChildSize - Width *= Parent.RelativeChildSize.X; - } - protected override TaikoPiece CreateMainPiece() => new TickPiece { Filled = HitObject.FirstTick @@ -55,7 +43,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (state) { case ArmedState.Hit: - Content.ScaleTo(0, 100, Easing.OutQuint); + Content.ScaleTo(0, 100, Easing.OutQuint).Expire(); break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 0c10c7142e..63e6cfb297 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -1,7 +1,6 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Linq; using osu.Framework.Graphics; using osu.Game.Rulesets.Objects.Drawables; @@ -38,30 +37,27 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { if (!userTriggered) { - if (timeOffset > HitObject.HitWindowGood) + if (!HitObject.HitWindows.CanBeHit(timeOffset)) AddJudgement(new TaikoJudgement { Result = HitResult.Miss }); return; } - double hitOffset = Math.Abs(timeOffset); - - if (hitOffset > HitObject.HitWindowMiss) + var result = HitObject.HitWindows.ResultFor(timeOffset); + if (result == HitResult.None) return; - if (!validKeyPressed) + if (!validKeyPressed || result == HitResult.Miss) AddJudgement(new TaikoJudgement { Result = HitResult.Miss }); - else if (hitOffset < HitObject.HitWindowGood) + else { AddJudgement(new TaikoJudgement { - Result = hitOffset < HitObject.HitWindowGreat ? HitResult.Great : HitResult.Good, + Result = result, Final = !HitObject.IsStrong }); SecondHitAllowed = true; } - else - AddJudgement(new TaikoJudgement { Result = HitResult.Miss }); } public override bool OnPressed(TaikoAction action) @@ -90,7 +86,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (State.Value) { case ArmedState.Idle: - this.Delay(HitObject.HitWindowMiss).Expire(); + this.Delay(HitObject.HitWindows.HalfWindowFor(HitResult.Miss)).Expire(); break; case ArmedState.Miss: this.FadeOut(100) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs index 249bb41d91..cf6236e872 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs index 9f0cd3e061..e8492ac168 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs index 294198f3ee..b5e232a65d 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 26e6585fb9..c9e488764c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -192,7 +192,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Size = BaseSize * Parent.RelativeChildSize; // Make the swell stop at the hit target - X = (float)Math.Max(Time.Current, HitObject.StartTime); + X = Math.Max(0, X); double t = Math.Min(HitObject.StartTime, Time.Current); if (t == HitObject.StartTime && !hasStarted) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index cc7dd2fa0f..e57c2f9944 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -12,7 +12,7 @@ using System.Collections.Generic; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { - public abstract class DrawableTaikoHitObject : DrawableScrollingHitObject, IKeyBindingHandler + public abstract class DrawableTaikoHitObject : DrawableHitObject, IKeyBindingHandler where TaikoHitType : TaikoHitObject { public override Vector2 OriginPosition => new Vector2(DrawHeight / 2); diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs index f4c78251d0..05c3f45d80 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs index 3264b77bc4..b68dac9e85 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; @@ -155,4 +155,4 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces .FadeEdgeEffectTo(edge_alpha_kiai, duration, Easing.OutQuint); } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs index 4642e318c4..26d099c101 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs index 60224a291d..7614f1d6d8 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs index c3fdc671a4..bccfaceb56 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs index 4b40bbf384..fa2d1c78e3 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs index 211bf910a4..0ff2742be6 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index a39d627cc4..181fee8393 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 01f9caf215..f72db4db6d 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Taiko.Objects @@ -21,4 +21,4 @@ namespace osu.Game.Rulesets.Taiko.Objects /// public double HitWindow => TickSpacing / 2; } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index 1b9b44fd99..c91a1f1714 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -1,35 +1,9 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; - namespace osu.Game.Rulesets.Taiko.Objects { public class Hit : TaikoHitObject { - /// - /// The hit window that results in a "GREAT" hit. - /// - public double HitWindowGreat = 35; - - /// - /// The hit window that results in a "GOOD" hit. - /// - public double HitWindowGood = 80; - - /// - /// The hit window that results in a "MISS". - /// - public double HitWindowMiss = 95; - - protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) - { - base.ApplyDefaultsToSelf(controlPointInfo, difficulty); - - HitWindowGreat = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 50, 35, 20); - HitWindowGood = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 120, 80, 50); - HitWindowMiss = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 135, 95, 70); - } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/RimHit.cs b/osu.Game.Rulesets.Taiko/Objects/RimHit.cs index 8e09842294..d161970c38 100644 --- a/osu.Game.Rulesets.Taiko/Objects/RimHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/RimHit.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs index cd2876ea2d..e17d11e3e7 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 1be91a7d94..6e0d0e380a 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects; diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs index c8bb73abbb..54f08e9015 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -124,4 +124,4 @@ namespace osu.Game.Rulesets.Taiko.Objects Odd } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs index c43899ebf1..002159439d 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -35,8 +35,8 @@ namespace osu.Game.Rulesets.Taiko.Replays { bool hitButton = true; - Frames.Add(new ReplayFrame(-100000, null, null, ReplayButtonState.None)); - Frames.Add(new ReplayFrame(Beatmap.HitObjects[0].StartTime - 1000, null, null, ReplayButtonState.None)); + Frames.Add(new TaikoReplayFrame(-100000, ReplayButtonState.None)); + Frames.Add(new TaikoReplayFrame(Beatmap.HitObjects[0].StartTime - 1000, ReplayButtonState.None)); for (int i = 0; i < Beatmap.HitObjects.Count; i++) { @@ -76,7 +76,7 @@ namespace osu.Game.Rulesets.Taiko.Replays break; } - Frames.Add(new ReplayFrame(j, null, null, button)); + Frames.Add(new TaikoReplayFrame(j, button)); d = (d + 1) % 4; if (++count == req) break; @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Taiko.Replays { foreach (var tick in drumRoll.NestedHitObjects.OfType()) { - Frames.Add(new ReplayFrame(tick.StartTime, null, null, hitButton ? ReplayButtonState.Right1 : ReplayButtonState.Right2)); + Frames.Add(new TaikoReplayFrame(tick.StartTime, hitButton ? ReplayButtonState.Right1 : ReplayButtonState.Right2)); hitButton = !hitButton; } } @@ -107,18 +107,18 @@ namespace osu.Game.Rulesets.Taiko.Replays button = hitButton ? ReplayButtonState.Left1 : ReplayButtonState.Left2; } - Frames.Add(new ReplayFrame(h.StartTime, null, null, button)); + Frames.Add(new TaikoReplayFrame(h.StartTime, button)); } else throw new InvalidOperationException("Unknown hit object type."); - Frames.Add(new ReplayFrame(endTime + KEY_UP_DELAY, null, null, ReplayButtonState.None)); + Frames.Add(new TaikoReplayFrame(endTime + KEY_UP_DELAY, ReplayButtonState.None)); if (i < Beatmap.HitObjects.Count - 1) { double waitTime = Beatmap.HitObjects[i + 1].StartTime - 1000; if (waitTime > endTime) - Frames.Add(new ReplayFrame(waitTime, null, null, ReplayButtonState.None)); + Frames.Add(new TaikoReplayFrame(waitTime, ReplayButtonState.None)); } hitButton = !hitButton; diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs index fce0179721..05e10b6fce 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Replays; diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs new file mode 100644 index 0000000000..0c60cdc109 --- /dev/null +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Replays; + +namespace osu.Game.Rulesets.Taiko.Replays +{ + public class TaikoReplayFrame : ReplayFrame + { + public override bool IsImportant => MouseLeft || MouseRight; + + public TaikoReplayFrame(double time, ReplayButtonState buttons) + : base(time, null, null, buttons) + { + } + } +} diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 3848e36fc9..b91f37d84d 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// /// Taiko fails at the end of the map if the player has not half-filled their HP bar. /// - protected override bool DefaultFailCondition => Hits == MaxHits && Health.Value <= 0.5; + protected override bool DefaultFailCondition => JudgedHits == MaxHits && Health.Value <= 0.5; private double hpIncreaseTick; private double hpIncreaseGreat; diff --git a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs index e74c12fa5d..8b4e77573f 100644 --- a/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; diff --git a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs index 1e3c0fbcf2..f668a09f21 100644 --- a/osu.Game.Rulesets.Taiko/TaikoInputManager.cs +++ b/osu.Game.Rulesets.Taiko/TaikoInputManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 4de9ba0ce7..50cc80db50 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; @@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Taiko public override int LegacyID => 1; - public TaikoRuleset(RulesetInfo rulesetInfo) + public TaikoRuleset(RulesetInfo rulesetInfo = null) : base(rulesetInfo) { } diff --git a/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs b/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs index 172c6e9d84..c7201150e9 100644 --- a/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs +++ b/osu.Game.Rulesets.Taiko/Tests/TestCaseInputDrum.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Taiko/Tests/TestCasePerformancePoints.cs b/osu.Game.Rulesets.Taiko/Tests/TestCasePerformancePoints.cs index 96d5b20b6e..3d2d97b6d3 100644 --- a/osu.Game.Rulesets.Taiko/Tests/TestCasePerformancePoints.cs +++ b/osu.Game.Rulesets.Taiko/Tests/TestCasePerformancePoints.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Tests public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints { public TestCasePerformancePoints() - : base(new TaikoRuleset(new RulesetInfo())) + : base(new TaikoRuleset()) { } } diff --git a/osu.Game.Rulesets.Taiko/Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/Tests/TestCaseTaikoPlayfield.cs index 1f13864c2a..fd396c201d 100644 --- a/osu.Game.Rulesets.Taiko/Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/Tests/TestCaseTaikoPlayfield.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -143,18 +143,18 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - rulesetContainer.Playfield.OnJudgement(h, new TaikoJudgement { Result = hitResult }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new TaikoJudgement { Result = hitResult }); if (RNG.Next(10) == 0) { - rulesetContainer.Playfield.OnJudgement(h, new TaikoJudgement { Result = hitResult }); - rulesetContainer.Playfield.OnJudgement(h, new TaikoStrongHitJudgement()); + ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new TaikoJudgement { Result = hitResult }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(h, new TaikoStrongHitJudgement()); } } private void addMissJudgement() { - rulesetContainer.Playfield.OnJudgement(new DrawableTestHit(new Hit()), new TaikoJudgement { Result = HitResult.Miss }); + ((TaikoPlayfield)rulesetContainer.Playfield).OnJudgement(new DrawableTestHit(new Hit()), new TaikoJudgement { Result = HitResult.Miss }); } private void addBarLine(bool major, double delay = scroll_time) diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs index 0b67613ec3..c0e8bd1b5a 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs index 830a01bfbc..1a9915f78e 100644 --- a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game.Rulesets.Taiko/UI/HitTarget.cs b/osu.Game.Rulesets.Taiko/UI/HitTarget.cs index 8f3b6840f3..fa2b6e737f 100644 --- a/osu.Game.Rulesets.Taiko/UI/HitTarget.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitTarget.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index 9b2ea095d2..98f20fd558 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs index e3e1d485d8..0f5065f3ec 100644 --- a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -65,4 +65,4 @@ namespace osu.Game.Rulesets.Taiko.UI Expire(); } } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 3fdbd056ce..49c87f7480 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Game.Rulesets.Taiko.Objects; -using osu.Game.Rulesets.UI; using OpenTK; using OpenTK.Graphics; using osu.Game.Rulesets.Taiko.Judgements; @@ -17,6 +16,7 @@ using System.Linq; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI { @@ -37,6 +37,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// private const float left_area_size = 240; + protected override bool UserScrollSpeedAdjustment => false; private readonly Container hitExplosionContainer; private readonly Container kiaiExplosionContainer; @@ -56,7 +57,7 @@ namespace osu.Game.Rulesets.Taiko.UI private readonly Box background; public TaikoPlayfield(ControlPointInfo controlPoints) - : base(Axes.X) + : base(ScrollingDirection.Left) { AddRangeInternal(new Drawable[] { @@ -208,6 +209,8 @@ namespace osu.Game.Rulesets.Taiko.UI { h.Depth = (float)h.HitObject.StartTime; + h.OnJudgement += OnJudgement; + base.Add(h); var barline = h as DrawableBarLine; @@ -220,7 +223,7 @@ namespace osu.Game.Rulesets.Taiko.UI swell.OnStart += () => topLevelHitContainer.Add(swell.CreateProxy()); } - public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) + internal void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { if (judgedObject.DisplayJudgement && judgementContainer.FirstOrDefault(j => j.JudgedObject == judgedObject) == null) { diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs index 614b446181..1b9821d698 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoRulesetContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -17,6 +17,7 @@ using osu.Game.Rulesets.Taiko.Replays; using OpenTK; using System.Linq; using osu.Framework.Input; +using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI { diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index d3e7958ec1..21bbc4993c 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.IO; diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs index a0904ee446..dce6c0f55b 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyStoryboardDecoderTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.IO; @@ -70,7 +70,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(new Vector2(320, 240), sprite.InitialPosition); Assert.IsTrue(sprite.IsDrawable); Assert.AreEqual(Anchor.Centre, sprite.Origin); - Assert.AreEqual(Path.Combine("SB", "lyric", "ja-21.png"), sprite.Path); + Assert.AreEqual("SB/lyric/ja-21.png", sprite.Path); var animation = background.Elements.ElementAt(12) as StoryboardAnimation; Assert.NotNull(animation); @@ -82,7 +82,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.IsTrue(animation.IsDrawable); Assert.AreEqual(AnimationLoopType.LoopForever, animation.LoopType); Assert.AreEqual(Anchor.Centre, animation.Origin); - Assert.AreEqual(Path.Combine("SB", "red jitter", "red_0000.jpg"), animation.Path); + Assert.AreEqual("SB/red jitter/red_0000.jpg", animation.Path); Assert.AreEqual(78993, animation.StartTime); } } diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs index 7143550ee2..186bd44640 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuJsonDecoderTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.IO; diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 77d78b8bd6..0b49bc8bb9 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Beatmaps.IO public void TestImportWhenClosed() { //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. - using (HeadlessGameHost host = new HeadlessGameHost("TestImportWhenClosed")) + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWhenClosed")) { var osu = loadOsu(host); @@ -37,6 +37,8 @@ namespace osu.Game.Tests.Beatmaps.IO ensureLoaded(osu); waitForOrAssert(() => !File.Exists(temp), "Temporary file still exists after standard import", 5000); + + host.Exit(); } } @@ -45,8 +47,8 @@ namespace osu.Game.Tests.Beatmaps.IO [Ignore("Binding IPC on Appveyor isn't working (port in use). Need to figure out why")] public void TestImportOverIPC() { - using (HeadlessGameHost host = new HeadlessGameHost("host", true)) - using (HeadlessGameHost client = new HeadlessGameHost("client", true)) + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("host", true)) + using (HeadlessGameHost client = new CleanRunHeadlessGameHost("client", true)) { Assert.IsTrue(host.IsPrimaryInstance); Assert.IsFalse(client.IsPrimaryInstance); @@ -64,13 +66,15 @@ namespace osu.Game.Tests.Beatmaps.IO ensureLoaded(osu); waitForOrAssert(() => !File.Exists(temp), "Temporary still exists after IPC import", 5000); + + host.Exit(); } } [Test] public void TestImportWhenFileOpen() { - using (HeadlessGameHost host = new HeadlessGameHost("TestImportWhenFileOpen")) + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportWhenFileOpen")) { var osu = loadOsu(host); @@ -86,6 +90,8 @@ namespace osu.Game.Tests.Beatmaps.IO File.Delete(temp); Assert.IsFalse(File.Exists(temp), "We likely held a read lock on the file when we shouldn't"); + + host.Exit(); } } @@ -117,8 +123,8 @@ namespace osu.Game.Tests.Beatmaps.IO //ensure we were stored to beatmap database backing... Assert.IsTrue(resultSets.Count() == 1, $@"Incorrect result count found ({resultSets.Count()} but should be 1)."); - Func> queryBeatmaps = () => store.QueryBeatmaps(s => s.BeatmapSet.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0); - Func> queryBeatmapSets = () => store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526); + IEnumerable queryBeatmaps() => store.QueryBeatmaps(s => s.BeatmapSet.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0); + IEnumerable queryBeatmapSets() => store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526); //if we don't re-check here, the set will be inserted but the beatmaps won't be present yet. waitForOrAssert(() => queryBeatmaps().Count() == 12, diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index ffe735c89f..44eb385e22 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.IO; diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs new file mode 100644 index 0000000000..f102e4c59f --- /dev/null +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -0,0 +1,247 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using NUnit.Framework; +using osu.Game.Online.Chat; + +namespace osu.Game.Tests.Chat +{ + [TestFixture] + public class MessageFormatterTests + { + [Test] + public void TestBareLink() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a http://www.basic-link.com/?test=test." }); + + Assert.AreEqual(result.Content, result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("http://www.basic-link.com/?test=test", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(36, result.Links[0].Length); + } + + [Test] + public void TestMultipleComplexLinks() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a http://test.io/link#fragment. (see https://twitter.com). Also, This string should not be altered. http://example.com/" }); + + Assert.AreEqual(result.Content, result.DisplayContent); + Assert.AreEqual(3, result.Links.Count); + + Assert.AreEqual("http://test.io/link#fragment", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(28, result.Links[0].Length); + + Assert.AreEqual("https://twitter.com", result.Links[1].Url); + Assert.AreEqual(45, result.Links[1].Index); + Assert.AreEqual(19, result.Links[1].Length); + + Assert.AreEqual("http://example.com/", result.Links[2].Url); + Assert.AreEqual(108, result.Links[2].Index); + Assert.AreEqual(19, result.Links[2].Length); + } + + [Test] + public void TestAjaxLinks() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "https://twitter.com/#!/hashbanglinks" }); + + Assert.AreEqual(result.Content, result.DisplayContent); + Assert.AreEqual(result.Content, result.Links[0].Url); + Assert.AreEqual(0, result.Links[0].Index); + Assert.AreEqual(36, result.Links[0].Length); + } + + [Test] + public void TestUnixHomeLinks() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "http://www.chiark.greenend.org.uk/~sgtatham/putty/" }); + + Assert.AreEqual(result.Content, result.DisplayContent); + Assert.AreEqual(result.Content, result.Links[0].Url); + Assert.AreEqual(0, result.Links[0].Index); + Assert.AreEqual(50, result.Links[0].Length); + } + + [Test] + public void TestCaseInsensitiveLinks() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "look: http://puu.sh/7Ggh8xcC6/asf0asd9876.NEF" }); + + Assert.AreEqual(result.Content, result.DisplayContent); + Assert.AreEqual(6, result.Links[0].Index); + Assert.AreEqual(39, result.Links[0].Length); + } + + [Test] + public void TestWikiLink() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [[Wiki Link]]." }); + + Assert.AreEqual("This is a Wiki Link.", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh/wiki/Wiki Link", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(9, result.Links[0].Length); + } + + [Test] + public void TestMultiWikiLink() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [[Wiki Link]] [[Wiki:Link]][[Wiki.Link]]." }); + + Assert.AreEqual("This is a Wiki Link Wiki:LinkWiki.Link.", result.DisplayContent); + Assert.AreEqual(3, result.Links.Count); + + Assert.AreEqual("https://osu.ppy.sh/wiki/Wiki Link", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(9, result.Links[0].Length); + + Assert.AreEqual("https://osu.ppy.sh/wiki/Wiki:Link", result.Links[1].Url); + Assert.AreEqual(20, result.Links[1].Index); + Assert.AreEqual(9, result.Links[1].Length); + + Assert.AreEqual("https://osu.ppy.sh/wiki/Wiki.Link", result.Links[2].Url); + Assert.AreEqual(29, result.Links[2].Index); + Assert.AreEqual(9, result.Links[2].Length); + } + + [Test] + public void TestOldFormatLink() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a (simple test)[https://osu.ppy.sh] of links." }); + + Assert.AreEqual("This is a simple test of links.", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(11, result.Links[0].Length); + } + + [Test] + public void TestNewFormatLink() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [https://osu.ppy.sh simple test]." }); + + Assert.AreEqual("This is a simple test.", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(11, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatLink() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [simple test](https://osu.ppy.sh)." }); + + Assert.AreEqual("This is a simple test.", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(11, result.Links[0].Length); + } + + [Test] + public void TestChannelLink() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is an #english and #japanese." }); + + Assert.AreEqual(result.Content, result.DisplayContent); + Assert.AreEqual(2, result.Links.Count); + Assert.AreEqual("osu://chan/#english", result.Links[0].Url); + Assert.AreEqual("osu://chan/#japanese", result.Links[1].Url); + } + + [Test] + public void TestOsuProtocol() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a custom protocol osu://chan/#english." }); + + Assert.AreEqual(result.Content, result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("osu://chan/#english", result.Links[0].Url); + Assert.AreEqual(26, result.Links[0].Index); + Assert.AreEqual(19, result.Links[0].Length); + + result = MessageFormatter.FormatMessage(new Message { Content = "This is a [custom protocol](osu://chan/#english)." }); + + Assert.AreEqual("This is a custom protocol.", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("osu://chan/#english", result.Links[0].Url); + Assert.AreEqual("#english", result.Links[0].Argument); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(15, result.Links[0].Length); + } + + [Test] + public void TestOsuMpProtocol() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "Join my multiplayer game osump://12346." }); + + Assert.AreEqual(result.Content, result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("osump://12346", result.Links[0].Url); + Assert.AreEqual(25, result.Links[0].Index); + Assert.AreEqual(13, result.Links[0].Length); + } + + [Test] + public void TestRecursiveBreaking() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [https://osu.ppy.sh [[simple test]]]." }); + + Assert.AreEqual("This is a [[simple test]].", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(15, result.Links[0].Length); + } + + [Test] + public void TestLinkComplex() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [http://www.simple-test.com simple test] with some [traps] and [[wiki links]]. Don't forget to visit https://osu.ppy.sh (now!)[http://google.com]\uD83D\uDE12" }); + + Assert.AreEqual("This is a simple test with some [traps] and wiki links. Don't forget to visit https://osu.ppy.sh now!\0\0\0", result.DisplayContent); + Assert.AreEqual(5, result.Links.Count); + + Link f = result.Links.Find(l => l.Url == "https://osu.ppy.sh/wiki/wiki links"); + Assert.AreEqual(44, f.Index); + Assert.AreEqual(10, f.Length); + + f = result.Links.Find(l => l.Url == "http://www.simple-test.com"); + Assert.AreEqual(10, f.Index); + Assert.AreEqual(11, f.Length); + + f = result.Links.Find(l => l.Url == "http://google.com"); + Assert.AreEqual(97, f.Index); + Assert.AreEqual(4, f.Length); + + f = result.Links.Find(l => l.Url == "https://osu.ppy.sh"); + Assert.AreEqual(78, f.Index); + Assert.AreEqual(18, f.Length); + + f = result.Links.Find(l => l.Url == "\uD83D\uDE12"); + Assert.AreEqual(101, f.Index); + Assert.AreEqual(3, f.Length); + } + + [Test] + public void TestEmoji() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "Hello world\uD83D\uDE12<--This is an emoji,There are more:\uD83D\uDE10\uD83D\uDE00,\uD83D\uDE20" }); + Assert.AreEqual("Hello world\0\0\0<--This is an emoji,There are more:\0\0\0\0\0\0,\0\0\0", result.DisplayContent); + Assert.AreEqual(result.Links.Count, 4); + Assert.AreEqual(result.Links[0].Index, 11); + Assert.AreEqual(result.Links[1].Index, 49); + Assert.AreEqual(result.Links[2].Index, 52); + Assert.AreEqual(result.Links[3].Index, 56); + Assert.AreEqual(result.Links[0].Url, "\uD83D\uDE12"); + Assert.AreEqual(result.Links[1].Url, "\uD83D\uDE10"); + Assert.AreEqual(result.Links[2].Url, "\uD83D\uDE00"); + Assert.AreEqual(result.Links[3].Url, "\uD83D\uDE20"); + } + } +} diff --git a/osu.Game.Tests/Resources/Resource.cs b/osu.Game.Tests/Resources/Resource.cs index 6c66b6818b..39c20e6b19 100644 --- a/osu.Game.Tests/Resources/Resource.cs +++ b/osu.Game.Tests/Resources/Resource.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -17,4 +17,4 @@ namespace osu.Game.Tests.Resources Assembly.LoadFrom(Path.Combine(localPath, @"osu.Game.Resources.dll")).GetManifestResourceStream($@"osu.Game.Resources.{name}"); } } -} \ No newline at end of file +} diff --git a/osu.Game.Tests/Visual/TestCaseAllPlayers.cs b/osu.Game.Tests/Visual/TestCaseAllPlayers.cs index 62b99487a9..912dbc4056 100644 --- a/osu.Game.Tests/Visual/TestCaseAllPlayers.cs +++ b/osu.Game.Tests/Visual/TestCaseAllPlayers.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Tests.Visual diff --git a/osu.Game.Tests/Visual/TestCaseAutoplay.cs b/osu.Game.Tests/Visual/TestCaseAutoplay.cs new file mode 100644 index 0000000000..d954d0543c --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseAutoplay.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.ComponentModel; +using System.Linq; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Screens.Play; + +namespace osu.Game.Tests.Visual +{ + [Description("Player instantiated with an autoplay mod.")] + public class TestCaseAutoplay : TestCasePlayer + { + protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset) + { + beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); + return base.CreatePlayer(beatmap, ruleset); + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs index 35cceaf6fa..f081d090c8 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatSyncedContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs index c09b987407..4a65d12977 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -128,6 +128,20 @@ namespace osu.Game.Tests.Visual selectedSets.Pop(); }); + private bool selectedBeatmapVisible() + { + var currentlySelected = carousel.Items.FirstOrDefault(s => s.Item is CarouselBeatmap && s.Item.State == CarouselItemState.Selected); + if (currentlySelected == null) + return true; + return currentlySelected.Item.Visible; + } + + private void checkInvisibleDifficultiesUnselectable() + { + nextRandom(); + AddAssert("Selection is visible", selectedBeatmapVisible); + } + /// /// Test keyboard traversal /// @@ -222,6 +236,15 @@ namespace osu.Game.Tests.Visual nextRandom(); AddAssert("ensure repeat", () => selectedSets.Contains(carousel.SelectedBeatmapSet)); + + AddStep("Add set with 100 difficulties", () => carousel.UpdateBeatmapSet(createTestBeatmapSetWithManyDifficulties(set_count + 1))); + AddStep("Filter Extra", () => carousel.Filter(new FilterCriteria { SearchText = "Extra 10" }, false)); + checkInvisibleDifficultiesUnselectable(); + checkInvisibleDifficultiesUnselectable(); + checkInvisibleDifficultiesUnselectable(); + checkInvisibleDifficultiesUnselectable(); + checkInvisibleDifficultiesUnselectable(); + AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); } /// @@ -330,26 +353,26 @@ namespace osu.Game.Tests.Visual } } - private BeatmapSetInfo createTestBeatmapSet(int i) + private BeatmapSetInfo createTestBeatmapSet(int id) { return new BeatmapSetInfo { - ID = i, - OnlineBeatmapSetID = i, + ID = id, + OnlineBeatmapSetID = id, Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), Metadata = new BeatmapMetadata { - OnlineBeatmapSetID = i, + OnlineBeatmapSetID = id, // Create random metadata, then we can check if sorting works based on these - Artist = $"peppy{i.ToString().PadLeft(6, '0')}", - Title = $"test set #{i}!", - AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, i - 1)), 5)) + Artist = $"peppy{id.ToString().PadLeft(6, '0')}", + Title = $"test set #{id}!", + AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, id - 1)), 5)) }, Beatmaps = new List(new[] { new BeatmapInfo { - OnlineBeatmapID = i * 10, + OnlineBeatmapID = id * 10, Path = "normal.osu", Version = "Normal", StarDifficulty = 2, @@ -360,7 +383,7 @@ namespace osu.Game.Tests.Visual }, new BeatmapInfo { - OnlineBeatmapID = i * 10 + 1, + OnlineBeatmapID = id * 10 + 1, Path = "hard.osu", Version = "Hard", StarDifficulty = 5, @@ -371,7 +394,7 @@ namespace osu.Game.Tests.Visual }, new BeatmapInfo { - OnlineBeatmapID = i * 10 + 2, + OnlineBeatmapID = id * 10 + 2, Path = "insane.osu", Version = "Insane", StarDifficulty = 6, @@ -384,6 +407,40 @@ namespace osu.Game.Tests.Visual }; } + private BeatmapSetInfo createTestBeatmapSetWithManyDifficulties(int id) + { + var toReturn = new BeatmapSetInfo + { + ID = id, + OnlineBeatmapSetID = id, + Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), + Metadata = new BeatmapMetadata + { + OnlineBeatmapSetID = id, + // Create random metadata, then we can check if sorting works based on these + Artist = $"peppy{id.ToString().PadLeft(6, '0')}", + Title = $"test set #{id}!", + AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, id - 1)), 5)) + }, + Beatmaps = new List(), + }; + for (int b = 1; b < 101; b++) + { + toReturn.Beatmaps.Add(new BeatmapInfo + { + OnlineBeatmapID = b * 10, + Path = $"extra{b}.osu", + Version = $"Extra {b}", + StarDifficulty = 2, + BaseDifficulty = new BeatmapDifficulty + { + OverallDifficulty = 3.5f, + } + }); + } + return toReturn; + } + private class TestBeatmapCarousel : BeatmapCarousel { public new List Items => base.Items; diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapDetailArea.cs b/osu.Game.Tests/Visual/TestCaseBeatmapDetailArea.cs index a3c1ad307f..3e94de0f3e 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapDetailArea.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using NUnit.Framework; diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapDetails.cs b/osu.Game.Tests/Visual/TestCaseBeatmapDetails.cs index 62aced7423..e5924fccf8 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapDetails.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs index 3a50e43239..bde071c4a3 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapOptionsOverlay.cs b/osu.Game.Tests/Visual/TestCaseBeatmapOptionsOverlay.cs index 12f1cf29ee..cfeed4b1f0 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapOptionsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapOptionsOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs index ad15833569..5ce5eb222e 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapScoresContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs index 6a2161809f..ad85b3ed52 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapSetOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs b/osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs index 7760bffdaf..34abef7d76 100644 --- a/osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs +++ b/osu.Game.Tests/Visual/TestCaseBreadcrumbs.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/TestCaseBreakOverlay.cs b/osu.Game.Tests/Visual/TestCaseBreakOverlay.cs index 328bbaedba..f9ed606080 100644 --- a/osu.Game.Tests/Visual/TestCaseBreakOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseBreakOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Timing; diff --git a/osu.Game.Tests/Visual/TestCaseButtonSystem.cs b/osu.Game.Tests/Visual/TestCaseButtonSystem.cs index 9d796617de..61da76970e 100644 --- a/osu.Game.Tests/Visual/TestCaseButtonSystem.cs +++ b/osu.Game.Tests/Visual/TestCaseButtonSystem.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/TestCaseChatDisplay.cs b/osu.Game.Tests/Visual/TestCaseChatDisplay.cs index 5bfa6c1de4..048106da26 100644 --- a/osu.Game.Tests/Visual/TestCaseChatDisplay.cs +++ b/osu.Game.Tests/Visual/TestCaseChatDisplay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game.Tests/Visual/TestCaseChatLink.cs b/osu.Game.Tests/Visual/TestCaseChatLink.cs new file mode 100644 index 0000000000..3a7be686e1 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseChatLink.cs @@ -0,0 +1,217 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Online.Chat; +using osu.Game.Overlays.Chat; +using osu.Game.Users; +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseChatLink : OsuTestCase + { + private readonly TestChatLineContainer textContainer; + private Color4 linkColour; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ChatLine), + typeof(Message), + typeof(LinkFlowContainer), + typeof(DummyEchoMessage), + typeof(LocalEchoMessage), + typeof(MessageFormatter) + }; + + private DependencyContainer dependencies; + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(parent); + + public TestCaseChatLink() + { + Add(textContainer = new TestChatLineContainer + { + Padding = new MarginPadding { Left = 20, Right = 20 }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + linkColour = colours.Blue; + dependencies.Cache(new ChatOverlay + { + AvailableChannels = + { + new Channel { Name = "#english" }, + new Channel { Name = "#japanese" } + } + }); + + testLinksGeneral(); + testEcho(); + } + + private void clear() => AddStep("clear messages", textContainer.Clear); + + private void addMessageWithChecks(string text, int linkAmount = 0, bool isAction = false, bool isImportant = false, params LinkAction[] expectedActions) + { + int index = textContainer.Count + 1; + var newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index)); + textContainer.Add(newLine); + + AddAssert($"msg #{index} has {linkAmount} link(s)", () => newLine.Message.Links.Count == linkAmount); + AddAssert($"msg #{index} has the right action", hasExpectedActions); + AddAssert($"msg #{index} is " + (isAction ? "italic" : "not italic"), () => newLine.ContentFlow.Any() && isAction == isItalic()); + AddAssert($"msg #{index} shows {linkAmount} link(s)", isShowingLinks); + + bool hasExpectedActions() + { + var expectedActionsList = expectedActions.ToList(); + + if (expectedActionsList.Count != newLine.Message.Links.Count) + return false; + + for (int i = 0; i < newLine.Message.Links.Count; i++) + { + var action = newLine.Message.Links[i].Action; + if (action != expectedActions[i]) return false; + } + + return true; + } + + bool isItalic() => newLine.ContentFlow.Where(d => d is OsuSpriteText).Cast().All(sprite => sprite.Font == "Exo2.0-MediumItalic"); + + bool isShowingLinks() + { + bool hasBackground = !string.IsNullOrEmpty(newLine.Message.Sender.Colour); + + Color4 textColour = isAction && hasBackground ? OsuColour.FromHex(newLine.Message.Sender.Colour) : Color4.White; + + var linkCompilers = newLine.ContentFlow.Where(d => d is DrawableLinkCompiler).ToList(); + var linkSprites = linkCompilers.SelectMany(comp => ((DrawableLinkCompiler)comp).Parts); + + return linkSprites.All(d => d.Colour == linkColour) + && newLine.ContentFlow.Except(linkSprites.Concat(linkCompilers)).All(d => d.Colour == textColour); + } + } + + private void testLinksGeneral() + { + addMessageWithChecks("test!"); + addMessageWithChecks("osu.ppy.sh!"); + addMessageWithChecks("https://osu.ppy.sh!", 1, expectedActions: LinkAction.External); + addMessageWithChecks("00:12:345 (1,2) - Test?", 1, expectedActions: LinkAction.OpenEditorTimestamp); + addMessageWithChecks("Wiki link for tasty [[Performance Points]]", 1, expectedActions: LinkAction.External); + addMessageWithChecks("(osu forums)[https://osu.ppy.sh/forum] (old link format)", 1, expectedActions: LinkAction.External); + addMessageWithChecks("[https://osu.ppy.sh/home New site] (new link format)", 1, expectedActions: LinkAction.External); + addMessageWithChecks("[osu forums](https://osu.ppy.sh/forum) (new link format 2)", 1, expectedActions: LinkAction.External); + addMessageWithChecks("[https://osu.ppy.sh/home This is only a link to the new osu webpage but this is supposed to test word wrap.]", 1, expectedActions: LinkAction.External); + addMessageWithChecks("is now listening to [https://osu.ppy.sh/s/93523 IMAGE -MATERIAL- ]", 1, true, expectedActions: LinkAction.OpenBeatmapSet); + addMessageWithChecks("is now playing [https://osu.ppy.sh/b/252238 IMAGE -MATERIAL- ]", 1, true, expectedActions: LinkAction.OpenBeatmap); + addMessageWithChecks("Let's (try)[https://osu.ppy.sh/home] [https://osu.ppy.sh/b/252238 multiple links] https://osu.ppy.sh/home", 3, + expectedActions: new[] { LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External }); + // note that there's 0 links here (they get removed if a channel is not found) + addMessageWithChecks("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present)."); + addMessageWithChecks("I am important!", 0, false, true); + addMessageWithChecks("feels important", 0, true, true); + addMessageWithChecks("likes to post this [https://osu.ppy.sh/home link].", 1, true, true, expectedActions: LinkAction.External); + addMessageWithChecks("Join my multiplayer game osump://12346.", 1, expectedActions: LinkAction.JoinMultiplayerMatch); + addMessageWithChecks("Join my [multiplayer game](osump://12346).", 1, expectedActions: LinkAction.JoinMultiplayerMatch); + addMessageWithChecks("Join my [#english](osu://chan/#english).", 1, expectedActions: LinkAction.OpenChannel); + addMessageWithChecks("Join my osu://chan/#english.", 1, expectedActions: LinkAction.OpenChannel); + addMessageWithChecks("Join my #english or #japanese channels.", 2, expectedActions: new[] { LinkAction.OpenChannel, LinkAction.OpenChannel }); + addMessageWithChecks("Join my #english or #nonexistent #hashtag channels.", 1, expectedActions: LinkAction.OpenChannel); + } + + private void testEcho() + { + int echoCounter = 0; + + addEchoWithWait("sent!", "received!"); + addEchoWithWait("https://osu.ppy.sh/home", null, 500); + addEchoWithWait("[https://osu.ppy.sh/forum let's try multiple words too!]"); + addEchoWithWait("(long loading times! clickable while loading?)[https://osu.ppy.sh/home]", null, 5000); + + void addEchoWithWait(string text, string completeText = null, double delay = 250) + { + var newLine = new ChatLine(new DummyEchoMessage(text)); + + AddStep($"send msg #{++echoCounter} after {delay}ms", () => + { + textContainer.Add(newLine); + Scheduler.AddDelayed(() => newLine.Message = new DummyMessage(completeText ?? text), delay); + }); + + AddUntilStep(() => textContainer.All(line => line.Message is DummyMessage), $"wait for msg #{echoCounter}"); + } + } + + private class DummyEchoMessage : LocalEchoMessage + { + public DummyEchoMessage(string text) + { + Content = text; + Timestamp = DateTimeOffset.Now; + Sender = DummyMessage.TEST_SENDER; + } + } + + private class DummyMessage : Message + { + private static long messageCounter; + + internal static readonly User TEST_SENDER_BACKGROUND = new User + { + Username = @"i-am-important", + Id = 42, + Colour = "#250cc9", + }; + + internal static readonly User TEST_SENDER = new User + { + Username = @"Somebody", + Id = 1, + }; + + public new DateTimeOffset Timestamp = DateTimeOffset.Now; + + public DummyMessage(string text, bool isAction = false, bool isImportant = false, int number = 0) + : base(messageCounter++) + { + Content = text; + IsAction = isAction; + Sender = new User + { + Username = $"User {number}", + Id = number, + Colour = isImportant ? "#250cc9" : null, + }; + } + } + + private class TestChatLineContainer : FillFlowContainer + { + protected override int Compare(Drawable x, Drawable y) + { + var xC = (ChatLine)x; + var yC = (ChatLine)y; + + return xC.Message.CompareTo(yC.Message); + } + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseContextMenu.cs b/osu.Game.Tests/Visual/TestCaseContextMenu.cs index 45e6464149..6098187dd6 100644 --- a/osu.Game.Tests/Visual/TestCaseContextMenu.cs +++ b/osu.Game.Tests/Visual/TestCaseContextMenu.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/TestCaseCursors.cs b/osu.Game.Tests/Visual/TestCaseCursors.cs new file mode 100644 index 0000000000..363f6b53f0 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseCursors.cs @@ -0,0 +1,274 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Framework.MathUtils; +using osu.Framework.Testing.Input; +using osu.Game.Graphics.Cursor; +using osu.Game.Graphics.Sprites; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseCursors : OsuTestCase + { + private readonly ManualInputManager inputManager; + private readonly CursorOverrideContainer cursorOverrideContainer; + private readonly CustomCursorBox[] cursorBoxes = new CustomCursorBox[6]; + + public TestCaseCursors() + { + Child = inputManager = new ManualInputManager + { + Child = cursorOverrideContainer = new CursorOverrideContainer + { + RelativeSizeAxes = Axes.Both, + Children = new[] + { + // Middle user + cursorBoxes[0] = new CustomCursorBox(Color4.Green) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f), + }, + // Top-left user + cursorBoxes[1] = new CustomCursorBox(Color4.Blue) + { + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.4f) + }, + // Bottom-right user + cursorBoxes[2] = new CustomCursorBox(Color4.Red) + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.4f) + }, + // Bottom-left local + cursorBoxes[3] = new CustomCursorBox(Color4.Magenta, false) + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.4f) + }, + // Top-right local + cursorBoxes[4] = new CustomCursorBox(Color4.Cyan, false) + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.4f) + }, + // Left-local + cursorBoxes[5] = new CustomCursorBox(Color4.Yellow, false) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.2f, 1), + }, + } + } + }; + + returnUserInput(); + + AddToggleStep("Smooth transitions", b => cursorBoxes.ForEach(box => box.SmoothTransition = b)); + + testUserCursor(); + testLocalCursor(); + testUserCursorOverride(); + testMultipleLocalCursors(); + returnUserInput(); + } + + /// + /// Returns input back to the user. + /// + private void returnUserInput() + { + AddStep("Return user input", () => inputManager.UseParentState = true); + } + + /// + /// -- Green Box -- + /// Tests whether hovering in and out of a drawable that provides the user cursor (green) + /// results in the correct visibility state for that cursor. + /// + private void testUserCursor() + { + AddStep("Move to green area", () => inputManager.MoveMouseTo(cursorBoxes[0])); + AddAssert("Check green cursor visible", () => checkVisible(cursorBoxes[0].Cursor)); + AddAssert("Check green cursor at mouse", () => checkAtMouse(cursorBoxes[0].Cursor)); + AddStep("Move out", moveOut); + AddAssert("Check green cursor invisible", () => !checkVisible(cursorBoxes[0].Cursor)); + AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor)); + } + + /// + /// -- Purple Box -- + /// Tests whether hovering in and out of a drawable that provides a local cursor (purple) + /// results in the correct visibility and state for that cursor. + /// + private void testLocalCursor() + { + AddStep("Move to purple area", () => inputManager.MoveMouseTo(cursorBoxes[3])); + AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor)); + AddAssert("Check purple cursor at mouse", () => checkAtMouse(cursorBoxes[3].Cursor)); + AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor)); + AddAssert("Check global cursor at mouse", () => checkAtMouse(cursorOverrideContainer.Cursor)); + AddStep("Move out", moveOut); + AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor)); + AddAssert("Check global cursor visible", () => checkVisible(cursorOverrideContainer.Cursor)); + } + + /// + /// -- Blue-Green Box Boundary -- + /// Tests whether overriding a user cursor (green) with another user cursor (blue) + /// results in the correct visibility and states for the cursors. + /// + private void testUserCursorOverride() + { + AddStep("Move to blue-green boundary", () => inputManager.MoveMouseTo(cursorBoxes[1].ScreenSpaceDrawQuad.BottomRight - new Vector2(10))); + AddAssert("Check blue cursor visible", () => checkVisible(cursorBoxes[1].Cursor)); + AddAssert("Check green cursor invisible", () => !checkVisible(cursorBoxes[0].Cursor)); + AddAssert("Check blue cursor at mouse", () => checkAtMouse(cursorBoxes[1].Cursor)); + AddStep("Move out", moveOut); + AddAssert("Check blue cursor not visible", () => !checkVisible(cursorBoxes[1].Cursor)); + AddAssert("Check green cursor not visible", () => !checkVisible(cursorBoxes[0].Cursor)); + } + + /// + /// -- Yellow-Purple Box Boundary -- + /// Tests whether multiple local cursors (purple + yellow) may be visible and at the mouse position at the same time. + /// + private void testMultipleLocalCursors() + { + AddStep("Move to yellow-purple boundary", () => inputManager.MoveMouseTo(cursorBoxes[5].ScreenSpaceDrawQuad.BottomRight - new Vector2(10))); + AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor)); + AddAssert("Check purple cursor at mouse", () => checkAtMouse(cursorBoxes[3].Cursor)); + AddAssert("Check yellow cursor visible", () => checkVisible(cursorBoxes[5].Cursor)); + AddAssert("Check yellow cursor at mouse", () => checkAtMouse(cursorBoxes[5].Cursor)); + AddStep("Move out", moveOut); + AddAssert("Check purple cursor visible", () => checkVisible(cursorBoxes[3].Cursor)); + AddAssert("Check yellow cursor visible", () => checkVisible(cursorBoxes[5].Cursor)); + } + + /// + /// -- Yellow-Blue Box Boundary -- + /// Tests whether a local cursor (yellow) may be displayed along with a user cursor override (blue). + /// + private void testUserOverrideWithLocal() + { + AddStep("Move to yellow-blue boundary", () => inputManager.MoveMouseTo(cursorBoxes[5].ScreenSpaceDrawQuad.TopRight - new Vector2(10))); + AddAssert("Check blue cursor visible", () => checkVisible(cursorBoxes[1].Cursor)); + AddAssert("Check blue cursor at mouse", () => checkAtMouse(cursorBoxes[1].Cursor)); + AddAssert("Check yellow cursor visible", () => checkVisible(cursorBoxes[5].Cursor)); + AddAssert("Check yellow cursor at mouse", () => checkAtMouse(cursorBoxes[5].Cursor)); + AddStep("Move out", moveOut); + AddAssert("Check blue cursor invisible", () => !checkVisible(cursorBoxes[1].Cursor)); + AddAssert("Check yellow cursor visible", () => checkVisible(cursorBoxes[5].Cursor)); + } + + /// + /// Moves the cursor to a point not covered by any cursor containers. + /// + private void moveOut() + => inputManager.MoveMouseTo(new Vector2(inputManager.ScreenSpaceDrawQuad.Centre.X, inputManager.ScreenSpaceDrawQuad.TopLeft.Y)); + + /// + /// Checks if a cursor is visible. + /// + /// The cursor to check. + private bool checkVisible(CursorContainer cursorContainer) => cursorContainer.State == Visibility.Visible; + + /// + /// Checks if a cursor is at the current inputmanager screen position. + /// + /// The cursor to check. + private bool checkAtMouse(CursorContainer cursorContainer) + => Precision.AlmostEquals(inputManager.CurrentState.Mouse.NativeState.Position, cursorContainer.ToScreenSpace(cursorContainer.ActiveCursor.DrawPosition)); + + private class CustomCursorBox : Container, IProvideCursor + { + public bool SmoothTransition; + + public CursorContainer Cursor { get; } + public bool ProvidingUserCursor { get; } + + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => base.ReceiveMouseInputAt(screenSpacePos) || SmoothTransition && !ProvidingUserCursor; + + private readonly Box background; + + public CustomCursorBox(Color4 cursorColour, bool providesUserCursor = true) + { + ProvidingUserCursor = providesUserCursor; + + Colour = cursorColour; + Masking = true; + + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.1f + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = providesUserCursor ? "User cursor" : "Local cursor" + }, + Cursor = new TestCursorContainer + { + State = providesUserCursor ? Visibility.Hidden : Visibility.Visible, + } + }; + } + + protected override bool OnHover(InputState state) + { + background.FadeTo(0.4f, 250, Easing.OutQuint); + return false; + } + + protected override void OnHoverLost(InputState state) + { + background.FadeTo(0.1f, 250); + base.OnHoverLost(state); + } + } + + private class TestCursorContainer : CursorContainer + { + protected override Drawable CreateCursor() => new TestCursor(); + + private class TestCursor : CircularContainer + { + public TestCursor() + { + Origin = Anchor.Centre; + + Size = new Vector2(50); + Masking = true; + + Blending = BlendingMode.Additive; + Alpha = 0.5f; + + Child = new Box { RelativeSizeAxes = Axes.Both }; + } + } + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseDialogOverlay.cs b/osu.Game.Tests/Visual/TestCaseDialogOverlay.cs index 6dd84b204f..d7fbf64664 100644 --- a/osu.Game.Tests/Visual/TestCaseDialogOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseDialogOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; diff --git a/osu.Game.Tests/Visual/TestCaseDirect.cs b/osu.Game.Tests/Visual/TestCaseDirect.cs index ede17fa775..8fa576135e 100644 --- a/osu.Game.Tests/Visual/TestCaseDirect.cs +++ b/osu.Game.Tests/Visual/TestCaseDirect.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs index 3bbe6de921..ec70253118 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs +++ b/osu.Game.Tests/Visual/TestCaseDrawableRoom.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -63,8 +63,8 @@ namespace osu.Game.Tests.Visual { Value = new[] { - new User { GlobalRank = 1355 }, - new User { GlobalRank = 8756 }, + new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 1355 } } }, + new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 8756 } } }, }, }, }), @@ -99,10 +99,10 @@ namespace osu.Game.Tests.Visual }, Participants = { - Value = new[] + Value = new[] { - new User { GlobalRank = 578975 }, - new User { GlobalRank = 24554 }, + new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 578975 } } }, + new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 24554 } } }, }, }, }), @@ -116,8 +116,8 @@ namespace osu.Game.Tests.Visual AddStep(@"change beatmap", () => first.Room.Beatmap.Value = null); AddStep(@"change participants", () => first.Room.Participants.Value = new[] { - new User { GlobalRank = 1254 }, - new User { GlobalRank = 123189 }, + new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 1254 } } }, + new User { Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 123189 } } }, }); } diff --git a/osu.Game.Tests/Visual/TestCaseDrawings.cs b/osu.Game.Tests/Visual/TestCaseDrawings.cs index a6ef3b309a..204b4f133e 100644 --- a/osu.Game.Tests/Visual/TestCaseDrawings.cs +++ b/osu.Game.Tests/Visual/TestCaseDrawings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Tests/Visual/TestCaseEditor.cs b/osu.Game.Tests/Visual/TestCaseEditor.cs index 6da5e514b2..37da41c228 100644 --- a/osu.Game.Tests/Visual/TestCaseEditor.cs +++ b/osu.Game.Tests/Visual/TestCaseEditor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs index d52f27f4ab..76771ecf82 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorCompose.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorCompose.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs index f8669cde4b..8717f15311 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeRadioButtons.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs index 02c32dfa56..6a47933a3c 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorComposeTimeline.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs b/osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs index 0d0f2609ef..edfcde22b3 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorMenuBar.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs index 6b7dedf9cf..755800c4e1 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSelectionLayer.cs @@ -1,12 +1,15 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; +using osu.Framework.Allocation; using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Edit.Layers.Selection; using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Objects; @@ -18,26 +21,10 @@ namespace osu.Game.Tests.Visual { public override IReadOnlyList RequiredTypes => new[] { typeof(SelectionLayer) }; - public TestCaseEditorSelectionLayer() + [BackgroundDependencyLoader] + private void load() { - var playfield = new OsuEditPlayfield - { - new DrawableHitCircle(new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f }), - new DrawableHitCircle(new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f }), - new DrawableSlider(new Slider - { - ControlPoints = new List - { - new Vector2(128, 256), - new Vector2(344, 256), - }, - Distance = 400, - Position = new Vector2(128, 256), - Velocity = 1, - TickDistance = 100, - Scale = 0.5f - }) - }; + var playfield = new OsuEditPlayfield(); Children = new Drawable[] { @@ -49,6 +36,30 @@ namespace osu.Game.Tests.Visual }, new SelectionLayer(playfield) }; + + var hitCircle1 = new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f }; + var hitCircle2 = new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f }; + var slider = new Slider + { + ControlPoints = new List + { + new Vector2(128, 256), + new Vector2(344, 256), + }, + Distance = 400, + Position = new Vector2(128, 256), + Velocity = 1, + TickDistance = 100, + Scale = 0.5f, + }; + + hitCircle1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + hitCircle2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + slider.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + + playfield.Add(new DrawableHitCircle(hitCircle1)); + playfield.Add(new DrawableHitCircle(hitCircle2)); + playfield.Add(new DrawableSlider(slider)); } } } diff --git a/osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs b/osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs index ef7404ad49..8c8699fffa 100644 --- a/osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs +++ b/osu.Game.Tests/Visual/TestCaseEditorSummaryTimeline.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseGamefield.cs b/osu.Game.Tests/Visual/TestCaseGamefield.cs index 9dce0cfe01..44f46dea18 100644 --- a/osu.Game.Tests/Visual/TestCaseGamefield.cs +++ b/osu.Game.Tests/Visual/TestCaseGamefield.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps.ControlPoints; @@ -56,25 +56,25 @@ namespace osu.Game.Tests.Visual Clock = new FramedClock(), Children = new Drawable[] { - new OsuRulesetContainer(new OsuRuleset(new RulesetInfo()), beatmap, false) + new OsuRulesetContainer(new OsuRuleset(), beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.TopLeft, Origin = Anchor.TopLeft }, - new TaikoRulesetContainer(new TaikoRuleset(new RulesetInfo()),beatmap, false) + new TaikoRulesetContainer(new TaikoRuleset(),beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.TopRight, Origin = Anchor.TopRight }, - new CatchRulesetContainer(new CatchRuleset(new RulesetInfo()),beatmap, false) + new CatchRulesetContainer(new CatchRuleset(),beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft }, - new ManiaRulesetContainer(new ManiaRuleset(new RulesetInfo()),beatmap, false) + new ManiaRulesetContainer(new ManiaRuleset(),beatmap, false) { Scale = new Vector2(0.5f), Anchor = Anchor.BottomRight, diff --git a/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs b/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs index 87552c3f17..9aa5607f6d 100644 --- a/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseGameplayMenuOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseGraph.cs b/osu.Game.Tests/Visual/TestCaseGraph.cs index 4d3fd267db..99184d4689 100644 --- a/osu.Game.Tests/Visual/TestCaseGraph.cs +++ b/osu.Game.Tests/Visual/TestCaseGraph.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game.Tests/Visual/TestCaseHistoricalSection.cs b/osu.Game.Tests/Visual/TestCaseHistoricalSection.cs index c60b21fa20..a7fc58f2b5 100644 --- a/osu.Game.Tests/Visual/TestCaseHistoricalSection.cs +++ b/osu.Game.Tests/Visual/TestCaseHistoricalSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseIconButton.cs b/osu.Game.Tests/Visual/TestCaseIconButton.cs index 345316708e..525e867c56 100644 --- a/osu.Game.Tests/Visual/TestCaseIconButton.cs +++ b/osu.Game.Tests/Visual/TestCaseIconButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game.Tests/Visual/TestCaseIntroSequence.cs b/osu.Game.Tests/Visual/TestCaseIntroSequence.cs index ba5cf8ef46..97116e7746 100644 --- a/osu.Game.Tests/Visual/TestCaseIntroSequence.cs +++ b/osu.Game.Tests/Visual/TestCaseIntroSequence.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseKeyConfiguration.cs b/osu.Game.Tests/Visual/TestCaseKeyConfiguration.cs index d39ac12a60..57bb36d144 100644 --- a/osu.Game.Tests/Visual/TestCaseKeyConfiguration.cs +++ b/osu.Game.Tests/Visual/TestCaseKeyConfiguration.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Overlays; diff --git a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs index 7fddc92ee6..ff1b320b5a 100644 --- a/osu.Game.Tests/Visual/TestCaseKeyCounter.cs +++ b/osu.Game.Tests/Visual/TestCaseKeyCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs index a01dbb7a6b..7b00f4a1d5 100644 --- a/osu.Game.Tests/Visual/TestCaseLeaderboard.cs +++ b/osu.Game.Tests/Visual/TestCaseLeaderboard.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game.Tests/Visual/TestCaseMedalOverlay.cs b/osu.Game.Tests/Visual/TestCaseMedalOverlay.cs index bd69719f10..f11c37f5b2 100644 --- a/osu.Game.Tests/Visual/TestCaseMedalOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseMedalOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseMods.cs b/osu.Game.Tests/Visual/TestCaseMods.cs index c78d3b1f9f..039d8bfdb6 100644 --- a/osu.Game.Tests/Visual/TestCaseMods.cs +++ b/osu.Game.Tests/Visual/TestCaseMods.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game.Tests/Visual/TestCaseMusicController.cs b/osu.Game.Tests/Visual/TestCaseMusicController.cs index 16f2fab321..9424a3fee7 100644 --- a/osu.Game.Tests/Visual/TestCaseMusicController.cs +++ b/osu.Game.Tests/Visual/TestCaseMusicController.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs b/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs index 46deca073f..b2d3ac8c4d 100644 --- a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs b/osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs index 179f17ab50..9c6c50858f 100644 --- a/osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs +++ b/osu.Game.Tests/Visual/TestCaseOnScreenDisplay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/TestCaseOsuGame.cs b/osu.Game.Tests/Visual/TestCaseOsuGame.cs index 3f869e7378..9e6776800e 100644 --- a/osu.Game.Tests/Visual/TestCaseOsuGame.cs +++ b/osu.Game.Tests/Visual/TestCaseOsuGame.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs index 3be4a18ec5..809de2b8db 100644 --- a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual // this is by no means clean. should be replacing inside of OsuGameBase somehow. var context = new OsuDbContext(); - Func contextFactory = () => context; + OsuDbContext contextFactory() => context; dependencies.Cache(rulesets = new RulesetStore(contextFactory)); dependencies.Cache(manager = new BeatmapManager(storage, contextFactory, rulesets, null) diff --git a/osu.Game.Tests/Visual/TestCasePlaybackControl.cs b/osu.Game.Tests/Visual/TestCasePlaybackControl.cs index ff59bb7bfd..82c0b8f4fd 100644 --- a/osu.Game.Tests/Visual/TestCasePlaybackControl.cs +++ b/osu.Game.Tests/Visual/TestCasePlaybackControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/TestCasePopupDialog.cs b/osu.Game.Tests/Visual/TestCasePopupDialog.cs index ed9c47a253..e3bae3955a 100644 --- a/osu.Game.Tests/Visual/TestCasePopupDialog.cs +++ b/osu.Game.Tests/Visual/TestCasePopupDialog.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/TestCaseRankGraph.cs b/osu.Game.Tests/Visual/TestCaseRankGraph.cs index 489fba6501..88631aa982 100644 --- a/osu.Game.Tests/Visual/TestCaseRankGraph.cs +++ b/osu.Game.Tests/Visual/TestCaseRankGraph.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Overlays.Profile; @@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual { Statistics = new UserStatistics { - Rank = 123456, + Ranks = new UserStatistics.UserRanks { Global = 123456 }, PP = 12345, } }; @@ -77,7 +77,7 @@ namespace osu.Game.Tests.Visual { Statistics = new UserStatistics { - Rank = 89000, + Ranks = new UserStatistics.UserRanks { Global = 89000 }, PP = 12345, }, RankHistory = new User.RankHistoryData @@ -93,7 +93,7 @@ namespace osu.Game.Tests.Visual { Statistics = new UserStatistics { - Rank = 89000, + Ranks = new UserStatistics.UserRanks { Global = 89000 }, PP = 12345, }, RankHistory = new User.RankHistoryData @@ -109,7 +109,7 @@ namespace osu.Game.Tests.Visual { Statistics = new UserStatistics { - Rank = 12000, + Ranks = new UserStatistics.UserRanks { Global = 12000 }, PP = 12345, }, RankHistory = new User.RankHistoryData diff --git a/osu.Game.Tests/Visual/TestCaseReplay.cs b/osu.Game.Tests/Visual/TestCaseReplay.cs index 8e92696e8d..237687458d 100644 --- a/osu.Game.Tests/Visual/TestCaseReplay.cs +++ b/osu.Game.Tests/Visual/TestCaseReplay.cs @@ -1,19 +1,35 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.ComponentModel; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual { + [Description("Player instantiated with a replay.")] public class TestCaseReplay : TestCasePlayer { protected override Player CreatePlayer(WorkingBeatmap beatmap, Ruleset ruleset) { + // We create a dummy RulesetContainer just to get the replay - we don't want to use mods here + // to simulate setting a replay rather than having the replay already set for us beatmap.Mods.Value = beatmap.Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }); - return base.CreatePlayer(beatmap, ruleset); + var dummyRulesetContainer = ruleset.CreateRulesetContainerWith(beatmap, false); + + // We have the replay + var replay = dummyRulesetContainer.Replay; + + // Reset the mods + beatmap.Mods.Value = beatmap.Mods.Value.Where(m => !(m is ModAutoplay)); + + return new ReplayPlayer(replay) + { + InitialBeatmap = beatmap + }; } } } diff --git a/osu.Game.Tests/Visual/TestCaseReplaySettingsOverlay.cs b/osu.Game.Tests/Visual/TestCaseReplaySettingsOverlay.cs index d795b51d34..595a93b194 100644 --- a/osu.Game.Tests/Visual/TestCaseReplaySettingsOverlay.cs +++ b/osu.Game.Tests/Visual/TestCaseReplaySettingsOverlay.cs @@ -1,10 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play.HUD; -using osu.Game.Screens.Play.ReplaySettings; +using osu.Game.Screens.Play.PlayerSettings; namespace osu.Game.Tests.Visual { @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual { ExampleContainer container; - Add(new ReplaySettingsOverlay + Add(new PlayerSettingsOverlay { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual Text = @"Button", })); - AddStep(@"Add checkbox", () => container.Add(new ReplayCheckbox + AddStep(@"Add checkbox", () => container.Add(new PlayerCheckbox { LabelText = "Checkbox", })); @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual })); } - private class ExampleContainer : ReplayGroup + private class ExampleContainer : PlayerSettingsGroup { protected override string Title => @"example"; } diff --git a/osu.Game.Tests/Visual/TestCaseResults.cs b/osu.Game.Tests/Visual/TestCaseResults.cs index 28ce9524e0..012d31e75a 100644 --- a/osu.Game.Tests/Visual/TestCaseResults.cs +++ b/osu.Game.Tests/Visual/TestCaseResults.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs index 4f167329a0..8c4aa02a68 100644 --- a/osu.Game.Tests/Visual/TestCaseRoomInspector.cs +++ b/osu.Game.Tests/Visual/TestCaseRoomInspector.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -54,12 +54,12 @@ namespace osu.Game.Tests.Visual { Value = new[] { - new User { Username = @"flyte", Id = 3103765, GlobalRank = 1425 }, - new User { Username = @"Cookiezi", Id = 124493, GlobalRank = 5466 }, - new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 2873 }, - new User { Username = @"Rafis", Id = 2558286, GlobalRank = 4687 }, - new User { Username = @"hvick225", Id = 50265, GlobalRank = 3258 }, - new User { Username = @"peppy", Id = 2, GlobalRank = 6251 } + new User { Username = @"flyte", Id = 3103765, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 142 } } }, + new User { Username = @"Cookiezi", Id = 124493, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 546 } } }, + new User { Username = @"Angelsim", Id = 1777162, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 287 } } }, + new User { Username = @"Rafis", Id = 2558286, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 468 } } }, + new User { Username = @"hvick225", Id = 50265, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 325 } } }, + new User { Username = @"peppy", Id = 2, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 625 } } }, } } }; @@ -80,8 +80,8 @@ namespace osu.Game.Tests.Visual AddStep(@"change max participants", () => room.MaxParticipants.Value = null); AddStep(@"change participants", () => room.Participants.Value = new[] { - new User { Username = @"filsdelama", Id = 2831793, GlobalRank = 8542 }, - new User { Username = @"_index", Id = 652457, GlobalRank = 15024 } + new User { Username = @"filsdelama", Id = 2831793, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 854 } } }, + new User { Username = @"_index", Id = 652457, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 150 } } } }); AddStep(@"change room", () => @@ -121,9 +121,9 @@ namespace osu.Game.Tests.Visual { Value = new[] { - new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 4 }, - new User { Username = @"HappyStick", Id = 256802, GlobalRank = 752 }, - new User { Username = @"-Konpaku-", Id = 2258797, GlobalRank = 571 } + new User { Username = @"Angelsim", Id = 1777162, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 4 } } }, + new User { Username = @"HappyStick", Id = 256802, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 752 } } }, + new User { Username = @"-Konpaku-", Id = 2258797, Statistics = new UserStatistics { Ranks = new UserStatistics.UserRanks { Global = 571 } } } } } }; diff --git a/osu.Game.Tests/Visual/TestCaseScoreCounter.cs b/osu.Game.Tests/Visual/TestCaseScoreCounter.cs index 8f82c5e7a9..a8dc96ad72 100644 --- a/osu.Game.Tests/Visual/TestCaseScoreCounter.cs +++ b/osu.Game.Tests/Visual/TestCaseScoreCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs new file mode 100644 index 0000000000..21d967c3e3 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseScrollingHitObjects.cs @@ -0,0 +1,184 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Framework.Extensions.IEnumerableExtensions; +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Timing; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.UI.Scrolling; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseScrollingHitObjects : OsuTestCase + { + public override IReadOnlyList RequiredTypes => new[] { typeof(Playfield) }; + + private readonly TestPlayfield[] playfields = new TestPlayfield[4]; + + public TestCaseScrollingHitObjects() + { + Add(new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + playfields[0] = new TestPlayfield(ScrollingDirection.Up), + playfields[1] = new TestPlayfield(ScrollingDirection.Down) + }, + new Drawable[] + { + playfields[2] = new TestPlayfield(ScrollingDirection.Left), + playfields[3] = new TestPlayfield(ScrollingDirection.Right) + } + } + }); + + AddSliderStep("Time range", 100, 10000, 5000, v => playfields.ForEach(p => p.VisibleTimeRange.Value = v)); + AddStep("Add control point", () => addControlPoint(Time.Current + 5000)); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + playfields.ForEach(p => p.HitObjects.AddControlPoint(new MultiplierControlPoint(0))); + + for (int i = 0; i <= 5000; i += 1000) + addHitObject(Time.Current + i); + + Scheduler.AddDelayed(() => addHitObject(Time.Current + 5000), 1000, true); + } + + private void addHitObject(double time) + { + playfields.ForEach(p => + { + var hitObject = new TestDrawableHitObject(time); + setAnchor(hitObject, p); + + p.Add(hitObject); + }); + } + + private void addControlPoint(double time) + { + playfields.ForEach(p => + { + p.HitObjects.AddControlPoint(new MultiplierControlPoint(time) { DifficultyPoint = { SpeedMultiplier = 3 } }); + p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 2000) { DifficultyPoint = { SpeedMultiplier = 2 } }); + p.HitObjects.AddControlPoint(new MultiplierControlPoint(time + 3000) { DifficultyPoint = { SpeedMultiplier = 1 } }); + + TestDrawableControlPoint createDrawablePoint(double t) + { + var obj = new TestDrawableControlPoint(p.Direction, t); + setAnchor(obj, p); + return obj; + } + + p.Add(createDrawablePoint(time)); + p.Add(createDrawablePoint(time + 2000)); + p.Add(createDrawablePoint(time + 3000)); + }); + } + + private void setAnchor(DrawableHitObject obj, TestPlayfield playfield) + { + switch (playfield.Direction) + { + case ScrollingDirection.Up: + obj.Anchor = Anchor.TopCentre; + break; + case ScrollingDirection.Down: + obj.Anchor = Anchor.BottomCentre; + break; + case ScrollingDirection.Left: + obj.Anchor = Anchor.CentreLeft; + break; + case ScrollingDirection.Right: + obj.Anchor = Anchor.CentreRight; + break; + } + } + + + private class TestPlayfield : ScrollingPlayfield + { + public readonly ScrollingDirection Direction; + + public TestPlayfield(ScrollingDirection direction) + : base(direction) + { + Direction = direction; + + Padding = new MarginPadding(2); + ScaledContent.Masking = true; + + AddInternal(new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.5f, + Depth = float.MaxValue + }); + } + } + + private class TestDrawableControlPoint : DrawableHitObject + { + public TestDrawableControlPoint(ScrollingDirection direction, double time) + : base(new HitObject { StartTime = time }) + { + Origin = Anchor.Centre; + + Add(new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both + }); + + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + RelativeSizeAxes = Axes.X; + Height = 2; + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + RelativeSizeAxes = Axes.Y; + Width = 2; + break; + } + } + + protected override void UpdateState(ArmedState state) + { + } + } + + private class TestDrawableHitObject : DrawableHitObject + { + public TestDrawableHitObject(double time) + : base(new HitObject { StartTime = time }) + { + Origin = Anchor.Centre; + AutoSizeAxes = Axes.Both; + + Add(new Box { Size = new Vector2(75) }); + } + + protected override void UpdateState(ArmedState state) + { + } + } + } +} diff --git a/osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs b/osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs deleted file mode 100644 index 40fb22af1e..0000000000 --- a/osu.Game.Tests/Visual/TestCaseScrollingPlayfield.cs +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using NUnit.Framework; -using osu.Framework.Extensions.IEnumerableExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Framework.Input; -using osu.Framework.Timing; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Timing; -using osu.Game.Rulesets.UI; -using osu.Game.Tests.Beatmaps; -using OpenTK; - -namespace osu.Game.Tests.Visual -{ - /// - /// The most minimal implementation of a playfield with scrolling hit objects. - /// - [TestFixture] - public class TestCaseScrollingPlayfield : OsuTestCase - { - public TestCaseScrollingPlayfield() - { - Clock = new FramedClock(); - - var objects = new List(); - - int time = 1500; - for (int i = 0; i < 50; i++) - { - objects.Add(new TestHitObject { StartTime = time }); - - time += 500; - } - - Beatmap b = new Beatmap - { - HitObjects = objects, - BeatmapInfo = new BeatmapInfo - { - BaseDifficulty = new BeatmapDifficulty(), - Metadata = new BeatmapMetadata() - } - }; - - WorkingBeatmap beatmap = new TestWorkingBeatmap(b); - - TestRulesetContainer horizontalRulesetContainer; - Add(horizontalRulesetContainer = new TestRulesetContainer(Axes.X, beatmap, true)); - - TestRulesetContainer verticalRulesetContainer; - Add(verticalRulesetContainer = new TestRulesetContainer(Axes.Y, beatmap, true)); - - AddStep("Reverse direction", () => - { - horizontalRulesetContainer.Playfield.Reverse(); - verticalRulesetContainer.Playfield.Reverse(); - }); - } - - [Test] - public void TestSpeedAdjustmentOrdering() - { - var hitObjectContainer = new ScrollingPlayfield.ScrollingHitObjectContainer(Axes.X); - - var speedAdjustments = new[] - { - new SpeedAdjustmentContainer(new MultiplierControlPoint()), - new SpeedAdjustmentContainer(new MultiplierControlPoint(1000) - { - TimingPoint = new TimingControlPoint { BeatLength = 500 } - }), - new SpeedAdjustmentContainer(new MultiplierControlPoint(2000) - { - TimingPoint = new TimingControlPoint { BeatLength = 1000 }, - DifficultyPoint = new DifficultyControlPoint { SpeedMultiplier = 2} - }), - new SpeedAdjustmentContainer(new MultiplierControlPoint(3000) - { - TimingPoint = new TimingControlPoint { BeatLength = 1000 }, - DifficultyPoint = new DifficultyControlPoint { SpeedMultiplier = 1} - }), - }; - - var hitObjects = new[] - { - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = -1000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject()), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 1000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 2000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 3000 }), - new DrawableTestHitObject(Axes.X, new TestHitObject { StartTime = 4000 }), - }; - - hitObjects.ForEach(h => hitObjectContainer.Add(h)); - speedAdjustments.ForEach(hitObjectContainer.AddSpeedAdjustment); - - // The 0th index in hitObjectContainer.SpeedAdjustments is the "default" control point - // Check multiplier of the default speed adjustment - Assert.AreEqual(1, hitObjectContainer.SpeedAdjustments[0].ControlPoint.Multiplier); - Assert.AreEqual(1, speedAdjustments[0].ControlPoint.Multiplier); - Assert.AreEqual(2, speedAdjustments[1].ControlPoint.Multiplier); - Assert.AreEqual(2, speedAdjustments[2].ControlPoint.Multiplier); - Assert.AreEqual(1, speedAdjustments[3].ControlPoint.Multiplier); - - // Check insertion of hit objects - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[4].Contains(hitObjects[0])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[3].Contains(hitObjects[1])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[2].Contains(hitObjects[2])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[1].Contains(hitObjects[3])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[4])); - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[0].Contains(hitObjects[5])); - - hitObjectContainer.RemoveSpeedAdjustment(hitObjectContainer.SpeedAdjustments[3]); - - // The hit object contained in this speed adjustment should be resorted into the one occuring before it - - Assert.IsTrue(hitObjectContainer.SpeedAdjustments[3].Contains(hitObjects[1])); - } - - private class TestRulesetContainer : ScrollingRulesetContainer - { - private readonly Axes scrollingAxes; - - public TestRulesetContainer(Axes scrollingAxes, WorkingBeatmap beatmap, bool isForCurrentRuleset) - : base(null, beatmap, isForCurrentRuleset) - { - this.scrollingAxes = scrollingAxes; - } - - public new TestPlayfield Playfield => base.Playfield; - - public override ScoreProcessor CreateScoreProcessor() => new TestScoreProcessor(); - - public override PassThroughInputManager CreateInputManager() => new PassThroughInputManager(); - - protected override BeatmapConverter CreateBeatmapConverter() => new TestBeatmapConverter(); - - protected override Playfield CreatePlayfield() => new TestPlayfield(scrollingAxes); - - protected override DrawableHitObject GetVisualRepresentation(TestHitObject h) => new DrawableTestHitObject(scrollingAxes, h); - } - - private class TestScoreProcessor : ScoreProcessor - { - protected override void OnNewJudgement(Judgement judgement) - { - } - } - - private class TestBeatmapConverter : BeatmapConverter - { - protected override IEnumerable ValidConversionTypes => new[] { typeof(HitObject) }; - - protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) - { - yield return original as TestHitObject; - } - } - - private class DrawableTestHitObject : DrawableScrollingHitObject - { - public DrawableTestHitObject(Axes scrollingAxes, TestHitObject hitObject) - : base(hitObject) - { - Anchor = scrollingAxes == Axes.Y ? Anchor.TopCentre : Anchor.CentreLeft; - Origin = Anchor.Centre; - - AutoSizeAxes = Axes.Both; - - Add(new Circle - { - Size = new Vector2(50) - }); - } - - protected override void UpdateState(ArmedState state) - { - } - } - - private class TestPlayfield : ScrollingPlayfield - { - protected override Container Content => content; - private readonly Container content; - - public TestPlayfield(Axes scrollingAxes) - : base(scrollingAxes) - { - InternalChildren = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.2f - }, - content = new Container { RelativeSizeAxes = Axes.Both } - }; - } - - public void Reverse() => Reversed.Toggle(); - } - - - private class TestHitObject : HitObject - { - } - } -} diff --git a/osu.Game.Tests/Visual/TestCaseSettings.cs b/osu.Game.Tests/Visual/TestCaseSettings.cs index 15a60386ef..923ae540db 100644 --- a/osu.Game.Tests/Visual/TestCaseSettings.cs +++ b/osu.Game.Tests/Visual/TestCaseSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/TestCaseSkipButton.cs b/osu.Game.Tests/Visual/TestCaseSkipButton.cs index 296c10a980..3fd66f8be3 100644 --- a/osu.Game.Tests/Visual/TestCaseSkipButton.cs +++ b/osu.Game.Tests/Visual/TestCaseSkipButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Screens.Play; diff --git a/osu.Game.Tests/Visual/TestCaseSocial.cs b/osu.Game.Tests/Visual/TestCaseSocial.cs index ff0707c8ab..d3ff18b37f 100644 --- a/osu.Game.Tests/Visual/TestCaseSocial.cs +++ b/osu.Game.Tests/Visual/TestCaseSocial.cs @@ -1,13 +1,26 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; +using System.Collections.Generic; using osu.Game.Overlays; +using osu.Game.Overlays.Social; using osu.Game.Users; namespace osu.Game.Tests.Visual { public class TestCaseSocial : OsuTestCase { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(UserPanel), + typeof(SocialPanel), + typeof(FilterControl), + typeof(SocialOverlay), + typeof(SocialGridPanel), + typeof(SocialListPanel) + }; + public TestCaseSocial() { SocialOverlay s = new SocialOverlay diff --git a/osu.Game.Tests/Visual/TestCaseSongProgress.cs b/osu.Game.Tests/Visual/TestCaseSongProgress.cs index fe534bc679..2320e8d8db 100644 --- a/osu.Game.Tests/Visual/TestCaseSongProgress.cs +++ b/osu.Game.Tests/Visual/TestCaseSongProgress.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game.Tests/Visual/TestCaseStoryboard.cs b/osu.Game.Tests/Visual/TestCaseStoryboard.cs index aa9618b208..089733c57e 100644 --- a/osu.Game.Tests/Visual/TestCaseStoryboard.cs +++ b/osu.Game.Tests/Visual/TestCaseStoryboard.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game.Tests/Visual/TestCaseTabControl.cs b/osu.Game.Tests/Visual/TestCaseTabControl.cs index 44a1732e16..5fc774ff42 100644 --- a/osu.Game.Tests/Visual/TestCaseTabControl.cs +++ b/osu.Game.Tests/Visual/TestCaseTabControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game.Tests/Visual/TestCaseTextAwesome.cs b/osu.Game.Tests/Visual/TestCaseTextAwesome.cs index e2b4914558..830dea406a 100644 --- a/osu.Game.Tests/Visual/TestCaseTextAwesome.cs +++ b/osu.Game.Tests/Visual/TestCaseTextAwesome.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseToolbar.cs b/osu.Game.Tests/Visual/TestCaseToolbar.cs index 9f538af09b..b596c4d5e0 100644 --- a/osu.Game.Tests/Visual/TestCaseToolbar.cs +++ b/osu.Game.Tests/Visual/TestCaseToolbar.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game.Tests/Visual/TestCaseTwoLayerButton.cs b/osu.Game.Tests/Visual/TestCaseTwoLayerButton.cs index 866d1f56ef..cbf3dd150a 100644 --- a/osu.Game.Tests/Visual/TestCaseTwoLayerButton.cs +++ b/osu.Game.Tests/Visual/TestCaseTwoLayerButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game.Tests/Visual/TestCaseUserPanel.cs b/osu.Game.Tests/Visual/TestCaseUserPanel.cs index 31f9789093..b18edf0ccb 100644 --- a/osu.Game.Tests/Visual/TestCaseUserPanel.cs +++ b/osu.Game.Tests/Visual/TestCaseUserPanel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/TestCaseUserProfile.cs b/osu.Game.Tests/Visual/TestCaseUserProfile.cs index 13b6509740..8acc8d1b5b 100644 --- a/osu.Game.Tests/Visual/TestCaseUserProfile.cs +++ b/osu.Game.Tests/Visual/TestCaseUserProfile.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -42,11 +42,10 @@ namespace osu.Game.Tests.Visual LastVisit = DateTimeOffset.Now, Age = 1, ProfileOrder = new[] { "me" }, - CountryRank = 1, Statistics = new UserStatistics { - Rank = 2148, - PP = 4567.89m + Ranks = new UserStatistics.UserRanks { Global = 2148, Country = 1 }, + PP = 4567.89m, }, RankHistory = new User.RankHistoryData { diff --git a/osu.Game.Tests/Visual/TestCaseUserRanks.cs b/osu.Game.Tests/Visual/TestCaseUserRanks.cs index e7b8047882..1926585f07 100644 --- a/osu.Game.Tests/Visual/TestCaseUserRanks.cs +++ b/osu.Game.Tests/Visual/TestCaseUserRanks.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game.Tests/Visual/TestCaseWaveform.cs b/osu.Game.Tests/Visual/TestCaseWaveform.cs index 4c6efd439f..dd5420400f 100644 --- a/osu.Game.Tests/Visual/TestCaseWaveform.cs +++ b/osu.Game.Tests/Visual/TestCaseWaveform.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using NUnit.Framework; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -15,6 +16,7 @@ using osu.Game.Screens.Edit.Screens.Compose.Timeline; namespace osu.Game.Tests.Visual { + [Ignore("CI regularly hangs on this TestCase...")] public class TestCaseWaveform : OsuTestCase { private readonly Bindable beatmapBacking = new Bindable(); diff --git a/osu.Game/Audio/SampleInfo.cs b/osu.Game/Audio/SampleInfo.cs index 71975bf0fa..e6f4a0b8d1 100644 --- a/osu.Game/Audio/SampleInfo.cs +++ b/osu.Game/Audio/SampleInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index b639de640a..4fd54e4364 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Beatmaps/BeatmapConverter.cs b/osu.Game/Beatmaps/BeatmapConverter.cs index e087eebbfe..20de4e9680 100644 --- a/osu.Game/Beatmaps/BeatmapConverter.cs +++ b/osu.Game/Beatmaps/BeatmapConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -39,12 +39,12 @@ namespace osu.Game.Beatmaps /// The converted Beatmap. protected virtual Beatmap ConvertBeatmap(Beatmap original) { - return new Beatmap - { - BeatmapInfo = original.BeatmapInfo, - ControlPointInfo = original.ControlPointInfo, - HitObjects = original.HitObjects.SelectMany(h => convert(h, original)).ToList() - }; + var beatmap = CreateBeatmap(); + beatmap.BeatmapInfo = original.BeatmapInfo; + beatmap.ControlPointInfo = original.ControlPointInfo; + beatmap.HitObjects = original.HitObjects.SelectMany(h => convert(h, original)).ToList(); + + return beatmap; } /// @@ -78,6 +78,11 @@ namespace osu.Game.Beatmaps /// protected abstract IEnumerable ValidConversionTypes { get; } + /// + /// Creates the that will be returned by this . + /// + protected virtual Beatmap CreateBeatmap() => new Beatmap(); + /// /// Performs the conversion of a hit object. /// This method is generally executed sequentially for all objects in a beatmap. diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index 03fbf9a0a7..3bfa70711b 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel.DataAnnotations.Schema; @@ -40,5 +40,17 @@ namespace osu.Game.Beatmaps return mid - (mid - min) * (5 - difficulty) / 5; return mid; } + + /// + /// Maps a difficulty value [0, 10] to a two-piece linear range of values. + /// + /// The difficulty value to be mapped. + /// The values that define the two linear ranges. + /// Minimum of the resulting range which will be achieved by a difficulty value of 0. + /// Midpoint of the resulting range which will be achieved by a difficulty value of 5. + /// Maximum of the resulting range which will be achieved by a difficulty value of 10. + /// Value to which the difficulty value maps in the specified range. + public static double DifficultyRange(double difficulty, (double od0, double od5, double od10) range) + => DifficultyRange(difficulty, range.od0, range.od5, range.od10); } } diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 1da3dc8a54..b151570806 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index ea7c4bd954..a27c3a2a88 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -287,15 +287,16 @@ namespace osu.Game.Beatmaps Import(archive); downloadNotification.State = ProgressNotificationState.Completed; + currentDownloads.Remove(request); }, TaskCreationOptions.LongRunning); - - currentDownloads.Remove(request); }; - request.Failure += data => + request.Failure += error => { + if (error is OperationCanceledException) return; + downloadNotification.State = ProgressNotificationState.Completed; - Logger.Error(data, "Failed to get beatmap download information"); + Logger.Error(error, "Beatmap download failed!"); currentDownloads.Remove(request); }; @@ -567,7 +568,6 @@ namespace osu.Game.Beatmaps using (var stream = new StreamReader(reader.GetStream(mapName))) metadata = Decoder.GetDecoder(stream).DecodeBeatmap(stream).Metadata; - // check if a set already exists with the same online id. if (metadata.OnlineBeatmapSetID != null) beatmapSet = beatmaps.BeatmapSets.FirstOrDefault(b => b.OnlineBeatmapSetID == metadata.OnlineBeatmapSetID); @@ -582,7 +582,6 @@ namespace osu.Game.Beatmaps Metadata = metadata }; - var mapNames = reader.Filenames.Where(f => f.EndsWith(".osu")); foreach (var name in mapNames) @@ -692,19 +691,18 @@ namespace osu.Game.Beatmaps protected override Storyboard GetStoryboard() { - if (BeatmapInfo?.Path == null && BeatmapSetInfo?.StoryboardFile == null) - return new Storyboard(); - try { - Decoder decoder; - using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo?.Path)))) - decoder = Decoder.GetDecoder(stream); + using (var beatmap = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) + { + Decoder decoder = Decoder.GetDecoder(beatmap); - // try for .osb first and fall back to .osu - string storyboardFile = BeatmapSetInfo.StoryboardFile ?? BeatmapInfo.Path; - using (var stream = new StreamReader(store.GetStream(getPathForFile(storyboardFile)))) - return decoder.GetStoryboardDecoder().DecodeStoryboard(stream); + if (BeatmapSetInfo?.StoryboardFile == null) + return decoder.GetStoryboardDecoder().DecodeStoryboard(beatmap); + + using (var storyboard = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile)))) + return decoder.GetStoryboardDecoder().DecodeStoryboard(beatmap, storyboard); + } } catch { diff --git a/osu.Game/Beatmaps/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs index 9010f922bb..a28266dc62 100644 --- a/osu.Game/Beatmaps/BeatmapMetadata.cs +++ b/osu.Game/Beatmaps/BeatmapMetadata.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Beatmaps/BeatmapMetrics.cs b/osu.Game/Beatmaps/BeatmapMetrics.cs index e0cd5f10e7..78527e7a02 100644 --- a/osu.Game/Beatmaps/BeatmapMetrics.cs +++ b/osu.Game/Beatmaps/BeatmapMetrics.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Beatmaps/BeatmapOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapOnlineInfo.cs index 6a988036c5..58e4b2b5aa 100644 --- a/osu.Game/Beatmaps/BeatmapOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapOnlineInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Beatmaps diff --git a/osu.Game/Beatmaps/BeatmapProcessor.cs b/osu.Game/Beatmaps/BeatmapProcessor.cs index 04680fe6fb..9b528699ef 100644 --- a/osu.Game/Beatmaps/BeatmapProcessor.cs +++ b/osu.Game/Beatmaps/BeatmapProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Beatmaps/BeatmapSetFileInfo.cs b/osu.Game/Beatmaps/BeatmapSetFileInfo.cs index 0e3aa61d9f..ae4a6772a2 100644 --- a/osu.Game/Beatmaps/BeatmapSetFileInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetFileInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel.DataAnnotations; diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index a41beaab81..982e41c92c 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index b38f74b3f7..be3107c7b9 100644 --- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Beatmaps/BeatmapStatistic.cs b/osu.Game/Beatmaps/BeatmapStatistic.cs index c1838d059b..d061651e71 100644 --- a/osu.Game/Beatmaps/BeatmapStatistic.cs +++ b/osu.Game/Beatmaps/BeatmapStatistic.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; @@ -11,4 +11,4 @@ namespace osu.Game.Beatmaps public string Content; public string Name; } -} \ No newline at end of file +} diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs index fb45c17454..df71c5c0d0 100644 --- a/osu.Game/Beatmaps/BeatmapStore.cs +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -156,6 +156,7 @@ namespace osu.Game.Beatmaps public IQueryable Beatmaps => GetContext().BeatmapInfo .Include(b => b.BeatmapSet).ThenInclude(s => s.Metadata) + .Include(b => b.BeatmapSet).ThenInclude(s => s.Files).ThenInclude(f => f.FileInfo) .Include(b => b.Metadata) .Include(b => b.Ruleset) .Include(b => b.BaseDifficulty); diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 115bba5d9d..2b49716853 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs index 59123380af..69988b2a29 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPointInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index c622d5310c..69027ffd73 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Beatmaps.ControlPoints diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 7671739cd9..566d14a0be 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Beatmaps.ControlPoints @@ -15,4 +15,4 @@ namespace osu.Game.Beatmaps.ControlPoints /// public bool OmitFirstBarLine; } -} \ No newline at end of file +} diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index c2c13e1909..ce06cc8a7b 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Audio; diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index c7bdbb5dd6..0592ef38c5 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps.Timing; @@ -17,4 +17,4 @@ namespace osu.Game.Beatmaps.ControlPoints /// public double BeatLength = 1000; } -} \ No newline at end of file +} diff --git a/osu.Game/Beatmaps/DifficultyCalculator.cs b/osu.Game/Beatmaps/DifficultyCalculator.cs index 687e1b2177..798268d05f 100644 --- a/osu.Game/Beatmaps/DifficultyCalculator.cs +++ b/osu.Game/Beatmaps/DifficultyCalculator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects; @@ -27,7 +27,6 @@ namespace osu.Game.Beatmaps Beatmap = CreateBeatmapConverter(beatmap).Convert(beatmap); Mods = mods ?? new Mod[0]; - ApplyMods(Mods); PreprocessHitObjects(); diff --git a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs index e4904786c7..37af06e9f5 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapBackgroundSprite.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs index ba79db3f48..90ccb27228 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs index 57a5abc4c7..2fc39c71e6 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 8259da9492..ace0541ea5 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 3ec83ed8d5..f4a3dacd53 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -64,7 +64,7 @@ namespace osu.Game.Beatmaps public override string ShortName => "dummy"; - public DummyRuleset(RulesetInfo rulesetInfo) + public DummyRuleset(RulesetInfo rulesetInfo = null) : base(rulesetInfo) { } diff --git a/osu.Game/Beatmaps/Formats/Decoder.cs b/osu.Game/Beatmaps/Formats/Decoder.cs index a6e2699262..1aae52208a 100644 --- a/osu.Game/Beatmaps/Formats/Decoder.cs +++ b/osu.Game/Beatmaps/Formats/Decoder.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -70,10 +70,11 @@ namespace osu.Game.Beatmaps.Formats protected abstract void ParseBeatmap(StreamReader stream, Beatmap beatmap); - public virtual Storyboard DecodeStoryboard(StreamReader stream) + public virtual Storyboard DecodeStoryboard(params StreamReader[] streams) { var storyboard = new Storyboard(); - ParseStoryboard(stream, storyboard); + foreach (StreamReader stream in streams) + ParseStoryboard(stream, storyboard); return storyboard; } diff --git a/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs index 29e7cee336..b0798e5a87 100644 --- a/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/JsonBeatmapDecoder.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.IO; diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index ea29e480ec..3847787a4c 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -8,7 +8,6 @@ using OpenTK.Graphics; using osu.Game.Beatmaps.Timing; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Beatmaps.ControlPoints; -using System.Collections.Generic; namespace osu.Game.Beatmaps.Formats { @@ -82,15 +81,12 @@ namespace osu.Game.Beatmaps.Formats case Section.HitObjects: handleHitObjects(line); break; - case Section.Variables: - handleVariables(line); - break; } } private void handleGeneral(string line) { - var pair = splitKeyVal(line, ':'); + var pair = SplitKeyVal(line, ':'); var metadata = beatmap.BeatmapInfo.Metadata; switch (pair.Key) @@ -149,7 +145,7 @@ namespace osu.Game.Beatmaps.Formats private void handleEditor(string line) { - var pair = splitKeyVal(line, ':'); + var pair = SplitKeyVal(line, ':'); switch (pair.Key) { @@ -173,7 +169,7 @@ namespace osu.Game.Beatmaps.Formats private void handleMetadata(string line) { - var pair = splitKeyVal(line, ':'); + var pair = SplitKeyVal(line, ':'); var metadata = beatmap.BeatmapInfo.Metadata; switch (pair.Key) @@ -214,7 +210,7 @@ namespace osu.Game.Beatmaps.Formats private void handleDifficulty(string line) { - var pair = splitKeyVal(line, ':'); + var pair = SplitKeyVal(line, ':'); var difficulty = beatmap.BeatmapInfo.BaseDifficulty; switch (pair.Key) @@ -242,8 +238,6 @@ namespace osu.Game.Beatmaps.Formats private void handleEvents(string line) { - DecodeVariables(ref line); - string[] split = line.Split(','); EventType type; @@ -359,7 +353,7 @@ namespace osu.Game.Beatmaps.Formats private void handleColours(string line) { - var pair = splitKeyVal(line, ':'); + var pair = SplitKeyVal(line, ':'); string[] split = pair.Value.Split(','); @@ -400,22 +394,5 @@ namespace osu.Game.Beatmaps.Formats if (obj != null) beatmap.HitObjects.Add(obj); } - - private void handleVariables(string line) - { - var pair = splitKeyVal(line, '='); - Variables[pair.Key] = pair.Value; - } - - private KeyValuePair splitKeyVal(string line, char separator) - { - var split = line.Trim().Split(new[] { separator }, 2); - - return new KeyValuePair - ( - split[0].Trim(), - split.Length > 1 ? split[1].Trim() : string.Empty - ); - } } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index e5ced5f772..e0fc439924 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -29,7 +29,6 @@ namespace osu.Game.Beatmaps.Formats } protected int BeatmapVersion; - protected readonly Dictionary Variables = new Dictionary(); public override Decoder GetStoryboardDecoder() => new LegacyStoryboardDecoder(BeatmapVersion); @@ -82,27 +81,15 @@ namespace osu.Game.Beatmaps.Formats protected abstract void ProcessSection(Section section, string line); - /// - /// Decodes any beatmap variables present in a line into their real values. - /// - /// The line which may contains variables. - protected void DecodeVariables(ref string line) + protected KeyValuePair SplitKeyVal(string line, char separator) { - while (line.IndexOf('$') >= 0) - { - string origLine = line; - string[] split = line.Split(','); - for (int i = 0; i < split.Length; i++) - { - var item = split[i]; - if (item.StartsWith("$") && Variables.ContainsKey(item)) - split[i] = Variables[item]; - } + var split = line.Trim().Split(new[] { separator }, 2); - line = string.Join(",", split); - if (line == origLine) - break; - } + return new KeyValuePair + ( + split[0].Trim(), + split.Length > 1 ? split[1].Trim() : string.Empty + ); } protected enum Section @@ -150,7 +137,7 @@ namespace osu.Game.Beatmaps.Formats CentreRight, BottomLeft, BottomRight - }; + } internal enum StoryLayer { diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 168f37e44e..a4ff060c83 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using OpenTK; @@ -19,6 +20,8 @@ namespace osu.Game.Beatmaps.Formats private StoryboardSprite storyboardSprite; private CommandTimelineGroup timelineGroup; + private readonly Dictionary variables = new Dictionary(); + public LegacyStoryboardDecoder() { } @@ -47,6 +50,9 @@ namespace osu.Game.Beatmaps.Formats case Section.Events: handleEvents(line); break; + case Section.Variables: + handleVariables(line); + break; } } @@ -59,7 +65,7 @@ namespace osu.Game.Beatmaps.Formats line = line.Substring(1); } - DecodeVariables(ref line); + decodeVariables(ref line); string[] split = line.Split(','); @@ -266,6 +272,35 @@ namespace osu.Game.Beatmaps.Formats throw new InvalidDataException($@"Unknown origin: {value}"); } - private string cleanFilename(string path) => FileSafety.PathSanitise(path.Trim('\"')); + private void handleVariables(string line) + { + var pair = SplitKeyVal(line, '='); + variables[pair.Key] = pair.Value; + } + + /// + /// Decodes any beatmap variables present in a line into their real values. + /// + /// The line which may contains variables. + private void decodeVariables(ref string line) + { + while (line.IndexOf('$') >= 0) + { + string origLine = line; + string[] split = line.Split(','); + for (int i = 0; i < split.Length; i++) + { + var item = split[i]; + if (item.StartsWith("$") && variables.ContainsKey(item)) + split[i] = variables[item]; + } + + line = string.Join(",", split); + if (line == origLine) + break; + } + } + + private string cleanFilename(string path) => FileSafety.PathStandardise(FileSafety.PathSanitise(path.Trim('\"'))); } } diff --git a/osu.Game/Beatmaps/IO/ArchiveReader.cs b/osu.Game/Beatmaps/IO/ArchiveReader.cs index 3af2a7ea2a..453a03b882 100644 --- a/osu.Game/Beatmaps/IO/ArchiveReader.cs +++ b/osu.Game/Beatmaps/IO/ArchiveReader.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -34,4 +34,4 @@ namespace osu.Game.Beatmaps.IO public abstract Stream GetUnderlyingStream(); } -} \ No newline at end of file +} diff --git a/osu.Game/Beatmaps/IO/LegacyFilesystemReader.cs b/osu.Game/Beatmaps/IO/LegacyFilesystemReader.cs index 79a47c8724..4a85f6f526 100644 --- a/osu.Game/Beatmaps/IO/LegacyFilesystemReader.cs +++ b/osu.Game/Beatmaps/IO/LegacyFilesystemReader.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.IO.File; diff --git a/osu.Game/Beatmaps/IO/OszArchiveReader.cs b/osu.Game/Beatmaps/IO/OszArchiveReader.cs index 491bd06487..ada7fb47bb 100644 --- a/osu.Game/Beatmaps/IO/OszArchiveReader.cs +++ b/osu.Game/Beatmaps/IO/OszArchiveReader.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs b/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs index 0b8b13f902..2a79c23e0b 100644 --- a/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs +++ b/osu.Game/Beatmaps/Legacy/LegacyBeatmap.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Beatmaps.Legacy diff --git a/osu.Game/Beatmaps/RankStatus.cs b/osu.Game/Beatmaps/RankStatus.cs index 17a4a4aa3f..5ca358ddef 100644 --- a/osu.Game/Beatmaps/RankStatus.cs +++ b/osu.Game/Beatmaps/RankStatus.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Beatmaps/Timing/BreakPeriod.cs b/osu.Game/Beatmaps/Timing/BreakPeriod.cs index 0cf4a0c65b..7345f0df82 100644 --- a/osu.Game/Beatmaps/Timing/BreakPeriod.cs +++ b/osu.Game/Beatmaps/Timing/BreakPeriod.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Beatmaps.Timing @@ -30,4 +30,4 @@ namespace osu.Game.Beatmaps.Timing /// public bool HasEffect => Duration >= MIN_BREAK_DURATION; } -} \ No newline at end of file +} diff --git a/osu.Game/Beatmaps/Timing/TimeSignatures.cs b/osu.Game/Beatmaps/Timing/TimeSignatures.cs index 94b36591f5..6b7d9e7e5a 100644 --- a/osu.Game/Beatmaps/Timing/TimeSignatures.cs +++ b/osu.Game/Beatmaps/Timing/TimeSignatures.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Beatmaps.Timing @@ -8,4 +8,4 @@ namespace osu.Game.Beatmaps.Timing SimpleQuadruple = 4, SimpleTriple = 3 } -} \ No newline at end of file +} diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 8c8cf212c1..c633b94951 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Audio.Track; diff --git a/osu.Game/Configuration/DatabasedConfigManager.cs b/osu.Game/Configuration/DatabasedConfigManager.cs new file mode 100644 index 0000000000..1f7a84c6d3 --- /dev/null +++ b/osu.Game/Configuration/DatabasedConfigManager.cs @@ -0,0 +1,71 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Configuration; +using osu.Game.Rulesets; + +namespace osu.Game.Configuration +{ + public abstract class DatabasedConfigManager : ConfigManager + where T : struct + { + private readonly SettingsStore settings; + + private readonly int variant; + + private readonly List databasedSettings; + + private readonly RulesetInfo ruleset; + + protected DatabasedConfigManager(SettingsStore settings, RulesetInfo ruleset = null, int variant = 0) + { + this.settings = settings; + this.ruleset = ruleset; + this.variant = variant; + + databasedSettings = settings.Query(ruleset?.ID, variant); + + InitialiseDefaults(); + } + + protected override void PerformLoad() + { + } + + protected override bool PerformSave() + { + return true; + } + + protected override void AddBindable(T lookup, Bindable bindable) + { + base.AddBindable(lookup, bindable); + + var setting = databasedSettings.FirstOrDefault(s => (int)s.Key == (int)(object)lookup); + if (setting != null) + { + bindable.Parse(setting.Value); + } + else + { + settings.Update(setting = new DatabasedSetting + { + Key = lookup, + Value = bindable.Value, + RulesetID = ruleset?.ID, + Variant = variant, + }); + + databasedSettings.Add(setting); + } + + bindable.ValueChanged += v => + { + setting.Value = v; + settings.Update(setting); + }; + } + } +} diff --git a/osu.Game/Configuration/DatabasedSetting.cs b/osu.Game/Configuration/DatabasedSetting.cs new file mode 100644 index 0000000000..7c2f65c854 --- /dev/null +++ b/osu.Game/Configuration/DatabasedSetting.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.ComponentModel.DataAnnotations.Schema; +using osu.Game.Database; + +namespace osu.Game.Configuration +{ + [Table("Settings")] + public class DatabasedSetting : IHasPrimaryKey + { + [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + public int ID { get; set; } + + public int? RulesetID { get; set; } + + public int? Variant { get; set; } + + [Column("Key")] + public int IntKey + { + get => (int)Key; + private set => Key = value; + } + + [Column("Value")] + public string StringValue + { + get => Value.ToString(); + set => Value = value; + } + + public object Key; + public object Value; + + public DatabasedSetting(object key, object value) + { + Key = key; + Value = value; + } + + /// + /// Constructor for derived classes that may require serialisation. + /// + public DatabasedSetting() + { + } + + public override string ToString() => $"{Key}=>{Value}"; + } +} diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index f4c7bdb586..c33dd91330 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; @@ -8,7 +8,7 @@ using osu.Game.Screens.Select; namespace osu.Game.Configuration { - public class OsuConfigManager : ConfigManager + public class OsuConfigManager : IniConfigManager { protected override void InitialiseDefaults() { @@ -39,6 +39,8 @@ namespace osu.Game.Configuration }; // Audio + Set(OsuSetting.VolumeInactive, 0.25, 0, 1, 0.01); + Set(OsuSetting.MenuVoice, true); Set(OsuSetting.MenuMusic, true); @@ -65,12 +67,15 @@ namespace osu.Game.Configuration // Gameplay Set(OsuSetting.DimLevel, 0.3, 0, 1, 0.01); + Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); Set(OsuSetting.ShowInterface, true); Set(OsuSetting.KeyOverlay, false); Set(OsuSetting.FloatingComments, false); + Set(OsuSetting.SpeedChangeVisualisation, SpeedChangeVisualisationMethod.Sequential); + // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -90,6 +95,7 @@ namespace osu.Game.Configuration GameplayCursorSize, AutoCursorSize, DimLevel, + BlurLevel, ShowStoryboard, KeyOverlay, FloatingComments, @@ -97,6 +103,7 @@ namespace osu.Game.Configuration MouseDisableButtons, MouseDisableWheel, AudioOffset, + VolumeInactive, MenuMusic, MenuVoice, CursorRotation, @@ -114,6 +121,7 @@ namespace osu.Game.Configuration ShowFpsDisplay, ChatDisplayHeight, Version, - ShowConvertedBeatmaps + ShowConvertedBeatmaps, + SpeedChangeVisualisation } } diff --git a/osu.Game/Configuration/RandomSelectAlgorithm.cs b/osu.Game/Configuration/RandomSelectAlgorithm.cs index cde657dba8..6f3d151b50 100644 --- a/osu.Game/Configuration/RandomSelectAlgorithm.cs +++ b/osu.Game/Configuration/RandomSelectAlgorithm.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Configuration/RankingType.cs b/osu.Game/Configuration/RankingType.cs index ff504ba292..20483a9b73 100644 --- a/osu.Game/Configuration/RankingType.cs +++ b/osu.Game/Configuration/RankingType.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; @@ -15,4 +15,4 @@ namespace osu.Game.Configuration Friends, Country } -} \ No newline at end of file +} diff --git a/osu.Game/Configuration/ReleaseStream.cs b/osu.Game/Configuration/ReleaseStream.cs index b258ab2f37..9deeb0bed8 100644 --- a/osu.Game/Configuration/ReleaseStream.cs +++ b/osu.Game/Configuration/ReleaseStream.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Configuration @@ -10,4 +10,4 @@ namespace osu.Game.Configuration //Beta40, //Stable } -} \ No newline at end of file +} diff --git a/osu.Game/Configuration/ScoreMeterType.cs b/osu.Game/Configuration/ScoreMeterType.cs index 8926f3ad81..6d4138c4c5 100644 --- a/osu.Game/Configuration/ScoreMeterType.cs +++ b/osu.Game/Configuration/ScoreMeterType.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Configuration @@ -9,4 +9,4 @@ namespace osu.Game.Configuration Colour, Error } -} \ No newline at end of file +} diff --git a/osu.Game/Configuration/ScreenshotFormat.cs b/osu.Game/Configuration/ScreenshotFormat.cs index 1a1a3f8920..1bc3013af9 100644 --- a/osu.Game/Configuration/ScreenshotFormat.cs +++ b/osu.Game/Configuration/ScreenshotFormat.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; @@ -13,4 +13,4 @@ namespace osu.Game.Configuration [Description("PNG (lossless)")] Png = 2 } -} \ No newline at end of file +} diff --git a/osu.Game/Configuration/SettingsStore.cs b/osu.Game/Configuration/SettingsStore.cs new file mode 100644 index 0000000000..9b18151c84 --- /dev/null +++ b/osu.Game/Configuration/SettingsStore.cs @@ -0,0 +1,44 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Game.Database; + +namespace osu.Game.Configuration +{ + public class SettingsStore : DatabaseBackedStore + { + public event Action SettingChanged; + + public SettingsStore(Func createContext) + : base(createContext) + { + } + + /// + /// Retrieve s for a specified ruleset/variant content. + /// + /// The ruleset's internal ID. + /// An optional variant. + /// + public List Query(int? rulesetId = null, int? variant = null) => + GetContext().DatabasedSetting.Where(b => b.RulesetID == rulesetId && b.Variant == variant).ToList(); + + public void Update(DatabasedSetting setting) + { + var context = GetContext(); + + var newValue = setting.Value; + + Refresh(ref setting); + + setting.Value = newValue; + + context.SaveChanges(); + + SettingChanged?.Invoke(); + } + } +} diff --git a/osu.Game/Configuration/SpeedChangeVisualisationMethod.cs b/osu.Game/Configuration/SpeedChangeVisualisationMethod.cs new file mode 100644 index 0000000000..644ae0a727 --- /dev/null +++ b/osu.Game/Configuration/SpeedChangeVisualisationMethod.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.ComponentModel; + +namespace osu.Game.Configuration +{ + public enum SpeedChangeVisualisationMethod + { + [Description("Sequential")] + Sequential, + [Description("Overlapping")] + Overlapping + } +} diff --git a/osu.Game/Database/DatabaseBackedStore.cs b/osu.Game/Database/DatabaseBackedStore.cs index d8c3ce6694..ec9967e097 100644 --- a/osu.Game/Database/DatabaseBackedStore.cs +++ b/osu.Game/Database/DatabaseBackedStore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -34,8 +34,14 @@ namespace osu.Game.Database if (context.Entry(obj).State != EntityState.Detached) return; var id = obj.ID; - obj = lookupSource?.SingleOrDefault(t => t.ID == id) ?? context.Find(id); - context.Entry(obj).Reload(); + var foundObject = lookupSource?.SingleOrDefault(t => t.ID == id) ?? context.Find(id); + if (foundObject != null) + { + obj = foundObject; + context.Entry(obj).Reload(); + } + else + context.Add(obj); } /// diff --git a/osu.Game/Database/DatabaseContextFactory.cs b/osu.Game/Database/DatabaseContextFactory.cs index 6154016083..b1917d92c4 100644 --- a/osu.Game/Database/DatabaseContextFactory.cs +++ b/osu.Game/Database/DatabaseContextFactory.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Platform; diff --git a/osu.Game/Database/IHasPrimaryKey.cs b/osu.Game/Database/IHasPrimaryKey.cs index 9af9852b03..c5ad5f22f9 100644 --- a/osu.Game/Database/IHasPrimaryKey.cs +++ b/osu.Game/Database/IHasPrimaryKey.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Database diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index f9509a279e..ae6d3a2aee 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -8,9 +8,10 @@ using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Logging; using osu.Framework.Logging; using osu.Game.Beatmaps; -using osu.Game.Input.Bindings; +using osu.Game.Configuration; using osu.Game.IO; using osu.Game.Rulesets; +using DatabasedKeyBinding = osu.Game.Input.Bindings.DatabasedKeyBinding; using LogLevel = Microsoft.Extensions.Logging.LogLevel; namespace osu.Game.Database @@ -22,6 +23,7 @@ namespace osu.Game.Database public DbSet BeatmapMetadata { get; set; } public DbSet BeatmapSetInfo { get; set; } public DbSet DatabasedKeyBinding { get; set; } + public DbSet DatabasedSetting { get; set; } public DbSet FileInfo { get; set; } public DbSet RulesetInfo { get; set; } @@ -80,9 +82,11 @@ namespace osu.Game.Database modelBuilder.Entity().HasIndex(b => b.DeletePending); modelBuilder.Entity().HasIndex(b => b.Hash).IsUnique(); - modelBuilder.Entity().HasIndex(b => b.Variant); + modelBuilder.Entity().HasIndex(b => new { b.RulesetID, b.Variant }); modelBuilder.Entity().HasIndex(b => b.IntAction); + modelBuilder.Entity().HasIndex(b => new { b.RulesetID, b.Variant }); + modelBuilder.Entity().HasIndex(b => b.Hash).IsUnique(); modelBuilder.Entity().HasIndex(b => b.ReferenceCount); diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs index 4fb08a41f3..c5cc14c25f 100644 --- a/osu.Game/Graphics/Backgrounds/Background.cs +++ b/osu.Game/Graphics/Backgrounds/Background.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 6312db3ad6..6f9d83473f 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -30,7 +30,9 @@ namespace osu.Game.Graphics.Backgrounds /// private const float edge_smoothness = 1; - public override bool HandleInput => false; + public override bool HandleKeyboardInput => false; + public override bool HandleMouseInput => false; + public Color4 ColourLight = Color4.White; public Color4 ColourDark = Color4.Black; diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index d5d75c9e29..5a5f283fb9 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs index dd2a265a0f..ad0b815957 100644 --- a/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs +++ b/osu.Game/Graphics/Containers/ConstrainedIconContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs new file mode 100644 index 0000000000..9f1b44af44 --- /dev/null +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -0,0 +1,100 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Online.Chat; +using System; +using System.Diagnostics; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Sprites; +using System.Collections.Generic; +using osu.Game.Overlays; +using osu.Game.Overlays.Notifications; + +namespace osu.Game.Graphics.Containers +{ + public class LinkFlowContainer : OsuTextFlowContainer + { + public LinkFlowContainer(Action defaultCreationParameters = null) + : base(defaultCreationParameters) + { + } + + public override bool HandleMouseInput => true; + + private OsuGame game; + + private Action showNotImplementedError; + + [BackgroundDependencyLoader(true)] + private void load(OsuGame game, NotificationOverlay notifications) + { + // will be null in tests + this.game = game; + + showNotImplementedError = () => notifications?.Post(new SimpleNotification + { + Text = @"This link type is not yet supported!", + Icon = FontAwesome.fa_life_saver, + }); + } + + public void AddLinks(string text, List links) + { + if (string.IsNullOrEmpty(text) || links == null) + return; + + if (links.Count == 0) + { + AddText(text); + return; + } + + int previousLinkEnd = 0; + foreach (var link in links) + { + AddText(text.Substring(previousLinkEnd, link.Index - previousLinkEnd)); + AddLink(text.Substring(link.Index, link.Length), link.Url, link.Action, link.Argument); + previousLinkEnd = link.Index + link.Length; + } + + AddText(text.Substring(previousLinkEnd)); + } + + public void AddLink(string text, string url, LinkAction linkType = LinkAction.External, string linkArgument = null, string tooltipText = null) + { + AddInternal(new DrawableLinkCompiler(AddText(text).ToList()) + { + TooltipText = tooltipText ?? (url != text ? url : string.Empty), + Action = () => + { + switch (linkType) + { + case LinkAction.OpenBeatmap: + // todo: replace this with overlay.ShowBeatmap(id) once an appropriate API call is implemented. + if (int.TryParse(linkArgument, out int beatmapId)) + Process.Start($"https://osu.ppy.sh/b/{beatmapId}"); + break; + case LinkAction.OpenBeatmapSet: + if (int.TryParse(linkArgument, out int setId)) + game?.ShowBeatmapSet(setId); + break; + case LinkAction.OpenChannel: + game?.OpenChannel(linkArgument); + break; + case LinkAction.OpenEditorTimestamp: + case LinkAction.JoinMultiplayerMatch: + case LinkAction.Spectate: + showNotImplementedError?.Invoke(); + break; + case LinkAction.External: + Process.Start(url); + break; + default: + throw new NotImplementedException($"This {nameof(LinkAction)} ({linkType.ToString()}) is missing an associated action."); + } + }, + }); + } + } +} diff --git a/osu.Game/Graphics/Containers/OsuClickableContainer.cs b/osu.Game/Graphics/Containers/OsuClickableContainer.cs index 8df533ad6e..b9ee1f4463 100644 --- a/osu.Game/Graphics/Containers/OsuClickableContainer.cs +++ b/osu.Game/Graphics/Containers/OsuClickableContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -16,6 +16,8 @@ namespace osu.Game.Graphics.Containers protected override Container Content => content; + protected virtual HoverClickSounds CreateHoverClickSounds(HoverSampleSet sampleSet) => new HoverClickSounds(sampleSet); + public OsuClickableContainer(HoverSampleSet sampleSet = HoverSampleSet.Normal) { this.sampleSet = sampleSet; @@ -33,7 +35,7 @@ namespace osu.Game.Graphics.Containers InternalChildren = new Drawable[] { content, - new HoverClickSounds(sampleSet) + CreateHoverClickSounds(sampleSet) }; } } diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index f67da52fc0..ec461b86fd 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -33,15 +33,6 @@ namespace osu.Game.Graphics.Containers // receive input outside our bounds so we can trigger a close event on ourselves. public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => BlockScreenWideMouse || base.ReceiveMouseInputAt(screenSpacePos); - protected override bool OnWheel(InputState state) - { - // always allow wheel to pass through to stuff outside our DrawRectangle. - if (!base.ReceiveMouseInputAt(state.Mouse.NativeState.Position)) - return false; - - return BlockPassThroughMouse; - } - protected override bool OnClick(InputState state) { if (!base.ReceiveMouseInputAt(state.Mouse.NativeState.Position)) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index 3f82ad2179..fd1742871b 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -1,8 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using OpenTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Input; @@ -10,24 +12,34 @@ namespace osu.Game.Graphics.Containers { public class OsuHoverContainer : OsuClickableContainer { - private Color4 hoverColour; + protected Color4 HoverColour; + + protected Color4 IdleColour = Color4.White; + + protected virtual IEnumerable EffectTargets => new[] { Content }; protected override bool OnHover(InputState state) { - this.FadeColour(hoverColour, 500, Easing.OutQuint); + EffectTargets.ForEach(d => d.FadeColour(HoverColour, 500, Easing.OutQuint)); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - this.FadeColour(Color4.White, 500, Easing.OutQuint); + EffectTargets.ForEach(d => d.FadeColour(IdleColour, 500, Easing.OutQuint)); base.OnHoverLost(state); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - hoverColour = colours.Yellow; + HoverColour = colours.Yellow; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + EffectTargets.ForEach(d => d.FadeColour(IdleColour)); } } } diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index 3fc9f439fa..1d5a2af899 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs b/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs index 143f38ced4..51adf5f232 100644 --- a/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs +++ b/osu.Game/Graphics/Containers/OsuTextFlowContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 362563507b..cb894ca382 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs b/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs index 781e149078..9f028490ef 100644 --- a/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs +++ b/osu.Game/Graphics/Containers/ReverseChildIDFillFlowContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Graphics/Containers/SectionsContainer.cs b/osu.Game/Graphics/Containers/SectionsContainer.cs index 1e2826189b..acb74588fd 100644 --- a/osu.Game/Graphics/Containers/SectionsContainer.cs +++ b/osu.Game/Graphics/Containers/SectionsContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs new file mode 100644 index 0000000000..0fae4579fa --- /dev/null +++ b/osu.Game/Graphics/Cursor/CursorOverrideContainer.cs @@ -0,0 +1,67 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Linq; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Input; + +namespace osu.Game.Graphics.Cursor +{ + /// + /// A container which provides a which can be overridden by hovered s. + /// + public class CursorOverrideContainer : Container, IProvideCursor + { + protected override Container Content => content; + private readonly Container content; + + /// + /// Whether any cursors can be displayed. + /// + public bool CanShowCursor = true; + + public CursorContainer Cursor { get; } + public bool ProvidingUserCursor => true; + + public CursorOverrideContainer() + { + AddRangeInternal(new Drawable[] + { + Cursor = new MenuCursor { State = Visibility.Hidden }, + content = new Container { RelativeSizeAxes = Axes.Both } + }); + } + + private InputManager inputManager; + + protected override void LoadComplete() + { + base.LoadComplete(); + inputManager = GetContainingInputManager(); + } + + private IProvideCursor currentTarget; + protected override void Update() + { + base.Update(); + + if (!CanShowCursor) + { + currentTarget?.Cursor?.Hide(); + return; + } + + var newTarget = inputManager.HoveredDrawables.OfType().FirstOrDefault(t => t.ProvidingUserCursor) ?? this; + + if (currentTarget == newTarget) + return; + + currentTarget?.Cursor?.Hide(); + newTarget.Cursor?.Show(); + + currentTarget = newTarget; + } + } +} diff --git a/osu.Game/Graphics/Cursor/IProvideCursor.cs b/osu.Game/Graphics/Cursor/IProvideCursor.cs new file mode 100644 index 0000000000..91b44234fb --- /dev/null +++ b/osu.Game/Graphics/Cursor/IProvideCursor.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Cursor; + +namespace osu.Game.Graphics.Cursor +{ + /// + /// Interface for s that display cursors which can replace the user's cursor. + /// + public interface IProvideCursor : IDrawable + { + /// + /// The cursor provided by this . + /// May be null if no cursor should be visible. + /// + CursorContainer Cursor { get; } + + /// + /// Whether should be displayed as the singular user cursor. This will temporarily hide any other user cursor. + /// This value is checked every frame and may be used to control whether multiple cursors are displayed (e.g. watching replays). + /// + bool ProvidingUserCursor { get; } + } +} diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 451422038f..bdee7d289d 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -100,8 +100,8 @@ namespace osu.Game.Graphics.Cursor protected override void PopOut() { - ActiveCursor.FadeTo(0, 900, Easing.OutQuint); - ActiveCursor.ScaleTo(0, 500, Easing.In); + ActiveCursor.FadeTo(0, 250, Easing.OutQuint); + ActiveCursor.ScaleTo(0.6f, 250, Easing.In); } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs index 1ece10bc60..d8910c5398 100644 --- a/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuContextMenuContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Cursor; @@ -11,4 +11,4 @@ namespace osu.Game.Graphics.Cursor { protected override Menu CreateMenu() => new OsuContextMenu(); } -} \ No newline at end of file +} diff --git a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs index e9d84b28a3..3706f31ded 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Graphics/IHasAccentColour.cs b/osu.Game/Graphics/IHasAccentColour.cs index 0c6bf98db4..84120764d1 100644 --- a/osu.Game/Graphics/IHasAccentColour.cs +++ b/osu.Game/Graphics/IHasAccentColour.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index 70017d3c6e..8e24807eaa 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Graphics/SpriteIcon.cs b/osu.Game/Graphics/SpriteIcon.cs index 326aa2fb79..a93cb4c6cd 100644 --- a/osu.Game/Graphics/SpriteIcon.cs +++ b/osu.Game/Graphics/SpriteIcon.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Graphics/Sprites/OsuSpriteText.cs b/osu.Game/Graphics/Sprites/OsuSpriteText.cs index cbd9d9582d..8c1c78906d 100644 --- a/osu.Game/Graphics/Sprites/OsuSpriteText.cs +++ b/osu.Game/Graphics/Sprites/OsuSpriteText.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/Textures/LargeTextureStore.cs b/osu.Game/Graphics/Textures/LargeTextureStore.cs index 166364c8dd..17fa7d4e24 100644 --- a/osu.Game/Graphics/Textures/LargeTextureStore.cs +++ b/osu.Game/Graphics/Textures/LargeTextureStore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Textures; diff --git a/osu.Game/Graphics/UserInterface/BackButton.cs b/osu.Game/Graphics/UserInterface/BackButton.cs index 6a3757ec0e..3f348dc19d 100644 --- a/osu.Game/Graphics/UserInterface/BackButton.cs +++ b/osu.Game/Graphics/UserInterface/BackButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index c25a9bf5e9..6381c242fe 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Graphics/UserInterface/BarGraph.cs b/osu.Game/Graphics/UserInterface/BarGraph.cs index 1a980e6bd5..3bc1598191 100644 --- a/osu.Game/Graphics/UserInterface/BarGraph.cs +++ b/osu.Game/Graphics/UserInterface/BarGraph.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -74,4 +74,4 @@ namespace osu.Game.Graphics.UserInterface } } } -} \ No newline at end of file +} diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index 65ece51a70..5ee0aba9cf 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -42,7 +42,9 @@ namespace osu.Game.Graphics.UserInterface //don't allow clicking between transitions and don't make the chevron clickable public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => Alpha == 1f && Text.ReceiveMouseInputAt(screenSpacePos); - public override bool HandleInput => State == Visibility.Visible; + + public override bool HandleKeyboardInput => State == Visibility.Visible; + public override bool HandleMouseInput => State == Visibility.Visible; private Visibility state; diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index f07bc4114f..99da8755bf 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index 206c7a839d..6d9bf231c3 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs index 0fac1c8092..9fb0594524 100644 --- a/osu.Game/Graphics/UserInterface/HoverClickSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverClickSounds.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/UserInterface/HoverSounds.cs b/osu.Game/Graphics/UserInterface/HoverSounds.cs index 24dbe37567..fabb344872 100644 --- a/osu.Game/Graphics/UserInterface/HoverSounds.cs +++ b/osu.Game/Graphics/UserInterface/HoverSounds.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index afffd930ef..5b266d9a59 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -15,7 +15,7 @@ namespace osu.Game.Graphics.UserInterface { public class IconButton : OsuClickableContainer { - private const float button_size = 30; + public const float BUTTON_SIZE = 30; private Color4? flashColour; /// @@ -106,7 +106,7 @@ namespace osu.Game.Graphics.UserInterface { Origin = Anchor.Centre, Anchor = Anchor.Centre, - Size = new Vector2(button_size), + Size = new Vector2(BUTTON_SIZE), CornerRadius = 5, Masking = true, EdgeEffect = new EdgeEffectParameters diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index 35e3f10526..366c063a0c 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Graphics/UserInterface/LoadingAnimation.cs b/osu.Game/Graphics/UserInterface/LoadingAnimation.cs index eb8ff5be86..54f818e307 100644 --- a/osu.Game/Graphics/UserInterface/LoadingAnimation.cs +++ b/osu.Game/Graphics/UserInterface/LoadingAnimation.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/MenuItemType.cs b/osu.Game/Graphics/UserInterface/MenuItemType.cs index bd89dbfced..21c743ecd3 100644 --- a/osu.Game/Graphics/UserInterface/MenuItemType.cs +++ b/osu.Game/Graphics/UserInterface/MenuItemType.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Graphics.UserInterface @@ -9,4 +9,4 @@ namespace osu.Game.Graphics.UserInterface Highlighted, Destructive, } -} \ No newline at end of file +} diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index f7df6cd4f4..ed2be25feb 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 081e59d3a7..be487bc062 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index 40ff1243dc..f06313c261 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -76,6 +76,16 @@ namespace osu.Game.Graphics.UserInterface Nub.Current.BindTo(Current); + Current.DisabledChanged += disabled => + { + Alpha = disabled ? 0.3f : 1; + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Current.ValueChanged += newValue => { if (newValue) @@ -83,11 +93,6 @@ namespace osu.Game.Graphics.UserInterface else sampleUnchecked?.Play(); }; - - Current.DisabledChanged += disabled => - { - Alpha = disabled ? 0.3f : 1; - }; } protected override bool OnHover(InputState state) diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index 4ce6c98744..5335f20bf9 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; @@ -36,4 +36,4 @@ namespace osu.Game.Graphics.UserInterface protected override void AnimateOpen() => this.FadeIn(fade_duration, Easing.OutQuint); protected override void AnimateClose() => this.FadeOut(fade_duration, Easing.OutQuint); } -} \ No newline at end of file +} diff --git a/osu.Game/Graphics/UserInterface/OsuDropdown.cs b/osu.Game/Graphics/UserInterface/OsuDropdown.cs index 4401b509fd..b230aa4260 100644 --- a/osu.Game/Graphics/UserInterface/OsuDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuDropdown.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs index bf835f0165..b0711a6667 100644 --- a/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs +++ b/osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index 7f16d73613..968c0eed98 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs index 1f78666d20..9ccbea2479 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenuItem.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -22,4 +22,4 @@ namespace osu.Game.Graphics.UserInterface Type = type; } } -} \ No newline at end of file +} diff --git a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs index 7f193a0e1a..8c519e5371 100644 --- a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index fd75269610..8f375d9885 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Globalization; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -17,8 +18,13 @@ using osu.Framework.Graphics.Shapes; namespace osu.Game.Graphics.UserInterface { public class OsuSliderBar : SliderBar, IHasTooltip, IHasAccentColour - where T : struct, IEquatable + where T : struct, IEquatable, IComparable, IConvertible { + /// + /// Maximum number of decimal digits to be displayed in the tooltip. + /// + private const int max_decimal_digits = 5; + private SampleChannel sample; private double lastSampleTime; private T lastSampleValue; @@ -32,18 +38,31 @@ namespace osu.Game.Graphics.UserInterface get { var bindableDouble = CurrentNumber as BindableNumber; - if (bindableDouble != null) + var bindableFloat = CurrentNumber as BindableNumber; + var floatValue = bindableDouble?.Value ?? bindableFloat?.Value; + var floatPrecision = bindableDouble?.Precision ?? bindableFloat?.Precision; + + if (floatValue != null) { - if (bindableDouble.MaxValue == 1 && (bindableDouble.MinValue == 0 || bindableDouble.MinValue == -1)) - return bindableDouble.Value.ToString(@"P0"); - return bindableDouble.Value.ToString(@"n1"); + var floatMinValue = bindableDouble?.MinValue ?? bindableFloat.MinValue; + var floatMaxValue = bindableDouble?.MaxValue ?? bindableFloat.MaxValue; + + if (floatMaxValue == 1 && (floatMinValue == 0 || floatMinValue == -1)) + return floatValue.Value.ToString("P0"); + + var decimalPrecision = normalise((decimal)floatPrecision, max_decimal_digits); + + // Find the number of significant digits (we could have less than 5 after normalize()) + var significantDigits = findPrecision(decimalPrecision); + + return floatValue.Value.ToString($"N{significantDigits}"); } var bindableInt = CurrentNumber as BindableNumber; if (bindableInt != null) - return bindableInt.Value.ToString(@"n0"); + return bindableInt.Value.ToString("N0"); - return Current.Value.ToString(); + return Current.Value.ToString(CultureInfo.InvariantCulture); } } @@ -169,5 +188,31 @@ namespace osu.Game.Graphics.UserInterface { Nub.MoveToX(RangePadding + UsableWidth * value, 250, Easing.OutQuint); } + + /// + /// Removes all non-significant digits, keeping at most a requested number of decimal digits. + /// + /// The decimal to normalize. + /// The maximum number of decimal digits to keep. The final result may have fewer decimal digits than this value. + /// The normalised decimal. + private decimal normalise(decimal d, int sd) + => decimal.Parse(Math.Round(d, sd).ToString(string.Concat("0.", new string('#', sd)), CultureInfo.InvariantCulture), CultureInfo.InvariantCulture); + + /// + /// Finds the number of digits after the decimal. + /// + /// The value to find the number of decimal digits for. + /// The number decimal digits. + private int findPrecision(decimal d) + { + int precision = 0; + while (d != Math.Round(d)) + { + d *= 10; + precision++; + } + + return precision; + } } } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index decbf57ad1..7ad9bc73a8 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -180,7 +180,6 @@ namespace osu.Game.Graphics.UserInterface } } - protected class OsuTabDropdownHeader : OsuDropdownHeader { public override Color4 AccentColour diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index a0d48e5ebe..3fd7760802 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index 3512b4cdb1..31093f1429 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index c69857a5c4..57ee334f6b 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index 0a402f9045..376f7a46ee 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Graphics/UserInterface/ProgressBar.cs b/osu.Game/Graphics/UserInterface/ProgressBar.cs index f22983a6e6..6021cf08be 100644 --- a/osu.Game/Graphics/UserInterface/ProgressBar.cs +++ b/osu.Game/Graphics/UserInterface/ProgressBar.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -18,7 +18,7 @@ namespace osu.Game.Graphics.UserInterface public Color4 FillColour { - set { fill.Colour = value; } + set { fill.FadeColour(value, 150, Easing.OutQuint); } } public Color4 BackgroundColour @@ -64,4 +64,4 @@ namespace osu.Game.Graphics.UserInterface protected override void OnUserChange() => OnSeek?.Invoke(Current); } -} \ No newline at end of file +} diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs index ce8d190dc0..3eeba02154 100644 --- a/osu.Game/Graphics/UserInterface/RollingCounter.cs +++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index ee4fc912f3..8fd9f41211 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs index ee5d3baf66..9398eb55f3 100644 --- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs +++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -68,4 +68,4 @@ namespace osu.Game.Graphics.UserInterface return base.OnKeyDown(state, args); } } -} \ No newline at end of file +} diff --git a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs index 211de72efc..cf09609516 100644 --- a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs +++ b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -32,4 +32,4 @@ namespace osu.Game.Graphics.UserInterface Current.Value = Current + amount; } } -} \ No newline at end of file +} diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index b4ca0d2e02..cefa4b3e28 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Graphics/UserInterface/TriangleButton.cs b/osu.Game/Graphics/UserInterface/TriangleButton.cs index 61e9705064..c87d81641f 100644 --- a/osu.Game/Graphics/UserInterface/TriangleButton.cs +++ b/osu.Game/Graphics/UserInterface/TriangleButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index f17b307826..751f4809dc 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -251,4 +251,4 @@ namespace osu.Game.Graphics.UserInterface } } } -} \ No newline at end of file +} diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs index 273a2279bf..ccf70af6ed 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -7,6 +7,7 @@ using osu.Framework.Threading; using OpenTK; using osu.Framework.Audio; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Game.Input.Bindings; namespace osu.Game.Graphics.UserInterface.Volume @@ -14,6 +15,7 @@ namespace osu.Game.Graphics.UserInterface.Volume public class VolumeControl : OverlayContainer { private readonly VolumeMeter volumeMeterMaster; + private readonly IconButton muteIcon; protected override bool BlockPassThroughMouse => false; @@ -34,6 +36,17 @@ namespace osu.Game.Graphics.UserInterface.Volume Spacing = new Vector2(15, 0), Children = new Drawable[] { + new Container + { + Size = new Vector2(IconButton.BUTTON_SIZE), + Child = muteIcon = new IconButton + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.fa_volume_up, + Action = () => Adjust(GlobalAction.ToggleMute), + } + }, volumeMeterMaster = new VolumeMeter("Master"), volumeMeterEffect = new VolumeMeter("Effects"), volumeMeterMusic = new VolumeMeter("Music") @@ -46,18 +59,10 @@ namespace osu.Game.Graphics.UserInterface.Volume { base.LoadComplete(); - volumeMeterMaster.Bindable.ValueChanged += volumeChanged; - volumeMeterEffect.Bindable.ValueChanged += volumeChanged; - volumeMeterMusic.Bindable.ValueChanged += volumeChanged; - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - - volumeMeterMaster.Bindable.ValueChanged -= volumeChanged; - volumeMeterEffect.Bindable.ValueChanged -= volumeChanged; - volumeMeterMusic.Bindable.ValueChanged -= volumeChanged; + volumeMeterMaster.Bindable.ValueChanged += _ => settingChanged(); + volumeMeterEffect.Bindable.ValueChanged += _ => settingChanged(); + volumeMeterMusic.Bindable.ValueChanged += _ => settingChanged(); + muted.ValueChanged += _ => settingChanged(); } public bool Adjust(GlobalAction action) @@ -76,23 +81,45 @@ namespace osu.Game.Graphics.UserInterface.Volume else volumeMeterMaster.Increase(); return true; + case GlobalAction.ToggleMute: + Show(); + muted.Toggle(); + return true; } return false; } - private void volumeChanged(double newVolume) + private void settingChanged() { Show(); schedulePopOut(); } + private readonly BindableDouble muteAdjustment = new BindableDouble(); + + private readonly BindableBool muted = new BindableBool(); + [BackgroundDependencyLoader] private void load(AudioManager audio) { volumeMeterMaster.Bindable.BindTo(audio.Volume); volumeMeterEffect.Bindable.BindTo(audio.VolumeSample); volumeMeterMusic.Bindable.BindTo(audio.VolumeTrack); + + muted.ValueChanged += mute => + { + if (mute) + { + audio.AddAdjustment(AdjustableProperty.Volume, muteAdjustment); + muteIcon.Icon = FontAwesome.fa_volume_off; + } + else + { + audio.RemoveAdjustment(AdjustableProperty.Volume, muteAdjustment); + muteIcon.Icon = FontAwesome.fa_volume_up; + } + }; } private ScheduledDelegate popOutDelegate; diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeControlReceptor.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeControlReceptor.cs index 7c740f16ce..2328533665 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeControlReceptor.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeControlReceptor.cs @@ -1,14 +1,15 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using osu.Framework.Graphics.Containers; +using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Game.Input.Bindings; namespace osu.Game.Graphics.UserInterface.Volume { - public class VolumeControlReceptor : Container, IKeyBindingHandler + public class VolumeControlReceptor : Container, IKeyBindingHandler, IHandleGlobalInput { public Func ActionRequested; diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs index d55b16563d..ef3702fdf3 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; @@ -70,11 +70,8 @@ namespace osu.Game.Graphics.UserInterface.Volume public double Volume { - get { return Bindable.Value; } - private set - { - Bindable.Value = value; - } + get => Bindable.Value; + private set => Bindable.Value = value; } public void Increase() diff --git a/osu.Game/IO/FileInfo.cs b/osu.Game/IO/FileInfo.cs index 31b63ecd21..94a3d455d4 100644 --- a/osu.Game/IO/FileInfo.cs +++ b/osu.Game/IO/FileInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel.DataAnnotations.Schema; diff --git a/osu.Game/IO/FileStore.cs b/osu.Game/IO/FileStore.cs index 4eca310424..31c608a5f4 100644 --- a/osu.Game/IO/FileStore.cs +++ b/osu.Game/IO/FileStore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/IO/Legacy/ILegacySerializable.cs b/osu.Game/IO/Legacy/ILegacySerializable.cs index a280a5d13a..43c12a631a 100644 --- a/osu.Game/IO/Legacy/ILegacySerializable.cs +++ b/osu.Game/IO/Legacy/ILegacySerializable.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.IO.Legacy @@ -8,4 +8,4 @@ namespace osu.Game.IO.Legacy void ReadFromStream(SerializationReader sr); void WriteToStream(SerializationWriter sw); } -} \ No newline at end of file +} diff --git a/osu.Game/IO/Legacy/SerializationReader.cs b/osu.Game/IO/Legacy/SerializationReader.cs index 393a13448e..75cbef80a5 100644 --- a/osu.Game/IO/Legacy/SerializationReader.cs +++ b/osu.Game/IO/Legacy/SerializationReader.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/IO/Legacy/SerializationWriter.cs b/osu.Game/IO/Legacy/SerializationWriter.cs index c8af66fd8a..f972796383 100644 --- a/osu.Game/IO/Legacy/SerializationWriter.cs +++ b/osu.Game/IO/Legacy/SerializationWriter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs index d63cceccf3..d1cf34629d 100644 --- a/osu.Game/IO/Serialization/Converters/TypedListConverter.cs +++ b/osu.Game/IO/Serialization/Converters/TypedListConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/IO/Serialization/Converters/Vector2Converter.cs b/osu.Game/IO/Serialization/Converters/Vector2Converter.cs index 87fbd31d21..2cad4bc0fb 100644 --- a/osu.Game/IO/Serialization/Converters/Vector2Converter.cs +++ b/osu.Game/IO/Serialization/Converters/Vector2Converter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/IO/Serialization/IJsonSerializable.cs b/osu.Game/IO/Serialization/IJsonSerializable.cs index 892c266fe3..9e3aaafc81 100644 --- a/osu.Game/IO/Serialization/IJsonSerializable.cs +++ b/osu.Game/IO/Serialization/IJsonSerializable.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Newtonsoft.Json; diff --git a/osu.Game/IO/Serialization/KeyContractResolver.cs b/osu.Game/IO/Serialization/KeyContractResolver.cs index 10375646ce..a8d1313091 100644 --- a/osu.Game/IO/Serialization/KeyContractResolver.cs +++ b/osu.Game/IO/Serialization/KeyContractResolver.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Humanizer; diff --git a/osu.Game/IPC/BeatmapIPCChannel.cs b/osu.Game/IPC/BeatmapIPCChannel.cs index 6a9019251c..64e5d526e6 100644 --- a/osu.Game/IPC/BeatmapIPCChannel.cs +++ b/osu.Game/IPC/BeatmapIPCChannel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Diagnostics; diff --git a/osu.Game/IPC/ScoreIPCChannel.cs b/osu.Game/IPC/ScoreIPCChannel.cs index ae44250e8d..7f93656549 100644 --- a/osu.Game/IPC/ScoreIPCChannel.cs +++ b/osu.Game/IPC/ScoreIPCChannel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Diagnostics; diff --git a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs index 7e9e25aeff..d20adda8ed 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBinding.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBinding.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel.DataAnnotations.Schema; diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs similarity index 83% rename from osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs rename to osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs index 784e6462f2..b6bc348a52 100644 --- a/osu.Game/Input/Bindings/DatabasedKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -14,7 +14,7 @@ namespace osu.Game.Input.Bindings /// A KeyBindingInputManager with a database backing for custom overrides. /// /// The type of the custom action. - public class DatabasedKeyBindingInputManager : KeyBindingContainer + public class DatabasedKeyBindingContainer : KeyBindingContainer where T : struct { private readonly RulesetInfo ruleset; @@ -23,7 +23,7 @@ namespace osu.Game.Input.Bindings private KeyBindingStore store; - public override IEnumerable DefaultKeyBindings => ruleset.CreateInstance().GetDefaultKeyBindings(); + public override IEnumerable DefaultKeyBindings => ruleset.CreateInstance().GetDefaultKeyBindings(variant ?? 0); /// /// Create a new instance. @@ -31,7 +31,7 @@ namespace osu.Game.Input.Bindings /// A reference to identify the current . Used to lookup mappings. Null for global mappings. /// An optional variant for the specified . Used when a ruleset has more than one possible keyboard layouts. /// Specify how to deal with multiple matches of s and s. - public DatabasedKeyBindingInputManager(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None) + public DatabasedKeyBindingContainer(RulesetInfo ruleset = null, int? variant = null, SimultaneousBindingMode simultaneousMode = SimultaneousBindingMode.None) : base(simultaneousMode) { this.ruleset = ruleset; diff --git a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs b/osu.Game/Input/Bindings/GlobalActionContainer.cs similarity index 60% rename from osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs rename to osu.Game/Input/Bindings/GlobalActionContainer.cs index 745508ec9e..17ec2af4b9 100644 --- a/osu.Game/Input/Bindings/GlobalKeyBindingInputManager.cs +++ b/osu.Game/Input/Bindings/GlobalActionContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -10,27 +10,36 @@ using osu.Framework.Input.Bindings; namespace osu.Game.Input.Bindings { - public class GlobalKeyBindingInputManager : DatabasedKeyBindingInputManager, IHandleGlobalInput + public class GlobalActionContainer : DatabasedKeyBindingContainer, IHandleGlobalInput { private readonly Drawable handler; - public GlobalKeyBindingInputManager(OsuGameBase game) + public GlobalActionContainer(OsuGameBase game) { if (game is IKeyBindingHandler) handler = game; } - public override IEnumerable DefaultKeyBindings => new[] + public override IEnumerable DefaultKeyBindings => GlobalKeyBindings.Concat(InGameKeyBindings); + + public IEnumerable GlobalKeyBindings => new[] { new KeyBinding(InputKey.F8, GlobalAction.ToggleChat), new KeyBinding(InputKey.F9, GlobalAction.ToggleSocial), new KeyBinding(new[] { InputKey.Control, InputKey.Alt, InputKey.R }, GlobalAction.ResetInputSettings), new KeyBinding(new[] { InputKey.Control, InputKey.T }, GlobalAction.ToggleToolbar), new KeyBinding(new[] { InputKey.Control, InputKey.O }, GlobalAction.ToggleSettings), - new KeyBinding(new[] { InputKey.Up }, GlobalAction.IncreaseVolume), - new KeyBinding(new[] { InputKey.MouseWheelUp }, GlobalAction.IncreaseVolume), - new KeyBinding(new[] { InputKey.Down }, GlobalAction.DecreaseVolume), - new KeyBinding(new[] { InputKey.MouseWheelDown }, GlobalAction.DecreaseVolume), + new KeyBinding(InputKey.Up, GlobalAction.IncreaseVolume), + new KeyBinding(InputKey.MouseWheelUp, GlobalAction.IncreaseVolume), + new KeyBinding(InputKey.Down, GlobalAction.DecreaseVolume), + new KeyBinding(InputKey.MouseWheelDown, GlobalAction.DecreaseVolume), + new KeyBinding(InputKey.F4, GlobalAction.ToggleMute), + }; + + public IEnumerable InGameKeyBindings => new[] + { + new KeyBinding(InputKey.Space, GlobalAction.SkipCutscene), + new KeyBinding(InputKey.Tilde, GlobalAction.QuickRetry) }; protected override IEnumerable KeyBindingInputQueue => @@ -55,5 +64,13 @@ namespace osu.Game.Input.Bindings IncreaseVolume, [Description("Decrease Volume")] DecreaseVolume, + [Description("Toggle mute")] + ToggleMute, + + // In-Game Keybindings + [Description("Skip Cutscene")] + SkipCutscene, + [Description("Quick Retry (Hold)")] + QuickRetry, } } diff --git a/osu.Game/Input/Handlers/ReplayInputHandler.cs b/osu.Game/Input/Handlers/ReplayInputHandler.cs index 5f86495580..8aa3a53cc2 100644 --- a/osu.Game/Input/Handlers/ReplayInputHandler.cs +++ b/osu.Game/Input/Handlers/ReplayInputHandler.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -45,4 +45,4 @@ namespace osu.Game.Input.Handlers } } } -} \ No newline at end of file +} diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index 9e2988417a..92159ab491 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Migrations/20180125143340_Settings.Designer.cs b/osu.Game/Migrations/20180125143340_Settings.Designer.cs new file mode 100644 index 0000000000..8e045abc6f --- /dev/null +++ b/osu.Game/Migrations/20180125143340_Settings.Designer.cs @@ -0,0 +1,329 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using osu.Game.Database; +using System; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20180125143340_Settings")] + partial class Settings + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.0-rtm-26452"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MD5Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntKey") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20180125143340_Settings.cs b/osu.Game/Migrations/20180125143340_Settings.cs new file mode 100644 index 0000000000..86a6b2dc5e --- /dev/null +++ b/osu.Game/Migrations/20180125143340_Settings.cs @@ -0,0 +1,57 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace osu.Game.Migrations +{ + public partial class Settings : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_KeyBinding_Variant", + table: "KeyBinding"); + + migrationBuilder.CreateTable( + name: "Settings", + columns: table => new + { + ID = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Key = table.Column(type: "INTEGER", nullable: false), + RulesetID = table.Column(type: "INTEGER", nullable: true), + Value = table.Column(type: "TEXT", nullable: true), + Variant = table.Column(type: "INTEGER", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Settings", x => x.ID); + }); + + migrationBuilder.CreateIndex( + name: "IX_KeyBinding_RulesetID_Variant", + table: "KeyBinding", + columns: new[] { "RulesetID", "Variant" }); + + migrationBuilder.CreateIndex( + name: "IX_Settings_RulesetID_Variant", + table: "Settings", + columns: new[] { "RulesetID", "Variant" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Settings"); + + migrationBuilder.DropIndex( + name: "IX_KeyBinding_RulesetID_Variant", + table: "KeyBinding"); + + migrationBuilder.CreateIndex( + name: "IX_KeyBinding_Variant", + table: "KeyBinding", + column: "Variant"); + } + } +} diff --git a/osu.Game/Migrations/20180131154205_AddMuteBinding.cs b/osu.Game/Migrations/20180131154205_AddMuteBinding.cs new file mode 100644 index 0000000000..fc1f2fff55 --- /dev/null +++ b/osu.Game/Migrations/20180131154205_AddMuteBinding.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Infrastructure; +using osu.Game.Database; +using osu.Game.Input.Bindings; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20180131154205_AddMuteBinding")] + public partial class AddMuteBinding : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql($"UPDATE KeyBinding SET Action = Action + 1 WHERE RulesetID IS NULL AND Variant IS NULL AND Action >= {(int)GlobalAction.ToggleMute}"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql($"DELETE FROM KeyBinding WHERE RulesetID IS NULL AND Variant IS NULL AND Action = {(int)GlobalAction.ToggleMute}"); + migrationBuilder.Sql($"UPDATE KeyBinding SET Action = Action - 1 WHERE RulesetID IS NULL AND Variant IS NULL AND Action > {(int)GlobalAction.ToggleMute}"); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 937c7b46ef..56632102cd 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -189,6 +189,28 @@ namespace osu.Game.Migrations b.ToTable("BeatmapSetInfo"); }); + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntKey") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => { b.Property("ID") @@ -208,7 +230,7 @@ namespace osu.Game.Migrations b.HasIndex("IntAction"); - b.HasIndex("Variant"); + b.HasIndex("RulesetID", "Variant"); b.ToTable("KeyBinding"); }); diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index daf56657d2..1d657b8664 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -126,6 +126,7 @@ namespace osu.Game.Online.API userReq.Success += u => { LocalUser.Value = u; + Username = LocalUser.Value.Username; failureCount = 0; //we're connected! diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 71b18103b0..ce6f3c7c7d 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Online/API/IOnlineComponent.cs b/osu.Game/Online/API/IOnlineComponent.cs index d213f5a0fc..a3a49b42ae 100644 --- a/osu.Game/Online/API/IOnlineComponent.cs +++ b/osu.Game/Online/API/IOnlineComponent.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Online.API diff --git a/osu.Game/Online/API/OAuth.cs b/osu.Game/Online/API/OAuth.cs index efb83cccc1..df8af7b8dc 100644 --- a/osu.Game/Online/API/OAuth.cs +++ b/osu.Game/Online/API/OAuth.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Diagnostics; diff --git a/osu.Game/Online/API/OAuthToken.cs b/osu.Game/Online/API/OAuthToken.cs index 0c9dc26b59..d2b9703a93 100644 --- a/osu.Game/Online/API/OAuthToken.cs +++ b/osu.Game/Online/API/OAuthToken.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -56,7 +56,6 @@ namespace osu.Game.Online.API } catch { - } return null; } diff --git a/osu.Game/Online/API/Requests/APIResponseBeatmapSet.cs b/osu.Game/Online/API/Requests/APIResponseBeatmapSet.cs index 1b30853421..8f011b4df7 100644 --- a/osu.Game/Online/API/Requests/APIResponseBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/APIResponseBeatmapSet.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index cdcc06a65c..34ebe0c92a 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; diff --git a/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs index 934ef7ffa2..4b6129e015 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs index 1e6ceaafc6..cba1d9471c 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapSetRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/API/Requests/GetFriendsRequest.cs b/osu.Game/Online/API/Requests/GetFriendsRequest.cs new file mode 100644 index 0000000000..5bc3d8e39e --- /dev/null +++ b/osu.Game/Online/API/Requests/GetFriendsRequest.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Game.Users; + +namespace osu.Game.Online.API.Requests +{ + public class GetFriendsRequest : APIRequest> + { + protected override string Target => @"friends"; + } +} diff --git a/osu.Game/Online/API/Requests/GetMessagesRequest.cs b/osu.Game/Online/API/Requests/GetMessagesRequest.cs index 858015e29b..a8f63887a1 100644 --- a/osu.Game/Online/API/Requests/GetMessagesRequest.cs +++ b/osu.Game/Online/API/Requests/GetMessagesRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -32,4 +32,4 @@ namespace osu.Game.Online.API.Requests protected override string Target => @"chat/messages"; } -} \ No newline at end of file +} diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 14605081b6..b726a3767a 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index abb473051f..70468c557a 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Humanizer; diff --git a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs index 431a14085f..3fcbe98b11 100644 --- a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Newtonsoft.Json; diff --git a/osu.Game/Online/API/Requests/GetUserRequest.cs b/osu.Game/Online/API/Requests/GetUserRequest.cs index 2e3e7b01c8..6a586bfe2e 100644 --- a/osu.Game/Online/API/Requests/GetUserRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Users; diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index e30a449978..7bdd1a94b9 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/GetUsersRequest.cs b/osu.Game/Online/API/Requests/GetUsersRequest.cs index 5fb8606e1e..267985a253 100644 --- a/osu.Game/Online/API/Requests/GetUsersRequest.cs +++ b/osu.Game/Online/API/Requests/GetUsersRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/ListChannelsRequest.cs b/osu.Game/Online/API/Requests/ListChannelsRequest.cs index febdf5c1f0..b387af9694 100644 --- a/osu.Game/Online/API/Requests/ListChannelsRequest.cs +++ b/osu.Game/Online/API/Requests/ListChannelsRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Online/API/Requests/PostMessageRequest.cs b/osu.Game/Online/API/Requests/PostMessageRequest.cs index f0c7cb9a9b..e13128cc3c 100644 --- a/osu.Game/Online/API/Requests/PostMessageRequest.cs +++ b/osu.Game/Online/API/Requests/PostMessageRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions; diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index 7d40300907..c54d0ea556 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index 77683ae857..35952fbc6e 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs new file mode 100644 index 0000000000..234781fb52 --- /dev/null +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics.Cursor; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using OpenTK; + +namespace osu.Game.Online.Chat +{ + /// + /// An invisible drawable that brings multiple pieces together to form a consumable clickable link. + /// + public class DrawableLinkCompiler : OsuHoverContainer, IHasTooltip + { + /// + /// Each word part of a chat link (split for word-wrap support). + /// + public List Parts; + + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => Parts.Any(d => d.ReceiveMouseInputAt(screenSpacePos)); + + protected override HoverClickSounds CreateHoverClickSounds(HoverSampleSet sampleSet) => new LinkHoverSounds(sampleSet, Parts); + + public DrawableLinkCompiler(IEnumerable parts) + { + Parts = parts.ToList(); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + IdleColour = colours.Blue; + } + + protected override IEnumerable EffectTargets => Parts; + + public string TooltipText { get; set; } + + private class LinkHoverSounds : HoverClickSounds + { + private readonly List parts; + + public LinkHoverSounds(HoverSampleSet sampleSet, List parts) + : base(sampleSet) + { + this.parts = parts; + } + + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => parts.Any(d => d.ReceiveMouseInputAt(screenSpacePos)); + } + } +} diff --git a/osu.Game/Online/Chat/ErrorMessage.cs b/osu.Game/Online/Chat/ErrorMessage.cs index 0bf18fda39..b083cb6a10 100644 --- a/osu.Game/Online/Chat/ErrorMessage.cs +++ b/osu.Game/Online/Chat/ErrorMessage.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Online.Chat diff --git a/osu.Game/Online/Chat/InfoMessage.cs b/osu.Game/Online/Chat/InfoMessage.cs index edadfe351d..3e521de28d 100644 --- a/osu.Game/Online/Chat/InfoMessage.cs +++ b/osu.Game/Online/Chat/InfoMessage.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Online/Chat/LocalEchoMessage.cs b/osu.Game/Online/Chat/LocalEchoMessage.cs index 079ec58686..1b31fe08d6 100644 --- a/osu.Game/Online/Chat/LocalEchoMessage.cs +++ b/osu.Game/Online/Chat/LocalEchoMessage.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Online.Chat diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index 972e4755c9..df3753da6a 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.ComponentModel; using Newtonsoft.Json; using osu.Game.Users; @@ -40,6 +41,17 @@ namespace osu.Game.Online.Chat { } + /// + /// The text that is displayed in chat. + /// + public string DisplayContent { get; set; } + + /// + /// The links found in this message. + /// + /// The s' and s are according to + public List Links; + public Message(long? id) { Id = id; diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs new file mode 100644 index 0000000000..906f42d50e --- /dev/null +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -0,0 +1,263 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace osu.Game.Online.Chat +{ + public static class MessageFormatter + { + // [[Performance Points]] -> wiki:Performance Points (https://osu.ppy.sh/wiki/Performance_Points) + private static readonly Regex wiki_regex = new Regex(@"\[\[([^\]]+)\]\]"); + + // (test)[https://osu.ppy.sh/b/1234] -> test (https://osu.ppy.sh/b/1234) + private static readonly Regex old_link_regex = new Regex(@"\(([^\)]*)\)\[([a-z]+://[^ ]+)\]"); + + // [https://osu.ppy.sh/b/1234 Beatmap [Hard] (poop)] -> Beatmap [hard] (poop) (https://osu.ppy.sh/b/1234) + private static readonly Regex new_link_regex = new Regex(@"\[([a-z]+://[^ ]+) ([^\[\]]*(((?\[)[^\[\]]*)+((?\])[^\[\]]*)+)*(?(open)(?!)))\]"); + + // [test](https://osu.ppy.sh/b/1234) -> test (https://osu.ppy.sh/b/1234) aka correct markdown format + private static readonly Regex markdown_link_regex = new Regex(@"\[([^\]]*)\]\(([a-z]+://[^ ]+)\)"); + + // advanced, RFC-compatible regular expression that matches any possible URL, *but* allows certain invalid characters that are widely used + // This is in the format (, [optional]): + // http[s]://.[:port][/path][?query][#fragment] + private static readonly Regex advanced_link_regex = new Regex( + // protocol + @"(?[a-z]*?:\/\/" + + // domain + tld + @"(?(?:[a-z0-9]\.|[a-z0-9][a-z0-9-]*[a-z0-9]\.)*[a-z0-9-]*[a-z0-9]" + + // port (optional) + @"(?::\d+)?)" + + // path (optional) + @"(?(?:(?:\/+(?:[a-z0-9$_\.\+!\*\',;:\(\)@&~=-]|%[0-9a-f]{2})*)*" + + // query (optional) + @"(?:\?(?:[a-z0-9$_\+!\*\',;:\(\)@&=\/~-]|%[0-9a-f]{2})*)?)?" + + // fragment (optional) + @"(?:#(?:[a-z0-9$_\+!\*\',;:\(\)@&=\/~-]|%[0-9a-f]{2})*)?)?)", + RegexOptions.IgnoreCase); + + // 00:00:000 (1,2,3) - test + private static readonly Regex time_regex = new Regex(@"\d\d:\d\d:\d\d\d? [^-]*"); + + // #osu + private static readonly Regex channel_regex = new Regex(@"(#[a-zA-Z]+[a-zA-Z0-9]+)"); + + // Unicode emojis + private static readonly Regex emoji_regex = new Regex(@"(\uD83D[\uDC00-\uDE4F])"); + + private static void handleMatches(Regex regex, string display, string link, MessageFormatterResult result, int startIndex = 0, LinkAction? linkActionOverride = null) + { + int captureOffset = 0; + foreach (Match m in regex.Matches(result.Text, startIndex)) + { + var index = m.Index - captureOffset; + + var displayText = string.Format(display, + m.Groups[0], + m.Groups.Count > 1 ? m.Groups[1].Value : "", + m.Groups.Count > 2 ? m.Groups[2].Value : "").Trim(); + + var linkText = string.Format(link, + m.Groups[0], + m.Groups.Count > 1 ? m.Groups[1].Value : "", + m.Groups.Count > 2 ? m.Groups[2].Value : "").Trim(); + + if (displayText.Length == 0 || linkText.Length == 0) continue; + + // Check for encapsulated links + if (result.Links.Find(l => l.Index <= index && l.Index + l.Length >= index + m.Length || index <= l.Index && index + m.Length >= l.Index + l.Length) == null) + { + result.Text = result.Text.Remove(index, m.Length).Insert(index, displayText); + + //since we just changed the line display text, offset any already processed links. + result.Links.ForEach(l => l.Index -= l.Index > index ? m.Length - displayText.Length : 0); + + var details = getLinkDetails(linkText); + result.Links.Add(new Link(linkText, index, displayText.Length, linkActionOverride ?? details.Action, details.Argument)); + + //adjust the offset for processing the current matches group. + captureOffset += m.Length - displayText.Length; + } + } + } + + private static void handleAdvanced(Regex regex, MessageFormatterResult result, int startIndex = 0) + { + foreach (Match m in regex.Matches(result.Text, startIndex)) + { + var index = m.Index; + var link = m.Groups["link"].Value; + var indexLength = link.Length; + + var details = getLinkDetails(link); + result.Links.Add(new Link(link, index, indexLength, details.Action, details.Argument)); + } + } + + private static LinkDetails getLinkDetails(string url) + { + var args = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + args[0] = args[0].TrimEnd(':'); + + switch (args[0]) + { + case "http": + case "https": + // length > 3 since all these links need another argument to work + if (args.Length > 3 && (args[1] == "osu.ppy.sh" || args[1] == "new.ppy.sh")) + { + switch (args[2]) + { + case "b": + case "beatmaps": + return new LinkDetails(LinkAction.OpenBeatmap, args[3]); + case "s": + case "beatmapsets": + case "d": + return new LinkDetails(LinkAction.OpenBeatmapSet, args[3]); + } + } + + return new LinkDetails(LinkAction.External, null); + case "osu": + // every internal link also needs some kind of argument + if (args.Length < 3) + return new LinkDetails(LinkAction.External, null); + + LinkAction linkType; + switch (args[1]) + { + case "chan": + linkType = LinkAction.OpenChannel; + break; + case "edit": + linkType = LinkAction.OpenEditorTimestamp; + break; + case "b": + linkType = LinkAction.OpenBeatmap; + break; + case "s": + case "dl": + linkType = LinkAction.OpenBeatmapSet; + break; + case "spectate": + linkType = LinkAction.Spectate; + break; + default: + linkType = LinkAction.External; + break; + } + + return new LinkDetails(linkType, args[2]); + case "osump": + return new LinkDetails(LinkAction.JoinMultiplayerMatch, args[1]); + default: + return new LinkDetails(LinkAction.External, null); + } + } + + private static MessageFormatterResult format(string toFormat, int startIndex = 0, int space = 3) + { + var result = new MessageFormatterResult(toFormat); + + // handle the [link display] format + handleMatches(new_link_regex, "{2}", "{1}", result, startIndex); + + // handle the standard markdown []() format + handleMatches(markdown_link_regex, "{1}", "{2}", result, startIndex); + + // handle the ()[] link format + handleMatches(old_link_regex, "{1}", "{2}", result, startIndex); + + // handle wiki links + handleMatches(wiki_regex, "{1}", "https://osu.ppy.sh/wiki/{1}", result, startIndex); + + // handle bare links + handleAdvanced(advanced_link_regex, result, startIndex); + + // handle editor times + handleMatches(time_regex, "{0}", "osu://edit/{0}", result, startIndex, LinkAction.OpenEditorTimestamp); + + // handle channels + handleMatches(channel_regex, "{0}", "osu://chan/{0}", result, startIndex, LinkAction.OpenChannel); + + var empty = ""; + while (space-- > 0) + empty += "\0"; + + handleMatches(emoji_regex, empty, "{0}", result, startIndex); + + return result; + } + + public static Message FormatMessage(Message inputMessage) + { + var result = format(inputMessage.Content); + + inputMessage.DisplayContent = result.Text; + + // Sometimes, regex matches are not in order + result.Links.Sort(); + inputMessage.Links = result.Links; + return inputMessage; + } + + public class MessageFormatterResult + { + public List Links = new List(); + public string Text; + public string OriginalText; + + public MessageFormatterResult(string text) + { + OriginalText = Text = text; + } + } + + public class LinkDetails + { + public LinkAction Action; + public string Argument; + + public LinkDetails(LinkAction action, string argument) + { + Action = action; + Argument = argument; + } + } + } + + public enum LinkAction + { + External, + OpenBeatmap, + OpenBeatmapSet, + OpenChannel, + OpenEditorTimestamp, + JoinMultiplayerMatch, + Spectate, + } + + public class Link : IComparable + { + public string Url; + public int Index; + public int Length; + public LinkAction Action; + public string Argument; + + public Link(string url, int startIndex, int length, LinkAction action, string argument) + { + Url = url; + Index = startIndex; + Length = length; + Action = action; + Argument = argument; + } + + public int CompareTo(Link otherLink) => Index > otherLink.Index ? 1 : -1; + } +} diff --git a/osu.Game/Online/Multiplayer/GameType.cs b/osu.Game/Online/Multiplayer/GameType.cs index 7bec0e94bb..01588b05d3 100644 --- a/osu.Game/Online/Multiplayer/GameType.cs +++ b/osu.Game/Online/Multiplayer/GameType.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index e808f2c3ad..1971f9941c 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; diff --git a/osu.Game/Online/Multiplayer/RoomStatus.cs b/osu.Game/Online/Multiplayer/RoomStatus.cs index 4f943596a7..1d82c8f6a8 100644 --- a/osu.Game/Online/Multiplayer/RoomStatus.cs +++ b/osu.Game/Online/Multiplayer/RoomStatus.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 257b78ea0a..624179cfe1 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using osu.Framework.Configuration; using osu.Framework.Screens; using osu.Game.Configuration; @@ -18,6 +19,7 @@ using OpenTK; using System.Linq; using System.Threading; using System.Threading.Tasks; +using osu.Framework.Audio; using osu.Framework.Input.Bindings; using osu.Framework.Platform; using osu.Framework.Threading; @@ -27,6 +29,7 @@ using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; using osu.Game.Screens.Play; using osu.Game.Input.Bindings; +using osu.Game.Rulesets.Mods; using OpenTK.Graphics; namespace osu.Game @@ -71,6 +74,7 @@ namespace osu.Game private OsuScreen screenStack; private VolumeControl volume; + private OnScreenDisplay onscreenDisplay; private Bindable configRuleset; public Bindable Ruleset = new Bindable(); @@ -79,6 +83,9 @@ namespace osu.Game private SettingsOverlay settings; + // todo: move this to SongSelect once Screen has the ability to unsuspend. + public readonly Bindable> SelectedMods = new Bindable>(new List()); + public OsuGame(string[] args = null) { this.args = args; @@ -110,15 +117,29 @@ namespace osu.Game Task.Run(() => BeatmapManager.Import(paths.ToArray())); } - dependencies.Cache(this); + dependencies.CacheAs(this); configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); Ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First(); Ruleset.ValueChanged += r => configRuleset.Value = r.ID ?? 0; + + LocalConfig.BindWith(OsuSetting.VolumeInactive, inactiveVolumeAdjust); } private ScheduledDelegate scoreLoad; + /// + /// Open chat to a channel matching the provided name, if present. + /// + /// The name of the channel. + public void OpenChannel(string channelName) => chat.OpenChannel(chat.AvailableChannels.Find(c => c.Name == channelName)); + + /// + /// Show a beatmap set as an overlay. + /// + /// The set to display. + public void ShowBeatmapSet(int setId) => beatmapSetOverlay.ShowBeatmapSet(setId); + protected void LoadScore(Score s) { scoreLoad?.Cancel(); @@ -157,6 +178,11 @@ namespace osu.Game { base.LoadComplete(); + // The next time this is updated is in UpdateAfterChildren, which occurs too late and results + // in the cursor being shown for a few frames during the intro. + // This prevents the cursor from showing until we have a screen with CursorVisible = true + CursorOverrideContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; + // hook up notifications to components. BeatmapManager.PostNotification = n => notifications?.Post(n); BeatmapManager.GetStableStorage = GetStorageForStableInstall; @@ -190,7 +216,7 @@ namespace osu.Game }, overlayContent.Add); loadComponentSingleFile(volume = new VolumeControl(), Add); - loadComponentSingleFile(new OnScreenDisplay(), Add); + loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add); //overlay elements loadComponentSingleFile(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); @@ -227,6 +253,7 @@ namespace osu.Game forwardLoggedErrorsToNotifications(); dependencies.Cache(settings); + dependencies.Cache(onscreenDisplay); dependencies.Cache(social); dependencies.Cache(direct); dependencies.Cache(chat); @@ -297,8 +324,6 @@ namespace osu.Game else Toolbar.State = Visibility.Visible; }; - - Cursor.State = Visibility.Hidden; } private void forwardLoggedErrorsToNotifications() @@ -388,6 +413,20 @@ namespace osu.Game return false; } + private readonly BindableDouble inactiveVolumeAdjust = new BindableDouble(); + + protected override void OnDeactivated() + { + base.OnDeactivated(); + Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeAdjust); + } + + protected override void OnActivated() + { + base.OnActivated(); + Audio.RemoveAdjustment(AdjustableProperty.Volume, inactiveVolumeAdjust); + } + public bool OnReleased(GlobalAction action) => false; private Container mainContent; @@ -447,7 +486,7 @@ namespace osu.Game mainContent.Padding = new MarginPadding { Top = ToolbarOffset }; - Cursor.State = currentScreen?.HasLocalCursorDisplayed == false ? Visibility.Visible : Visibility.Hidden; + CursorOverrideContainer.CanShowCursor = currentScreen?.CursorVisible ?? false; } private void screenAdded(Screen newScreen) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index e311aea8e4..937b204c81 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -44,6 +44,10 @@ namespace osu.Game protected KeyBindingStore KeyBindingStore; + protected SettingsStore SettingsStore; + + protected CursorOverrideContainer CursorOverrideContainer; + protected override string MainResourceFile => @"osu.Game.Resources.dll"; public APIAccess API; @@ -52,8 +56,6 @@ namespace osu.Game protected override Container Content => content; - protected MenuCursor Cursor; - public Bindable Beatmap { get; private set; } private Bindable fpsDisplayVisible; @@ -93,7 +95,7 @@ namespace osu.Game dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore(Resources, @"Textures")))); - dependencies.Cache(this); + dependencies.CacheAs(this); dependencies.Cache(LocalConfig); runMigrations(); @@ -109,10 +111,11 @@ namespace osu.Game dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory.GetContext, RulesetStore, API, Host)); dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, contextFactory.GetContext, Host, BeatmapManager, RulesetStore)); dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory.GetContext, RulesetStore)); + dependencies.Cache(SettingsStore = new SettingsStore(contextFactory.GetContext)); dependencies.Cache(new OsuColour()); //this completely overrides the framework default. will need to change once we make a proper FontStore. - dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 }, true); + dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 }); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont")); @@ -209,23 +212,16 @@ namespace osu.Game { base.LoadComplete(); - GlobalKeyBindingInputManager globalBinding; + GlobalActionContainer globalBinding; - base.Content.Add(new DrawSizePreservingFillContainer + CursorOverrideContainer = new CursorOverrideContainer { RelativeSizeAxes = Axes.Both }; + CursorOverrideContainer.Child = globalBinding = new GlobalActionContainer(this) { - Children = new Drawable[] - { - Cursor = new MenuCursor(), - globalBinding = new GlobalKeyBindingInputManager(this) - { - RelativeSizeAxes = Axes.Both, - Child = content = new OsuTooltipContainer(Cursor) - { - RelativeSizeAxes = Axes.Both, - } - } - } - }); + RelativeSizeAxes = Axes.Both, + Child = content = new OsuTooltipContainer(CursorOverrideContainer.Cursor) { RelativeSizeAxes = Axes.Both } + }; + + base.Content.Add(new DrawSizePreservingFillContainer { Child = CursorOverrideContainer }); KeyBindingStore.Register(globalBinding); dependencies.Cache(globalBinding); diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 46ee5a9cdb..eec69214de 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 3ecff85bee..1b8fff36ec 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 2317e8562a..b09e151ebc 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 128ea7d2d3..7f052f443f 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/BeatmapSet/DownloadButton.cs b/osu.Game/Overlays/BeatmapSet/DownloadButton.cs index 47787d2ced..9691036b87 100644 --- a/osu.Game/Overlays/BeatmapSet/DownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/DownloadButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/FavouriteButton.cs index 1b22853656..51492fff44 100644 --- a/osu.Game/Overlays/BeatmapSet/FavouriteButton.cs +++ b/osu.Game/Overlays/BeatmapSet/FavouriteButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 4135aef268..36b6a9964a 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/BeatmapSet/HeaderButton.cs b/osu.Game/Overlays/BeatmapSet/HeaderButton.cs index ac5683de00..f859c8f692 100644 --- a/osu.Game/Overlays/BeatmapSet/HeaderButton.cs +++ b/osu.Game/Overlays/BeatmapSet/HeaderButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index b4aea898b2..a0b6d9cefa 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/BeatmapSet/PreviewButton.cs b/osu.Game/Overlays/BeatmapSet/PreviewButton.cs index 52edd1714f..4f5a6ba718 100644 --- a/osu.Game/Overlays/BeatmapSet/PreviewButton.cs +++ b/osu.Game/Overlays/BeatmapSet/PreviewButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -82,7 +82,8 @@ namespace osu.Game.Overlays.BeatmapSet if (Playing.Value && preview != null) { - progress.Width = (float)(preview.CurrentTime / preview.Length); + // prevent negative (potential infinite) width if a track without length was loaded + progress.Width = preview.Length > 0 ? (float)(preview.CurrentTime / preview.Length) : 0f; } } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs index bbb4ef767c..826a7c53f3 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ClickableUsername.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs index 2d5913d8ca..7ef86d349a 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableScore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index e3b878587d..66d7a9e4e1 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 4b496ed118..b6efd3b3b0 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index 6df31b9f85..bee1e9284b 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/BeatmapSetOverlay.cs b/osu.Game/Overlays/BeatmapSetOverlay.cs index 0a88f586b5..f0f8a6ef10 100644 --- a/osu.Game/Overlays/BeatmapSetOverlay.cs +++ b/osu.Game/Overlays/BeatmapSetOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Chat/ChannelListItem.cs b/osu.Game/Overlays/Chat/ChannelListItem.cs index f4cf806044..19418c63a8 100644 --- a/osu.Game/Overlays/Chat/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/ChannelListItem.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/Chat/ChannelSection.cs b/osu.Game/Overlays/Chat/ChannelSection.cs index 5068b415bc..132891bcc0 100644 --- a/osu.Game/Overlays/Chat/ChannelSection.cs +++ b/osu.Game/Overlays/Chat/ChannelSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs index 4362b3f787..3684c47e40 100644 --- a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 32f933ff42..dd41dd5428 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -1,6 +1,7 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -82,16 +83,18 @@ namespace osu.Game.Overlays.Chat private Message message; private OsuSpriteText username; - private OsuTextFlowContainer contentFlow; + private LinkFlowContainer contentFlow; + + public LinkFlowContainer ContentFlow => contentFlow; public Message Message { - get { return message; } + get => message; set { if (message == value) return; - message = value; + message = MessageFormatter.FormatMessage(value); if (!IsLoaded) return; @@ -101,8 +104,9 @@ namespace osu.Game.Overlays.Chat } [BackgroundDependencyLoader(true)] - private void load(OsuColour colours) + private void load(OsuColour colours, ChatOverlay chat) { + this.chat = chat; customUsernameColour = colours.ChatBlue; } @@ -187,7 +191,18 @@ namespace osu.Game.Overlays.Chat Padding = new MarginPadding { Left = message_padding + padding }, Children = new Drawable[] { - contentFlow = new OsuTextFlowContainer(t => { t.TextSize = text_size; }) + contentFlow = new LinkFlowContainer(t => + { + if (Message.IsAction) + { + t.Font = @"Exo2.0-MediumItalic"; + + if (senderHasBackground) + t.Colour = OsuColour.FromHex(message.Sender.Colour); + } + + t.TextSize = text_size; + }) { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, @@ -195,31 +210,26 @@ namespace osu.Game.Overlays.Chat } } }; - if (message.IsAction && senderHasBackground) - contentFlow.Colour = OsuColour.FromHex(message.Sender.Colour); updateMessageContent(); FinishTransforms(true); } + private ChatOverlay chat; + private void updateMessageContent() { this.FadeTo(message is LocalEchoMessage ? 0.4f : 1.0f, 500, Easing.OutQuint); timestamp.FadeTo(message is LocalEchoMessage ? 0 : 1, 500, Easing.OutQuint); timestamp.Text = $@"{message.Timestamp.LocalDateTime:HH:mm:ss}"; - username.Text = $@"{message.Sender.Username}" + (senderHasBackground ? "" : ":"); + username.Text = $@"{message.Sender.Username}" + (senderHasBackground || message.IsAction ? "" : ":"); - if (message.IsAction) - { - contentFlow.Clear(); - contentFlow.AddText("[", sprite => sprite.Padding = new MarginPadding { Right = action_padding }); - contentFlow.AddText(message.Content, sprite => sprite.Font = @"Exo2.0-MediumItalic"); - contentFlow.AddText("]", sprite => sprite.Padding = new MarginPadding { Left = action_padding }); - } - else - contentFlow.Text = message.Content; + // remove non-existent channels from the link list + message.Links.RemoveAll(link => link.Action == LinkAction.OpenChannel && chat?.AvailableChannels.Any(c => c.Name == link.Argument) != true); + contentFlow.Clear(); + contentFlow.AddLinks(message.DisplayContent, message.Links); } private class MessageSender : OsuClickableContainer, IHasContextMenu diff --git a/osu.Game/Overlays/Chat/ChatTabControl.cs b/osu.Game/Overlays/Chat/ChatTabControl.cs index f58ee8f819..f028590bb4 100644 --- a/osu.Game/Overlays/Chat/ChatTabControl.cs +++ b/osu.Game/Overlays/Chat/ChatTabControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Chat/DrawableChannel.cs b/osu.Game/Overlays/Chat/DrawableChannel.cs index 7179d8ed90..d12df70b74 100644 --- a/osu.Game/Overlays/Chat/DrawableChannel.cs +++ b/osu.Game/Overlays/Chat/DrawableChannel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 20c1cf9332..b973640837 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -60,6 +60,7 @@ namespace osu.Game.Overlays public Bindable ChatHeight { get; set; } + public List AvailableChannels { get; private set; } = new List(); private readonly Container channelSelectionContainer; private readonly ChannelSelectionOverlay channelSelection; @@ -190,6 +191,8 @@ namespace osu.Game.Overlays private double startDragChatHeight; private bool isDragging; + public void OpenChannel(Channel channel) => addChannel(channel); + protected override bool OnDragStart(InputState state) { isDragging = tabsArea.IsHovered; @@ -299,6 +302,8 @@ namespace osu.Game.Overlays ListChannelsRequest req = new ListChannelsRequest(); req.Success += delegate (List channels) { + AvailableChannels = channels; + Scheduler.Add(delegate { addChannel(channels.Find(c => c.Name == @"#lazer")); diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index d2bd50cad6..790c097789 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Overlays/Dialog/PopupDialogButton.cs b/osu.Game/Overlays/Dialog/PopupDialogButton.cs index 5818061402..40200e6417 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs index a17c4a7bf2..38c5ea34c5 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogCancelButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs b/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs index 3d99987080..fb21ffc00a 100644 --- a/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs +++ b/osu.Game/Overlays/Dialog/PopupDialogOkButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index 7853eefd2c..ef4d2bdc00 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index a40f20850e..2cc51f9e4c 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index 3a1004fd44..403eeb7e10 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 5980cde5fd..e0d806c90f 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -16,7 +16,6 @@ using osu.Game.Graphics.Sprites; using OpenTK.Graphics; using osu.Framework.Input; using osu.Game.Graphics.UserInterface; -using osu.Framework.Logging; using osu.Game.Online.API.Requests; using osu.Framework.Configuration; using osu.Framework.Audio.Track; @@ -65,12 +64,14 @@ namespace osu.Game.Overlays.Direct Colour = Color4.Black.Opacity(0.3f), }; + private OsuColour colours; [BackgroundDependencyLoader(permitNulls: true)] private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay) { this.beatmaps = beatmaps; this.beatmapSetOverlay = beatmapSetOverlay; + this.colours = colours; AddInternal(content = new Container { @@ -107,6 +108,8 @@ namespace osu.Game.Overlays.Direct beatmaps.BeatmapDownloadBegan += attachDownload; } + public override bool DisposeOnDeathRemoval => true; + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); @@ -181,7 +184,6 @@ namespace osu.Game.Overlays.Direct { progressBar.Current.Value = 0; progressBar.FadeOut(500); - Logger.Error(e, "Failed to get beatmap download information"); }; request.DownloadProgressed += progress => progressBar.Current.Value = progress; @@ -189,7 +191,7 @@ namespace osu.Game.Overlays.Direct request.Success += data => { progressBar.Current.Value = 1; - progressBar.FadeOut(500); + progressBar.FillColour = colours.Yellow; }; } diff --git a/osu.Game/Overlays/Direct/DownloadButton.cs b/osu.Game/Overlays/Direct/DownloadButton.cs index 28f5344eae..2b29b9c5f9 100644 --- a/osu.Game/Overlays/Direct/DownloadButton.cs +++ b/osu.Game/Overlays/Direct/DownloadButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -50,4 +50,4 @@ namespace osu.Game.Overlays.Direct icon.ScaleTo(1f, 500, Easing.OutElastic); } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs index 46ba000a28..84a09547aa 100644 --- a/osu.Game/Overlays/Direct/FilterControl.cs +++ b/osu.Game/Overlays/Direct/FilterControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Direct/Header.cs b/osu.Game/Overlays/Direct/Header.cs index 77743a3a4b..2245f70ed3 100644 --- a/osu.Game/Overlays/Direct/Header.cs +++ b/osu.Game/Overlays/Direct/Header.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 75a3358d51..1d67bc2d90 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; @@ -9,6 +9,7 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; +using osu.Framework.IO.Stores; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; @@ -39,6 +40,8 @@ namespace osu.Game.Overlays.Direct private readonly SpriteIcon icon; private readonly LoadingAnimation loadingAnimation; + private readonly BindableDouble muteBindable = new BindableDouble(); + private const float transition_duration = 500; private bool loading @@ -83,9 +86,10 @@ namespace osu.Game.Overlays.Direct } [BackgroundDependencyLoader] - private void load(OsuColour colour) + private void load(OsuColour colour, AudioManager audio) { hoverColour = colour.Yellow; + this.audio = audio; } protected override bool OnClick(InputState state) @@ -128,21 +132,36 @@ namespace osu.Game.Overlays.Direct return; } - Preview.Seek(0); - Preview.Start(); + Preview.Restart(); + + audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable); } else { + audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable); + Preview?.Stop(); loading = false; } } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + Playing.Value = false; + } + private TrackLoader trackLoader; + private AudioManager audio; private void beginAudioLoad() { - if (trackLoader != null) return; + if (trackLoader != null) + { + Preview = trackLoader.Preview; + Playing.TriggerChange(); + return; + } loading = true; @@ -164,6 +183,7 @@ namespace osu.Game.Overlays.Direct private readonly string preview; public Track Preview; + private TrackManager trackManager; public TrackLoader(string preview) { @@ -171,13 +191,22 @@ namespace osu.Game.Overlays.Direct } [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load(AudioManager audio, FrameworkConfigManager config) { + // create a local trackManager to bypass the mute we are applying above. + audio.AddItem(trackManager = new TrackManager(new OnlineStore())); + + // add back the user's music volume setting (since we are no longer in the global TrackManager's hierarchy). + config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume); + if (!string.IsNullOrEmpty(preview)) - { - Preview = audio.Track.Get(preview); - Preview.Volume.Value = 0.5; - } + Preview = trackManager.Get(preview); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + trackManager?.Dispose(); } } } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 7994483043..05b5bba09c 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -298,7 +298,7 @@ namespace osu.Game.Overlays Task.Run(() => { var onlineIds = response.Select(r => r.OnlineBeatmapSetID).ToList(); - var presentOnlineIds = beatmaps.QueryBeatmapSets(s => onlineIds.Contains(s.OnlineBeatmapSetID)).Select(r => r.OnlineBeatmapSetID).ToList(); + var presentOnlineIds = beatmaps.QueryBeatmapSets(s => onlineIds.Contains(s.OnlineBeatmapSetID) && !s.DeletePending).Select(r => r.OnlineBeatmapSetID).ToList(); var sets = response.Select(r => r.ToBeatmapSet(rulesets)).Where(b => !presentOnlineIds.Contains(b.OnlineBeatmapSetID)).ToList(); // may not need scheduling; loads async internally. @@ -313,6 +313,14 @@ namespace osu.Game.Overlays api.Queue(getSetsRequest); } + protected override void PopOut() + { + base.PopOut(); + + if (playing != null) + playing.PreviewPlaying.Value = false; + } + private int distinctCount(List list) => list.Distinct().ToArray().Length; public class ResultCounts diff --git a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs index 4a7e4f4e6e..a4c1621266 100644 --- a/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/GlobalKeyBindingsSection.cs @@ -1,8 +1,8 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Input.Bindings; using osu.Game.Graphics; +using osu.Game.Input.Bindings; using osu.Game.Overlays.Settings; namespace osu.Game.Overlays.KeyBinding @@ -12,20 +12,32 @@ namespace osu.Game.Overlays.KeyBinding public override FontAwesome Icon => FontAwesome.fa_osu_hot; public override string Header => "Global"; - public GlobalKeyBindingsSection(KeyBindingContainer manager) + public GlobalKeyBindingsSection(GlobalActionContainer manager) { Add(new DefaultBindingsSubsection(manager)); + Add(new InGameKeyBindingsSubsection(manager)); } + private class DefaultBindingsSubsection : KeyBindingsSubsection { protected override string Header => string.Empty; - public DefaultBindingsSubsection(KeyBindingContainer manager) + public DefaultBindingsSubsection(GlobalActionContainer manager) : base(null) { - Defaults = manager.DefaultKeyBindings; + Defaults = manager.GlobalKeyBindings; + } + } + + private class InGameKeyBindingsSubsection : KeyBindingsSubsection + { + protected override string Header => "In Game"; + + public InGameKeyBindingsSubsection(GlobalActionContainer manager) : base(null) + { + Defaults = manager.InGameKeyBindings; } } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 509a4f3856..379d25313e 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs index c670cc0153..6cbc926fc3 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingsSubsection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs b/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs index 885e149cb2..c2a4ea8a12 100644 --- a/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs +++ b/osu.Game/Overlays/KeyBinding/RulesetBindingsSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; @@ -24,4 +24,4 @@ namespace osu.Game.Overlays.KeyBinding Add(new VariantBindingsSubsection(ruleset, variant)); } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs index dca5f53b4a..85a587b003 100644 --- a/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs +++ b/osu.Game/Overlays/KeyBinding/VariantBindingsSubsection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets; @@ -21,4 +21,4 @@ namespace osu.Game.Overlays.KeyBinding Defaults = rulesetInstance.GetDefaultKeyBindings(variant); } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/KeyBindingOverlay.cs b/osu.Game/Overlays/KeyBindingOverlay.cs index 4394d0fec0..b311ee68c0 100644 --- a/osu.Game/Overlays/KeyBindingOverlay.cs +++ b/osu.Game/Overlays/KeyBindingOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -15,7 +15,7 @@ namespace osu.Game.Overlays protected override Drawable CreateHeader() => new SettingsHeader("key configuration", "Customise your keys!"); [BackgroundDependencyLoader(permitNulls: true)] - private void load(RulesetStore rulesets, GlobalKeyBindingInputManager global) + private void load(RulesetStore rulesets, GlobalActionContainer global) { AddSection(new GlobalKeyBindingsSection(global)); @@ -28,4 +28,4 @@ namespace osu.Game.Overlays { } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index fe3a846eb2..cc784d954d 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/MainSettings.cs b/osu.Game/Overlays/MainSettings.cs index 4fe86d62fd..be822f9b06 100644 --- a/osu.Game/Overlays/MainSettings.cs +++ b/osu.Game/Overlays/MainSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 776f2ffadb..bd6adffdc7 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index c6be428987..8edfdf9d95 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -183,8 +183,6 @@ namespace osu.Game.Overlays.MedalSplash description.FadeInFromZero(duration * 2); break; } - - } } diff --git a/osu.Game/Overlays/Mods/AssistedSection.cs b/osu.Game/Overlays/Mods/AssistedSection.cs index b3cbb410e4..978b12da19 100644 --- a/osu.Game/Overlays/Mods/AssistedSection.cs +++ b/osu.Game/Overlays/Mods/AssistedSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Input; diff --git a/osu.Game/Overlays/Mods/DifficultyIncreaseSection.cs b/osu.Game/Overlays/Mods/DifficultyIncreaseSection.cs index fc759eb7d9..cbf67893a9 100644 --- a/osu.Game/Overlays/Mods/DifficultyIncreaseSection.cs +++ b/osu.Game/Overlays/Mods/DifficultyIncreaseSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Input; diff --git a/osu.Game/Overlays/Mods/DifficultyReductionSection.cs b/osu.Game/Overlays/Mods/DifficultyReductionSection.cs index dd3b5965f3..c44af8fc4d 100644 --- a/osu.Game/Overlays/Mods/DifficultyReductionSection.cs +++ b/osu.Game/Overlays/Mods/DifficultyReductionSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Input; diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index 21f07bb0a4..91063bfa38 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -188,17 +188,19 @@ namespace osu.Game.Overlays.Mods start = Mods.Length - 1; for (int i = start; i < Mods.Length && i >= 0; i += direction) - { - if (Mods[i].HasImplementation) - { - changeSelectedIndex(i); - return; - } - } + if (SelectAt(i)) return; Deselect(); } + public bool SelectAt(int index) + { + if (!Mods[index].HasImplementation) return false; + + changeSelectedIndex(index); + return true; + } + public void Deselect() => changeSelectedIndex(-1); private void displayMod(Mod mod) diff --git a/osu.Game/Overlays/Mods/ModButtonEmpty.cs b/osu.Game/Overlays/Mods/ModButtonEmpty.cs index f776c174d2..e9e2683816 100644 --- a/osu.Game/Overlays/Mods/ModButtonEmpty.cs +++ b/osu.Game/Overlays/Mods/ModButtonEmpty.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 50310d1b27..03c1f0468c 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -113,6 +113,23 @@ namespace osu.Game.Overlays.Mods } } + /// + /// Select one or more mods in this section. + /// + /// The types of s which should be deselected. + public void SelectTypes(IEnumerable mods) + { + foreach (var button in buttons) + { + for (int i = 0; i < button.Mods.Length; i++) + { + foreach (var mod in mods) + if (mod.GetType().IsInstanceOfType(button.Mods[i])) + button.SelectAt(i); + } + } + } + protected ModSection() { AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index cc5a17358d..d7268fb186 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -51,6 +51,8 @@ namespace osu.Game.Overlays.Mods [BackgroundDependencyLoader(permitNulls: true)] private void load(OsuColour colours, OsuGame osu, RulesetStore rulesets) { + SelectedMods.ValueChanged += selectedModsChanged; + LowMultiplierColour = colours.Red; HighMultiplierColour = colours.Green; @@ -63,6 +65,37 @@ namespace osu.Game.Overlays.Mods Ruleset.TriggerChange(); } + private void selectedModsChanged(IEnumerable obj) + { + foreach (ModSection section in ModSectionsContainer.Children) + section.SelectTypes(obj); + + updateMods(); + } + + private void updateMods() + { + double multiplier = 1.0; + bool ranked = true; + + foreach (Mod mod in SelectedMods.Value) + { + multiplier *= mod.ScoreMultiplier; + ranked &= mod.Ranked; + } + + MultiplierLabel.Text = $"{multiplier:N2}x"; + if (!ranked) + MultiplierLabel.Text += " (Unranked)"; + + if (multiplier > 1.0) + MultiplierLabel.FadeColour(HighMultiplierColour, 200); + else if (multiplier < 1.0) + MultiplierLabel.FadeColour(LowMultiplierColour, 200); + else + MultiplierLabel.FadeColour(Color4.White, 200); + } + protected override void PopOut() { base.PopOut(); @@ -97,6 +130,7 @@ namespace osu.Game.Overlays.Mods { foreach (ModSection section in ModSectionsContainer.Children) section.DeselectAll(); + refreshSelectedMods(); } @@ -119,30 +153,7 @@ namespace osu.Game.Overlays.Mods refreshSelectedMods(); } - private void refreshSelectedMods() - { - SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray(); - - double multiplier = 1.0; - bool ranked = true; - - foreach (Mod mod in SelectedMods.Value) - { - multiplier *= mod.ScoreMultiplier; - ranked &= mod.Ranked; - } - - MultiplierLabel.Text = $"{multiplier:N2}x"; - if (!ranked) - MultiplierLabel.Text += " (Unranked)"; - - if (multiplier > 1.0) - MultiplierLabel.FadeColour(HighMultiplierColour, 200); - else if (multiplier < 1.0) - MultiplierLabel.FadeColour(LowMultiplierColour, 200); - else - MultiplierLabel.FadeColour(Color4.White, 200); - } + private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray(); public ModSelectOverlay() { diff --git a/osu.Game/Overlays/Music/CollectionsDropdown.cs b/osu.Game/Overlays/Music/CollectionsDropdown.cs index 3b11d9f52a..648a00993d 100644 --- a/osu.Game/Overlays/Music/CollectionsDropdown.cs +++ b/osu.Game/Overlays/Music/CollectionsDropdown.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Music/FilterControl.cs b/osu.Game/Overlays/Music/FilterControl.cs index 52d311e501..fa437fc2e8 100644 --- a/osu.Game/Overlays/Music/FilterControl.cs +++ b/osu.Game/Overlays/Music/FilterControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 8168929f9c..34dcc36699 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -148,7 +148,6 @@ namespace osu.Game.Overlays.Music private class PlaylistItemHandle : SpriteIcon { - public PlaylistItemHandle() { Anchor = Anchor.TopLeft; diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 245b2d36ce..31b7d0f9aa 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -230,7 +230,6 @@ namespace osu.Game.Overlays.Music items.ChangeChildDepth(draggedItem, dstIndex); } - private class ItemSearchContainer : FillFlowContainer, IHasFilterableChildren { public IEnumerable FilterTerms => new string[] { }; diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index d913895159..2125984785 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 685fb5c6ab..5f2c21e5d9 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -1,12 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; @@ -20,10 +18,12 @@ using osu.Framework.Localisation; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Overlays.Music; -using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Music; +using OpenTK; +using OpenTK.Graphics; namespace osu.Game.Overlays { @@ -65,6 +65,12 @@ namespace osu.Game.Overlays AlwaysPresent = true; } + protected override bool OnDragStart(InputState state) + { + base.OnDragStart(state); + return true; + } + protected override bool OnDrag(InputState state) { if (base.OnDrag(state)) return true; diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs index 5744e8c189..2f46bb4a71 100644 --- a/osu.Game/Overlays/NotificationOverlay.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs b/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs index 7fba75c4fc..ea2928607f 100644 --- a/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs +++ b/osu.Game/Overlays/Notifications/IHasCompletionTarget.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -9,4 +9,4 @@ namespace osu.Game.Overlays.Notifications { Action CompletionTarget { get; set; } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index dc2dcf2d74..66db57c18f 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index 42fcc3aa0f..13a69fbe3a 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -168,5 +168,4 @@ namespace osu.Game.Overlays.Notifications // the layout portion of this is being tracked as a framework issue (https://github.com/ppy/osu-framework/issues/1297). protected override bool RequiresChildrenUpdate => true; } - } diff --git a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs index d70868046b..df2be95b40 100644 --- a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Framework.Graphics.Colour; - namespace osu.Game.Overlays.Notifications { public class ProgressCompletionNotification : SimpleNotification @@ -21,4 +20,4 @@ namespace osu.Game.Overlays.Notifications IconBackgound.Colour = ColourInfo.GradientVertical(colours.GreenDark, colours.GreenLight); } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index d797372390..b36ac6eebc 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -217,7 +217,6 @@ namespace osu.Game.Overlays.Notifications }; } - [BackgroundDependencyLoader] private void load(OsuColour colours) { diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index 1e691e2a5a..c3d5a52476 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index ce0feeb4c6..bbb2c476f4 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -1,11 +1,11 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Configuration; -using osu.Framework.Extensions; +using osu.Framework.Configuration.Tracking; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -22,7 +22,8 @@ namespace osu.Game.Overlays { private readonly Container box; - public override bool HandleInput => false; + public override bool HandleKeyboardInput => false; + public override bool HandleMouseInput => false; private readonly SpriteText textLine1; private readonly SpriteText textLine2; @@ -117,43 +118,62 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load(FrameworkConfigManager frameworkConfig) { - trackSetting(frameworkConfig.GetBindable(FrameworkSetting.FrameSync), v => display(v, "Frame Limiter", v.GetDescription(), "Ctrl+F7")); - trackSetting(frameworkConfig.GetBindable(FrameworkSetting.AudioDevice), v => display(v, "Audio Device", string.IsNullOrEmpty(v) ? "Default" : v, v)); - trackSetting(frameworkConfig.GetBindable(FrameworkSetting.ShowLogOverlay), v => display(v, "Debug Logs", v ? "visible" : "hidden", "Ctrl+F10")); - - Action displayResolution = delegate { display(null, "Screen Resolution", frameworkConfig.Get(FrameworkSetting.Width) + "x" + frameworkConfig.Get(FrameworkSetting.Height)); }; - - trackSetting(frameworkConfig.GetBindable(FrameworkSetting.Width), v => displayResolution()); - trackSetting(frameworkConfig.GetBindable(FrameworkSetting.Height), v => displayResolution()); - - trackSetting(frameworkConfig.GetBindable(FrameworkSetting.CursorSensitivity), v => display(v, "Cursor Sensitivity", v.ToString(@"0.##x"), "Ctrl+Alt+R to reset")); - trackSetting(frameworkConfig.GetBindable(FrameworkSetting.ActiveInputHandlers), - delegate (string v) - { - bool raw = v.Contains("Raw"); - display(raw, "Raw Input", raw ? "enabled" : "disabled", "Ctrl+Alt+R to reset"); - }); - - trackSetting(frameworkConfig.GetBindable(FrameworkSetting.WindowMode), v => display(v, "Screen Mode", v.ToString(), "Alt+Enter")); + BeginTracking(this, frameworkConfig); } - private readonly List references = new List(); + private readonly Dictionary<(object, IConfigManager), TrackedSettings> trackedConfigManagers = new Dictionary<(object, IConfigManager), TrackedSettings>(); - private void trackSetting(Bindable bindable, Bindable.BindableValueChanged action) + /// + /// Registers a to have its settings tracked by this . + /// + /// The object that is registering the to be tracked. + /// The to be tracked. + /// If is null. + /// If is already being tracked from the same . + public void BeginTracking(object source, ITrackableConfigManager configManager) { - // we need to keep references as we bind - references.Add(bindable); + if (configManager == null) throw new ArgumentNullException(nameof(configManager)); - bindable.ValueChanged += action; + if (trackedConfigManagers.ContainsKey((source, configManager))) + throw new InvalidOperationException($"{nameof(configManager)} is already registered."); + + var trackedSettings = configManager.CreateTrackedSettings(); + if (trackedSettings == null) + return; + + configManager.LoadInto(trackedSettings); + trackedSettings.SettingChanged += display; + + trackedConfigManagers.Add((source, configManager), trackedSettings); } - private void display(object rawValue, string settingName, string settingValue, string shortcut = @"") + /// + /// Unregisters a from having its settings tracked by this . + /// + /// The object that registered the to be tracked. + /// The that is being tracked. + /// If is null. + /// If is not being tracked from the same . + public void StopTracking(object source, ITrackableConfigManager configManager) + { + if (configManager == null) throw new ArgumentNullException(nameof(configManager)); + + if (!trackedConfigManagers.TryGetValue((source, configManager), out var existing)) + throw new InvalidOperationException($"{nameof(configManager)} is not registered."); + + existing.Unload(); + existing.SettingChanged -= display; + + trackedConfigManagers.Remove((source, configManager)); + } + + private void display(SettingDescription description) { Schedule(() => { - textLine1.Text = settingName.ToUpper(); - textLine2.Text = settingValue; - textLine3.Text = shortcut.ToUpper(); + textLine1.Text = description.Name.ToUpper(); + textLine2.Text = description.Value; + textLine3.Text = description.Shortcut.ToUpper(); box.Animate( b => b.FadeIn(500, Easing.OutQuint), @@ -166,16 +186,16 @@ namespace osu.Game.Overlays int optionCount = 0; int selectedOption = -1; - if (rawValue is bool) + if (description.RawValue is bool) { optionCount = 1; - if ((bool)rawValue) selectedOption = 0; + if ((bool)description.RawValue) selectedOption = 0; } - else if (rawValue is Enum) + else if (description.RawValue is Enum) { - var values = Enum.GetValues(rawValue.GetType()); + var values = Enum.GetValues(description.RawValue.GetType()); optionCount = values.Length; - selectedOption = Convert.ToInt32(rawValue); + selectedOption = Convert.ToInt32(description.RawValue); } textLine2.Origin = optionCount > 0 ? Anchor.BottomCentre : Anchor.Centre; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 960bb60287..d085800f41 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Diagnostics; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -9,6 +10,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; @@ -16,9 +18,6 @@ using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Users; -using System.Diagnostics; -using System.Collections.Generic; -using osu.Framework.Graphics.Cursor; namespace osu.Game.Overlays.Profile { @@ -103,7 +102,7 @@ namespace osu.Game.Overlays.Profile Y = -75, Size = new Vector2(25, 25) }, - new LinkFlowContainer.ProfileLink(user) + new ProfileLink(user) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -319,22 +318,24 @@ namespace osu.Game.Overlays.Profile colourBar.Show(); } - Action boldItalic = t => + void boldItalic(SpriteText t) { t.Font = @"Exo2.0-BoldItalic"; t.Alpha = 1; - }; + } if (user.Age != null) { infoTextLeft.AddText($"{user.Age} years old ", boldItalic); } + if (user.Country != null) { infoTextLeft.AddText("from "); infoTextLeft.AddText(user.Country.FullName, boldItalic); countryFlag.Country = user.Country; } + infoTextLeft.NewParagraph(); if (user.JoinDate.ToUniversalTime().Year < 2008) @@ -346,6 +347,7 @@ namespace osu.Game.Overlays.Profile infoTextLeft.AddText("Joined "); infoTextLeft.AddText(user.JoinDate.LocalDateTime.ToShortDateString(), boldItalic); } + infoTextLeft.NewLine(); infoTextLeft.AddText("Last seen "); infoTextLeft.AddText(user.LastVisit.LocalDateTime.ToShortDateString(), boldItalic); @@ -394,16 +396,17 @@ namespace osu.Game.Overlays.Profile scoreText.Add(createScoreText("Replays Watched by Others")); scoreNumberText.Add(createScoreNumberText(user.Statistics.ReplaysWatched.ToString(@"#,0"))); + gradeSSPlus.DisplayCount = user.Statistics.GradesCount.SSPlus; + gradeSSPlus.Show(); gradeSS.DisplayCount = user.Statistics.GradesCount.SS; gradeSS.Show(); + gradeSPlus.DisplayCount = user.Statistics.GradesCount.SPlus; + gradeSPlus.Show(); gradeS.DisplayCount = user.Statistics.GradesCount.S; gradeS.Show(); gradeA.DisplayCount = user.Statistics.GradesCount.A; gradeA.Show(); - gradeSPlus.DisplayCount = 0; - gradeSSPlus.DisplayCount = 0; - rankGraph.User.Value = user; } } @@ -430,10 +433,38 @@ namespace osu.Game.Overlays.Profile if (string.IsNullOrEmpty(str)) return; infoTextRight.AddIcon(icon); - infoTextRight.AddLink(" " + str, url); + if (url != null) + { + infoTextRight.AddLink(" " + str, url); + } else + { + infoTextRight.AddText(" " + str); + } infoTextRight.NewLine(); } + private class ProfileLink : OsuHoverContainer, IHasTooltip + { + public string TooltipText => "View Profile in Browser"; + + public override bool HandleMouseInput => true; + + public ProfileLink(User user) + { + Action = () => Process.Start($@"https://osu.ppy.sh/users/{user.Id}"); + + AutoSizeAxes = Axes.Both; + + Child = new OsuSpriteText + { + Text = user.Username, + Font = @"Exo2.0-RegularItalic", + TextSize = 30, + }; + } + } + + private class GradeBadge : Container { private const float width = 50; @@ -471,59 +502,5 @@ namespace osu.Game.Overlays.Profile badge.Texture = textures.Get($"Grades/{grade}"); } } - - private class LinkFlowContainer : OsuTextFlowContainer - { - public override bool HandleInput => true; - - public LinkFlowContainer(Action defaultCreationParameters = null) : base(defaultCreationParameters) - { - } - - protected override SpriteText CreateSpriteText() => new LinkText(); - - public void AddLink(string text, string url) => AddText(text, link => ((LinkText)link).Url = url); - - public class LinkText : OsuSpriteText - { - private readonly OsuHoverContainer content; - - public override bool HandleInput => content.Action != null; - - protected override Container Content => content ?? (Container)this; - - protected override IEnumerable FlowingChildren => Children; - - public string Url - { - set - { - if (value != null) - content.Action = () => Process.Start(value); - } - } - - public LinkText() - { - AddInternal(content = new OsuHoverContainer - { - AutoSizeAxes = Axes.Both, - }); - } - } - - public class ProfileLink : LinkText, IHasTooltip - { - public string TooltipText => "View Profile in Browser"; - - public ProfileLink(User user) - { - Text = user.Username; - Url = $@"https://osu.ppy.sh/users/{user.Id}"; - Font = @"Exo2.0-RegularItalic"; - TextSize = 30; - } - } - } } } diff --git a/osu.Game/Overlays/Profile/ProfileSection.cs b/osu.Game/Overlays/Profile/ProfileSection.cs index 99178570a6..1c23fa575e 100644 --- a/osu.Game/Overlays/Profile/ProfileSection.cs +++ b/osu.Game/Overlays/Profile/ProfileSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Profile/RankGraph.cs b/osu.Game/Overlays/Profile/RankGraph.cs index d216789b1a..429049c7bc 100644 --- a/osu.Game/Overlays/Profile/RankGraph.cs +++ b/osu.Game/Overlays/Profile/RankGraph.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -105,7 +105,7 @@ namespace osu.Game.Overlays.Profile return; } - int[] userRanks = user.RankHistory?.Data ?? new[] { user.Statistics.Rank }; + int[] userRanks = user.RankHistory?.Data ?? new[] { user.Statistics.Ranks.Global }; ranks = userRanks.Select((x, index) => new KeyValuePair(index, x)).Where(x => x.Value != 0).ToArray(); if (ranks.Length > 1) @@ -124,9 +124,11 @@ namespace osu.Game.Overlays.Profile private void updateRankTexts() { - rankText.Text = User.Value.Statistics.Rank > 0 ? $"#{User.Value.Statistics.Rank:#,0}" : "no rank"; - performanceText.Text = User.Value.Statistics.PP != null ? $"{User.Value.Statistics.PP:#,0}pp" : string.Empty; - relativeText.Text = $"{User.Value.Country?.FullName} #{User.Value.CountryRank:#,0}"; + var user = User.Value; + + performanceText.Text = user.Statistics.PP != null ? $"{user.Statistics.PP:#,0}pp" : string.Empty; + rankText.Text = user.Statistics.Ranks.Global > 0 ? $"#{user.Statistics.Ranks.Global:#,0}" : "no rank"; + relativeText.Text = user.Country != null && user.Statistics.Ranks.Country > 0 ? $"{user.Country.FullName} #{user.Statistics.Ranks.Country:#,0}" : "no rank"; } private void showHistoryRankTexts(int dayIndex) diff --git a/osu.Game/Overlays/Profile/Sections/AboutSection.cs b/osu.Game/Overlays/Profile/Sections/AboutSection.cs index 1d15300eca..5c56355d65 100644 --- a/osu.Game/Overlays/Profile/Sections/AboutSection.cs +++ b/osu.Game/Overlays/Profile/Sections/AboutSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Overlays.Profile.Sections diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index bfd8db5d9c..8a40f0a489 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index 4bfb8107b4..da070d1cc2 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs index 3e88795b77..760054716f 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapsSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Online.API.Requests; diff --git a/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs b/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs index 0607549f20..4956015b3f 100644 --- a/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs +++ b/osu.Game/Overlays/Profile/Sections/DrawableProfileRow.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs index 14ab5d8279..2f8f8aa0ae 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index e54f012faf..176b4bc30a 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs b/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs index ab99abdccd..82b520cf10 100644 --- a/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs +++ b/osu.Game/Overlays/Profile/Sections/HistoricalSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs index aabe3c98de..896ffc33f6 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs index 907c26e5e8..74291c587e 100644 --- a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs +++ b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Overlays.Profile.Sections.Kudosu; diff --git a/osu.Game/Overlays/Profile/Sections/MedalsSection.cs b/osu.Game/Overlays/Profile/Sections/MedalsSection.cs index 47a3e6f4d0..fe5543f264 100644 --- a/osu.Game/Overlays/Profile/Sections/MedalsSection.cs +++ b/osu.Game/Overlays/Profile/Sections/MedalsSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Overlays.Profile.Sections diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs index 1d4045c379..3864002367 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs index c3296dae4f..3b814b0542 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawablePerformanceScore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index e40ce14326..51b202844a 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs index 56b2950f89..61154b2280 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableTotalScore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index 472800860c..8e20953457 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs index 6f050750e4..59b16c0987 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Profile/Sections/RanksSection.cs b/osu.Game/Overlays/Profile/Sections/RanksSection.cs index 7691100d7a..64687284cb 100644 --- a/osu.Game/Overlays/Profile/Sections/RanksSection.cs +++ b/osu.Game/Overlays/Profile/Sections/RanksSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Overlays.Profile.Sections.Ranks; diff --git a/osu.Game/Overlays/Profile/Sections/RecentSection.cs b/osu.Game/Overlays/Profile/Sections/RecentSection.cs index 7bd41eac79..78b139efe8 100644 --- a/osu.Game/Overlays/Profile/Sections/RecentSection.cs +++ b/osu.Game/Overlays/Profile/Sections/RecentSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Overlays.Profile.Sections diff --git a/osu.Game/Overlays/Profile/SupporterIcon.cs b/osu.Game/Overlays/Profile/SupporterIcon.cs index b5cd94e54b..8f89dfe2ea 100644 --- a/osu.Game/Overlays/Profile/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/SupporterIcon.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs index 9fa266c5fe..84d28e95ed 100644 --- a/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs +++ b/osu.Game/Overlays/SearchableList/DisplayStyleControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/SearchableList/HeaderTabControl.cs b/osu.Game/Overlays/SearchableList/HeaderTabControl.cs index 56569fcca5..2dd9d7de29 100644 --- a/osu.Game/Overlays/SearchableList/HeaderTabControl.cs +++ b/osu.Game/Overlays/SearchableList/HeaderTabControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs index 8d7d1ce994..ffc6a370ec 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/SearchableList/SearchableListHeader.cs b/osu.Game/Overlays/SearchableList/SearchableListHeader.cs index 4239a123b8..0f2650ad40 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListHeader.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListHeader.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs index d1d40388e1..3998af05b2 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs b/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs index 2870607519..a528a3c35d 100644 --- a/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs +++ b/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Overlays/Settings/DangerousSettingsButton.cs b/osu.Game/Overlays/Settings/DangerousSettingsButton.cs index 7c324658a3..69c0c03552 100644 --- a/osu.Game/Overlays/Settings/DangerousSettingsButton.cs +++ b/osu.Game/Overlays/Settings/DangerousSettingsButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs index a2f3ad545b..5260fb89d4 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/AudioDevicesSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -70,4 +70,4 @@ namespace osu.Game.Overlays.Settings.Sections.Audio audio.OnLostDevice += onDeviceChanged; } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs index 41a1bad364..ad1eec3c68 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/MainMenuSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs index 4ae127c816..598195333c 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/OffsetSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs index d197f8c466..92ee01dd7a 100644 --- a/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Audio/VolumeSettings.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Graphics; +using osu.Game.Configuration; namespace osu.Game.Overlays.Settings.Sections.Audio { @@ -12,11 +13,12 @@ namespace osu.Game.Overlays.Settings.Sections.Audio protected override string Header => "Volume"; [BackgroundDependencyLoader] - private void load(AudioManager audio) + private void load(AudioManager audio, OsuConfigManager config) { Children = new Drawable[] { new SettingsSlider { LabelText = "Master", Bindable = audio.Volume, KeyboardStep = 0.1f }, + new SettingsSlider { LabelText = "Master (Window Inactive)", Bindable = config.GetBindable(OsuSetting.VolumeInactive), KeyboardStep = 0.1f }, new SettingsSlider { LabelText = "Effect", Bindable = audio.VolumeSample, KeyboardStep = 0.1f }, new SettingsSlider { LabelText = "Music", Bindable = audio.VolumeTrack, KeyboardStep = 0.1f }, }; diff --git a/osu.Game/Overlays/Settings/Sections/AudioSection.cs b/osu.Game/Overlays/Settings/Sections/AudioSection.cs index 738c9e94d7..ad074f6328 100644 --- a/osu.Game/Overlays/Settings/Sections/AudioSection.cs +++ b/osu.Game/Overlays/Settings/Sections/AudioSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs index 23e7433732..9a5946bf4e 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs index c042aeb19b..867410b178 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GeneralSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/DebugSection.cs b/osu.Game/Overlays/Settings/Sections/DebugSection.cs index 05b7171eed..fb4d4f62a8 100644 --- a/osu.Game/Overlays/Settings/Sections/DebugSection.cs +++ b/osu.Game/Overlays/Settings/Sections/DebugSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -21,4 +21,4 @@ namespace osu.Game.Overlays.Settings.Sections }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs index 8ec6af5cd0..b60b0d9531 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/GeneralSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -22,6 +22,12 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay Bindable = config.GetBindable(OsuSetting.DimLevel), KeyboardStep = 0.1f }, + new SettingsSlider + { + LabelText = "Background blur", + Bindable = config.GetBindable(OsuSetting.BlurLevel), + KeyboardStep = 0.1f + }, new SettingsCheckbox { LabelText = "Show score overlay", diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs new file mode 100644 index 0000000000..4e8706137c --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ScrollingSettings.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Configuration; + +namespace osu.Game.Overlays.Settings.Sections.Gameplay +{ + public class ScrollingSettings : SettingsSubsection + { + protected override string Header => "Scrolling"; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + Children = new[] + { + new SettingsEnumDropdown + { + LabelText = "Visualise speed changes as", + Bindable = config.GetBindable(OsuSetting.SpeedChangeVisualisation), + } + }; + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs index 03cd2118b9..4bbd87c7e6 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/SongSelectSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index 035a3c7a13..8a2131fb1c 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -21,6 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections { new GeneralSettings(), new SongSelectSettings(), + new ScrollingSettings() }; } @@ -35,4 +36,4 @@ namespace osu.Game.Overlays.Settings.Sections } } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs index 552b8bea1b..113ef10bad 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LanguageSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index 9e962a64a6..e0f940e14c 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index 3bca0af3af..caee7639e4 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs index 77148986ff..f7dfd9471b 100644 --- a/osu.Game/Overlays/Settings/Sections/GeneralSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GeneralSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index 00e6b8b722..b9d76c05f0 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; using osu.Game.Configuration; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 3d09d6b901..8f775e686a 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs index 7fe5be2fa1..e779538fc8 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs index 8e84a25bb9..7e9ff018c4 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/RendererSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs index 04a9a4d70c..a34a76ff40 100644 --- a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs index 00a1c093fd..49ac650f92 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -21,4 +21,4 @@ namespace osu.Game.Overlays.Settings.Sections.Input }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs index 392bc6f1bd..c368b8fea7 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/MouseSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -33,6 +33,11 @@ namespace osu.Game.Overlays.Settings.Sections.Input LabelText = "Cursor Sensitivity", Bindable = config.GetBindable(FrameworkSetting.CursorSensitivity) }, + new SettingsCheckbox + { + LabelText = "Map absolute input to window", + Bindable = config.GetBindable(FrameworkSetting.MapAbsoluteInputToWindow) + }, new SettingsEnumDropdown { LabelText = "Confine mouse cursor to window", @@ -88,6 +93,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input // this bindable will still act as the "interactive" bindable displayed during a drag. base.Bindable = new BindableDouble(doubleValue.Value) { + Default = doubleValue.Default, MinValue = doubleValue.MinValue, MaxValue = doubleValue.MaxValue }; diff --git a/osu.Game/Overlays/Settings/Sections/InputSection.cs b/osu.Game/Overlays/Settings/Sections/InputSection.cs index 5ece8aad77..ae4167fe52 100644 --- a/osu.Game/Overlays/Settings/Sections/InputSection.cs +++ b/osu.Game/Overlays/Settings/Sections/InputSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs index 8ae520651a..027b5b5aeb 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DeleteAllBeatmapsDialog.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index 9ab4143613..1223310c74 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs index b42c64d324..808b32f881 100644 --- a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs index 4494da1bf4..a002b8516c 100644 --- a/osu.Game/Overlays/Settings/Sections/OnlineSection.cs +++ b/osu.Game/Overlays/Settings/Sections/OnlineSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -18,4 +18,4 @@ namespace osu.Game.Overlays.Settings.Sections }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs index b4475aebb1..f6915896d7 100644 --- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs +++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/SettingsButton.cs b/osu.Game/Overlays/Settings/SettingsButton.cs index 19493f6c70..9fccc6476f 100644 --- a/osu.Game/Overlays/Settings/SettingsButton.cs +++ b/osu.Game/Overlays/Settings/SettingsButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/SettingsCheckbox.cs b/osu.Game/Overlays/Settings/SettingsCheckbox.cs index 659754ce79..773cb04313 100644 --- a/osu.Game/Overlays/Settings/SettingsCheckbox.cs +++ b/osu.Game/Overlays/Settings/SettingsCheckbox.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/SettingsDropdown.cs b/osu.Game/Overlays/Settings/SettingsDropdown.cs index bf2cd10b9d..4356d8a599 100644 --- a/osu.Game/Overlays/Settings/SettingsDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsDropdown.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs index 5725ee8439..d4a5a1a861 100644 --- a/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs +++ b/osu.Game/Overlays/Settings/SettingsEnumDropdown.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index bf417a2fac..b9581bac8a 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -70,4 +70,4 @@ namespace osu.Game.Overlays.Settings }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Settings/SettingsHeader.cs b/osu.Game/Overlays/Settings/SettingsHeader.cs index 80d60b6e5d..7cdd24b48d 100644 --- a/osu.Game/Overlays/Settings/SettingsHeader.cs +++ b/osu.Game/Overlays/Settings/SettingsHeader.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -61,4 +61,4 @@ namespace osu.Game.Overlays.Settings }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index da50c2b444..5afc415d83 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -7,7 +7,6 @@ using OpenTK.Graphics; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; @@ -16,6 +15,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using OpenTK; namespace osu.Game.Overlays.Settings { @@ -33,22 +33,10 @@ namespace osu.Game.Overlays.Settings private SpriteText text; - private readonly RestoreDefaultValueButton restoreDefaultValueButton = new RestoreDefaultValueButton(); + private readonly RestoreDefaultValueButton restoreDefaultButton; public bool ShowsDefaultIndicator = true; - private Color4? restoreDefaultValueColour; - - public Color4 RestoreDefaultValueColour - { - get { return restoreDefaultValueColour ?? Color4.White; } - set - { - restoreDefaultValueColour = value; - restoreDefaultValueButton?.SetButtonColour(RestoreDefaultValueColour); - } - } - public virtual string LabelText { get { return text?.Text ?? string.Empty; } @@ -69,10 +57,7 @@ namespace osu.Game.Overlays.Settings public virtual Bindable Bindable { - get - { - return bindable; - } + get { return bindable; } set { @@ -80,8 +65,8 @@ namespace osu.Game.Overlays.Settings controlWithCurrent?.Current.BindTo(bindable); if (ShowsDefaultIndicator) { - restoreDefaultValueButton.Bindable = bindable.GetBoundCopy(); - restoreDefaultValueButton.Bindable.TriggerChange(); + restoreDefaultButton.Bindable = bindable.GetBoundCopy(); + restoreDefaultButton.Bindable.TriggerChange(); } } } @@ -103,38 +88,30 @@ namespace osu.Game.Overlays.Settings AutoSizeAxes = Axes.Y; Padding = new MarginPadding { Right = SettingsOverlay.CONTENT_MARGINS }; - FlowContent = new FillFlowContainer + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = 5 }, + restoreDefaultButton = new RestoreDefaultValueButton(), + FlowContent = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS }, + Child = Control = CreateControl() + }, }; - - if ((Control = CreateControl()) != null) - { - if (controlWithCurrent != null) - controlWithCurrent.Current.DisabledChanged += disabled => { Colour = disabled ? Color4.Gray : Color4.White; }; - FlowContent.Add(Control); - } } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { - AddInternal(FlowContent); - - if (restoreDefaultValueButton != null) - { - if (!restoreDefaultValueColour.HasValue) - restoreDefaultValueColour = colours.Yellow; - restoreDefaultValueButton.SetButtonColour(RestoreDefaultValueColour); - AddInternal(restoreDefaultValueButton); - } + if (controlWithCurrent != null) + controlWithCurrent.Current.DisabledChanged += disabled => { Colour = disabled ? Color4.Gray : Color4.White; }; } - private class RestoreDefaultValueButton : Box, IHasTooltip + private class RestoreDefaultValueButton : Container, IHasTooltip { private Bindable bindable; + public Bindable Bindable { get { return bindable; } @@ -157,6 +134,36 @@ namespace osu.Game.Overlays.Settings Alpha = 0f; } + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + buttonColour = colour.Yellow; + + Child = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + CornerRadius = 3, + Masking = true, + Colour = buttonColour, + EdgeEffect = new EdgeEffectParameters + { + Colour = buttonColour.Opacity(0.1f), + Type = EdgeEffectType.Glow, + Radius = 2, + }, + Size = new Vector2(0.33f, 0.8f), + Child = new Box { RelativeSizeAxes = Axes.Both }, + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + UpdateState(); + } + public string TooltipText => "Revert to default"; protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; @@ -174,7 +181,7 @@ namespace osu.Game.Overlays.Settings { hovering = true; UpdateState(); - return true; + return false; } protected override void OnHoverLost(InputState state) @@ -193,9 +200,10 @@ namespace osu.Game.Overlays.Settings { if (bindable == null) return; - var colour = bindable.Disabled ? Color4.Gray : buttonColour; - this.FadeTo(bindable.IsDefault ? 0f : hovering && !bindable.Disabled ? 1f : 0.5f, 200, Easing.OutQuint); - this.FadeColour(ColourInfo.GradientHorizontal(colour.Opacity(0.8f), colour.Opacity(0)), 200, Easing.OutQuint); + + this.FadeTo(bindable.IsDefault ? 0f : + hovering && !bindable.Disabled ? 1f : 0.65f, 200, Easing.OutQuint); + this.FadeColour(bindable.Disabled ? Color4.Gray : buttonColour, 200, Easing.OutQuint); } } } diff --git a/osu.Game/Overlays/Settings/SettingsLabel.cs b/osu.Game/Overlays/Settings/SettingsLabel.cs index 6a1d3ae72c..db7712c873 100644 --- a/osu.Game/Overlays/Settings/SettingsLabel.cs +++ b/osu.Game/Overlays/Settings/SettingsLabel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index a107878fb8..546b40a1f2 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Settings/SettingsSlider.cs b/osu.Game/Overlays/Settings/SettingsSlider.cs index 49d73f77ec..708d9437a5 100644 --- a/osu.Game/Overlays/Settings/SettingsSlider.cs +++ b/osu.Game/Overlays/Settings/SettingsSlider.cs @@ -1,22 +1,21 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; namespace osu.Game.Overlays.Settings { public class SettingsSlider : SettingsSlider> - where T : struct, IEquatable + where T : struct, IEquatable, IComparable, IConvertible { } public class SettingsSlider : SettingsItem - where T : struct, IEquatable - where U : SliderBar, new() + where T : struct, IEquatable, IComparable, IConvertible + where U : OsuSliderBar, new() { protected override Drawable CreateControl() => new U { diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 79a644b2cb..f0191f3af1 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Overlays/Settings/SettingsTextBox.cs b/osu.Game/Overlays/Settings/SettingsTextBox.cs index 710330ad41..8f901ef252 100644 --- a/osu.Game/Overlays/Settings/SettingsTextBox.cs +++ b/osu.Game/Overlays/Settings/SettingsTextBox.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Overlays/Settings/Sidebar.cs b/osu.Game/Overlays/Settings/Sidebar.cs index 4e51ae3a2e..8792eafdbe 100644 --- a/osu.Game/Overlays/Settings/Sidebar.cs +++ b/osu.Game/Overlays/Settings/Sidebar.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/Settings/SidebarButton.cs b/osu.Game/Overlays/Settings/SidebarButton.cs index bc5357f05a..a4c35204f4 100644 --- a/osu.Game/Overlays/Settings/SidebarButton.cs +++ b/osu.Game/Overlays/Settings/SidebarButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index f798d63e5a..c003046242 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -20,7 +20,7 @@ namespace osu.Game.Overlays { public abstract class SettingsOverlay : OsuFocusedOverlayContainer { - public const float CONTENT_MARGINS = 10; + public const float CONTENT_MARGINS = 15; public const float TRANSITION_LENGTH = 600; diff --git a/osu.Game/Overlays/Social/FilterControl.cs b/osu.Game/Overlays/Social/FilterControl.cs index cf4097643e..382b3fd0e7 100644 --- a/osu.Game/Overlays/Social/FilterControl.cs +++ b/osu.Game/Overlays/Social/FilterControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; @@ -22,7 +22,8 @@ namespace osu.Game.Overlays.Social public enum SocialSortCriteria { Rank, - //Location, + Name, + Location, //[Description("Time Zone")] //TimeZone, //[Description("World Map")] diff --git a/osu.Game/Overlays/Social/Header.cs b/osu.Game/Overlays/Social/Header.cs index 2674854327..7bb4b4dde9 100644 --- a/osu.Game/Overlays/Social/Header.cs +++ b/osu.Game/Overlays/Social/Header.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Overlays.SearchableList; @@ -18,7 +18,8 @@ namespace osu.Game.Overlays.Social protected override Color4 BackgroundColour => OsuColour.FromHex(@"38202e"); protected override float TabStripWidth => 438; - protected override SocialTab DefaultTab => SocialTab.OnlinePlayers; + + protected override SocialTab DefaultTab => SocialTab.AllPlayers; protected override FontAwesome Icon => FontAwesome.fa_users; protected override Drawable CreateHeaderText() @@ -53,12 +54,12 @@ namespace osu.Game.Overlays.Social public enum SocialTab { - [Description("Online Players")] - OnlinePlayers, - //[Description("Online Friends")] - //OnlineFriends, - //[Description("Online Team Members")] - //OnlineTeamMembers, + [Description("All Players")] + AllPlayers, + [Description("Friends")] + Friends, + //[Description("Team Members")] + //TeamMembers, //[Description("Chat Channels")] //ChatChannels, } diff --git a/osu.Game/Overlays/Social/SocialGridPanel.cs b/osu.Game/Overlays/Social/SocialGridPanel.cs new file mode 100644 index 0000000000..f9fbce123d --- /dev/null +++ b/osu.Game/Overlays/Social/SocialGridPanel.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Users; + +namespace osu.Game.Overlays.Social +{ + public class SocialGridPanel : SocialPanel + { + public SocialGridPanel(User user) : base(user) + { + Width = 300; + } + } +} diff --git a/osu.Game/Overlays/Social/SocialListPanel.cs b/osu.Game/Overlays/Social/SocialListPanel.cs new file mode 100644 index 0000000000..0f102005d6 --- /dev/null +++ b/osu.Game/Overlays/Social/SocialListPanel.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Game.Users; + +namespace osu.Game.Overlays.Social +{ + public class SocialListPanel : SocialPanel + { + public SocialListPanel(User user) : base(user) + { + RelativeSizeAxes = Axes.X; + } + } +} diff --git a/osu.Game/Overlays/Social/SocialPanel.cs b/osu.Game/Overlays/Social/SocialPanel.cs new file mode 100644 index 0000000000..54fb88f929 --- /dev/null +++ b/osu.Game/Overlays/Social/SocialPanel.cs @@ -0,0 +1,60 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input; +using osu.Game.Users; + +namespace osu.Game.Overlays.Social +{ + public class SocialPanel : UserPanel + { + private const double hover_transition_time = 400; + + public SocialPanel(User user) : base(user) + { + } + + private readonly EdgeEffectParameters edgeEffectNormal = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0f, 1f), + Radius = 2f, + Colour = Color4.Black.Opacity(0.25f), + }; + + private readonly EdgeEffectParameters edgeEffectHovered = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0f, 5f), + Radius = 10f, + Colour = Color4.Black.Opacity(0.3f), + }; + + protected override bool OnHover(InputState state) + { + Content.TweenEdgeEffectTo(edgeEffectHovered, hover_transition_time, Easing.OutQuint); + Content.MoveToY(-4, hover_transition_time, Easing.OutQuint); + + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + Content.TweenEdgeEffectTo(edgeEffectNormal, hover_transition_time, Easing.OutQuint); + Content.MoveToY(0, hover_transition_time, Easing.OutQuint); + + base.OnHoverLost(state); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + this.FadeInFromZero(200, Easing.Out); + } + } +} diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs index 954a838461..ddcb933e5d 100644 --- a/osu.Game/Overlays/SocialOverlay.cs +++ b/osu.Game/Overlays/SocialOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -9,19 +9,22 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.SearchableList; using osu.Game.Overlays.Social; using osu.Game.Users; +using osu.Framework.Configuration; +using osu.Framework.Threading; namespace osu.Game.Overlays { public class SocialOverlay : SearchableListOverlay, IOnlineComponent { - private readonly FillFlowContainer panelFlow; + private APIAccess api; + private readonly LoadingAnimation loading; + private FillFlowContainer panels; protected override Color4 BackgroundColour => OsuColour.FromHex(@"60284b"); protected override Color4 TrianglesColourLight => OsuColour.FromHex(@"672b51"); @@ -31,27 +34,15 @@ namespace osu.Game.Overlays protected override SearchableListFilterControl CreateFilterControl() => new FilterControl(); private IEnumerable users; - private readonly LoadingAnimation loading; - public IEnumerable Users { get { return users; } set { - if (users?.Equals(value) ?? false) return; - users = value; + if (users?.Equals(value) ?? false) + return; - if (users == null) - panelFlow.Clear(); - else - { - panelFlow.ChildrenEnumerable = users.Select(u => - { - var p = new UserPanel(u) { Width = 300 }; - p.Status.BindTo(u.Status); - return p; - }); - } + users = value?.ToList(); } } @@ -62,57 +53,153 @@ namespace osu.Game.Overlays ThirdWaveColour = OsuColour.FromHex(@"9b2b6e"); FourthWaveColour = OsuColour.FromHex(@"6d214d"); - ScrollFlow.Children = new[] + Add(loading = new LoadingAnimation()); + + Filter.Search.Current.ValueChanged += text => { - new OsuContextMenuContainer + if (!string.IsNullOrEmpty(text)) { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Child = panelFlow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 20 }, - Spacing = new Vector2(10f), - } - }, + // force searching in players until searching for friends is supported + Header.Tabs.Current.Value = SocialTab.AllPlayers; + + if (Filter.Tabs.Current.Value != SocialSortCriteria.Rank) + Filter.Tabs.Current.Value = SocialSortCriteria.Rank; + } }; - Add(loading = new LoadingAnimation()); + Header.Tabs.Current.ValueChanged += tab => Scheduler.AddOnce(updateSearch); + + Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch); + + Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += sortOrder => Scheduler.AddOnce(updateSearch); + + currentQuery.ValueChanged += query => + { + queryChangedDebounce?.Cancel(); + + if (string.IsNullOrEmpty(query)) + Scheduler.AddOnce(updateSearch); + else + queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); + }; + + currentQuery.BindTo(Filter.Search.Current); } [BackgroundDependencyLoader] private void load(APIAccess api) { - if (Users == null) - reloadUsers(api); + this.api = api; + api.Register(this); } - private void reloadUsers(APIAccess api) + private void recreatePanels(PanelDisplayStyle displayStyle) { - Users = null; + clearPanels(); - // no this is not the correct data source, but it's something. - var request = new GetUsersRequest(); - request.Success += res => + if (Users == null) + return; + + var newPanels = new FillFlowContainer { - Users = res.Select(e => e.User); - loading.Hide(); + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10f), + Margin = new MarginPadding { Top = 10 }, + ChildrenEnumerable = Users.Select(u => + { + SocialPanel panel; + switch (displayStyle) + { + case PanelDisplayStyle.Grid: + panel = new SocialGridPanel(u) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }; + break; + default: + panel = new SocialListPanel(u); + break; + } + panel.Status.BindTo(u.Status); + return panel; + }) }; - api.Queue(request); + LoadComponentAsync(newPanels, f => + { + if(panels != null) + ScrollFlow.Remove(panels); + + ScrollFlow.Add(panels = newPanels); + }); + } + + private APIRequest getUsersRequest; + + private readonly Bindable currentQuery = new Bindable(); + + private ScheduledDelegate queryChangedDebounce; + + private void updateSearch() + { + queryChangedDebounce?.Cancel(); + + if (!IsLoaded) + return; + + Users = null; + clearPanels(); + loading.Hide(); + getUsersRequest?.Cancel(); + + if (api?.IsLoggedIn != true) + return; + + switch (Header.Tabs.Current.Value) + { + case SocialTab.Friends: + var friendRequest = new GetFriendsRequest(); // TODO filter arguments? + friendRequest.Success += updateUsers; + api.Queue(getUsersRequest = friendRequest); + break; + default: + var userRequest = new GetUsersRequest(); // TODO filter arguments! + userRequest.Success += response => updateUsers(response.Select(r => r.User)); + api.Queue(getUsersRequest = userRequest); + break; + } loading.Show(); } + private void updateUsers(IEnumerable newUsers) + { + Users = newUsers; + loading.Hide(); + recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); + } + + private void clearPanels() + { + if (panels != null) + { + panels.Expire(); + panels = null; + } + } + public void APIStateChanged(APIAccess api, APIState state) { switch (state) { case APIState.Online: - reloadUsers(api); + Scheduler.AddOnce(updateSearch); break; default: Users = null; + clearPanels(); break; } } @@ -120,7 +207,7 @@ namespace osu.Game.Overlays public enum SortDirection { - Descending, Ascending, + Descending } } diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index ef1f7c8c70..8ac4e44a84 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index c039f9d311..f3a25b79a1 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs index b0171feb30..fd78db5a8b 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs b/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs index 5c64ae69ec..5922b6212c 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs index 9f020cada5..3bce67765a 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarHomeButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs index b615cd3303..451af65ce7 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index f38c772890..6d58c78c37 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; @@ -87,7 +87,8 @@ namespace osu.Game.Overlays.Toolbar ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(); } - public override bool HandleInput => !ruleset.Disabled; + public override bool HandleKeyboardInput => !ruleset.Disabled; + public override bool HandleMouseInput => !ruleset.Disabled; private void disabledChanged(bool isDisabled) => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs index 81c57a984f..428467fece 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index c093767e52..9cff2e4a77 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs index 59314b8771..0f7f34c36a 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs index d0d76dd5d2..1b0c821b54 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Toolbar } [BackgroundDependencyLoader(true)] - private void load(SettingsOverlay settings) + private void load(MainSettings settings) { StateContainer = settings; } diff --git a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs index 74d1da4384..519210d6e2 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs b/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs index 76218bce1b..ba015119a0 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs index 3714094924..c2dfea9a08 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarUserButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index c2e7fc5b44..59f940a19d 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index 3f9703a523..074d83a5ad 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs new file mode 100644 index 0000000000..56eac730b0 --- /dev/null +++ b/osu.Game/Rulesets/Configuration/IRulesetConfigManager.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Configuration.Tracking; + +namespace osu.Game.Rulesets.Configuration +{ + public interface IRulesetConfigManager : ITrackableConfigManager + { + } +} diff --git a/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs new file mode 100644 index 0000000000..9f244f6267 --- /dev/null +++ b/osu.Game/Rulesets/Configuration/RulesetConfigManager.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Configuration; + +namespace osu.Game.Rulesets.Configuration +{ + public abstract class RulesetConfigManager : DatabasedConfigManager, IRulesetConfigManager + where T : struct + { + protected RulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int variant) : base(settings, ruleset, variant) + { + } + } +} diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 36740b96cb..7f22b3764c 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs index b1ed5bc8b5..b10c21af6c 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/Handle.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs index 22d993e7cd..359cdd009a 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HandleContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs index 8f380b77c3..864851dcd3 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/HitObjectSelectionBox.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -165,7 +165,8 @@ namespace osu.Game.Rulesets.Edit.Layers.Selection } private bool isActive = true; - public override bool HandleInput => isActive; + public override bool HandleKeyboardInput => isActive; + public override bool HandleMouseInput => isActive; public override void Hide() { diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs b/osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs index 8326ebeeac..6f8c946165 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/OriginHandle.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs index aec16bd46d..beedb415c2 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs index 98bcfd0ec8..93755d400a 100644 --- a/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs +++ b/osu.Game/Rulesets/Edit/Layers/Selection/SelectionLayer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; diff --git a/osu.Game/Rulesets/Edit/ToolboxGroup.cs b/osu.Game/Rulesets/Edit/ToolboxGroup.cs index 70e4d3a0c5..e153607f47 100644 --- a/osu.Game/Rulesets/Edit/ToolboxGroup.cs +++ b/osu.Game/Rulesets/Edit/ToolboxGroup.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Game.Screens.Play.ReplaySettings; +using osu.Game.Screens.Play.PlayerSettings; namespace osu.Game.Rulesets.Edit { - public class ToolboxGroup : ReplayGroup + public class ToolboxGroup : PlayerSettingsGroup { protected override string Title => "toolbox"; diff --git a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs index dd182dcbdb..a548795df3 100644 --- a/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/HitObjectCompositionTool.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs b/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs index eba873f0cf..db5fecf525 100644 --- a/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs +++ b/osu.Game/Rulesets/Edit/Tools/ICompositionTool.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Edit.Tools diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 3d7880f56f..c1bf55b214 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -40,7 +40,8 @@ namespace osu.Game.Rulesets.Judgements Anchor = Anchor.Centre, Text = judgement.Result.GetDescription().ToUpper(), Font = @"Venera", - TextSize = 16 + Scale = new Vector2(0.85f, 1), + TextSize = 12 } }; } diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index f8c9b9734f..c2216fea51 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs index 2d7cda5f1f..81268e0ad4 100644 --- a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs +++ b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Mods diff --git a/osu.Game/Rulesets/Mods/IApplicableMod.cs b/osu.Game/Rulesets/Mods/IApplicableMod.cs index ed2b652598..8e56a90d47 100644 --- a/osu.Game/Rulesets/Mods/IApplicableMod.cs +++ b/osu.Game/Rulesets/Mods/IApplicableMod.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Mods diff --git a/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs b/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs new file mode 100644 index 0000000000..d89d6f20d8 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IApplicableToBeatmapConverter.cs @@ -0,0 +1,22 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Mods +{ + /// + /// Interface for a that applies changes to a . + /// + /// The type of converted . + public interface IApplicableToBeatmapConverter : IApplicableMod + where TObject : HitObject + { + /// + /// Applies this to a . + /// + /// The to apply to. + void ApplyToBeatmapConverter(BeatmapConverter beatmapConverter); + } +} diff --git a/osu.Game/Rulesets/Mods/IApplicableToClock.cs b/osu.Game/Rulesets/Mods/IApplicableToClock.cs index 8bb4e2b97d..46c1648951 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToClock.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToClock.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Timing; diff --git a/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs b/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs index a95aa4370c..a87ae701c1 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; diff --git a/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs b/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs index fb9d7128c0..cd39f90ac4 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToDrawableHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs b/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs index 1964ad728f..c20abe0151 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Mods/IApplicableToRulesetContainer.cs b/osu.Game/Rulesets/Mods/IApplicableToRulesetContainer.cs index eae8c9d15c..f03866e7bb 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToRulesetContainer.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToRulesetContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs index 2314999d4f..f45bbab194 100644 --- a/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs +++ b/osu.Game/Rulesets/Mods/IApplicableToScoreProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs index 68ed545701..26cdcde9fe 100644 --- a/osu.Game/Rulesets/Mods/Mod.cs +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index bddb97f374..3356a56c33 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -1,34 +1,34 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets.Mods { - public abstract class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer + public class ModAutoplay : ModAutoplay, IApplicableToRulesetContainer where T : HitObject { - protected abstract Score CreateReplayScore(Beatmap beatmap); + protected virtual Score CreateReplayScore(Beatmap beatmap) => new Score { Replay = new Replay() }; - public virtual void ApplyToRulesetContainer(RulesetContainer rulesetContainer) - { - rulesetContainer.SetReplay(CreateReplayScore(rulesetContainer.Beatmap)?.Replay); - } + public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; + + public virtual void ApplyToRulesetContainer(RulesetContainer rulesetContainer) => rulesetContainer.SetReplay(CreateReplayScore(rulesetContainer.Beatmap)?.Replay); } - public class ModAutoplay : Mod, IApplicableFailOverride + public abstract class ModAutoplay : Mod, IApplicableFailOverride { public override string Name => "Autoplay"; public override string ShortenedName => "AT"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto; public override string Description => "Watch a perfect automated play through the song"; public override double ScoreMultiplier => 0; - public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; public bool AllowFail => false; + public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; } } diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index 581fbc5e3a..c0480b0647 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; @@ -9,6 +9,7 @@ namespace osu.Game.Rulesets.Mods { public override string Name => "Cinema"; public override string ShortenedName => "CN"; + public override bool HasImplementation => false; public override FontAwesome Icon => FontAwesome.fa_osu_mod_cinema; } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModDaycore.cs b/osu.Game/Rulesets/Mods/ModDaycore.cs index cbad224316..180199cd70 100644 --- a/osu.Game/Rulesets/Mods/ModDaycore.cs +++ b/osu.Game/Rulesets/Mods/ModDaycore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Audio; @@ -23,4 +23,4 @@ namespace osu.Game.Rulesets.Mods base.ApplyToClock(clock); } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs index d8aa5ea1d2..0b8f4b0b5b 100644 --- a/osu.Game/Rulesets/Mods/ModDoubleTime.cs +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -24,4 +24,4 @@ namespace osu.Game.Rulesets.Mods clock.Rate = 1.5; } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModEasy.cs b/osu.Game/Rulesets/Mods/ModEasy.cs index aaf083fd9e..5c5b9b1b44 100644 --- a/osu.Game/Rulesets/Mods/ModEasy.cs +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -27,4 +27,4 @@ namespace osu.Game.Rulesets.Mods difficulty.OverallDifficulty *= ratio; } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs index b7499e624a..9858e00083 100644 --- a/osu.Game/Rulesets/Mods/ModFlashlight.cs +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; @@ -14,4 +14,4 @@ namespace osu.Game.Rulesets.Mods public override string Description => "Restricted view area."; public override bool Ranked => true; } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModHalfTime.cs b/osu.Game/Rulesets/Mods/ModHalfTime.cs index a9e49bb4b0..bb9ed0047d 100644 --- a/osu.Game/Rulesets/Mods/ModHalfTime.cs +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -24,4 +24,4 @@ namespace osu.Game.Rulesets.Mods clock.Rate = 0.75; } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModHardRock.cs b/osu.Game/Rulesets/Mods/ModHardRock.cs index 36d82362e3..c4c0f38faf 100644 --- a/osu.Game/Rulesets/Mods/ModHardRock.cs +++ b/osu.Game/Rulesets/Mods/ModHardRock.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Mods { const float ratio = 1.4f; difficulty.CircleSize *= 1.3f; // CS uses a custom 1.3 ratio. - difficulty.ApproachRate *= ratio; + difficulty.ApproachRate = Math.Min(difficulty.ApproachRate * ratio, 10.0f); difficulty.DrainRate *= ratio; difficulty.OverallDifficulty *= ratio; } diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs index 25f6ad024d..303a46f629 100644 --- a/osu.Game/Rulesets/Mods/ModHidden.cs +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; @@ -13,4 +13,4 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.DifficultyIncrease; public override bool Ranked => true; } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModNightcore.cs b/osu.Game/Rulesets/Mods/ModNightcore.cs index 5cefd89023..ad4df55b91 100644 --- a/osu.Game/Rulesets/Mods/ModNightcore.cs +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Audio; @@ -23,4 +23,4 @@ namespace osu.Game.Rulesets.Mods base.ApplyToClock(clock); } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModNoFail.cs b/osu.Game/Rulesets/Mods/ModNoFail.cs index 8aefd1b88e..9686eff99c 100644 --- a/osu.Game/Rulesets/Mods/ModNoFail.cs +++ b/osu.Game/Rulesets/Mods/ModNoFail.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 59539d2b2c..bb12b2e39f 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Scoring; diff --git a/osu.Game/Rulesets/Mods/ModRelax.cs b/osu.Game/Rulesets/Mods/ModRelax.cs index a3f38e4ff6..e8328c3ac7 100644 --- a/osu.Game/Rulesets/Mods/ModRelax.cs +++ b/osu.Game/Rulesets/Mods/ModRelax.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -14,4 +14,4 @@ namespace osu.Game.Rulesets.Mods public override double ScoreMultiplier => 0; public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModNoFail), typeof(ModSuddenDeath) }; } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index bc42c69cbe..490825220c 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Rulesets/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs index 15ffc4ad63..8aeb880be8 100644 --- a/osu.Game/Rulesets/Mods/ModType.cs +++ b/osu.Game/Rulesets/Mods/ModType.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Mods diff --git a/osu.Game/Rulesets/Mods/MultiMod.cs b/osu.Game/Rulesets/Mods/MultiMod.cs index c40d107bda..1de5297e22 100644 --- a/osu.Game/Rulesets/Mods/MultiMod.cs +++ b/osu.Game/Rulesets/Mods/MultiMod.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Mods @@ -12,4 +12,4 @@ namespace osu.Game.Rulesets.Mods public Mod[] Mods; } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Objects/BezierApproximator.cs b/osu.Game/Rulesets/Objects/BezierApproximator.cs index 12be591aab..6ed83a5f57 100644 --- a/osu.Game/Rulesets/Objects/BezierApproximator.cs +++ b/osu.Game/Rulesets/Objects/BezierApproximator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -147,4 +147,4 @@ namespace osu.Game.Rulesets.Objects return output; } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Objects/CatmullApproximator.cs b/osu.Game/Rulesets/Objects/CatmullApproximator.cs new file mode 100644 index 0000000000..364b4e995a --- /dev/null +++ b/osu.Game/Rulesets/Objects/CatmullApproximator.cs @@ -0,0 +1,70 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using OpenTK; + +namespace osu.Game.Rulesets.Objects +{ + public class CatmullApproximator + { + /// + /// The amount of pieces to calculate for each controlpoint quadruplet. + /// + private const int detail = 50; + + private readonly List controlPoints; + + public CatmullApproximator(List controlPoints) + { + this.controlPoints = controlPoints; + } + + + /// + /// Creates a piecewise-linear approximation of a Catmull-Rom spline. + /// + /// A list of vectors representing the piecewise-linear approximation. + public List CreateCatmull() + { + var result = new List(); + + for (int i = 0; i < controlPoints.Count - 1; i++) + { + var v1 = i > 0 ? controlPoints[i - 1] : controlPoints[i]; + var v2 = controlPoints[i]; + var v3 = i < controlPoints.Count - 1 ? controlPoints[i + 1] : v2 + v2 - v1; + var v4 = i < controlPoints.Count - 2 ? controlPoints[i + 2] : v3 + v3 - v2; + + for (int c = 0; c < detail; c++) + { + result.Add(findPoint(ref v1, ref v2, ref v3, ref v4, (float)c / detail)); + result.Add(findPoint(ref v1, ref v2, ref v3, ref v4, (float)(c + 1) / detail)); + } + } + + return result; + } + + /// + /// Finds a point on the spline at the position of a parameter. + /// + /// The first vector. + /// The second vector. + /// The third vector. + /// The fourth vector. + /// The parameter at which to find the point on the spline, in the range [0, 1]. + /// The point on the spline at . + private Vector2 findPoint(ref Vector2 vec1, ref Vector2 vec2, ref Vector2 vec3, ref Vector2 vec4, float t) + { + float t2 = t * t; + float t3 = t * t2; + + Vector2 result; + result.X = 0.5f * (2f * vec2.X + (-vec1.X + vec3.X) * t + (2f * vec1.X - 5f * vec2.X + 4f * vec3.X - vec4.X) * t2 + (-vec1.X + 3f * vec2.X - 3f * vec3.X + vec4.X) * t3); + result.Y = 0.5f * (2f * vec2.Y + (-vec1.Y + vec3.Y) * t + (2f * vec1.Y - 5f * vec2.Y + 4f * vec3.Y - vec4.Y) * t2 + (-vec1.Y + 3f * vec2.Y - 3f * vec3.Y + vec4.Y) * t3); + + return result; + } + } +} diff --git a/osu.Game/Rulesets/Objects/CircularArcApproximator.cs b/osu.Game/Rulesets/Objects/CircularArcApproximator.cs index 642793fa3f..cc319d1a8f 100644 --- a/osu.Game/Rulesets/Objects/CircularArcApproximator.cs +++ b/osu.Game/Rulesets/Objects/CircularArcApproximator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs b/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs index 5e57c57f4d..02b8f2e654 100644 --- a/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs +++ b/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Objects.Drawables @@ -9,4 +9,4 @@ namespace osu.Game.Rulesets.Objects.Drawables Hit, Miss } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 45a7275c53..2db02724ed 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -29,59 +29,55 @@ namespace osu.Game.Rulesets.Objects.Drawables /// public virtual Color4 AccentColour { get; set; } = Color4.Gray; + // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first + protected virtual string SampleNamespace => null; + + protected List Samples = new List(); + protected virtual IEnumerable GetSamples() => HitObject.Samples; + + private List nestedHitObjects; + public IReadOnlyList NestedHitObjects => nestedHitObjects; + + public event Action OnJudgement; + public event Action OnJudgementRemoved; + + public IReadOnlyList Judgements => judgements; + private readonly List judgements = new List(); + /// /// Whether a visible judgement should be displayed when this representation is hit. /// public virtual bool DisplayJudgement => true; - public override bool RemoveCompletedTransforms => false; - public override bool RemoveWhenNotAlive => false; - - protected DrawableHitObject(HitObject hitObject) - { - HitObject = hitObject; - } + /// + /// Whether this and all of its nested s have been hit. + /// + public bool IsHit => Judgements.Any(j => j.Final && j.IsHit) && (NestedHitObjects?.All(n => n.IsHit) ?? true); /// - /// The screen-space point that causes this to be selected in the Editor. + /// Whether this and all of its nested s have been judged. /// - public virtual Vector2 SelectionPoint => ScreenSpaceDrawQuad.Centre; - - /// - /// The screen-space quad that outlines this for selections in the Editor. - /// - public virtual Quad SelectionQuad => ScreenSpaceDrawQuad; - } - - public abstract class DrawableHitObject : DrawableHitObject - where TObject : HitObject - { - public event Action OnJudgement; - public event Action OnJudgementRemoved; - - public new readonly TObject HitObject; - - public override bool HandleInput => Interactive; - public bool Interactive = true; + public bool AllJudged => (!ProvidesJudgement || judgementFinalized) && (NestedHitObjects?.All(h => h.AllJudged) ?? true); /// /// Whether this can be judged. /// protected virtual bool ProvidesJudgement => true; - private readonly List judgements = new List(); - public IReadOnlyList Judgements => judgements; + private bool judgementOccurred; + private bool judgementFinalized => judgements.LastOrDefault()?.Final == true; - protected List Samples = new List(); - protected virtual IEnumerable GetSamples() => HitObject.Samples; + public bool Interactive = true; + public override bool HandleKeyboardInput => Interactive; + public override bool HandleMouseInput => Interactive; - // Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first - protected virtual string SampleNamespace => null; + public override bool RemoveWhenNotAlive => false; + public override bool RemoveCompletedTransforms => false; + protected override bool RequiresChildrenUpdate => true; public readonly Bindable State = new Bindable(); - protected DrawableHitObject(TObject hitObject) - : base(hitObject) + protected DrawableHitObject(HitObject hitObject) { HitObject = hitObject; } @@ -133,18 +129,55 @@ namespace osu.Game.Rulesets.Objects.Drawables State.TriggerChange(); } - protected void PlaySamples() - { - Samples.ForEach(s => s?.Play()); - } - - private bool judgementOccurred; - private bool judgementFinalized => judgements.LastOrDefault()?.Final == true; + protected abstract void UpdateState(ArmedState state); /// - /// Whether this and all of its nested s have been judged. + /// Bind to apply a custom state which can override the default implementation. /// - public bool AllJudged => (!ProvidesJudgement || judgementFinalized) && (NestedHitObjects?.All(h => h.AllJudged) ?? true); + public event Action ApplyCustomUpdateState; + + /// + /// Plays all the hitsounds for this . + /// + public void PlaySamples() => Samples.ForEach(s => s?.Play()); + + protected override void Update() + { + base.Update(); + + var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; + + while (judgements.Count > 0) + { + var lastJudgement = judgements[judgements.Count - 1]; + if (lastJudgement.TimeOffset + endTime <= Time.Current) + break; + + judgements.RemoveAt(judgements.Count - 1); + State.Value = ArmedState.Idle; + + OnJudgementRemoved?.Invoke(this, lastJudgement); + } + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + UpdateJudgement(false); + } + + protected virtual void AddNested(DrawableHitObject h) + { + if (nestedHitObjects == null) + nestedHitObjects = new List(); + + h.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j); + h.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j); + h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j); + + nestedHitObjects.Add(h); + } /// /// Notifies that a new judgement has occurred for this . @@ -209,53 +242,30 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Whether the user triggered this check. /// The offset from the end time at which this check occurred. A > 0 /// implies that this check occurred after the end time of . - protected virtual void CheckForJudgements(bool userTriggered, double timeOffset) { } - - protected override void Update() + protected virtual void CheckForJudgements(bool userTriggered, double timeOffset) { - base.Update(); - - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - - while (judgements.Count > 0) - { - var lastJudgement = judgements[judgements.Count - 1]; - if (lastJudgement.TimeOffset + endTime <= Time.Current) - break; - - judgements.RemoveAt(judgements.Count - 1); - State.Value = ArmedState.Idle; - - OnJudgementRemoved?.Invoke(this, lastJudgement); - } - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - UpdateJudgement(false); - } - - private List> nestedHitObjects; - protected IEnumerable> NestedHitObjects => nestedHitObjects; - - protected virtual void AddNested(DrawableHitObject h) - { - if (nestedHitObjects == null) - nestedHitObjects = new List>(); - - h.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j); - h.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j); - h.ApplyCustomUpdateState += (d, s) => ApplyCustomUpdateState?.Invoke(d, s); - nestedHitObjects.Add(h); } /// - /// Bind to apply a custom state which can override the default implementation. + /// The screen-space point that causes this to be selected in the Editor. /// - public event Action ApplyCustomUpdateState; + public virtual Vector2 SelectionPoint => ScreenSpaceDrawQuad.Centre; - protected abstract void UpdateState(ArmedState state); + /// + /// The screen-space quad that outlines this for selections in the Editor. + /// + public virtual Quad SelectionQuad => ScreenSpaceDrawQuad; + } + + public abstract class DrawableHitObject : DrawableHitObject + where TObject : HitObject + { + public new readonly TObject HitObject; + + protected DrawableHitObject(TObject hitObject) + : base(hitObject) + { + HitObject = hitObject; + } } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs deleted file mode 100644 index 538bb826ad..0000000000 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Game.Rulesets.Objects.Types; - -namespace osu.Game.Rulesets.Objects.Drawables -{ - /// - /// A basic class that overrides and implements . - /// This object does not need to have its set to be able to scroll, as this will - /// will be set by the scrolling container that contains it. - /// - public abstract class DrawableScrollingHitObject : DrawableHitObject, IScrollingHitObject - where TObject : HitObject - { - public BindableDouble LifetimeOffset { get; } = new BindableDouble(); - - Axes IScrollingHitObject.ScrollingAxes - { - set - { - RelativePositionAxes |= value; - - if ((value & Axes.X) > 0) - X = (float)HitObject.StartTime; - if ((value & Axes.Y) > 0) - Y = (float)HitObject.StartTime; - } - } - - public override bool RemoveWhenNotAlive => false; - protected override bool RequiresChildrenUpdate => true; - - protected DrawableScrollingHitObject(TObject hitObject) - : base(hitObject) - { - } - - private double? lifetimeStart; - public override double LifetimeStart - { - get { return lifetimeStart ?? HitObject.StartTime - LifetimeOffset; } - set { lifetimeStart = value; } - } - - private double? lifetimeEnd; - public override double LifetimeEnd - { - get - { - var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime; - return lifetimeEnd ?? endTime + LifetimeOffset; - } - set { lifetimeEnd = value; } - } - - protected override void AddNested(DrawableHitObject h) - { - var scrollingHitObject = h as IScrollingHitObject; - scrollingHitObject?.LifetimeOffset.BindTo(LifetimeOffset); - - base.AddNested(h); - } - } -} \ No newline at end of file diff --git a/osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs b/osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs index 0314ef3037..d10149facd 100644 --- a/osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs +++ b/osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs index 30b65237a4..55dd0a16cc 100644 --- a/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/IScrollingHitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; @@ -28,4 +28,4 @@ namespace osu.Game.Rulesets.Objects.Drawables /// Axes ScrollingAxes { set; } } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 4f06f6afe1..75cb65eff0 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -49,6 +49,19 @@ namespace osu.Game.Rulesets.Objects [JsonIgnore] public bool Kiai { get; private set; } + private float overallDifficulty = BeatmapDifficulty.DEFAULT_DIFFICULTY; + + private HitWindows hitWindows; + + /// + /// The hit windows for this . + /// + public HitWindows HitWindows + { + get => hitWindows ?? (hitWindows = new HitWindows(overallDifficulty)); + protected set => hitWindows = value; + } + private readonly SortedList nestedHitObjects = new SortedList((h1, h2) => h1.StartTime.CompareTo(h2.StartTime)); [JsonIgnore] @@ -75,6 +88,9 @@ namespace osu.Game.Rulesets.Objects Kiai = effectPoint.KiaiMode; SampleControlPoint = samplePoint; + + overallDifficulty = difficulty.OverallDifficulty; + hitWindows = null; } protected virtual void CreateNestedHitObjects() diff --git a/osu.Game/Rulesets/Objects/HitObjectParser.cs b/osu.Game/Rulesets/Objects/HitObjectParser.cs index ea0b5e0d2e..5a38daa654 100644 --- a/osu.Game/Rulesets/Objects/HitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/HitObjectParser.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Objects diff --git a/osu.Game/Rulesets/Objects/HitWindows.cs b/osu.Game/Rulesets/Objects/HitWindows.cs new file mode 100644 index 0000000000..0ec8389b4f --- /dev/null +++ b/osu.Game/Rulesets/Objects/HitWindows.cs @@ -0,0 +1,173 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets.Objects +{ + public class HitWindows + { + private static readonly IReadOnlyDictionary base_ranges = new Dictionary + { + { HitResult.Perfect, (44.8, 38.8, 27.8) }, + { HitResult.Great, (128, 98, 68 ) }, + { HitResult.Good, (194, 164, 134) }, + { HitResult.Ok, (254, 224, 194) }, + { HitResult.Meh, (302, 272, 242) }, + { HitResult.Miss, (376, 346, 316) }, + }; + + /// + /// Hit window for a result. + /// The user can only achieve receive this result if is true. + /// + public double Perfect { get; protected set; } + + /// + /// Hit window for a result. + /// + public double Great { get; protected set; } + + /// + /// Hit window for a result. + /// + public double Good { get; protected set; } + + /// + /// Hit window for an result. + /// The user can only achieve this result if is true. + /// + public double Ok { get; protected set; } + + /// + /// Hit window for a result. + /// + public double Meh { get; protected set; } + + /// + /// Hit window for a result. + /// + public double Miss { get; protected set; } + + /// + /// Whether it's possible to achieve a result. + /// + public bool AllowsPerfect; + + /// + /// Whether it's possible to achieve a result. + /// + public bool AllowsOk; + + /// + /// Constructs hit windows by fitting a parameter to a 2-part piecewise linear function for each hit window. + /// + /// The parameter. + public HitWindows(double difficulty) + { + Perfect = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Perfect]); + Great = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Great]); + Good = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Good]); + Ok = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Ok]); + Meh = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Meh]); + Miss = BeatmapDifficulty.DifficultyRange(difficulty, base_ranges[HitResult.Miss]); + } + + /// + /// Retrieves the for a time offset. + /// + /// The time offset. + /// The hit result, or if doesn't result in a judgement. + public HitResult ResultFor(double timeOffset) + { + timeOffset = Math.Abs(timeOffset); + + if (AllowsPerfect && timeOffset <= HalfWindowFor(HitResult.Perfect)) + return HitResult.Perfect; + if (timeOffset <= HalfWindowFor(HitResult.Great)) + return HitResult.Great; + if (timeOffset <= HalfWindowFor(HitResult.Good)) + return HitResult.Good; + if (AllowsOk && timeOffset <= HalfWindowFor(HitResult.Ok)) + return HitResult.Ok; + if (timeOffset <= HalfWindowFor(HitResult.Meh)) + return HitResult.Meh; + if (timeOffset <= HalfWindowFor(HitResult.Miss)) + return HitResult.Miss; + + return HitResult.None; + } + + /// + /// Retrieves half the hit window for a . + /// This is useful if the hit window for one half of the hittable range of a is required. + /// + /// The expected . + /// One half of the hit window for . + public double HalfWindowFor(HitResult result) + { + switch (result) + { + case HitResult.Perfect: + return Perfect / 2; + case HitResult.Great: + return Great / 2; + case HitResult.Good: + return Good / 2; + case HitResult.Ok: + return Ok / 2; + case HitResult.Meh: + return Meh / 2; + case HitResult.Miss: + return Miss / 2; + default: + throw new ArgumentException(nameof(result)); + } + } + + /// + /// Given a time offset, whether the can ever be hit in the future with a non- result. + /// This happens if . + /// + /// The time offset. + /// Whether the can be hit at any point in the future from this time offset. + public bool CanBeHit(double timeOffset) => timeOffset <= HalfWindowFor(HitResult.Meh); + + /// + /// Multiplies all hit windows by a value. + /// + /// The hit windows to multiply. + /// The value to multiply each hit window by. + public static HitWindows operator *(HitWindows windows, double value) + { + windows.Perfect *= value; + windows.Great *= value; + windows.Good *= value; + windows.Ok *= value; + windows.Meh *= value; + windows.Miss *= value; + + return windows; + } + + /// + /// Divides all hit windows by a value. + /// + /// The hit windows to divide. + /// The value to divide each hit window by. + public static HitWindows operator /(HitWindows windows, double value) + { + windows.Perfect /= value; + windows.Great /= value; + windows.Good /= value; + windows.Ok /= value; + windows.Meh /= value; + windows.Miss /= value; + + return windows; + } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs index 30c10c302a..366449a910 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index fbf02f5345..d0e7e09ad2 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs index 781fe8f7fa..6132ea63a6 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSlider.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs index 0652737b12..1df7cce899 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index bdbd7a9e65..5fdc9a07e1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -77,6 +77,10 @@ namespace osu.Game.Rulesets.Objects.Legacy if (repeatCount > 9000) throw new ArgumentOutOfRangeException(nameof(repeatCount), @"Repeat count is way too high"); + // osu-stable treated the first span of the slider as a repeat, but no repeats are happening + repeatCount = Math.Max(0, repeatCount - 1); + + if (split.Length > 7) length = Convert.ToDouble(split[7], CultureInfo.InvariantCulture); @@ -84,8 +88,7 @@ namespace osu.Game.Rulesets.Objects.Legacy readCustomSampleBanks(split[10], bankInfo); // One node for each repeat + the start and end nodes - // Note that the first length of the slider is considered a repeat, but there are no actual repeats happening - int nodes = Math.Max(0, repeatCount - 1) + 2; + int nodes = repeatCount + 2; // Populate node sample bank infos with the default hit object sample bank var nodeBankInfos = new List(); @@ -128,7 +131,7 @@ namespace osu.Game.Rulesets.Objects.Legacy // Generate the final per-node samples var nodeSamples = new List>(nodes); - for (int i = 0; i <= repeatCount; i++) + for (int i = 0; i < nodes; i++) nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i])); result = CreateSlider(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo, points, length, curveType, repeatCount, nodeSamples); diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs index 09f005e666..16ea008216 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectType.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -15,4 +15,4 @@ namespace osu.Game.Rulesets.Objects.Legacy ColourHax = 112, Hold = 1 << 7 } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index 6dc8a07630..df7c8b0a83 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -1,8 +1,7 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; -using System; using System.Collections.Generic; using OpenTK; using osu.Game.Audio; @@ -18,34 +17,23 @@ namespace osu.Game.Rulesets.Objects.Legacy /// private const float base_scoring_distance = 100; + /// + /// s don't need a curve since they're converted to ruleset-specific hitobjects. + /// + public SliderCurve Curve { get; } = null; public List ControlPoints { get; set; } public CurveType CurveType { get; set; } public double Distance { get; set; } public List> RepeatSamples { get; set; } - public int RepeatCount { get; set; } = 1; + public int RepeatCount { get; set; } - public double EndTime => StartTime + RepeatCount * Distance / Velocity; + public double EndTime => StartTime + this.SpanCount() * Distance / Velocity; public double Duration => EndTime - StartTime; public double Velocity = 1; - public Vector2 PositionAt(double progress) - { - throw new NotImplementedException(); - } - - public double ProgressAt(double progress) - { - throw new NotImplementedException(); - } - - public int RepeatAt(double progress) - { - throw new NotImplementedException(); - } - protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index 2a65b853b7..d756dc71ee 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 2060b84222..ad51b636d3 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs index 1dda577320..24006a4901 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index adc0c064bc..d70c58e262 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs index f72c5b9894..0def535129 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index 0c1000965c..330b8acfec 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 0062d29446..19f9a93976 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index 75a6d80560..513ea0616b 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index 2b2dbe0765..4dbcc6d017 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs index 7088cc480b..1eafc477fa 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index 529a28ac15..1d3bbd0946 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index b472423a1d..a5e22602b0 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs index abef667d91..3047228cdc 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects.Types; diff --git a/osu.Game/Rulesets/Objects/SliderCurve.cs b/osu.Game/Rulesets/Objects/SliderCurve.cs index 363c330d3d..2b16f463df 100644 --- a/osu.Game/Rulesets/Objects/SliderCurve.cs +++ b/osu.Game/Rulesets/Objects/SliderCurve.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -41,6 +41,8 @@ namespace osu.Game.Rulesets.Objects break; return subpath; + case CurveType.Catmull: + return new CatmullApproximator(subControlPoints).CreateCatmull(); } return new BezierApproximator(subControlPoints).CreateBezier(); diff --git a/osu.Game/Rulesets/Objects/Types/CurveType.cs b/osu.Game/Rulesets/Objects/Types/CurveType.cs index 18db712a65..9b6772539e 100644 --- a/osu.Game/Rulesets/Objects/Types/CurveType.cs +++ b/osu.Game/Rulesets/Objects/Types/CurveType.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Objects.Types diff --git a/osu.Game/Rulesets/Objects/Types/IHasCombo.cs b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs index f053fdcf49..a10f5d814d 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasCombo.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Objects.Types diff --git a/osu.Game/Rulesets/Objects/Types/IHasCurve.cs b/osu.Game/Rulesets/Objects/Types/IHasCurve.cs index 399138bc24..0254a829f4 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasCurve.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasCurve.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -11,6 +11,11 @@ namespace osu.Game.Rulesets.Objects.Types /// public interface IHasCurve : IHasDistance, IHasRepeats { + /// + /// The curve. + /// + SliderCurve Curve { get; } + /// /// The control points that shape the curve. /// @@ -20,7 +25,10 @@ namespace osu.Game.Rulesets.Objects.Types /// The type of curve. /// CurveType CurveType { get; } + } + public static class HasCurveExtensions + { /// /// Computes the position on the curve at a given progress, accounting for repeat logic. /// @@ -28,20 +36,28 @@ namespace osu.Game.Rulesets.Objects.Types /// /// /// [0, 1] where 0 is the beginning of the curve and 1 is the end of the curve. - Vector2 PositionAt(double progress); + public static Vector2 PositionAt(this IHasCurve obj, double progress) + => obj.Curve.PositionAt(obj.ProgressAt(progress)); /// /// Finds the progress along the curve, accounting for repeat logic. /// /// [0, 1] where 0 is the beginning of the curve and 1 is the end of the curve. /// [0, 1] where 0 is the beginning of the curve and 1 is the end of the curve. - double ProgressAt(double progress); + public static double ProgressAt(this IHasCurve obj, double progress) + { + double p = progress * obj.SpanCount() % 1; + if (obj.SpanAt(progress) % 2 == 1) + p = 1 - p; + return p; + } /// - /// Determines which repeat of the curve the progress point is on. + /// Determines which span of the curve the progress point is on. /// /// [0, 1] where 0 is the beginning of the curve and 1 is the end of the curve. - /// [0, RepeatCount] where 0 is the first run. - int RepeatAt(double progress); + /// [0, SpanCount) where 0 is the first run. + public static int SpanAt(this IHasCurve obj, double progress) + => (int)(progress * obj.SpanCount()); } } diff --git a/osu.Game/Rulesets/Objects/Types/IHasDistance.cs b/osu.Game/Rulesets/Objects/Types/IHasDistance.cs index a5e487a0ba..98ef898f22 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasDistance.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasDistance.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Objects.Types diff --git a/osu.Game/Rulesets/Objects/Types/IHasEndTime.cs b/osu.Game/Rulesets/Objects/Types/IHasEndTime.cs index ac30afe5fb..1fedb8e061 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasEndTime.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasEndTime.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Objects.Types diff --git a/osu.Game/Rulesets/Objects/Types/IHasHold.cs b/osu.Game/Rulesets/Objects/Types/IHasHold.cs index 4054fc4fd1..1c33187e93 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasHold.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasHold.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Objects.Types diff --git a/osu.Game/Rulesets/Objects/Types/IHasPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasPosition.cs index 6eca86656d..0d9cd5ad2e 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasPosition.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs index 2fe2424d49..75dd3776f9 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Audio; @@ -21,4 +21,13 @@ namespace osu.Game.Rulesets.Objects.Types /// List> RepeatSamples { get; } } + + public static class HasRepeatsExtensions + { + /// + /// The amount of times the length of this spans. + /// + /// The object that has repeats. + public static int SpanCount(this IHasRepeats obj) => obj.RepeatCount + 1; + } } diff --git a/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs index b0ad3af7d2..f73f338778 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs @@ -1,7 +1,6 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs index 222e8f762f..fc2d21481f 100644 --- a/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs @@ -1,7 +1,6 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - namespace osu.Game.Rulesets.Objects.Types { /// diff --git a/osu.Game/Rulesets/Replays/AutoGenerator.cs b/osu.Game/Rulesets/Replays/AutoGenerator.cs index b8bb63675a..21aa77d4cd 100644 --- a/osu.Game/Rulesets/Replays/AutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/AutoGenerator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 06f7259f78..c245407bbf 100644 --- a/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -102,8 +102,14 @@ namespace osu.Game.Rulesets.Replays if (hasFrames) { - //if we changed frames, we want to execute once *exactly* on the frame's time. - if (currentDirection == time.CompareTo(NextFrame.Time) && advanceFrame()) + // check if the next frame is in the "future" for the current playback direction + if (currentDirection != time.CompareTo(NextFrame.Time)) + { + // if we didn't change frames, we need to ensure we are allowed to run frames in between, else return null. + if (inImportantSection) + return null; + } + else if (advanceFrame()) { // If going backwards, we need to execute once _before_ the frame time to reverse any judgements // that would occur as a result of this frame in forward playback @@ -111,10 +117,6 @@ namespace osu.Game.Rulesets.Replays return currentTime = CurrentFrame.Time - 1; return currentTime = CurrentFrame.Time; } - - //if we didn't change frames, we need to ensure we are allowed to run frames in between, else return null. - if (inImportantSection) - return null; } return currentTime = time; diff --git a/osu.Game/Rulesets/Replays/IAutoGenerator.cs b/osu.Game/Rulesets/Replays/IAutoGenerator.cs index 10925a27cb..7e26fb5758 100644 --- a/osu.Game/Rulesets/Replays/IAutoGenerator.cs +++ b/osu.Game/Rulesets/Replays/IAutoGenerator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Rulesets.Replays diff --git a/osu.Game/Rulesets/Replays/Replay.cs b/osu.Game/Rulesets/Replays/Replay.cs index 89e19434f0..27a77addba 100644 --- a/osu.Game/Rulesets/Replays/Replay.cs +++ b/osu.Game/Rulesets/Replays/Replay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Rulesets/Replays/ReplayButtonState.cs b/osu.Game/Rulesets/Replays/ReplayButtonState.cs index be55a153cb..4421a79af8 100644 --- a/osu.Game/Rulesets/Replays/ReplayButtonState.cs +++ b/osu.Game/Rulesets/Replays/ReplayButtonState.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -15,4 +15,4 @@ namespace osu.Game.Rulesets.Replays Right2 = 8, Smoke = 16 } -} \ No newline at end of file +} diff --git a/osu.Game/Rulesets/Replays/ReplayFrame.cs b/osu.Game/Rulesets/Replays/ReplayFrame.cs index 02c969f648..4f8ed5163e 100644 --- a/osu.Game/Rulesets/Replays/ReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/ReplayFrame.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -52,7 +52,6 @@ namespace osu.Game.Rulesets.Replays protected ReplayFrame() { - } public ReplayFrame(double time, float? mouseX, float? mouseY, ReplayButtonState buttonState) diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 64a2157069..4f256621fb 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -34,9 +34,9 @@ namespace osu.Game.Rulesets public Mod GetAutoplayMod() => GetAllMods().First(mod => mod is ModAutoplay); - protected Ruleset(RulesetInfo rulesetInfo) + protected Ruleset(RulesetInfo rulesetInfo = null) { - RulesetInfo = rulesetInfo; + RulesetInfo = rulesetInfo ?? createRulesetInfo(); } /// @@ -88,5 +88,17 @@ namespace osu.Game.Rulesets /// The variant. /// A descriptive name of the variant. public virtual string GetVariantName(int variant) => string.Empty; + + /// + /// Create a ruleset info based on this ruleset. + /// + /// A filled . + private RulesetInfo createRulesetInfo() => new RulesetInfo + { + Name = Description, + ShortName = ShortName, + InstantiationInfo = GetType().AssemblyQualifiedName, + ID = LegacyID + }; } } diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index c5324d92a9..43da3670b0 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index 3038c51e64..01e3b6848f 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -58,30 +58,21 @@ namespace osu.Game.Rulesets { var context = GetContext(); - var instances = loaded_assemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r, new RulesetInfo())).ToList(); + var instances = loaded_assemblies.Values.Select(r => (Ruleset)Activator.CreateInstance(r, (RulesetInfo)null)).ToList(); //add all legacy modes in correct order foreach (var r in instances.Where(r => r.LegacyID >= 0).OrderBy(r => r.LegacyID)) { - var rulesetInfo = createRulesetInfo(r); - if (context.RulesetInfo.SingleOrDefault(rsi => rsi.ID == rulesetInfo.ID) == null) - { - context.RulesetInfo.Add(rulesetInfo); - } + if (context.RulesetInfo.SingleOrDefault(rsi => rsi.ID == r.RulesetInfo.ID) == null) + context.RulesetInfo.Add(r.RulesetInfo); } context.SaveChanges(); //add any other modes foreach (var r in instances.Where(r => r.LegacyID < 0)) - { - var us = createRulesetInfo(r); - - var existing = context.RulesetInfo.FirstOrDefault(ri => ri.InstantiationInfo == us.InstantiationInfo); - - if (existing == null) - context.RulesetInfo.Add(us); - } + if (context.RulesetInfo.FirstOrDefault(ri => ri.InstantiationInfo == r.RulesetInfo.InstantiationInfo) == null) + context.RulesetInfo.Add(r.RulesetInfo); context.SaveChanges(); @@ -124,13 +115,5 @@ namespace osu.Game.Rulesets { } } - - private RulesetInfo createRulesetInfo(Ruleset ruleset) => new RulesetInfo - { - Name = ruleset.Description, - ShortName = ruleset.ShortName, - InstantiationInfo = ruleset.GetType().AssemblyQualifiedName, - ID = ruleset.LegacyID - }; } } diff --git a/osu.Game/Rulesets/Scoring/HitResult.cs b/osu.Game/Rulesets/Scoring/HitResult.cs index 49ab9fd2f0..05f3b82810 100644 --- a/osu.Game/Rulesets/Scoring/HitResult.cs +++ b/osu.Game/Rulesets/Scoring/HitResult.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs b/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs index 4f603049db..ba16d78b37 100644 --- a/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Scoring/PerformanceCalculator.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Rulesets/Scoring/Score.cs b/osu.Game/Rulesets/Scoring/Score.cs index 025335ba55..ed79333a16 100644 --- a/osu.Game/Rulesets/Scoring/Score.cs +++ b/osu.Game/Rulesets/Scoring/Score.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 23c4464bb1..e8271059ca 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -171,10 +171,10 @@ namespace osu.Game.Rulesets.Scoring public readonly Bindable Mode = new Bindable(); - protected sealed override bool HasCompleted => Hits == MaxHits; + protected sealed override bool HasCompleted => JudgedHits == MaxHits; protected int MaxHits { get; private set; } - protected int Hits { get; private set; } + protected int JudgedHits { get; private set; } private double maxHighestCombo; @@ -259,7 +259,7 @@ namespace osu.Game.Rulesets.Scoring baseScore += judgement.NumericResult; rollingMaxBaseScore += judgement.MaxNumericResult; - Hits++; + JudgedHits++; } else if (judgement.IsHit) bonusScore += judgement.NumericResult; @@ -279,7 +279,7 @@ namespace osu.Game.Rulesets.Scoring baseScore -= judgement.NumericResult; rollingMaxBaseScore -= judgement.MaxNumericResult; - Hits--; + JudgedHits--; } else if (judgement.IsHit) bonusScore -= judgement.NumericResult; @@ -305,14 +305,14 @@ namespace osu.Game.Rulesets.Scoring { if (storeResults) { - MaxHits = Hits; + MaxHits = JudgedHits; maxHighestCombo = HighestCombo; maxBaseScore = baseScore; } base.Reset(storeResults); - Hits = 0; + JudgedHits = 0; baseScore = 0; rollingMaxBaseScore = 0; bonusScore = 0; diff --git a/osu.Game/Rulesets/Scoring/ScoreRank.cs b/osu.Game/Rulesets/Scoring/ScoreRank.cs index f4a6a1e03c..5df52ddf95 100644 --- a/osu.Game/Rulesets/Scoring/ScoreRank.cs +++ b/osu.Game/Rulesets/Scoring/ScoreRank.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Rulesets/Scoring/ScoreStore.cs b/osu.Game/Rulesets/Scoring/ScoreStore.cs index d8a79d8cfb..d21ca79736 100644 --- a/osu.Game/Rulesets/Scoring/ScoreStore.cs +++ b/osu.Game/Rulesets/Scoring/ScoreStore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -10,6 +10,7 @@ using osu.Game.Database; using osu.Game.IO.Legacy; using osu.Game.IPC; using osu.Game.Rulesets.Replays; +using osu.Game.Users; using SharpCompress.Compressors.LZMA; namespace osu.Game.Rulesets.Scoring @@ -54,7 +55,7 @@ namespace osu.Game.Rulesets.Scoring var beatmapHash = sr.ReadString(); score.Beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == beatmapHash); /* score.PlayerName = */ - sr.ReadString(); + score.User = new User { Username = sr.ReadString() }; /* var localScoreChecksum = */ sr.ReadString(); /* score.Count300 = */ @@ -107,7 +108,10 @@ namespace osu.Game.Rulesets.Scoring using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize)) using (var reader = new StreamReader(lzma)) + { score.Replay = createLegacyReplay(reader); + score.Replay.User = score.User; + } } } @@ -129,9 +133,22 @@ namespace osu.Game.Rulesets.Scoring { var split = l.Split('|'); - if (split.Length < 4 || float.Parse(split[0]) < 0) continue; + if (split.Length < 4) + continue; - lastTime += float.Parse(split[0]); + if (split[0] == "-12345") + { + // Todo: The seed is provided in split[3], which we'll need to use at some point + continue; + } + + var diff = float.Parse(split[0]); + lastTime += diff; + + // Todo: At some point we probably want to rewind and play back the negative-time frames + // but for now we'll achieve equal playback to stable by skipping negative frames + if (diff < 0) + continue; frames.Add(new ReplayFrame( lastTime, diff --git a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs b/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs deleted file mode 100644 index b093cf3303..0000000000 --- a/osu.Game/Rulesets/Timing/LinearScrollingContainer.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Graphics; - -namespace osu.Game.Rulesets.Timing -{ - /// - /// A which scrolls linearly relative to the start time. - /// - public class LinearScrollingContainer : ScrollingContainer - { - private readonly MultiplierControlPoint controlPoint; - - public LinearScrollingContainer(MultiplierControlPoint controlPoint) - { - this.controlPoint = controlPoint; - } - - protected override void Update() - { - base.Update(); - - if ((ScrollingAxes & Axes.X) > 0) X = (float)(controlPoint.StartTime - Time.Current); - if ((ScrollingAxes & Axes.Y) > 0) Y = (float)(controlPoint.StartTime - Time.Current); - } - } -} diff --git a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs index ba0e66e04c..450b5da7b8 100644 --- a/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs +++ b/osu.Game/Rulesets/Timing/MultiplierControlPoint.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Timing /// /// The time in milliseconds at which this starts. /// - public readonly double StartTime; + public double StartTime; /// /// The multiplier which this provides. diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs deleted file mode 100644 index eac596297a..0000000000 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Linq; -using osu.Framework.Caching; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Drawables; -using OpenTK; -using osu.Game.Rulesets.Objects.Types; - -namespace osu.Game.Rulesets.Timing -{ - /// - /// A container that scrolls relative to the current time. Will autosize to the total duration of all contained hit objects along the scrolling axes. - /// - public abstract class ScrollingContainer : Container - { - /// - /// Gets or sets the range of time that is visible by the length of the scrolling axes. - /// - public readonly BindableDouble VisibleTimeRange = new BindableDouble { Default = 1000 }; - - /// - /// The axes through which this scrolls. This is set by the . - /// - internal Axes ScrollingAxes; - - public override bool RemoveWhenNotAlive => false; - protected override bool RequiresChildrenUpdate => true; - - /// - /// The control point that defines the speed adjustments for this container. This is set by the . - /// - internal MultiplierControlPoint ControlPoint; - - private Cached durationBacking; - - /// - /// Creates a new . - /// - protected ScrollingContainer() - { - RelativeSizeAxes = Axes.Both; - RelativePositionAxes = Axes.Both; - } - - protected override int Compare(Drawable x, Drawable y) - { - var hX = (DrawableHitObject)x; - var hY = (DrawableHitObject)y; - - int result = hY.HitObject.StartTime.CompareTo(hX.HitObject.StartTime); - if (result != 0) - return result; - return base.Compare(y, x); - } - - public override void Add(DrawableHitObject drawable) - { - durationBacking.Invalidate(); - base.Add(drawable); - } - - public override bool Remove(DrawableHitObject drawable) - { - durationBacking.Invalidate(); - return base.Remove(drawable); - } - - // Todo: This may underestimate the size of the hit object in some cases, but won't be too much of a problem for now - private double computeDuration() => Math.Max(0, Children.Select(c => (c.HitObject as IHasEndTime)?.EndTime ?? c.HitObject.StartTime).DefaultIfEmpty().Max() - ControlPoint.StartTime) + 1000; - - /// - /// An approximate total duration of this scrolling container. - /// - public double Duration => durationBacking.IsValid ? durationBacking : (durationBacking.Value = computeDuration()); - - protected override void Update() - { - base.Update(); - - RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)ControlPoint.StartTime : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)ControlPoint.StartTime : 0); - - // We want our size and position-space along the scrolling axes to span our duration to completely enclose all the hit objects - Size = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)Duration : Size.X, (ScrollingAxes & Axes.Y) > 0 ? (float)Duration : Size.Y); - // And we need to make sure the hit object's position-space doesn't change due to our resizing - RelativeChildSize = Size; - } - } -} diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs deleted file mode 100644 index 81e3a5c70e..0000000000 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.Objects.Drawables; -using OpenTK; - -namespace osu.Game.Rulesets.Timing -{ - /// - /// A container that provides the speed adjustments defined by s to affect the scroll speed - /// of container s. - /// - public class SpeedAdjustmentContainer : Container - { - /// - /// Gets or sets the range of time that is visible by the length of the scrolling axes. - /// - public readonly Bindable VisibleTimeRange = new Bindable { Default = 1000 }; - - /// - /// Whether to reverse the scrolling direction is reversed. - /// - public readonly BindableBool Reversed = new BindableBool(); - - protected override Container Content => content; - private readonly Container content; - - /// - /// The axes which the content of this container will scroll through. - /// - public Axes ScrollingAxes - { - get { return scrollingContainer.ScrollingAxes; } - set { scrollingContainer.ScrollingAxes = value; } - } - - public override bool RemoveWhenNotAlive => false; - protected override bool RequiresChildrenUpdate => true; - - /// - /// The that defines the speed adjustments. - /// - public readonly MultiplierControlPoint ControlPoint; - - private readonly ScrollingContainer scrollingContainer; - - /// - /// Creates a new . - /// - /// The that defines the speed adjustments. - public SpeedAdjustmentContainer(MultiplierControlPoint controlPoint) - { - ControlPoint = controlPoint; - RelativeSizeAxes = Axes.Both; - - scrollingContainer = CreateScrollingContainer(); - scrollingContainer.ControlPoint = ControlPoint; - scrollingContainer.VisibleTimeRange.BindTo(VisibleTimeRange); - - AddInternal(content = scrollingContainer); - } - - protected override void Update() - { - float multiplier = (float)ControlPoint.Multiplier; - - // The speed adjustment happens by modifying our size by the multiplier while maintaining the visible time range as the relatve size for our children - Size = new Vector2((ScrollingAxes & Axes.X) > 0 ? multiplier : 1, (ScrollingAxes & Axes.Y) > 0 ? multiplier : 1); - - if (Reversed) - { - RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)-VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)-VisibleTimeRange : 1); - RelativeChildOffset = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 0, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 0); - Origin = Anchor = Anchor.BottomRight; - } - else - { - RelativeChildSize = new Vector2((ScrollingAxes & Axes.X) > 0 ? (float)VisibleTimeRange : 1, (ScrollingAxes & Axes.Y) > 0 ? (float)VisibleTimeRange : 1); - RelativeChildOffset = Vector2.Zero; - Origin = Anchor = Anchor.TopLeft; - } - } - - public override double LifetimeStart => ControlPoint.StartTime - VisibleTimeRange; - public override double LifetimeEnd => ControlPoint.StartTime + scrollingContainer.Duration + VisibleTimeRange; - - public override void Add(DrawableHitObject drawable) - { - var scrollingHitObject = drawable as IScrollingHitObject; - - if (scrollingHitObject != null) - { - scrollingHitObject.LifetimeOffset.BindTo(VisibleTimeRange); - scrollingHitObject.ScrollingAxes = ScrollingAxes; - } - - base.Add(drawable); - } - - /// - /// Whether a point in time falls within this s affecting timespan. - /// - public bool CanContain(double startTime) => ControlPoint.StartTime <= startTime; - - /// - /// Creates the which contains the scrolling s of this container. - /// - /// The . - protected virtual ScrollingContainer CreateScrollingContainer() => new LinearScrollingContainer(ControlPoint); - } -} diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs new file mode 100644 index 0000000000..c26a6cdff0 --- /dev/null +++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Objects.Drawables; + +namespace osu.Game.Rulesets.UI +{ + public class HitObjectContainer : CompositeDrawable + { + public virtual IEnumerable Objects => InternalChildren.Cast(); + public virtual IEnumerable AliveObjects => AliveInternalChildren.Cast(); + + public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); + public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); + } +} diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs index 90f63aeab6..f01069118c 100644 --- a/osu.Game/Rulesets/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs index b4a26344d5..a7fed7059b 100644 --- a/osu.Game/Rulesets/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -1,15 +1,12 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; +using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Objects.Drawables; using OpenTK; -using osu.Game.Rulesets.Judgements; using osu.Framework.Allocation; -using System.Collections.Generic; -using System.Linq; namespace osu.Game.Rulesets.UI { @@ -18,26 +15,27 @@ namespace osu.Game.Rulesets.UI /// /// The HitObjects contained in this Playfield. /// - public HitObjectContainer HitObjects { get; protected set; } + public HitObjectContainer HitObjects { get; private set; } public Container ScaledContent; - /// - /// Whether we are currently providing the local user a gameplay cursor. - /// - public virtual bool ProvidingUserCursor => false; - protected override Container Content => content; private readonly Container content; + private List nestedPlayfields; + + /// + /// All the s nested inside this playfield. + /// + public IReadOnlyList NestedPlayfields => nestedPlayfields; + /// /// A container for keeping track of DrawableHitObjects. /// /// Whether we want our internal coordinate system to be scaled to a specified width. protected Playfield(float? customWidth = null) { - // Default height since we force relative size axes - Size = Vector2.One; + RelativeSizeAxes = Axes.Both; AddInternal(ScaledContent = new ScaledContainer { @@ -51,29 +49,21 @@ namespace osu.Game.Rulesets.UI } } }); - - HitObjects = new HitObjectContainer - { - RelativeSizeAxes = Axes.Both, - }; } [BackgroundDependencyLoader] private void load() { - Add(HitObjects); - } + HitObjects = CreateHitObjectContainer(); + HitObjects.RelativeSizeAxes = Axes.Both; - public override Axes RelativeSizeAxes - { - get { return Axes.Both; } - set { throw new InvalidOperationException($@"{nameof(Playfield)}'s {nameof(RelativeSizeAxes)} should never be changed from {Axes.Both}"); } + Add(HitObjects); } /// /// Performs post-processing tasks (if any) after all DrawableHitObjects are loaded into this Playfield. /// - public virtual void PostProcess() { } + public virtual void PostProcess() => nestedPlayfields?.ForEach(p => p.PostProcess()); /// /// Adds a DrawableHitObject to this Playfield. @@ -88,19 +78,23 @@ namespace osu.Game.Rulesets.UI public virtual void Remove(DrawableHitObject h) => HitObjects.Remove(h); /// - /// Triggered when a new occurs on a . + /// Registers a as a nested . + /// This does not add the to the draw hierarchy. /// - /// The object that occured for. - /// The that occurred. - public virtual void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { } - - public class HitObjectContainer : CompositeDrawable + /// The to add. + protected void AddNested(Playfield otherPlayfield) { - public virtual IEnumerable Objects => InternalChildren.OfType(); - public virtual void Add(DrawableHitObject hitObject) => AddInternal(hitObject); - public virtual bool Remove(DrawableHitObject hitObject) => RemoveInternal(hitObject); + if (nestedPlayfields == null) + nestedPlayfields = new List(); + + nestedPlayfields.Add(otherPlayfield); } + /// + /// Creates the container that will be used to contain the s. + /// + protected virtual HitObjectContainer CreateHitObjectContainer() => new HitObjectContainer(); + private class ScaledContainer : Container { /// @@ -110,6 +104,12 @@ namespace osu.Game.Rulesets.UI //dividing by the customwidth will effectively scale our content to the required container size. protected override Vector2 DrawScale => CustomWidth.HasValue ? new Vector2(DrawSize.X / CustomWidth.Value) : base.DrawScale; + + protected override void Update() + { + base.Update(); + RelativeChildSize = new Vector2(DrawScale.X, RelativeChildSize.Y); + } } } } diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 3706033b68..0f88b262f6 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -13,7 +13,12 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using osu.Framework.Configuration; +using osu.Framework.Graphics.Cursor; using osu.Framework.Input; +using osu.Game.Configuration; +using osu.Game.Overlays; +using osu.Game.Rulesets.Configuration; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; using OpenTK; @@ -33,6 +38,11 @@ namespace osu.Game.Rulesets.UI /// public bool AspectAdjust = true; + /// + /// The selected variant. + /// + public virtual int Variant => 0; + /// /// The input manager for this RulesetContainer. /// @@ -44,14 +54,9 @@ namespace osu.Game.Rulesets.UI public PassThroughInputManager KeyBindingInputManager; /// - /// Whether we are currently providing the local user a gameplay cursor. + /// Whether a replay is currently loaded. /// - public virtual bool ProvidingUserCursor => false; - - /// - /// Whether we have a replay loaded currently. - /// - public bool HasReplayLoaded => ReplayInputManager?.ReplayInputHandler != null; + public readonly BindableBool HasReplayLoaded = new BindableBool(); public abstract IEnumerable Objects { get; } @@ -61,8 +66,21 @@ namespace osu.Game.Rulesets.UI /// public Playfield Playfield => playfield.Value; + /// + /// The cursor provided by this . May be null if no cursor is provided. + /// + public readonly CursorContainer Cursor; + protected readonly Ruleset Ruleset; + private IRulesetConfigManager rulesetConfig; + private OnScreenDisplay onScreenDisplay; + + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) + => dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + /// /// A visual representation of a . /// @@ -71,6 +89,22 @@ namespace osu.Game.Rulesets.UI { Ruleset = ruleset; playfield = new Lazy(CreatePlayfield); + + Cursor = CreateCursor(); + } + + [BackgroundDependencyLoader(true)] + private void load(OnScreenDisplay onScreenDisplay, SettingsStore settings) + { + this.onScreenDisplay = onScreenDisplay; + + rulesetConfig = CreateConfig(Ruleset, settings); + + if (rulesetConfig != null) + { + dependencies.Cache(rulesetConfig); + onScreenDisplay?.BeginTracking(this, rulesetConfig); + } } public abstract ScoreProcessor CreateScoreProcessor(); @@ -96,13 +130,34 @@ namespace osu.Game.Rulesets.UI Replay = replay; ReplayInputManager.ReplayInputHandler = replay != null ? CreateReplayInputHandler(replay) : null; + + HasReplayLoaded.Value = ReplayInputManager.ReplayInputHandler != null; } + + /// + /// Creates the cursor. May be null if the doesn't provide a custom cursor. + /// + protected virtual CursorContainer CreateCursor() => null; + + protected virtual IRulesetConfigManager CreateConfig(Ruleset ruleset, SettingsStore settings) => null; + /// /// Creates a Playfield. /// /// The Playfield. protected abstract Playfield CreatePlayfield(); + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (rulesetConfig != null) + { + onScreenDisplay?.StopTracking(this, rulesetConfig); + rulesetConfig = null; + } + } } /// @@ -142,9 +197,7 @@ namespace osu.Game.Rulesets.UI /// /// Whether the specified beatmap is assumed to be specific to the current ruleset. /// - protected readonly bool IsForCurrentRuleset; - - public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor; + public readonly bool IsForCurrentRuleset; public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(this); @@ -177,6 +230,10 @@ namespace osu.Game.Rulesets.UI if (!converter.CanConvert(workingBeatmap.Beatmap)) throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can not be converted for the current ruleset (converter: {converter})."); + // Apply conversion adjustments before converting + foreach (var mod in Mods.OfType>()) + mod.ApplyToBeatmapConverter(converter); + // Convert the beatmap Beatmap = converter.Convert(workingBeatmap.Beatmap); @@ -184,13 +241,13 @@ namespace osu.Game.Rulesets.UI foreach (var mod in Mods.OfType()) mod.ApplyToDifficulty(Beatmap.BeatmapInfo.BaseDifficulty); + // Post-process the beatmap + processor.PostProcess(Beatmap); + // Apply defaults foreach (var h in Beatmap.HitObjects) h.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty); - // Post-process the beatmap - processor.PostProcess(Beatmap); - KeyBindingInputManager = CreateInputManager(); KeyBindingInputManager.RelativeSizeAxes = Axes.Both; @@ -209,6 +266,9 @@ namespace osu.Game.Rulesets.UI AddInternal(KeyBindingInputManager); KeyBindingInputManager.Add(Playfield); + if (Cursor != null) + KeyBindingInputManager.Add(Cursor); + loadObjects(); } @@ -249,12 +309,7 @@ namespace osu.Game.Rulesets.UI if (drawableObject == null) continue; - drawableObject.OnJudgement += (d, j) => - { - Playfield.OnJudgement(d, j); - OnJudgement?.Invoke(j); - }; - + drawableObject.OnJudgement += (d, j) => OnJudgement?.Invoke(j); drawableObject.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(j); Playfield.Add(drawableObject); diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index 5cd79cff29..f465d0e202 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.UI public abstract class RulesetInputManager : PassThroughInputManager, ICanAttachKeyCounter, IHasReplayHandler where T : struct { - public class RulesetKeyBindingContainer : DatabasedKeyBindingInputManager + public class RulesetKeyBindingContainer : DatabasedKeyBindingContainer { public RulesetKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique) : base(ruleset, variant, unique) @@ -136,9 +136,22 @@ namespace osu.Game.Rulesets.UI int loops = 0; while (validState && requireMoreUpdateLoops && loops++ < max_catch_up_updates_per_frame) + { if (!base.UpdateSubTree()) return false; + UpdateSubTreeMasking(this, ScreenSpaceDrawQuad.AABBFloat); + + if (isAttached) + { + // When handling replay input, we need to consider the possibility of fast-forwarding, which may cause the clock to be updated + // to a point very far into the future, then playing a frame at that time. In such a case, lifetime MUST be updated before + // input is handled. This is why base.Update is not called from the derived Update when handling replay input, and is instead + // called manually at the correct time here. + base.Update(); + } + } + return true; } @@ -173,8 +186,11 @@ namespace osu.Game.Rulesets.UI // to ensure that the its time is valid for our children before input is processed Clock.ProcessFrame(); - // Process input - base.Update(); + if (!isAttached) + { + // For non-replay input handling, this provides equivalent input ordering as if Update was not overridden + base.Update(); + } } #endregion diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs new file mode 100644 index 0000000000..372bdb1030 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingDirection.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.UI.Scrolling +{ + public enum ScrollingDirection + { + /// + /// Hitobjects will scroll vertically from the bottom of the hitobject container. + /// + Up, + /// + /// Hitobjects will scroll vertically from the top of the hitobject container. + /// + Down, + /// + /// Hitobjects will scroll horizontally from the right of the hitobject container. + /// + Left, + /// + /// Hitobjects will scroll horizontally from the left of the hitobject container. + /// + Right + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs new file mode 100644 index 0000000000..530ed653aa --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -0,0 +1,116 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Caching; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Lists; +using osu.Game.Configuration; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Timing; +using osu.Game.Rulesets.UI.Scrolling.Visualisers; + +namespace osu.Game.Rulesets.UI.Scrolling +{ + public class ScrollingHitObjectContainer : HitObjectContainer + { + /// + /// The duration required to scroll through one length of the before any control point adjustments. + /// + public readonly BindableDouble TimeRange = new BindableDouble + { + MinValue = 0, + MaxValue = double.MaxValue + }; + + /// + /// The control points that adjust the scrolling speed. + /// + protected readonly SortedList ControlPoints = new SortedList(); + + private readonly ScrollingDirection direction; + + private Cached initialStateCache = new Cached(); + + public ScrollingHitObjectContainer(ScrollingDirection direction) + { + this.direction = direction; + + RelativeSizeAxes = Axes.Both; + + TimeRange.ValueChanged += v => initialStateCache.Invalidate(); + } + + private ISpeedChangeVisualiser speedChangeVisualiser; + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + switch (config.Get(OsuSetting.SpeedChangeVisualisation)) + { + case SpeedChangeVisualisationMethod.Sequential: + speedChangeVisualiser = new SequentialSpeedChangeVisualiser(ControlPoints); + break; + case SpeedChangeVisualisationMethod.Overlapping: + speedChangeVisualiser = new OverlappingSpeedChangeVisualiser(ControlPoints); + break; + } + } + + public override void Add(DrawableHitObject hitObject) + { + initialStateCache.Invalidate(); + base.Add(hitObject); + } + + public override bool Remove(DrawableHitObject hitObject) + { + var result = base.Remove(hitObject); + if (result) + initialStateCache.Invalidate(); + return result; + } + + public void AddControlPoint(MultiplierControlPoint controlPoint) + { + ControlPoints.Add(controlPoint); + initialStateCache.Invalidate(); + } + + public bool RemoveControlPoint(MultiplierControlPoint controlPoint) + { + var result = ControlPoints.Remove(controlPoint); + if (result) + initialStateCache.Invalidate(); + return result; + } + + public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) + { + if ((invalidation & (Invalidation.RequiredParentSizeToFit | Invalidation.DrawInfo)) > 0) + initialStateCache.Invalidate(); + + return base.Invalidate(invalidation, source, shallPropagate); + } + + protected override void Update() + { + base.Update(); + + if (!initialStateCache.IsValid) + { + speedChangeVisualiser.ComputeInitialStates(Objects, direction, TimeRange, DrawSize); + initialStateCache.Validate(); + } + } + + protected override void UpdateAfterChildrenLife() + { + base.UpdateAfterChildrenLife(); + + // We need to calculate this as soon as possible after lifetimes so that hitobjects get the final say in their positions + speedChangeVisualiser.ComputePositions(AliveObjects, direction, Time.Current, TimeRange, DrawSize); + } + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs new file mode 100644 index 0000000000..287e917c7b --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -0,0 +1,122 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; +using osu.Framework.Input; +using osu.Framework.MathUtils; +using osu.Game.Rulesets.Objects.Drawables; +using OpenTK.Input; + +namespace osu.Game.Rulesets.UI.Scrolling +{ + /// + /// A type of specialized towards scrolling s. + /// + public abstract class ScrollingPlayfield : Playfield + { + /// + /// The default span of time visible by the length of the scrolling axes. + /// This is clamped between and . + /// + private const double time_span_default = 1500; + /// + /// The minimum span of time that may be visible by the length of the scrolling axes. + /// + private const double time_span_min = 50; + /// + /// The maximum span of time that may be visible by the length of the scrolling axes. + /// + private const double time_span_max = 10000; + /// + /// The step increase/decrease of the span of time visible by the length of the scrolling axes. + /// + private const double time_span_step = 50; + + /// + /// The span of time that is visible by the length of the scrolling axes. + /// For example, only hit objects with start time less than or equal to 1000 will be visible with = 1000. + /// + public readonly BindableDouble VisibleTimeRange = new BindableDouble(time_span_default) + { + Default = time_span_default, + MinValue = time_span_min, + MaxValue = time_span_max + }; + + /// + /// Whether the player can change . + /// + protected virtual bool UserScrollSpeedAdjustment => true; + + /// + /// The container that contains the s and s. + /// + public new ScrollingHitObjectContainer HitObjects => (ScrollingHitObjectContainer)base.HitObjects; + + private readonly ScrollingDirection direction; + + /// + /// Creates a new . + /// + /// The axes on which s in this container should scroll. + /// Whether we want our internal coordinate system to be scaled to a specified width + protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null) + : base(customWidth) + { + this.direction = direction; + } + + [BackgroundDependencyLoader] + private void load() + { + HitObjects.TimeRange.BindTo(VisibleTimeRange); + } + + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + { + if (!UserScrollSpeedAdjustment) + return false; + + if (state.Keyboard.ControlPressed) + { + switch (args.Key) + { + case Key.Minus: + transformVisibleTimeRangeTo(VisibleTimeRange + time_span_step, 200, Easing.OutQuint); + break; + case Key.Plus: + transformVisibleTimeRangeTo(VisibleTimeRange - time_span_step, 200, Easing.OutQuint); + break; + } + } + + return false; + } + + private void transformVisibleTimeRangeTo(double newTimeRange, double duration = 0, Easing easing = Easing.None) + { + this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing)); + } + + protected sealed override HitObjectContainer CreateHitObjectContainer() => new ScrollingHitObjectContainer(direction); + + private class TransformVisibleTimeRange : Transform + { + private double valueAt(double time) + { + if (time < StartTime) return StartValue; + if (time >= EndTime) return EndValue; + + return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + } + + public override string TargetMember => "VisibleTimeRange.Value"; + + protected override void Apply(ScrollingPlayfield d, double time) => d.VisibleTimeRange.Value = valueAt(time); + protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value; + } + } +} diff --git a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs similarity index 76% rename from osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs rename to osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs index f1b8838fa9..5f6b6801ce 100644 --- a/osu.Game/Rulesets/UI/ScrollingRulesetContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingRulesetContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -13,7 +13,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Timing; -namespace osu.Game.Rulesets.UI +namespace osu.Game.Rulesets.UI.Scrolling { /// /// A type of that supports a . @@ -70,12 +70,10 @@ namespace osu.Game.Rulesets.UI // Perform some post processing of the timing changes timingChanges = timingChanges - // Collapse sections after the last hit object - .Where(s => s.StartTime <= lastObjectTime) - // Collapse sections with the same start time - .GroupBy(s => s.StartTime).Select(g => g.Last()).OrderBy(s => s.StartTime) - // Collapse sections with the same beat length - .GroupBy(s => s.TimingPoint.BeatLength * s.DifficultyPoint.SpeedMultiplier).Select(g => g.First()); + // Collapse sections after the last hit object + .Where(s => s.StartTime <= lastObjectTime) + // Collapse sections with the same start time + .GroupBy(s => s.StartTime).Select(g => g.Last()).OrderBy(s => s.StartTime); DefaultControlPoints.AddRange(timingChanges); @@ -88,8 +86,8 @@ namespace osu.Game.Rulesets.UI private void applySpeedAdjustment(MultiplierControlPoint controlPoint, ScrollingPlayfield playfield) { - playfield.HitObjects.AddSpeedAdjustment(CreateSpeedAdjustmentContainer(controlPoint)); - playfield.NestedPlayfields.ForEach(p => applySpeedAdjustment(controlPoint, p)); + playfield.HitObjects.AddControlPoint(controlPoint); + playfield.NestedPlayfields?.OfType().ForEach(p => applySpeedAdjustment(controlPoint, p)); } /// @@ -108,12 +106,5 @@ namespace osu.Game.Rulesets.UI return new MultiplierControlPoint(time, DefaultControlPoints[index].DeepClone()); } - - /// - /// Creates a that facilitates the movement of hit objects. - /// - /// The that provides the speed adjustments for the hitobjects. - /// The . - protected virtual SpeedAdjustmentContainer CreateSpeedAdjustmentContainer(MultiplierControlPoint controlPoint) => new SpeedAdjustmentContainer(controlPoint); } } diff --git a/osu.Game/Rulesets/UI/Scrolling/Visualisers/ISpeedChangeVisualiser.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/ISpeedChangeVisualiser.cs new file mode 100644 index 0000000000..46d71e1602 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/ISpeedChangeVisualiser.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Game.Rulesets.Objects.Drawables; +using OpenTK; + +namespace osu.Game.Rulesets.UI.Scrolling.Visualisers +{ + public interface ISpeedChangeVisualiser + { + /// + /// Computes the states of s that are constant, such as lifetime and spatial length. + /// This is invoked once whenever or changes. + /// + /// The s whose states should be computed. + /// The scrolling direction. + /// The duration required to scroll through one length of the screen before any control point adjustments. + /// The length of the screen that is scrolled through. + void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length); + + /// + /// Computes the states of s that change depending on , such as position. + /// This is invoked once per frame. + /// + /// The s whose states should be computed. + /// The scrolling direction. + /// The current time. + /// The duration required to scroll through one length of the screen before any control point adjustments. + /// The length of the screen that is scrolled through. + void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length); + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs new file mode 100644 index 0000000000..4cce90ee94 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/OverlappingSpeedChangeVisualiser.cs @@ -0,0 +1,80 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Framework.Lists; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Timing; +using OpenTK; + +namespace osu.Game.Rulesets.UI.Scrolling.Visualisers +{ + public class OverlappingSpeedChangeVisualiser : ISpeedChangeVisualiser + { + private readonly SortedList controlPoints; + + public OverlappingSpeedChangeVisualiser(SortedList controlPoints) + { + this.controlPoints = controlPoints; + } + + public void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var controlPoint = controlPointAt(obj.HitObject.StartTime); + obj.LifetimeStart = obj.HitObject.StartTime - timeRange / controlPoint.Multiplier; + + if (obj.NestedHitObjects != null) + { + ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length); + ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); + } + } + } + + public void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var controlPoint = controlPointAt(obj.HitObject.StartTime); + + var position = (obj.HitObject.StartTime - currentTime) * controlPoint.Multiplier / timeRange; + + switch (direction) + { + case ScrollingDirection.Up: + obj.Y = (float)(position * length.Y); + break; + case ScrollingDirection.Down: + obj.Y = (float)(-position * length.Y); + break; + case ScrollingDirection.Left: + obj.X = (float)(position * length.X); + break; + case ScrollingDirection.Right: + obj.X = (float)(-position * length.X); + break; + } + } + } + + private readonly MultiplierControlPoint searchPoint = new MultiplierControlPoint(); + private MultiplierControlPoint controlPointAt(double time) + { + if (controlPoints.Count == 0) + return new MultiplierControlPoint(double.NegativeInfinity); + + if (time < controlPoints[0].StartTime) + return controlPoints[0]; + + searchPoint.StartTime = time; + int index = controlPoints.BinarySearch(searchPoint); + + if (index < 0) + index = ~index - 1; + + return controlPoints[index]; + } + } +} diff --git a/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs b/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs new file mode 100644 index 0000000000..94705426f8 --- /dev/null +++ b/osu.Game/Rulesets/UI/Scrolling/Visualisers/SequentialSpeedChangeVisualiser.cs @@ -0,0 +1,103 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Timing; +using OpenTK; + +namespace osu.Game.Rulesets.UI.Scrolling.Visualisers +{ + public class SequentialSpeedChangeVisualiser : ISpeedChangeVisualiser + { + private readonly Dictionary hitObjectPositions = new Dictionary(); + + private readonly IReadOnlyList controlPoints; + + public SequentialSpeedChangeVisualiser(IReadOnlyList controlPoints) + { + this.controlPoints = controlPoints; + } + + public void ComputeInitialStates(IEnumerable hitObjects, ScrollingDirection direction, double timeRange, Vector2 length) + { + foreach (var obj in hitObjects) + { + var startPosition = hitObjectPositions[obj] = positionAt(obj.HitObject.StartTime, timeRange); + + obj.LifetimeStart = obj.HitObject.StartTime - timeRange - 1000; + + if (obj.HitObject is IHasEndTime endTime) + { + var diff = positionAt(endTime.EndTime, timeRange) - startPosition; + + switch (direction) + { + case ScrollingDirection.Up: + case ScrollingDirection.Down: + obj.Height = (float)(diff * length.Y); + break; + case ScrollingDirection.Left: + case ScrollingDirection.Right: + obj.Width = (float)(diff * length.X); + break; + } + } + + if (obj.NestedHitObjects != null) + { + ComputeInitialStates(obj.NestedHitObjects, direction, timeRange, length); + ComputePositions(obj.NestedHitObjects, direction, obj.HitObject.StartTime, timeRange, length); + } + } + } + + public void ComputePositions(IEnumerable hitObjects, ScrollingDirection direction, double currentTime, double timeRange, Vector2 length) + { + var timelinePosition = positionAt(currentTime, timeRange); + + foreach (var obj in hitObjects) + { + var finalPosition = hitObjectPositions[obj] - timelinePosition; + + switch (direction) + { + case ScrollingDirection.Up: + obj.Y = (float)(finalPosition * length.Y); + break; + case ScrollingDirection.Down: + obj.Y = (float)(-finalPosition * length.Y); + break; + case ScrollingDirection.Left: + obj.X = (float)(finalPosition * length.X); + break; + case ScrollingDirection.Right: + obj.X = (float)(-finalPosition * length.X); + break; + } + } + } + + private double positionAt(double time, double timeRange) + { + double length = 0; + for (int i = 0; i < controlPoints.Count; i++) + { + var current = controlPoints[i]; + var next = i < controlPoints.Count - 1 ? controlPoints[i + 1] : null; + + if (i > 0 && current.StartTime > time) + continue; + + // Duration of the current control point + var currentDuration = (next?.StartTime ?? double.PositiveInfinity) - current.StartTime; + + length += Math.Min(currentDuration, time - current.StartTime) * current.Multiplier / timeRange; + } + + return length; + } + } +} diff --git a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/ScrollingPlayfield.cs deleted file mode 100644 index cff3a029e6..0000000000 --- a/osu.Game/Rulesets/UI/ScrollingPlayfield.cs +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using System.Linq; -using OpenTK.Input; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Transforms; -using osu.Framework.Input; -using osu.Framework.MathUtils; -using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Timing; - -namespace osu.Game.Rulesets.UI -{ - /// - /// A type of specialized towards scrolling s. - /// - public class ScrollingPlayfield : Playfield - { - /// - /// The default span of time visible by the length of the scrolling axes. - /// This is clamped between and . - /// - private const double time_span_default = 1500; - /// - /// The minimum span of time that may be visible by the length of the scrolling axes. - /// - private const double time_span_min = 50; - /// - /// The maximum span of time that may be visible by the length of the scrolling axes. - /// - private const double time_span_max = 10000; - /// - /// The step increase/decrease of the span of time visible by the length of the scrolling axes. - /// - private const double time_span_step = 50; - - /// - /// The span of time that is visible by the length of the scrolling axes. - /// For example, only hit objects with start time less than or equal to 1000 will be visible with = 1000. - /// - public readonly BindableDouble VisibleTimeRange = new BindableDouble(time_span_default) - { - Default = time_span_default, - MinValue = time_span_min, - MaxValue = time_span_max - }; - - /// - /// Whether to reverse the scrolling direction is reversed. Note that this does _not_ invert the hit objects. - /// - protected readonly BindableBool Reversed = new BindableBool(); - - /// - /// The container that contains the s and s. - /// - public new readonly ScrollingHitObjectContainer HitObjects; - - /// - /// Creates a new . - /// - /// The axes on which s in this container should scroll. - /// Whether we want our internal coordinate system to be scaled to a specified width - protected ScrollingPlayfield(Axes scrollingAxes, float? customWidth = null) - : base(customWidth) - { - base.HitObjects = HitObjects = new ScrollingHitObjectContainer(scrollingAxes) { RelativeSizeAxes = Axes.Both }; - HitObjects.VisibleTimeRange.BindTo(VisibleTimeRange); - HitObjects.Reversed.BindTo(Reversed); - } - - private List nestedPlayfields; - /// - /// All the s nested inside this playfield. - /// - public IEnumerable NestedPlayfields => nestedPlayfields; - - /// - /// Adds a to this playfield. The nested - /// will be given all of the same speed adjustments as this playfield. - /// - /// The to add. - protected void AddNested(ScrollingPlayfield otherPlayfield) - { - if (nestedPlayfields == null) - nestedPlayfields = new List(); - - nestedPlayfields.Add(otherPlayfield); - } - - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) - { - if (state.Keyboard.ControlPressed) - { - switch (args.Key) - { - case Key.Minus: - transformVisibleTimeRangeTo(VisibleTimeRange + time_span_step, 200, Easing.OutQuint); - break; - case Key.Plus: - transformVisibleTimeRangeTo(VisibleTimeRange - time_span_step, 200, Easing.OutQuint); - break; - } - } - - return false; - } - - private void transformVisibleTimeRangeTo(double newTimeRange, double duration = 0, Easing easing = Easing.None) - { - this.TransformTo(this.PopulateTransform(new TransformVisibleTimeRange(), newTimeRange, duration, easing)); - } - - private class TransformVisibleTimeRange : Transform - { - private double valueAt(double time) - { - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - - public override string TargetMember => "VisibleTimeRange.Value"; - - protected override void Apply(ScrollingPlayfield d, double time) => d.VisibleTimeRange.Value = valueAt(time); - protected override void ReadIntoStartValue(ScrollingPlayfield d) => StartValue = d.VisibleTimeRange.Value; - } - - /// - /// A container that provides the foundation for sorting s into s. - /// - public class ScrollingHitObjectContainer : HitObjectContainer - { - /// - /// Gets or sets the range of time that is visible by the length of the scrolling axes. - /// For example, only hit objects with start time less than or equal to 1000 will be visible with = 1000. - /// - public readonly BindableDouble VisibleTimeRange = new BindableDouble { Default = 1000 }; - - /// - /// Whether to reverse the scrolling direction is reversed. - /// - public readonly BindableBool Reversed = new BindableBool(); - - private readonly SortedContainer speedAdjustments; - public IReadOnlyList SpeedAdjustments => speedAdjustments; - - private readonly SpeedAdjustmentContainer defaultSpeedAdjustment; - - private readonly Axes scrollingAxes; - - /// - /// Creates a new . - /// - /// The axes upon which hit objects should appear to scroll inside this container. - public ScrollingHitObjectContainer(Axes scrollingAxes) - { - this.scrollingAxes = scrollingAxes; - - AddInternal(speedAdjustments = new SortedContainer { RelativeSizeAxes = Axes.Both }); - - // Default speed adjustment - AddSpeedAdjustment(defaultSpeedAdjustment = new SpeedAdjustmentContainer(new MultiplierControlPoint(0))); - } - - /// - /// Adds a to this container, re-sorting all hit objects - /// in the last that occurred (time-wise) before it. - /// - /// The . - public void AddSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) - { - speedAdjustment.ScrollingAxes = scrollingAxes; - speedAdjustment.VisibleTimeRange.BindTo(VisibleTimeRange); - speedAdjustment.Reversed.BindTo(Reversed); - - if (speedAdjustments.Count > 0) - { - // We need to re-sort all hit objects in the speed adjustment container prior to figure out if they - // should now lie within this one - var existingAdjustment = adjustmentContainerAt(speedAdjustment.ControlPoint.StartTime); - for (int i = 0; i < existingAdjustment.Count; i++) - { - DrawableHitObject hitObject = existingAdjustment[i]; - - if (!speedAdjustment.CanContain(hitObject.HitObject.StartTime)) - continue; - - existingAdjustment.Remove(hitObject); - speedAdjustment.Add(hitObject); - - i--; - } - } - - speedAdjustments.Add(speedAdjustment); - } - - /// - /// Removes a from this container, re-sorting all hit objects - /// which it contained into new s. - /// - /// The to remove. - public void RemoveSpeedAdjustment(SpeedAdjustmentContainer speedAdjustment) - { - if (speedAdjustment == defaultSpeedAdjustment) - throw new InvalidOperationException($"The default {nameof(SpeedAdjustmentContainer)} must not be removed."); - - if (!speedAdjustments.Remove(speedAdjustment)) - return; - - while (speedAdjustment.Count > 0) - { - DrawableHitObject hitObject = speedAdjustment[0]; - - speedAdjustment.Remove(hitObject); - Add(hitObject); - } - } - - public override IEnumerable Objects => speedAdjustments.SelectMany(s => s.Children); - - /// - /// Adds a hit object to this . The hit objects will be queued to be processed - /// new s are added to this . - /// - /// The hit object to add. - public override void Add(DrawableHitObject hitObject) - { - if (!(hitObject is IScrollingHitObject)) - throw new InvalidOperationException($"Hit objects added to a {nameof(ScrollingHitObjectContainer)} must implement {nameof(IScrollingHitObject)}."); - - adjustmentContainerAt(hitObject.HitObject.StartTime).Add(hitObject); - } - - public override bool Remove(DrawableHitObject hitObject) => speedAdjustments.Any(s => s.Remove(hitObject)); - - /// - /// Finds the which provides the speed adjustment active at a time. - /// If there is no active at the time, then the first (time-wise) speed adjustment is returned. - /// - /// The time to find the active at. - /// The active at . Null if there are no speed adjustments. - private SpeedAdjustmentContainer adjustmentContainerAt(double time) => speedAdjustments.FirstOrDefault(c => c.CanContain(time)) ?? defaultSpeedAdjustment; - - private class SortedContainer : Container - { - protected override int Compare(Drawable x, Drawable y) - { - var sX = (SpeedAdjustmentContainer)x; - var sY = (SpeedAdjustmentContainer)y; - - // ReSharper disable once ImpureMethodCallOnReadonlyValueField - int result = sY.ControlPoint.StartTime.CompareTo(sX.ControlPoint.StartTime); - if (result != 0) - return result; - return base.Compare(y, x); - } - } - } - } -} diff --git a/osu.Game/Screens/BackgroundScreen.cs b/osu.Game/Screens/BackgroundScreen.cs index 5b07ca6020..c5e5883b99 100644 --- a/osu.Game/Screens/BackgroundScreen.cs +++ b/osu.Game/Screens/BackgroundScreen.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 7ae3f6931e..1ce84289b2 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -1,9 +1,10 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Transforms; using OpenTK; using osu.Game.Beatmaps; using osu.Game.Graphics.Backgrounds; @@ -19,10 +20,7 @@ namespace osu.Game.Screens.Backgrounds public WorkingBeatmap Beatmap { - get - { - return beatmap; - } + get { return beatmap; } set { if (beatmap == value && beatmap != null) @@ -56,11 +54,8 @@ namespace osu.Game.Screens.Backgrounds Beatmap = beatmap; } - public void BlurTo(Vector2 sigma, double duration, Easing easing = Easing.None) - { - background?.BlurTo(sigma, duration, easing); - blurTarget = sigma; - } + public TransformSequence BlurTo(Vector2 sigma, double duration, Easing easing = Easing.None) + => background?.BlurTo(blurTarget = sigma, duration, easing); public override bool Equals(BackgroundScreen other) { diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs index dd377938a7..629f5ea3db 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenCustom.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics.Backgrounds; @@ -23,4 +23,4 @@ namespace osu.Game.Screens.Backgrounds return base.Equals(other) && textureName == backgroundScreenCustom.textureName; } } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index 36867a84d5..24e744d234 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs index 15aa8d10fe..758032a711 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenEmpty.cs @@ -1,10 +1,9 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Screens.Backgrounds { public class BackgroundScreenEmpty : BackgroundScreen { - } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Charts/ChartInfo.cs b/osu.Game/Screens/Charts/ChartInfo.cs index 32577f3e05..70ca3b8b67 100644 --- a/osu.Game/Screens/Charts/ChartInfo.cs +++ b/osu.Game/Screens/Charts/ChartInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Screens.Charts diff --git a/osu.Game/Screens/Charts/ChartListing.cs b/osu.Game/Screens/Charts/ChartListing.cs index 41c2a01600..376cc76ef5 100644 --- a/osu.Game/Screens/Charts/ChartListing.cs +++ b/osu.Game/Screens/Charts/ChartListing.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Direct/OnlineListing.cs b/osu.Game/Screens/Direct/OnlineListing.cs index ff6c599e6f..38f4d6a771 100644 --- a/osu.Game/Screens/Direct/OnlineListing.cs +++ b/osu.Game/Screens/Direct/OnlineListing.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Screens.Direct diff --git a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs index 0e57407928..69a1296701 100644 --- a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs +++ b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Components/PlaybackControl.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs index 5ffa66c43e..05e47ef5b1 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackControl.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs index b9b6867ea6..9a78e6e189 100644 --- a/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs +++ b/osu.Game/Screens/Edit/Components/TimeInfoContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs index cdb2985473..dfb67e4228 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BookmarkPart.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs index 380f8e2c7b..29cee20a9b 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/BreakPart.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs index 3759470c9a..a8e62d77ad 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/ControlPointPart.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs index b2308aca71..c7f40327a9 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs index df95a5c384..c3c8dd9de0 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/TimelinePart.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs index a63d02a0a5..8a472dc357 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/SummaryTimeline.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs index 91f5e9b222..f8d3133ae9 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/DurationVisualisation.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs index 4719db37d1..4271375740 100644 --- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs +++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Visualisations/PointVisualisation.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 76f51d1c33..bb43099352 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs index 17b2e64d8e..ab699d1832 100644 --- a/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Menus/EditorMenuBar.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuItem.cs b/osu.Game/Screens/Edit/Menus/EditorMenuItem.cs index c7e36522cf..ec936fb023 100644 --- a/osu.Game/Screens/Edit/Menus/EditorMenuItem.cs +++ b/osu.Game/Screens/Edit/Menus/EditorMenuItem.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Edit/Menus/EditorMenuItemSpacer.cs b/osu.Game/Screens/Edit/Menus/EditorMenuItemSpacer.cs index 5060165ef7..1b16b886b0 100644 --- a/osu.Game/Screens/Edit/Menus/EditorMenuItemSpacer.cs +++ b/osu.Game/Screens/Edit/Menus/EditorMenuItemSpacer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Screens.Edit.Menus diff --git a/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs b/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs index dae2e4b320..a7569330bd 100644 --- a/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs +++ b/osu.Game/Screens/Edit/Menus/ScreenSelectionTabControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs index 6bc7356f26..d42c0bfdac 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Compose.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Compose.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs index 10b6c07f3d..e2510ec016 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/DrawableRadioButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs index 055362d9e1..5c28cc106a 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs index 5f1def4a2e..f178f739dd 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/RadioButtons/RadioButtonCollection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/BeatmapWaveformGraph.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/BeatmapWaveformGraph.cs index 5acee675e8..f82ff5f286 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/BeatmapWaveformGraph.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/BeatmapWaveformGraph.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs index 81beb4a4de..c308b2b9f8 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollableTimeline.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs index 3e1d0329a9..f71607a6cf 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/ScrollingTimelineContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs b/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs index 0c6fc5d133..a0802f0d7d 100644 --- a/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs +++ b/osu.Game/Screens/Edit/Screens/Compose/Timeline/TimelineButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Edit/Screens/Design/Design.cs b/osu.Game/Screens/Edit/Screens/Design/Design.cs index edd5ae1a1e..16a71846ac 100644 --- a/osu.Game/Screens/Edit/Screens/Design/Design.cs +++ b/osu.Game/Screens/Edit/Screens/Design/Design.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Edit/Screens/EditorScreen.cs b/osu.Game/Screens/Edit/Screens/EditorScreen.cs index ac248930d8..2e654b4373 100644 --- a/osu.Game/Screens/Edit/Screens/EditorScreen.cs +++ b/osu.Game/Screens/Edit/Screens/EditorScreen.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; diff --git a/osu.Game/Screens/Edit/Screens/EditorScreenMode.cs b/osu.Game/Screens/Edit/Screens/EditorScreenMode.cs index 578d888193..67e50b34ac 100644 --- a/osu.Game/Screens/Edit/Screens/EditorScreenMode.cs +++ b/osu.Game/Screens/Edit/Screens/EditorScreenMode.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Screens/Loader.cs b/osu.Game/Screens/Loader.cs index 1f332312ba..94238285ad 100644 --- a/osu.Game/Screens/Loader.cs +++ b/osu.Game/Screens/Loader.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index 5e55166c19..268be51347 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -222,7 +222,8 @@ namespace osu.Game.Screens.Menu boxHoverLayer.FadeOut(800, Easing.OutExpo); } - public override bool HandleInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f; + public override bool HandleKeyboardInput => state != ButtonState.Exploded; + public override bool HandleMouseInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f; protected override void Update() { diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index c82d90d16c..72c26af2a6 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -157,7 +157,6 @@ namespace osu.Game.Screens.Menu return true; } - return false; } @@ -200,7 +199,8 @@ namespace osu.Game.Screens.Menu private MenuState state; - public override bool HandleInput => state != MenuState.Exit; + public override bool HandleKeyboardInput => state != MenuState.Exit; + public override bool HandleMouseInput => state != MenuState.Exit; public MenuState State { diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index d0ad613640..8285416ecb 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -19,8 +19,7 @@ namespace osu.Game.Screens.Menu private Color4 iconColour; public override bool ShowOverlaysOnEnter => false; - - public override bool HasLocalCursorDisplayed => true; + public override bool CursorVisible => false; public Disclaimer() { diff --git a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs index 071de99209..29ae35fca4 100644 --- a/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs +++ b/osu.Game/Screens/Menu/FlowContainerWithOrigin.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index a6a1afa320..10b08d704d 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -31,9 +31,8 @@ namespace osu.Game.Screens.Menu private SampleChannel welcome; private SampleChannel seeya; - public override bool HasLocalCursorDisplayed => true; - public override bool ShowOverlaysOnEnter => false; + public override bool CursorVisible => false; protected override BackgroundScreen CreateBackground() => new BackgroundScreenEmpty(); diff --git a/osu.Game/Screens/Menu/IntroSequence.cs b/osu.Game/Screens/Menu/IntroSequence.cs index 5fca389708..ff3b4eba56 100644 --- a/osu.Game/Screens/Menu/IntroSequence.cs +++ b/osu.Game/Screens/Menu/IntroSequence.cs @@ -1,7 +1,6 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Linq; using OpenTK; using OpenTK.Graphics; @@ -188,7 +187,7 @@ namespace osu.Game.Screens.Menu mediumRing.ResizeTo(130, 340, Easing.OutQuad); mediumRing.Foreground.ResizeTo(1, 880, Easing.Out); - Func remainingTime = () => length - TransformDelay; + double remainingTime() => length - TransformDelay; using (BeginDelayedSequence(250, true)) { diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 5b86fd6ca3..3a3f3d4650 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -64,7 +64,8 @@ namespace osu.Game.Screens.Menu private readonly float[] frequencyAmplitudes = new float[256]; - public override bool HandleInput => false; + public override bool HandleKeyboardInput => false; + public override bool HandleMouseInput => false; private Shader shader; private readonly Texture texture; diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index fac0ec1422..1e68b2a22d 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index 9317780eac..f94e2bddc1 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; @@ -19,7 +19,8 @@ namespace osu.Game.Screens.Menu { public class MenuSideFlashes : BeatSyncedContainer { - public override bool HandleInput => false; + public override bool HandleKeyboardInput => false; + public override bool HandleMouseInput => false; private readonly Bindable beatmap = new Bindable(); diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index 9ca12702e5..b91ff0d74b 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -231,7 +231,7 @@ namespace osu.Game.Screens.Menu /// If true, the new animation is delayed until all previous transforms finish. If false, existing transformed are cleared. public void AppendAnimatingAction(Action action, bool waitForPrevious) { - Action runnableAction = () => + void runnableAction() { if (waitForPrevious) this.DelayUntilTransformsFinished().Schedule(action); @@ -240,12 +240,12 @@ namespace osu.Game.Screens.Menu ClearTransforms(); action(); } - }; + } if (IsLoaded) runnableAction(); else - Schedule(() => runnableAction()); + Schedule(runnableAction); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multiplayer/DrawableGameType.cs b/osu.Game/Screens/Multiplayer/DrawableGameType.cs index 5b85fcc4da..5c57232299 100644 --- a/osu.Game/Screens/Multiplayer/DrawableGameType.cs +++ b/osu.Game/Screens/Multiplayer/DrawableGameType.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Multiplayer/DrawableRoom.cs b/osu.Game/Screens/Multiplayer/DrawableRoom.cs index 0ba4aaa364..cc2828fb91 100644 --- a/osu.Game/Screens/Multiplayer/DrawableRoom.cs +++ b/osu.Game/Screens/Multiplayer/DrawableRoom.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -229,7 +229,6 @@ namespace osu.Game.Screens.Multiplayer { coverContainer.FadeIn(transition_duration); - LoadComponentAsync(new BeatmapSetCover(value.BeatmapSet) { Anchor = Anchor.Centre, diff --git a/osu.Game/Screens/Multiplayer/Lobby.cs b/osu.Game/Screens/Multiplayer/Lobby.cs index b297835ca9..0676f2d729 100644 --- a/osu.Game/Screens/Multiplayer/Lobby.cs +++ b/osu.Game/Screens/Multiplayer/Lobby.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Multiplayer/Match.cs b/osu.Game/Screens/Multiplayer/Match.cs index e50a7199a4..2ceead1266 100644 --- a/osu.Game/Screens/Multiplayer/Match.cs +++ b/osu.Game/Screens/Multiplayer/Match.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Multiplayer/MatchCreate.cs b/osu.Game/Screens/Multiplayer/MatchCreate.cs index c232c38d08..d60ee8ba48 100644 --- a/osu.Game/Screens/Multiplayer/MatchCreate.cs +++ b/osu.Game/Screens/Multiplayer/MatchCreate.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Multiplayer/ModeTypeInfo.cs b/osu.Game/Screens/Multiplayer/ModeTypeInfo.cs index 40d385418a..92dff890e1 100644 --- a/osu.Game/Screens/Multiplayer/ModeTypeInfo.cs +++ b/osu.Game/Screens/Multiplayer/ModeTypeInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Multiplayer/ParticipantInfo.cs b/osu.Game/Screens/Multiplayer/ParticipantInfo.cs index 2197b7477c..0fd4f4d08d 100644 --- a/osu.Game/Screens/Multiplayer/ParticipantInfo.cs +++ b/osu.Game/Screens/Multiplayer/ParticipantInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; @@ -35,7 +35,7 @@ namespace osu.Game.Screens.Multiplayer { set { - var ranks = value.Select(u => u.GlobalRank); + var ranks = value.Select(u => u.Statistics.Ranks.Global); levelRangeLower.Text = ranks.Min().ToString(); levelRangeHigher.Text = ranks.Max().ToString(); } diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs index 8d7401500f..03bfb39c3b 100644 --- a/osu.Game/Screens/Multiplayer/RoomInspector.cs +++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 0013d1a882..a2d41dc206 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -35,9 +35,12 @@ namespace osu.Game.Screens /// public virtual bool ShowOverlaysOnEnter => true; - protected new OsuGameBase Game => base.Game as OsuGameBase; + /// + /// Whether this allows the cursor to be displayed. + /// + public virtual bool CursorVisible => true; - public virtual bool HasLocalCursorDisplayed => false; + protected new OsuGameBase Game => base.Game as OsuGameBase; private OsuLogo logo; diff --git a/osu.Game/Screens/Play/BreaksOverlay/ArrowsOverlay.cs b/osu.Game/Screens/Play/BreaksOverlay/ArrowsOverlay.cs index 0b775d5c35..9fdf90bd28 100644 --- a/osu.Game/Screens/Play/BreaksOverlay/ArrowsOverlay.cs +++ b/osu.Game/Screens/Play/BreaksOverlay/ArrowsOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/BreaksOverlay/BlurredIcon.cs b/osu.Game/Screens/Play/BreaksOverlay/BlurredIcon.cs index f16e7c7b96..5395d7688e 100644 --- a/osu.Game/Screens/Play/BreaksOverlay/BlurredIcon.cs +++ b/osu.Game/Screens/Play/BreaksOverlay/BlurredIcon.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Play/BreaksOverlay/BreakOverlay.cs b/osu.Game/Screens/Play/BreaksOverlay/BreakOverlay.cs index 7ef1ef8d8a..af7c1ef5aa 100644 --- a/osu.Game/Screens/Play/BreaksOverlay/BreakOverlay.cs +++ b/osu.Game/Screens/Play/BreaksOverlay/BreakOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -41,6 +41,12 @@ namespace osu.Game.Screens.Play.BreaksOverlay private readonly InfoContainer info; private readonly ArrowsOverlay arrowsOverlay; + public BreakOverlay(bool letterboxing, ScoreProcessor scoreProcessor) + : this(letterboxing) + { + bindProcessor(scoreProcessor); + } + public BreakOverlay(bool letterboxing) { this.letterboxing = letterboxing; @@ -148,7 +154,7 @@ namespace osu.Game.Screens.Play.BreaksOverlay arrowsOverlay.Hide(); } - public void BindProcessor(ScoreProcessor processor) + private void bindProcessor(ScoreProcessor processor) { info.AccuracyDisplay.Current.BindTo(processor.Accuracy); info.GradeDisplay.Current.BindTo(processor.Rank); diff --git a/osu.Game/Screens/Play/BreaksOverlay/GlowIcon.cs b/osu.Game/Screens/Play/BreaksOverlay/GlowIcon.cs index b27eef632c..bad9df2093 100644 --- a/osu.Game/Screens/Play/BreaksOverlay/GlowIcon.cs +++ b/osu.Game/Screens/Play/BreaksOverlay/GlowIcon.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; diff --git a/osu.Game/Screens/Play/BreaksOverlay/InfoContainer.cs b/osu.Game/Screens/Play/BreaksOverlay/InfoContainer.cs index 1bf9b26cc9..d7ab4ff2e5 100644 --- a/osu.Game/Screens/Play/BreaksOverlay/InfoContainer.cs +++ b/osu.Game/Screens/Play/BreaksOverlay/InfoContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Play/BreaksOverlay/InfoLine.cs b/osu.Game/Screens/Play/BreaksOverlay/InfoLine.cs index 751523d68c..b39eaf1c22 100644 --- a/osu.Game/Screens/Play/BreaksOverlay/InfoLine.cs +++ b/osu.Game/Screens/Play/BreaksOverlay/InfoLine.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Play/BreaksOverlay/LetterboxOverlay.cs b/osu.Game/Screens/Play/BreaksOverlay/LetterboxOverlay.cs index 4733a5482b..f4c9362fff 100644 --- a/osu.Game/Screens/Play/BreaksOverlay/LetterboxOverlay.cs +++ b/osu.Game/Screens/Play/BreaksOverlay/LetterboxOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/Screens/Play/BreaksOverlay/RemainingTimeCounter.cs b/osu.Game/Screens/Play/BreaksOverlay/RemainingTimeCounter.cs index 0df7bb97e0..015fefb423 100644 --- a/osu.Game/Screens/Play/BreaksOverlay/RemainingTimeCounter.cs +++ b/osu.Game/Screens/Play/BreaksOverlay/RemainingTimeCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics.Sprites; diff --git a/osu.Game/Screens/Play/FailOverlay.cs b/osu.Game/Screens/Play/FailOverlay.cs index 09f2e15c57..8a37009f56 100644 --- a/osu.Game/Screens/Play/FailOverlay.cs +++ b/osu.Game/Screens/Play/FailOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Input; diff --git a/osu.Game/Screens/Play/GameplayMenuOverlay.cs b/osu.Game/Screens/Play/GameplayMenuOverlay.cs index 094c0331f4..615c124ea7 100644 --- a/osu.Game/Screens/Play/GameplayMenuOverlay.cs +++ b/osu.Game/Screens/Play/GameplayMenuOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -142,8 +142,6 @@ namespace osu.Game.Screens.Play } } - public override bool HandleInput => State == Visibility.Visible; - protected override void PopIn() => this.FadeIn(transition_duration, Easing.In); protected override void PopOut() => this.FadeOut(transition_duration, Easing.In); diff --git a/osu.Game/Screens/Play/HUD/ComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounter.cs index 47099f96e9..f88ef3a862 100644 --- a/osu.Game/Screens/Play/HUD/ComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; diff --git a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs index a4732f6796..3a38360332 100644 --- a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Play/HUD/HealthDisplay.cs b/osu.Game/Screens/Play/HUD/HealthDisplay.cs index a146172085..2f918f37de 100644 --- a/osu.Game/Screens/Play/HUD/HealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/HealthDisplay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index fd0e71ece8..8091809431 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Screens/Play/HUD/ReplaySettingsOverlay.cs b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs similarity index 73% rename from osu.Game/Screens/Play/HUD/ReplaySettingsOverlay.cs rename to osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs index c07eebdef8..e6cf1f7982 100644 --- a/osu.Game/Screens/Play/HUD/ReplaySettingsOverlay.cs +++ b/osu.Game/Screens/Play/HUD/PlayerSettingsOverlay.cs @@ -1,31 +1,32 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Screens.Play.ReplaySettings; using OpenTK; using osu.Framework.Input; +using osu.Game.Screens.Play.PlayerSettings; using OpenTK.Input; namespace osu.Game.Screens.Play.HUD { - public class ReplaySettingsOverlay : VisibilityContainer + public class PlayerSettingsOverlay : VisibilityContainer { private const int fade_duration = 200; public bool ReplayLoaded; public readonly PlaybackSettings PlaybackSettings; + public readonly VisualSettings VisualSettings; //public readonly CollectionSettings CollectionSettings; //public readonly DiscussionSettings DiscussionSettings; - public ReplaySettingsOverlay() + public PlayerSettingsOverlay() { AlwaysPresent = true; RelativeSizeAxes = Axes.Both; - Child = new FillFlowContainer + Child = new FillFlowContainer { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -33,11 +34,12 @@ namespace osu.Game.Screens.Play.HUD Direction = FillDirection.Vertical, Spacing = new Vector2(0, 20), Margin = new MarginPadding { Top = 100, Right = 10 }, - Children = new[] + Children = new PlayerSettingsGroup[] { //CollectionSettings = new CollectionSettings(), //DiscussionSettings = new DiscussionSettings(), PlaybackSettings = new PlaybackSettings(), + VisualSettings = new VisualSettings() } }; @@ -47,6 +49,9 @@ namespace osu.Game.Screens.Play.HUD protected override void PopIn() => this.FadeIn(fade_duration); protected override void PopOut() => this.FadeOut(fade_duration); + //We want to handle keyboard inputs all the time in order to trigger ToggleVisibility() when not visible + public override bool HandleKeyboardInput => true; + protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) { if (args.Repeat) return false; diff --git a/osu.Game/Screens/Play/HUD/StandardComboCounter.cs b/osu.Game/Screens/Play/HUD/StandardComboCounter.cs index 04fe78116e..0e4861a305 100644 --- a/osu.Game/Screens/Play/HUD/StandardComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/StandardComboCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs index 351db533f3..b7508fd43f 100644 --- a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index f4b5efe1e5..e68a17f014 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -6,6 +6,8 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; +using osu.Framework.Timing; +using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; @@ -32,14 +34,14 @@ namespace osu.Game.Screens.Play public readonly HealthDisplay HealthDisplay; public readonly SongProgress Progress; public readonly ModDisplay ModDisplay; - public readonly ReplaySettingsOverlay ReplaySettingsOverlay; + public readonly PlayerSettingsOverlay PlayerSettingsOverlay; private Bindable showHud; - private bool replayLoaded; + private readonly BindableBool replayLoaded = new BindableBool(); private static bool hasShownNotificationOnce; - public HUDOverlay() + public HUDOverlay(ScoreProcessor scoreProcessor, RulesetContainer rulesetContainer, DecoupleableInterpolatingFramedClock decoupledClock, WorkingBeatmap working, IAdjustableClock adjustableSourceClock) { RelativeSizeAxes = Axes.Both; @@ -56,9 +58,21 @@ namespace osu.Game.Screens.Play HealthDisplay = CreateHealthDisplay(), Progress = CreateProgress(), ModDisplay = CreateModsContainer(), - ReplaySettingsOverlay = CreateReplaySettingsOverlay(), + PlayerSettingsOverlay = CreatePlayerSettingsOverlay() } }); + + BindProcessor(scoreProcessor); + BindRulesetContainer(rulesetContainer); + + Progress.Objects = rulesetContainer.Objects; + Progress.AudioClock = decoupledClock; + Progress.AllowSeeking = rulesetContainer.HasReplayLoaded; + Progress.OnSeek = pos => decoupledClock.Seek(pos); + + ModDisplay.Current.BindTo(working.Mods); + + PlayerSettingsOverlay.PlaybackSettings.AdjustableClock = adjustableSourceClock; } [BackgroundDependencyLoader(true)] @@ -91,20 +105,37 @@ namespace osu.Game.Screens.Play } } - public virtual void BindRulesetContainer(RulesetContainer rulesetContainer) + protected override void LoadComplete() + { + base.LoadComplete(); + + replayLoaded.ValueChanged += replayLoadedValueChanged; + replayLoaded.TriggerChange(); + } + + private void replayLoadedValueChanged(bool loaded) + { + PlayerSettingsOverlay.ReplayLoaded = loaded; + + if (loaded) + { + PlayerSettingsOverlay.Show(); + ModDisplay.FadeIn(200); + } + else + { + PlayerSettingsOverlay.Hide(); + ModDisplay.Delay(2000).FadeOut(200); + } + } + + protected virtual void BindRulesetContainer(RulesetContainer rulesetContainer) { (rulesetContainer.KeyBindingInputManager as ICanAttachKeyCounter)?.Attach(KeyCounter); - replayLoaded = rulesetContainer.HasReplayLoaded; + replayLoaded.BindTo(rulesetContainer.HasReplayLoaded); - ReplaySettingsOverlay.ReplayLoaded = replayLoaded; - - // in the case a replay isn't loaded, we want some elements to only appear briefly. - if (!replayLoaded) - { - ReplaySettingsOverlay.Hide(); - ModDisplay.Delay(2000).FadeOut(200); - } + Progress.BindRulestContainer(rulesetContainer); } protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) @@ -182,9 +213,9 @@ namespace osu.Game.Screens.Play Margin = new MarginPadding { Top = 20, Right = 10 }, }; - protected virtual ReplaySettingsOverlay CreateReplaySettingsOverlay() => new ReplaySettingsOverlay(); + protected virtual PlayerSettingsOverlay CreatePlayerSettingsOverlay() => new PlayerSettingsOverlay(); - public virtual void BindProcessor(ScoreProcessor processor) + protected virtual void BindProcessor(ScoreProcessor processor) { ScoreCounter?.Current.BindTo(processor.TotalScore); AccuracyCounter?.Current.BindTo(processor.Accuracy); diff --git a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs index 11f9a484dd..f5df02d758 100644 --- a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs @@ -1,18 +1,18 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Input; -using OpenTK.Input; using osu.Framework.Allocation; using System; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; using OpenTK.Graphics; namespace osu.Game.Screens.Play { - public class HotkeyRetryOverlay : Container + public class HotkeyRetryOverlay : Container, IKeyBindingHandler { public Action Action; @@ -40,28 +40,20 @@ namespace osu.Game.Screens.Play }; } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public bool OnPressed(GlobalAction action) { - if (args.Repeat) return false; + if (action != GlobalAction.QuickRetry) return false; - if (args.Key == Key.Tilde) - { - overlay.FadeIn(activate_delay, Easing.Out); - return true; - } - - return base.OnKeyDown(state, args); + overlay.FadeIn(activate_delay, Easing.Out); + return true; } - protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) + public bool OnReleased(GlobalAction action) { - if (args.Key == Key.Tilde && !fired) - { - overlay.FadeOut(fadeout_delay, Easing.Out); - return true; - } + if (action != GlobalAction.QuickRetry) return false; - return base.OnKeyUp(state, args); + overlay.FadeOut(fadeout_delay, Easing.Out); + return true; } protected override void Update() diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index e507055d5f..05fa756c62 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index a6baeeafb6..c0ca03beb1 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Input.Bindings; @@ -27,4 +27,4 @@ namespace osu.Game.Screens.Play return false; } } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index 2f077f5c0a..e40776ae4a 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -111,7 +111,8 @@ namespace osu.Game.Screens.Play } } - public override bool HandleInput => receptor == null; + public override bool HandleKeyboardInput => receptor == null; + public override bool HandleMouseInput => receptor == null; private Receptor receptor; diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboard.cs index 3516dbbad8..2c10f7a01a 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboard.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Input; diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index 12ec976316..2c51f38fa2 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Input; diff --git a/osu.Game/Screens/Play/PauseContainer.cs b/osu.Game/Screens/Play/PauseContainer.cs index 3bd28511c7..ac497868bf 100644 --- a/osu.Game/Screens/Play/PauseContainer.cs +++ b/osu.Game/Screens/Play/PauseContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index d4cfa0b3d4..72864482d5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -1,44 +1,44 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Configuration; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Input; -using osu.Framework.Logging; -using osu.Framework.Screens; -using osu.Framework.Timing; -using osu.Game.Configuration; -using osu.Game.Rulesets; -using osu.Game.Rulesets.UI; -using osu.Game.Screens.Backgrounds; using System; using System.Linq; using System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Input; +using osu.Framework.Logging; +using osu.Framework.Screens; using osu.Framework.Threading; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Configuration; +using osu.Game.Graphics; +using osu.Game.Graphics.Cursor; +using osu.Game.Online.API; +using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; -using osu.Game.Screens.Ranking; -using osu.Framework.Audio.Sample; -using osu.Game.Beatmaps; -using osu.Game.Online.API; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Play.BreaksOverlay; +using osu.Game.Screens.Ranking; using osu.Game.Storyboards.Drawables; -using OpenTK.Graphics; +using OpenTK; namespace osu.Game.Screens.Play { - public class Player : OsuScreen + public class Player : OsuScreen, IProvideCursor { protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); public override bool ShowOverlaysOnEnter => false; - public override bool HasLocalCursorDisplayed => !pauseContainer.IsPaused && !HasFailed && RulesetContainer.ProvidingUserCursor; - public Action RestartRequested; public override bool AllowBeatmapRulesetChange => false; @@ -51,6 +51,9 @@ namespace osu.Game.Screens.Play public int RestartCount; + public CursorContainer Cursor => RulesetContainer.Cursor; + public bool ProvidingUserCursor => RulesetContainer?.Cursor != null && !RulesetContainer.HasReplayLoaded.Value; + private IAdjustableClock adjustableSourceClock; private FramedOffsetClock offsetClock; private DecoupleableInterpolatingFramedClock decoupledClock; @@ -67,6 +70,7 @@ namespace osu.Game.Screens.Play #region User Settings private Bindable dimLevel; + private Bindable blurLevel; private Bindable showStoryboard; private Bindable mouseWheelDisabled; private Bindable userAudioOffset; @@ -75,7 +79,6 @@ namespace osu.Game.Screens.Play #endregion - private BreakOverlay breakOverlay; private Container storyboardContainer; private DrawableStoryboard storyboard; @@ -90,6 +93,7 @@ namespace osu.Game.Screens.Play this.api = api; dimLevel = config.GetBindable(OsuSetting.DimLevel); + blurLevel = config.GetBindable(OsuSetting.BlurLevel); showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); @@ -150,6 +154,8 @@ namespace osu.Game.Screens.Play userAudioOffset.ValueChanged += v => offsetClock.Offset = v; userAudioOffset.TriggerChange(); + scoreProcessor = RulesetContainer.CreateScoreProcessor(); + Children = new Drawable[] { storyboardContainer = new Container @@ -165,34 +171,33 @@ namespace osu.Game.Screens.Play OnRetry = Restart, OnQuit = Exit, CheckCanPause = () => AllowPause && ValidForResume && !HasFailed && !RulesetContainer.HasReplayLoaded, - OnPause = () => { + OnPause = () => + { pauseContainer.Retries = RestartCount; hudOverlay.KeyCounter.IsCounting = pauseContainer.IsPaused; }, - OnResume = () => { - hudOverlay.KeyCounter.IsCounting = true; - }, + OnResume = () => hudOverlay.KeyCounter.IsCounting = true, Children = new Drawable[] { - new SkipButton(firstObjectTime) { AudioClock = decoupledClock }, new Container { RelativeSizeAxes = Axes.Both, Clock = offsetClock, Child = RulesetContainer, }, - hudOverlay = new HUDOverlay + new SkipButton(firstObjectTime) { AudioClock = decoupledClock }, + hudOverlay = new HUDOverlay(scoreProcessor, RulesetContainer, decoupledClock, working, adjustableSourceClock) { Anchor = Anchor.Centre, Origin = Anchor.Centre }, - breakOverlay = new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks) + new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, scoreProcessor) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Clock = decoupledClock, Breaks = beatmap.Breaks - }, + } } }, failOverlay = new FailOverlay @@ -202,7 +207,10 @@ namespace osu.Game.Screens.Play }, new HotkeyRetryOverlay { - Action = () => { + Action = () => + { + if (!IsCurrentScreen) return; + //we want to hide the hitrenderer immediately (looks better). //we may be able to remove this once the mouse cursor trail is improved. RulesetContainer?.Hide(); @@ -211,25 +219,9 @@ namespace osu.Game.Screens.Play } }; - scoreProcessor = RulesetContainer.CreateScoreProcessor(); - if (showStoryboard) initializeStoryboard(false); - hudOverlay.BindProcessor(scoreProcessor); - hudOverlay.BindRulesetContainer(RulesetContainer); - - hudOverlay.Progress.Objects = RulesetContainer.Objects; - hudOverlay.Progress.AudioClock = decoupledClock; - hudOverlay.Progress.AllowSeeking = RulesetContainer.HasReplayLoaded; - hudOverlay.Progress.OnSeek = pos => decoupledClock.Seek(pos); - - hudOverlay.ModDisplay.Current.BindTo(working.Mods); - - breakOverlay.BindProcessor(scoreProcessor); - - hudOverlay.ReplaySettingsOverlay.PlaybackSettings.AdjustableClock = adjustableSourceClock; - // Bind ScoreProcessor to ourselves scoreProcessor.AllJudged += onCompletion; scoreProcessor.Failed += onFail; @@ -284,6 +276,8 @@ namespace osu.Game.Screens.Play { onCompletionEvent = Schedule(delegate { + if (!IsCurrentScreen) return; + var score = new Score { Beatmap = Beatmap.Value.BeatmapInfo, @@ -316,10 +310,9 @@ namespace osu.Game.Screens.Play if (!loadedSuccessfully) return; - (Background as BackgroundScreenBeatmap)?.BlurTo(Vector2.Zero, 1000, Easing.OutQuint); - - dimLevel.ValueChanged += dimLevel_ValueChanged; - showStoryboard.ValueChanged += showStoryboard_ValueChanged; + dimLevel.ValueChanged += _ => updateBackgroundElements(); + blurLevel.ValueChanged += _ => updateBackgroundElements(); + showStoryboard.ValueChanged += _ => updateBackgroundElements(); updateBackgroundElements(); Content.Alpha = 0; @@ -375,14 +368,12 @@ namespace osu.Game.Screens.Play return true; } - private void dimLevel_ValueChanged(double newValue) - => updateBackgroundElements(); - - private void showStoryboard_ValueChanged(bool newValue) - => updateBackgroundElements(); - private void updateBackgroundElements() { + if (!IsCurrentScreen) return; + + const float duration = 800; + var opacity = 1 - (float)dimLevel; if (showStoryboard && storyboard == null) @@ -391,17 +382,16 @@ namespace osu.Game.Screens.Play var beatmap = Beatmap.Value; var storyboardVisible = showStoryboard && beatmap.Storyboard.HasDrawable; - storyboardContainer.FadeColour(new Color4(opacity, opacity, opacity, 1), 800); - storyboardContainer.FadeTo(storyboardVisible && opacity > 0 ? 1 : 0); + storyboardContainer + .FadeColour(OsuColour.Gray(opacity), duration, Easing.OutQuint) + .FadeTo(storyboardVisible && opacity > 0 ? 1 : 0, duration, Easing.OutQuint); - Background?.FadeTo(!storyboardVisible || beatmap.Background == null ? opacity : 0, 800, Easing.OutQuint); + (Background as BackgroundScreenBeatmap)?.BlurTo(new Vector2((float)blurLevel.Value * 25), duration, Easing.OutQuint); + Background?.FadeTo(!storyboardVisible || beatmap.Background == null ? opacity : 0, duration, Easing.OutQuint); } private void fadeOut() { - dimLevel.ValueChanged -= dimLevel_ValueChanged; - showStoryboard.ValueChanged -= showStoryboard_ValueChanged; - const float fade_out_duration = 250; RulesetContainer?.FadeOut(fade_out_duration); diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 15a97096e7..2950990779 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -13,6 +13,7 @@ using osu.Game.Screens.Backgrounds; using OpenTK; using osu.Framework.Localisation; using osu.Game.Screens.Menu; +using osu.Game.Screens.Play.PlayerSettings; namespace osu.Game.Screens.Play { @@ -21,6 +22,7 @@ namespace osu.Game.Screens.Play private Player player; private BeatmapMetadataDisplay info; + private VisualSettings visualSettings; private bool showOverlays = true; public override bool ShowOverlaysOnEnter => showOverlays; @@ -49,6 +51,12 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, Origin = Anchor.Centre, }); + Add(visualSettings = new VisualSettings + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding(25) + }); LoadComponentAsync(player); } @@ -110,7 +118,7 @@ namespace osu.Game.Screens.Play private void pushWhenLoaded() { - if (player.LoadState != LoadState.Ready) + if (player.LoadState != LoadState.Ready || visualSettings.IsHovered) { Schedule(pushWhenLoaded); return; diff --git a/osu.Game/Screens/Play/ReplaySettings/CollectionSettings.cs b/osu.Game/Screens/Play/PlayerSettings/CollectionSettings.cs similarity index 81% rename from osu.Game/Screens/Play/ReplaySettings/CollectionSettings.cs rename to osu.Game/Screens/Play/PlayerSettings/CollectionSettings.cs index 482581abca..f18b0876a2 100644 --- a/osu.Game/Screens/Play/ReplaySettings/CollectionSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/CollectionSettings.cs @@ -1,15 +1,15 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Music; -using System.Collections.Generic; -namespace osu.Game.Screens.Play.ReplaySettings +namespace osu.Game.Screens.Play.PlayerSettings { - public class CollectionSettings : ReplayGroup + public class CollectionSettings : PlayerSettingsGroup { protected override string Title => @"collections"; diff --git a/osu.Game/Screens/Play/ReplaySettings/DiscussionSettings.cs b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs similarity index 79% rename from osu.Game/Screens/Play/ReplaySettings/DiscussionSettings.cs rename to osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs index 9c4fb03517..e6d4fe3e09 100644 --- a/osu.Game/Screens/Play/ReplaySettings/DiscussionSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/DiscussionSettings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; @@ -6,9 +6,9 @@ using osu.Framework.Graphics; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Screens.Play.ReplaySettings +namespace osu.Game.Screens.Play.PlayerSettings { - public class DiscussionSettings : ReplayGroup + public class DiscussionSettings : PlayerSettingsGroup { protected override string Title => @"discussions"; @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play.ReplaySettings { Children = new Drawable[] { - new ReplayCheckbox + new PlayerCheckbox { LabelText = "Show floating comments", Bindable = config.GetBindable(OsuSetting.FloatingComments) diff --git a/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs similarity index 80% rename from osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs rename to osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs index 3109552532..6878bb098e 100644 --- a/osu.Game/Screens/Play/ReplaySettings/PlaybackSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlaybackSettings.cs @@ -1,15 +1,15 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Timing; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Timing; using osu.Game.Graphics.Sprites; -namespace osu.Game.Screens.Play.ReplaySettings +namespace osu.Game.Screens.Play.PlayerSettings { - public class PlaybackSettings : ReplayGroup + public class PlaybackSettings : PlayerSettingsGroup { private const int padding = 10; @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Play.ReplaySettings public IAdjustableClock AdjustableClock { set; get; } - private readonly ReplaySliderBar sliderbar; + private readonly PlayerSliderBar sliderbar; public PlaybackSettings() { @@ -42,24 +42,24 @@ namespace osu.Game.Screens.Play.ReplaySettings { Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Text = "1x", Font = @"Exo2.0-Bold", } }, }, - sliderbar = new ReplaySliderBar + sliderbar = new PlayerSliderBar { Bindable = new BindableDouble(1) { Default = 1, MinValue = 0.5, MaxValue = 2, - Precision = 0.01, + Precision = 0.1, }, } }; - sliderbar.Bindable.ValueChanged += rateMultiplier => multiplierText.Text = $"{rateMultiplier}x"; + sliderbar.Bindable.ValueChanged += rateMultiplier => multiplierText.Text = $"{sliderbar.Bar.TooltipText}x"; + sliderbar.Bindable.TriggerChange(); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Play/ReplaySettings/ReplayCheckbox.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs similarity index 73% rename from osu.Game/Screens/Play/ReplaySettings/ReplayCheckbox.cs rename to osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs index 7ad1e4f527..89fbbb8bf2 100644 --- a/osu.Game/Screens/Play/ReplaySettings/ReplayCheckbox.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerCheckbox.cs @@ -1,13 +1,13 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Screens.Play.ReplaySettings +namespace osu.Game.Screens.Play.PlayerSettings { - public class ReplayCheckbox : OsuCheckbox + public class PlayerCheckbox : OsuCheckbox { [BackgroundDependencyLoader] private void load(OsuColour colours) diff --git a/osu.Game/Screens/Play/ReplaySettings/ReplayGroup.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs similarity index 93% rename from osu.Game/Screens/Play/ReplaySettings/ReplayGroup.cs rename to osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs index 06cd783cae..e8a4bc6b27 100644 --- a/osu.Game/Screens/Play/ReplaySettings/ReplayGroup.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSettingsGroup.cs @@ -1,8 +1,6 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -10,10 +8,12 @@ using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; +using OpenTK; +using OpenTK.Graphics; -namespace osu.Game.Screens.Play.ReplaySettings +namespace osu.Game.Screens.Play.PlayerSettings { - public abstract class ReplayGroup : Container + public abstract class PlayerSettingsGroup : Container { /// /// The title to be displayed in the header of this group. @@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play.ReplaySettings private Color4 buttonActiveColour; - protected ReplayGroup() + protected PlayerSettingsGroup() { AutoSizeAxes = Axes.Y; Width = container_width; diff --git a/osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs similarity index 72% rename from osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs rename to osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs index e80ec092d9..43fe14cc24 100644 --- a/osu.Game/Screens/Play/ReplaySettings/ReplaySliderBar.cs +++ b/osu.Game/Screens/Play/PlayerSettings/PlayerSliderBar.cs @@ -1,18 +1,20 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Allocation; -using osu.Game.Graphics.UserInterface; using System; -using osu.Game.Graphics; +using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Settings; -namespace osu.Game.Screens.Play.ReplaySettings +namespace osu.Game.Screens.Play.PlayerSettings { - public class ReplaySliderBar : SettingsSlider - where T : struct, IEquatable + public class PlayerSliderBar : SettingsSlider + where T : struct, IEquatable, IComparable, IConvertible { + public OsuSliderBar Bar => (OsuSliderBar)Control; + protected override Drawable CreateControl() => new Sliderbar { Margin = new MarginPadding { Top = 5, Bottom = 5 }, diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs new file mode 100644 index 0000000000..1a7b80ec9a --- /dev/null +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -0,0 +1,52 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Configuration; +using osu.Game.Graphics.Sprites; + +namespace osu.Game.Screens.Play.PlayerSettings +{ + public class VisualSettings : PlayerSettingsGroup + { + protected override string Title => "Visual settings"; + + private readonly PlayerSliderBar dimSliderBar; + private readonly PlayerSliderBar blurSliderBar; + private readonly PlayerCheckbox showStoryboardToggle; + private readonly PlayerCheckbox mouseWheelDisabledToggle; + + public VisualSettings() + { + Children = new Drawable[] + { + new OsuSpriteText + { + Text = "Background dim:" + }, + dimSliderBar = new PlayerSliderBar(), + new OsuSpriteText + { + Text = "Background blur:" + }, + blurSliderBar = new PlayerSliderBar(), + new OsuSpriteText + { + Text = "Toggles:" + }, + showStoryboardToggle = new PlayerCheckbox { LabelText = "Storyboards" }, + mouseWheelDisabledToggle = new PlayerCheckbox { LabelText = "Disable mouse wheel" } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + dimSliderBar.Bindable = config.GetBindable(OsuSetting.DimLevel); + blurSliderBar.Bindable = config.GetBindable(OsuSetting.BlurLevel); + showStoryboardToggle.Bindable = config.GetBindable(OsuSetting.ShowStoryboard); + mouseWheelDisabledToggle.Bindable = config.GetBindable(OsuSetting.MouseDisableWheel); + } + } +} diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 4748ddfd71..a26d5b3050 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Replays; diff --git a/osu.Game/Screens/Play/SkipButton.cs b/osu.Game/Screens/Play/SkipButton.cs index 6519a8db36..f67a9b801e 100644 --- a/osu.Game/Screens/Play/SkipButton.cs +++ b/osu.Game/Screens/Play/SkipButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -14,13 +14,14 @@ using osu.Game.Graphics.Sprites; using osu.Game.Screens.Ranking; using OpenTK; using OpenTK.Graphics; -using OpenTK.Input; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; +using osu.Framework.Input.Bindings; +using osu.Game.Input.Bindings; namespace osu.Game.Screens.Play { - public class SkipButton : Container + public class SkipButton : OverlayContainer, IKeyBindingHandler { private readonly double startTime; public IAdjustableClock AudioClock; @@ -31,10 +32,14 @@ namespace osu.Game.Screens.Play private FadeContainer fadeContainer; private double displayTime; + public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true; + public SkipButton(double startTime) { this.startTime = startTime; + State = Visibility.Visible; + RelativePositionAxes = Axes.Both; RelativeSizeAxes = Axes.Both; @@ -111,26 +116,36 @@ namespace osu.Game.Screens.Play Expire(); } + protected override void PopIn() + { + this.FadeIn(); + } + + protected override void PopOut() + { + this.FadeOut(); + } + protected override void Update() { base.Update(); remainingTimeBox.ResizeWidthTo((float)Math.Max(0, 1 - (Time.Current - displayTime) / (beginFadeTime - displayTime)), 120, Easing.OutQuint); } - protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) + public bool OnPressed(GlobalAction action) { - if (args.Repeat) return false; - - switch (args.Key) + switch (action) { - case Key.Space: + case GlobalAction.SkipCutscene: button.TriggerOnClick(); return true; } - return base.OnKeyDown(state, args); + return false; } + public bool OnReleased(GlobalAction action) => false; + private class FadeContainer : Container, IStateful { public event Action StateChanged; @@ -140,16 +155,11 @@ namespace osu.Game.Screens.Play public Visibility State { - get - { - return state; - } + get { return state; } set { - if (state == value) - return; + bool stateChanged = value != state; - var lastState = state; state = value; scheduledHide?.Cancel(); @@ -157,7 +167,8 @@ namespace osu.Game.Screens.Play switch (state) { case Visibility.Visible: - if (lastState == Visibility.Hidden) + // we may be triggered to become visible mnultiple times but we only want to transform once. + if (stateChanged) this.FadeIn(500, Easing.OutExpo); if (!IsHovered) diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 68f0cb3661..12f501a632 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -9,9 +9,12 @@ using System.Collections.Generic; using osu.Game.Graphics; using osu.Framework.Allocation; using System.Linq; +using osu.Framework.Configuration; using osu.Framework.Timing; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.UI; + namespace osu.Game.Screens.Play { public class SongProgress : OverlayContainer @@ -28,7 +31,8 @@ namespace osu.Game.Screens.Play public Action OnSeek; - public override bool HandleInput => AllowSeeking; + public override bool HandleKeyboardInput => AllowSeeking; + public override bool HandleMouseInput => AllowSeeking; private IClock audioClock; public IClock AudioClock { set { audioClock = info.AudioClock = value; } } @@ -53,6 +57,8 @@ namespace osu.Game.Screens.Play } } + private readonly BindableBool replayLoaded = new BindableBool(); + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -97,6 +103,14 @@ namespace osu.Game.Screens.Play protected override void LoadComplete() { State = Visibility.Visible; + + replayLoaded.ValueChanged += v => AllowSeeking = v; + replayLoaded.TriggerChange(); + } + + public void BindRulestContainer(RulesetContainer rulesetContainer) + { + replayLoaded.BindTo(rulesetContainer.HasReplayLoaded); } private bool allowSeeking; diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index 7fabf2e80e..ffe7ae04f8 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index 38c680902a..49a3b98db8 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game/Screens/Play/SongProgressInfo.cs b/osu.Game/Screens/Play/SongProgressInfo.cs index 06d7176cc5..3ef7750b49 100644 --- a/osu.Game/Screens/Play/SongProgressInfo.cs +++ b/osu.Game/Screens/Play/SongProgressInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs index 81dbf3eca4..48013f7943 100644 --- a/osu.Game/Screens/Play/SquareGraph.cs +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -21,7 +21,8 @@ namespace osu.Game.Screens.Play public int ColumnCount => columns.Length; - public override bool HandleInput => false; + public override bool HandleKeyboardInput => false; + public override bool HandleMouseInput => false; private int progress; public int Progress diff --git a/osu.Game/Screens/Ranking/AspectContainer.cs b/osu.Game/Screens/Ranking/AspectContainer.cs index 4699b4ab92..ce7c985118 100644 --- a/osu.Game/Screens/Ranking/AspectContainer.cs +++ b/osu.Game/Screens/Ranking/AspectContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -17,4 +17,4 @@ namespace osu.Game.Screens.Ranking Width = DrawHeight; } } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Ranking/ResultMode.cs b/osu.Game/Screens/Ranking/ResultMode.cs index eeb04033ea..7057ff9b17 100644 --- a/osu.Game/Screens/Ranking/ResultMode.cs +++ b/osu.Game/Screens/Ranking/ResultMode.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Screens.Ranking @@ -9,4 +9,4 @@ namespace osu.Game.Screens.Ranking Ranking, Share } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Ranking/ResultModeButton.cs b/osu.Game/Screens/Ranking/ResultModeButton.cs index d38611c45a..9a99cbba7a 100644 --- a/osu.Game/Screens/Ranking/ResultModeButton.cs +++ b/osu.Game/Screens/Ranking/ResultModeButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Ranking/ResultModeTabControl.cs b/osu.Game/Screens/Ranking/ResultModeTabControl.cs index 06a6d31e37..cadcbd4819 100644 --- a/osu.Game/Screens/Ranking/ResultModeTabControl.cs +++ b/osu.Game/Screens/Ranking/ResultModeTabControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -27,4 +27,4 @@ namespace osu.Game.Screens.Ranking Origin = TabContainer.Origin }; } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 406887624c..15be68f91b 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Screens/Ranking/ResultsPage.cs b/osu.Game/Screens/Ranking/ResultsPage.cs index 037d5ada09..9e726624e5 100644 --- a/osu.Game/Screens/Ranking/ResultsPage.cs +++ b/osu.Game/Screens/Ranking/ResultsPage.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Ranking/ResultsPageRanking.cs b/osu.Game/Screens/Ranking/ResultsPageRanking.cs index c9d1061bd1..364fcee552 100644 --- a/osu.Game/Screens/Ranking/ResultsPageRanking.cs +++ b/osu.Game/Screens/Ranking/ResultsPageRanking.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 0d29b74dfd..11acc89448 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index fcf87de655..27652b96b8 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 98acd0815d..6a6042d7d4 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -51,7 +51,8 @@ namespace osu.Game.Screens.Select /// public Action SelectionChanged; - public override bool HandleInput => AllowSelection; + public override bool HandleKeyboardInput => AllowSelection; + public override bool HandleMouseInput => AllowSelection; /// /// Used to avoid firing null selections before the initial beatmaps have been loaded via . @@ -235,8 +236,8 @@ namespace osu.Game.Screens.Select /// True if a selection could be made, else False. public bool SelectNextRandom() { - var visible = beatmapSets.Where(s => !s.Filtered).ToList(); - if (!visible.Any()) + var visibleSets = beatmapSets.Where(s => !s.Filtered).ToList(); + if (!visibleSets.Any()) return false; if (selectedBeatmap != null) @@ -253,20 +254,21 @@ namespace osu.Game.Screens.Select if (RandomAlgorithm == RandomSelectAlgorithm.RandomPermutation) { - var notYetVisitedSets = visible.Except(previouslyVisitedRandomSets).ToList(); + var notYetVisitedSets = visibleSets.Except(previouslyVisitedRandomSets).ToList(); if (!notYetVisitedSets.Any()) { - previouslyVisitedRandomSets.Clear(); - notYetVisitedSets = visible; + previouslyVisitedRandomSets.RemoveAll(s => visibleSets.Contains(s)); + notYetVisitedSets = visibleSets; } set = notYetVisitedSets.ElementAt(RNG.Next(notYetVisitedSets.Count)); previouslyVisitedRandomSets.Add(set); } else - set = visible.ElementAt(RNG.Next(visible.Count)); + set = visibleSets.ElementAt(RNG.Next(visibleSets.Count)); - select(set.Beatmaps.Skip(RNG.Next(set.Beatmaps.Count())).FirstOrDefault()); + var visibleBeatmaps = set.Beatmaps.Where(s => !s.Filtered).ToList(); + select(visibleBeatmaps[RNG.Next(visibleBeatmaps.Count)]); return true; } diff --git a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs index aa37705cdf..15a19cfe86 100644 --- a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs +++ b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 4403d412fc..20b9644b06 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs index bd0f745016..fe9e360a0d 100644 --- a/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs +++ b/osu.Game/Screens/Select/BeatmapDetailAreaTabControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 79d76dd00e..688ec685b0 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index c25ba66475..7476df4955 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index d7e7b1e265..091de003a4 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 885595fc51..4427a0b7ab 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs index a600693e31..ff23f437db 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroup.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroup.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs index 5701760221..146bdf0009 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselGroupEagerSelect.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/Carousel/CarouselItem.cs b/osu.Game/Screens/Select/Carousel/CarouselItem.cs index 7d76aee253..1fbadb31be 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselItem.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index cea658b06c..38cb5fc5d8 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 40ffcfdc80..d8cfd79e12 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index cb354b3602..2d1433e769 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 3c9cffadfb..4e3b852ce5 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Select/Details/FailRetryGraph.cs b/osu.Game/Screens/Select/Details/FailRetryGraph.cs index 4d75c49d17..a7e1e2adc5 100644 --- a/osu.Game/Screens/Select/Details/FailRetryGraph.cs +++ b/osu.Game/Screens/Select/Details/FailRetryGraph.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index 19bcad367e..bf10b19928 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Select/EditSongSelect.cs b/osu.Game/Screens/Select/EditSongSelect.cs index 37f2663d91..f05fa17578 100644 --- a/osu.Game/Screens/Select/EditSongSelect.cs +++ b/osu.Game/Screens/Select/EditSongSelect.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Screens.Select diff --git a/osu.Game/Screens/Select/Filter/GroupMode.cs b/osu.Game/Screens/Select/Filter/GroupMode.cs index b9e0938fcc..b63b3d2ab5 100644 --- a/osu.Game/Screens/Select/Filter/GroupMode.cs +++ b/osu.Game/Screens/Select/Filter/GroupMode.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Screens/Select/Filter/SortMode.cs b/osu.Game/Screens/Select/Filter/SortMode.cs index 4beecb730e..1cd9aff498 100644 --- a/osu.Game/Screens/Select/Filter/SortMode.cs +++ b/osu.Game/Screens/Select/Filter/SortMode.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 2dbd63f77b..a371e6e7d1 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 8e99e29c1f..7c65b9c36a 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets; diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index 40c3cf0fd4..21e6108489 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index ae6c7d3c1e..c6754d14a5 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/ImportFromStablePopup.cs b/osu.Game/Screens/Select/ImportFromStablePopup.cs index 03e9462636..70188c3b95 100644 --- a/osu.Game/Screens/Select/ImportFromStablePopup.cs +++ b/osu.Game/Screens/Select/ImportFromStablePopup.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs index 5bd78d5971..7ecc2e62ee 100644 --- a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs +++ b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index ac47fade48..6be6523175 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -93,7 +93,8 @@ namespace osu.Game.Screens.Select.Leaderboards get { return scope; } set { - if (value == scope) return; + if (value == scope) + return; scope = value; updateScores(); @@ -107,8 +108,6 @@ namespace osu.Game.Screens.Select.Leaderboards get { return placeholderState; } set { - if (value == placeholderState) return; - if (value != PlaceholderState.Successful) { getScoresRequest?.Cancel(); @@ -116,6 +115,9 @@ namespace osu.Game.Screens.Select.Leaderboards Scores = null; } + if (value == placeholderState) + return; + switch (placeholderState = value) { case PlaceholderState.NetworkFailure: @@ -171,7 +173,8 @@ namespace osu.Game.Screens.Select.Leaderboards get { return beatmap; } set { - if (beatmap == value) return; + if (beatmap == value) + return; beatmap = value; Scores = null; @@ -259,7 +262,8 @@ namespace osu.Game.Screens.Select.Leaderboards private void onUpdateFailed(Exception e) { - if (e is OperationCanceledException) return; + if (e is OperationCanceledException) + return; PlaceholderState = PlaceholderState.NetworkFailure; Logger.Error(e, @"Couldn't fetch beatmap scores!"); @@ -294,7 +298,8 @@ namespace osu.Game.Screens.Select.Leaderboards if (!scrollContainer.IsScrolledToEnd()) fadeStart -= LeaderboardScore.HEIGHT; - if (scrollFlow == null) return; + if (scrollFlow == null) + return; foreach (var c in scrollFlow.Children) { diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs index 857a716ab7..de01b846c2 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; diff --git a/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs b/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs index 4f94087d30..d6bad1b10b 100644 --- a/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs +++ b/osu.Game/Screens/Select/Leaderboards/MessagePlaceholder.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Screens/Select/Leaderboards/Placeholder.cs b/osu.Game/Screens/Select/Leaderboards/Placeholder.cs index 8427259106..91e49c297a 100644 --- a/osu.Game/Screens/Select/Leaderboards/Placeholder.cs +++ b/osu.Game/Screens/Select/Leaderboards/Placeholder.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs b/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs index 69a478f12a..65e599da73 100644 --- a/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs +++ b/osu.Game/Screens/Select/Leaderboards/RetrievalFailurePlaceholder.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 9143da326d..b4249e251c 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Screens.Select diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index 5f1bdcc9bb..35331ec981 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index 789064a5f1..2e8b2f9014 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index a3997640ba..739bc39269 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Overlays; using osu.Game.Overlays.Mods; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Edit; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; @@ -47,10 +48,13 @@ namespace osu.Game.Screens.Select private SampleChannel sampleConfirm; [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay) + private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, OsuGame game) { sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); + if (game != null) + modSelect.SelectedMods.BindTo(game.SelectedMods); + Footer.AddButton(@"mods", colours.Yellow, modSelect, Key.F1, float.MaxValue); BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.fa_times_circle_o, colours.Purple, null, Key.Number1); @@ -121,6 +125,9 @@ namespace osu.Game.Screens.Select if (Beatmap.Value.Track != null) Beatmap.Value.Track.Looping = false; + Beatmap.Value.Mods.UnbindBindings(); + Beatmap.Value.Mods.Value = new Mod[] { }; + return false; } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 919cfcfbe4..2421a4fdfe 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -181,7 +181,7 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader(permitNulls: true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuGame osu, OsuColour colours) { - dependencies.Cache(this); + dependencies.CacheAs(this); if (Footer != null) { @@ -266,7 +266,7 @@ namespace osu.Game.Screens.Select /// private void carouselSelectionChanged(BeatmapInfo beatmap) { - Action performLoad = delegate + void performLoad() { // We may be arriving here due to another component changing the bindable Beatmap. // In these cases, the other component has already loaded the beatmap, so we don't need to do so again. @@ -279,7 +279,7 @@ namespace osu.Game.Screens.Select } UpdateBeatmap(Beatmap.Value); - }; + } if (beatmap?.Equals(beatmapNoDebounce) == true) return; diff --git a/osu.Game/Screens/Select/WedgeBackground.cs b/osu.Game/Screens/Select/WedgeBackground.cs index 4841fcdd09..db96eeb83b 100644 --- a/osu.Game/Screens/Select/WedgeBackground.cs +++ b/osu.Game/Screens/Select/WedgeBackground.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Extensions.Color4Extensions; @@ -37,4 +37,4 @@ namespace osu.Game.Screens.Select }; } } -} \ No newline at end of file +} diff --git a/osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs b/osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs index f12d7ab9ce..63000d6c54 100644 --- a/osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs +++ b/osu.Game/Screens/Tournament/Components/DrawingsConfigManager.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; @@ -6,7 +6,7 @@ using osu.Framework.Platform; namespace osu.Game.Screens.Tournament.Components { - public class DrawingsConfigManager : ConfigManager + public class DrawingsConfigManager : IniConfigManager { protected override string Filename => @"drawings.ini"; diff --git a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs b/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs index d2b2feb68d..10548c6db9 100644 --- a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs +++ b/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 08f27dfde9..201c02ca05 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -265,7 +265,7 @@ namespace osu.Game.Screens.Tournament private void writeResults(string text) { - Action writeAction = () => + void writeAction() { try { @@ -280,9 +280,9 @@ namespace osu.Game.Screens.Tournament { Logger.Error(ex, "Failed to write results."); } - }; + } - writeOp = writeOp?.ContinueWith(t => { writeAction(); }) ?? Task.Run(writeAction); + writeOp = writeOp?.ContinueWith(t => { writeAction(); }) ?? Task.Run((Action)writeAction); } private void reloadTeams() diff --git a/osu.Game/Screens/Tournament/Group.cs b/osu.Game/Screens/Tournament/Group.cs index bd13ced2cd..068a817f3c 100644 --- a/osu.Game/Screens/Tournament/Group.cs +++ b/osu.Game/Screens/Tournament/Group.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Screens/Tournament/GroupContainer.cs b/osu.Game/Screens/Tournament/GroupContainer.cs index ba73a61c92..30919c36a5 100644 --- a/osu.Game/Screens/Tournament/GroupContainer.cs +++ b/osu.Game/Screens/Tournament/GroupContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs index 5bae30458e..008e4d759f 100644 --- a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs +++ b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs b/osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs index 2739711c35..ff26d1de13 100644 --- a/osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs +++ b/osu.Game/Screens/Tournament/Teams/DrawingsTeam.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Screens.Tournament.Teams diff --git a/osu.Game/Screens/Tournament/Teams/ITeamList.cs b/osu.Game/Screens/Tournament/Teams/ITeamList.cs index 9427ebc7fb..6340bc00a7 100644 --- a/osu.Game/Screens/Tournament/Teams/ITeamList.cs +++ b/osu.Game/Screens/Tournament/Teams/ITeamList.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs b/osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs index ce3b5ed941..943e7d8cae 100644 --- a/osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs +++ b/osu.Game/Screens/Tournament/Teams/StorageBackedTeamList.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index 0d8b57e46c..2de3a1c762 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Storyboards/CommandTimeline.cs b/osu.Game/Storyboards/CommandTimeline.cs index b9bb6629d1..d3b246a497 100644 --- a/osu.Game/Storyboards/CommandTimeline.cs +++ b/osu.Game/Storyboards/CommandTimeline.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Caching; diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index c6d9202121..54588070b3 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Storyboards/CommandTrigger.cs b/osu.Game/Storyboards/CommandTrigger.cs index e2731f9c45..bfefbb1976 100644 --- a/osu.Game/Storyboards/CommandTrigger.cs +++ b/osu.Game/Storyboards/CommandTrigger.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Storyboards diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 5df88b342f..2489369493 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; @@ -26,7 +26,8 @@ namespace osu.Game.Storyboards.Drawables protected override Container Content => content; protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480); - public override bool HandleInput => false; + public override bool HandleKeyboardInput => false; + public override bool HandleMouseInput => false; private bool passing = true; public bool Passing diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index 9757756316..ef782abbe5 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs index 737704f6d0..a738916e8d 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; diff --git a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index 9153b3e514..a39805f74e 100644 --- a/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs index 3b21c47b96..2fa480a1b5 100644 --- a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs +++ b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Storyboards/Drawables/IFlippable.cs b/osu.Game/Storyboards/Drawables/IFlippable.cs index 4d21c9d140..eff0f7f32a 100644 --- a/osu.Game/Storyboards/Drawables/IFlippable.cs +++ b/osu.Game/Storyboards/Drawables/IFlippable.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Storyboards/IStoryboardElement.cs b/osu.Game/Storyboards/IStoryboardElement.cs index 74b6a8d8bc..ab78a50d68 100644 --- a/osu.Game/Storyboards/IStoryboardElement.cs +++ b/osu.Game/Storyboards/IStoryboardElement.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs index 4eca910c1e..e2587debc9 100644 --- a/osu.Game/Storyboards/Storyboard.cs +++ b/osu.Game/Storyboards/Storyboard.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; diff --git a/osu.Game/Storyboards/StoryboardAnimation.cs b/osu.Game/Storyboards/StoryboardAnimation.cs index 98936df9e5..d56be26d73 100644 --- a/osu.Game/Storyboards/StoryboardAnimation.cs +++ b/osu.Game/Storyboards/StoryboardAnimation.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Storyboards/StoryboardLayer.cs b/osu.Game/Storyboards/StoryboardLayer.cs index f565b13eb5..ba2676b9e5 100644 --- a/osu.Game/Storyboards/StoryboardLayer.cs +++ b/osu.Game/Storyboards/StoryboardLayer.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Storyboards.Drawables; diff --git a/osu.Game/Storyboards/StoryboardSample.cs b/osu.Game/Storyboards/StoryboardSample.cs index e7a157c2f4..8779ba9a0f 100644 --- a/osu.Game/Storyboards/StoryboardSample.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs index 349a59dee0..774f82b860 100644 --- a/osu.Game/Storyboards/StoryboardSprite.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 82248c2cb8..af482dc250 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Audio.Track; diff --git a/osu.Game/Tests/CleanRunHeadlessGameHost.cs b/osu.Game/Tests/CleanRunHeadlessGameHost.cs new file mode 100644 index 0000000000..b6ff6dcf84 --- /dev/null +++ b/osu.Game/Tests/CleanRunHeadlessGameHost.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Platform; + +namespace osu.Game.Tests +{ + /// + /// A headless host which cleans up before running (removing any remnants from a previous execution). + /// + public class CleanRunHeadlessGameHost : HeadlessGameHost + { + public CleanRunHeadlessGameHost(string gameName = @"", bool bindIPC = false, bool realtime = true) + : base(gameName, bindIPC, realtime) + { + Storage.DeleteDirectory(string.Empty); + } + } +} diff --git a/osu.Game/Tests/Platform/TestStorage.cs b/osu.Game/Tests/Platform/TestStorage.cs index e583183d46..7199f5ea86 100644 --- a/osu.Game/Tests/Platform/TestStorage.cs +++ b/osu.Game/Tests/Platform/TestStorage.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Platform; diff --git a/osu.Game/Tests/Visual/OsuTestCase.cs b/osu.Game/Tests/Visual/OsuTestCase.cs index b2c8be47bd..97aada2971 100644 --- a/osu.Game/Tests/Visual/OsuTestCase.cs +++ b/osu.Game/Tests/Visual/OsuTestCase.cs @@ -1,8 +1,7 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osu.Framework.Platform; using osu.Framework.Testing; namespace osu.Game.Tests.Visual @@ -11,11 +10,8 @@ namespace osu.Game.Tests.Visual { public override void RunTest() { - using (var host = new HeadlessGameHost($"test-{Guid.NewGuid()}", realtime: false)) - { - host.Storage.DeleteDirectory(string.Empty); + using (var host = new CleanRunHeadlessGameHost($"test-{Guid.NewGuid()}", realtime: false)) host.Run(new OsuTestCaseTestRunner(this)); - } } public class OsuTestCaseTestRunner : OsuGameBase diff --git a/osu.Game/Tests/Visual/ScreenTestCase.cs b/osu.Game/Tests/Visual/ScreenTestCase.cs index 2f0831d84a..290b330827 100644 --- a/osu.Game/Tests/Visual/ScreenTestCase.cs +++ b/osu.Game/Tests/Visual/ScreenTestCase.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Screens; diff --git a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs index 8b93be9bb5..c531edb893 100644 --- a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs +++ b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; diff --git a/osu.Game/Tests/Visual/TestCasePlayer.cs b/osu.Game/Tests/Visual/TestCasePlayer.cs index 933781890f..181ed5e0e6 100644 --- a/osu.Game/Tests/Visual/TestCasePlayer.cs +++ b/osu.Game/Tests/Visual/TestCasePlayer.cs @@ -1,7 +1,6 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.IO; using System.Linq; using System.Text; @@ -18,24 +17,19 @@ namespace osu.Game.Tests.Visual { public abstract class TestCasePlayer : ScreenTestCase { - private readonly Type ruleset; + private readonly Ruleset ruleset; protected Player Player; private TestWorkingBeatmap working; - /// - /// Create a TestCase which runs through the Player screen. - /// - /// An optional ruleset type which we want to target. If not provided we'll allow all rulesets to be tested. - protected TestCasePlayer(Type ruleset) + protected TestCasePlayer(Ruleset ruleset) { this.ruleset = ruleset; } protected TestCasePlayer() { - } [BackgroundDependencyLoader] @@ -48,14 +42,21 @@ namespace osu.Game.Tests.Visual Depth = int.MaxValue }); - string instantiation = ruleset?.AssemblyQualifiedName; - - foreach (var r in rulesets.AvailableRulesets.Where(rs => instantiation == null || rs.InstantiationInfo == instantiation)) + if (ruleset != null) { Player p = null; - AddStep(r.Name, () => p = loadPlayerFor(r)); + AddStep(ruleset.RulesetInfo.Name, () => p = loadPlayerFor(ruleset)); AddUntilStep(() => p.IsLoaded); } + else + { + foreach (var r in rulesets.AvailableRulesets) + { + Player p = null; + AddStep(r.Name, () => p = loadPlayerFor(r)); + AddUntilStep(() => p.IsLoaded); + } + } } protected virtual Beatmap CreateBeatmap() @@ -69,21 +70,21 @@ namespace osu.Game.Tests.Visual return beatmap; } - private Player loadPlayerFor(RulesetInfo r) + private Player loadPlayerFor(RulesetInfo ri) => loadPlayerFor(ri.CreateInstance()); + + private Player loadPlayerFor(Ruleset r) { var beatmap = CreateBeatmap(); - beatmap.BeatmapInfo.Ruleset = r; - - var instance = r.CreateInstance(); + beatmap.BeatmapInfo.Ruleset = r.RulesetInfo; working = new TestWorkingBeatmap(beatmap); - working.Mods.Value = new[] { instance.GetAllMods().First(m => m is ModNoFail) }; + working.Mods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) }; if (Player != null) Remove(Player); - var player = CreatePlayer(working, instance); + var player = CreatePlayer(working, r); LoadComponentAsync(player, LoadScreen); diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index 7ced0305fd..4386028f7f 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs index 46ddaee637..71f9cb1a7e 100644 --- a/osu.Game/Users/Country.cs +++ b/osu.Game/Users/Country.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Users/Medal.cs b/osu.Game/Users/Medal.cs index aa7382b457..51517e3e34 100644 --- a/osu.Game/Users/Medal.cs +++ b/osu.Game/Users/Medal.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Users diff --git a/osu.Game/Users/Team.cs b/osu.Game/Users/Team.cs index 7d5c0322fe..49b1a0f08e 100644 --- a/osu.Game/Users/Team.cs +++ b/osu.Game/Users/Team.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE namespace osu.Game.Users diff --git a/osu.Game/Users/UpdateableAvatar.cs b/osu.Game/Users/UpdateableAvatar.cs index d55c0caad7..2edd7cbf55 100644 --- a/osu.Game/Users/UpdateableAvatar.cs +++ b/osu.Game/Users/UpdateableAvatar.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; @@ -44,7 +44,7 @@ namespace osu.Game.Users new Avatar(user) { RelativeSizeAxes = Axes.Both, - OnLoadComplete = d => d.FadeInFromZero(200), + OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint), }) ); } diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 5c0e5f1f95..21c59a6aeb 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -26,10 +26,6 @@ namespace osu.Game.Users [JsonProperty(@"age")] public int? Age; - public int GlobalRank; - - public int CountryRank; - //public Team Team; [JsonProperty(@"profile_colour")] @@ -39,10 +35,14 @@ namespace osu.Game.Users public string AvatarUrl; [JsonProperty(@"cover_url")] - public string CoverUrl; + public string CoverUrl + { + get { return Cover?.Url; } + set { Cover = new UserCover { Url = value }; } + } - //[JsonProperty(@"cover")] - //public UserCover Cover; + [JsonProperty(@"cover")] + public UserCover Cover; public class UserCover { @@ -56,19 +56,19 @@ namespace osu.Game.Users public int? Id; } - [JsonProperty(@"isAdmin")] + [JsonProperty(@"is_admin")] public bool IsAdmin; - [JsonProperty(@"isSupporter")] + [JsonProperty(@"is_supporter")] public bool IsSupporter; - [JsonProperty(@"isGMT")] + [JsonProperty(@"is_gmt")] public bool IsGMT; - [JsonProperty(@"isQAT")] + [JsonProperty(@"is_qat")] public bool IsQAT; - [JsonProperty(@"isBNG")] + [JsonProperty(@"is_bng")] public bool IsBNG; [JsonProperty(@"is_active")] @@ -107,7 +107,7 @@ namespace osu.Game.Users [JsonProperty(@"playmode")] public string PlayMode; - [JsonProperty(@"profileOrder")] + [JsonProperty(@"profile_order")] public string[] ProfileOrder; [JsonProperty(@"kudosu")] diff --git a/osu.Game/Users/UserCoverBackground.cs b/osu.Game/Users/UserCoverBackground.cs index 68c97fc8fd..f6bb40b6d2 100644 --- a/osu.Game/Users/UserCoverBackground.cs +++ b/osu.Game/Users/UserCoverBackground.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index e0a4e3184d..c62ba392b8 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; @@ -28,9 +28,12 @@ namespace osu.Game.Users private const float content_padding = 10; private const float status_height = 30; - private readonly Container statusBar; - private readonly Box statusBg; - private readonly OsuSpriteText statusMessage; + private Container statusBar; + private Box statusBg; + private OsuSpriteText statusMessage; + + private Container content; + protected override Container Content => content; public readonly Bindable Status = new Bindable(); @@ -45,133 +48,7 @@ namespace osu.Game.Users this.user = user; - FillFlowContainer infoContainer; - Height = height - status_height; - Masking = true; - CornerRadius = 5; - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Radius = 4, - }; - - Children = new Drawable[] - { - new DelayedLoadWrapper(new UserCoverBackground(user) - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(200), - }, 0) { RelativeSizeAxes = Axes.Both }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(0.7f), - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Top = content_padding, Left = content_padding, Right = content_padding }, - Children = new Drawable[] - { - new UpdateableAvatar - { - Size = new Vector2(height - status_height - content_padding * 2), - User = user, - Masking = true, - CornerRadius = 5, - EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Colour = Color4.Black.Opacity(0.25f), - Radius = 4, - }, - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = height - status_height - content_padding }, - Children = new Drawable[] - { - new OsuSpriteText - { - Text = user.Username, - TextSize = 18, - Font = @"Exo2.0-SemiBoldItalic", - }, - infoContainer = new FillFlowContainer - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - AutoSizeAxes = Axes.X, - Height = 20f, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5f, 0f), - Children = new Drawable[] - { - new DrawableFlag(user.Country) - { - Width = 30f, - RelativeSizeAxes = Axes.Y, - }, - }, - }, - }, - }, - }, - }, - statusBar = new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Alpha = 0f, - Children = new Drawable[] - { - statusBg = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.5f, - }, - new FillFlowContainer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(5f, 0f), - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Icon = FontAwesome.fa_circle_o, - Shadow = true, - Size = new Vector2(14), - }, - statusMessage = new OsuSpriteText - { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = @"Exo2.0-Semibold", - }, - }, - }, - }, - }, - }; - - if (user.IsSupporter) - infoContainer.Add(new SupporterIcon - { - RelativeSizeAxes = Axes.Y, - Width = 20f, - }); } [BackgroundDependencyLoader(permitNulls: true)] @@ -180,6 +57,139 @@ namespace osu.Game.Users if (colours == null) throw new ArgumentNullException(nameof(colours)); + FillFlowContainer infoContainer; + + AddInternal(content = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 5, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.25f), + Radius = 4, + }, + + Children = new Drawable[] + { + new DelayedLoadWrapper(new UserCoverBackground(user) + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill, + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out) + }, 300) { RelativeSizeAxes = Axes.Both }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.7f), + }, + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Top = content_padding, Horizontal = content_padding }, + Children = new Drawable[] + { + new UpdateableAvatar + { + Size = new Vector2(height - status_height - content_padding * 2), + User = user, + Masking = true, + CornerRadius = 5, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(0.25f), + Radius = 4, + }, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = height - status_height - content_padding }, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = user.Username, + TextSize = 18, + Font = @"Exo2.0-SemiBoldItalic", + }, + infoContainer = new FillFlowContainer + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.X, + Height = 20f, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5f, 0f), + Children = new Drawable[] + { + new DrawableFlag(user.Country) + { + Width = 30f, + RelativeSizeAxes = Axes.Y, + }, + }, + }, + }, + }, + }, + }, + statusBar = new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Alpha = 0f, + Children = new Drawable[] + { + statusBg = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.5f, + }, + new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(5f, 0f), + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Icon = FontAwesome.fa_circle_o, + Shadow = true, + Size = new Vector2(14), + }, + statusMessage = new OsuSpriteText + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Font = @"Exo2.0-Semibold", + }, + }, + }, + }, + }, + } + }); + + if (user.IsSupporter) + { + infoContainer.Add(new SupporterIcon + { + RelativeSizeAxes = Axes.Y, + Width = 20f, + }); + } + Status.ValueChanged += displayStatus; Status.ValueChanged += status => statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs index 15b57553a6..c29bc91d17 100644 --- a/osu.Game/Users/UserStatistics.cs +++ b/osu.Game/Users/UserStatistics.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Newtonsoft.Json; @@ -22,8 +22,11 @@ namespace osu.Game.Users [JsonProperty(@"pp")] public decimal? PP; - [JsonProperty(@"pp_rank")] - public int Rank; + [JsonProperty(@"pp_rank")] // the API sometimes only returns this value in condensed user responses + private int rank { set => Ranks.Global = value; } + + [JsonProperty(@"rank")] + public UserRanks Ranks; [JsonProperty(@"ranked_score")] public long RankedScore; @@ -51,14 +54,30 @@ namespace osu.Game.Users public struct Grades { + [JsonProperty(@"ssh")] + public int SSPlus; + [JsonProperty(@"ss")] public int SS; + [JsonProperty(@"sh")] + public int SPlus; + [JsonProperty(@"s")] public int S; [JsonProperty(@"a")] public int A; } + + public struct UserRanks + { + [JsonProperty(@"global")] + public int Global; + + [JsonProperty(@"country")] + public int Country; + } + } } diff --git a/osu.Game/Users/UserStatus.cs b/osu.Game/Users/UserStatus.cs index 37b796630b..9ee1b5a08d 100644 --- a/osu.Game/Users/UserStatus.cs +++ b/osu.Game/Users/UserStatus.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK.Graphics; diff --git a/osu.Game/osu.nuspec b/osu.Game/osu.nuspec index 4c529f57e5..bb7d382cee 100644 --- a/osu.Game/osu.nuspec +++ b/osu.Game/osu.nuspec @@ -12,12 +12,12 @@ click the circles. to the beat. click the circles. testing - Copyright ppy Pty Ltd 2007-2017 + Copyright ppy Pty Ltd 2007-2018 en-AU - + diff --git a/osu.licenseheader b/osu.licenseheader index 30ea2f9ad9..798b25e550 100644 --- a/osu.licenseheader +++ b/osu.licenseheader @@ -1,9 +1,9 @@ extensions: .cs -// Copyright (c) 2007-2017 ppy Pty Ltd . +// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE extensions: .xml .config .xsd \ No newline at end of file diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 20007e3306..3b62dbe579 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -173,7 +173,9 @@ NEXT_LINE True NEVER + NEVER False + NEVER False True False @@ -598,7 +600,7 @@ </TypePattern> </Patterns> Copyright (c) 2007-$CURRENT_YEAR$ ppy Pty Ltd <contact@ppy.sh>. -Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE +Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />