diff --git a/.vscode/launch.json b/.vscode/launch.json index c836ff97bc..0e07b0a067 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -3,6 +3,9 @@ "configurations": [ { "name": "Launch VisualTests", + "windows": { + "type": "clr" + }, "type": "mono", "request": "launch", "program": "${workspaceRoot}/osu.Desktop.VisualTests/bin/Debug/osu!.exe", @@ -15,6 +18,9 @@ }, { "name": "Launch Desktop", + "windows": { + "type": "clr" + }, "type": "mono", "request": "launch", "program": "${workspaceRoot}/osu.Desktop/bin/Debug/osu!.exe", @@ -27,6 +33,11 @@ }, { "name": "Attach", + "windows": { + "type": "clr", + "request": "attach", + "processName": "osu!" + }, "type": "mono", "request": "attach", "address": "localhost", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 03f5bc4c6c..6918afa620 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -8,13 +8,26 @@ "taskName": "build", "isShellCommand": true, "showOutput": "silent", - "command": "xbuild", - "windows": { - "command": "msbuild" - }, + "command": "msbuild", "args": [ // Ask msbuild to generate full paths for file names. - "/property:GenerateFullPaths=true" + "/property:GenerateFullPaths=true", + "/property:DebugType=portable" + ], + // Use the standard MS compiler pattern to detect errors, warnings and infos + "problemMatcher": "$msCompile", + "isBuildCommand": true + }, + { + "taskName": "rebuild", + "isShellCommand": true, + "showOutput": "silent", + "command": "msbuild", + "args": [ + // Ask msbuild to generate full paths for file names. + "/property:GenerateFullPaths=true", + "/property:DebugType=portable", + "/target:Clean,Build" ], // Use the standard MS compiler pattern to detect errors, warnings and infos "problemMatcher": "$msCompile", diff --git a/osu-framework b/osu-framework index 2234013e59..9204b83850 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 2234013e59a99116ee9f9e56a95ff8a6667db2a7 +Subproject commit 9204b838504a51ffe7577c103b91270a2687bfb8 diff --git a/osu-resources b/osu-resources index 0cba3cbc16..b90c4ed490 160000 --- a/osu-resources +++ b/osu-resources @@ -1 +1 @@ -Subproject commit 0cba3cbc167cfe94e07fe5b629c925e190be939e +Subproject commit b90c4ed490f76f2995662b3a8af3a32b8756a012 diff --git a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj index 901117b026..1f9726b573 100644 --- a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj +++ b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj @@ -22,6 +22,7 @@ DEBUG;TRACE prompt 4 + 6 AnyCPU diff --git a/osu.Desktop.Tests/VisualTests.cs b/osu.Desktop.Tests/VisualTests.cs index 6519dbe917..6ef924e873 100644 --- a/osu.Desktop.Tests/VisualTests.cs +++ b/osu.Desktop.Tests/VisualTests.cs @@ -4,11 +4,6 @@ using NUnit.Framework; using osu.Desktop.VisualTests; using osu.Framework.Desktop.Platform; -using osu.Game.Modes; -using osu.Game.Modes.Catch; -using osu.Game.Modes.Mania; -using osu.Game.Modes.Osu; -using osu.Game.Modes.Taiko; namespace osu.Desktop.Tests { @@ -20,11 +15,6 @@ namespace osu.Desktop.Tests { using (var host = new HeadlessGameHost()) { - Ruleset.Register(new OsuRuleset()); - Ruleset.Register(new TaikoRuleset()); - Ruleset.Register(new ManiaRuleset()); - Ruleset.Register(new CatchRuleset()); - host.Run(new AutomatedVisualTestGame()); } } diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj index ccb979afaa..f0620c98ef 100644 --- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj +++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj @@ -21,6 +21,7 @@ prompt 4 false + 6 pdbonly @@ -74,21 +75,21 @@ {69051C69-12AE-4E7D-A3E6-460D2E282312} osu.Desktop.VisualTests - + {58F6C80C-1253-4A0E-A465-B8C85EBEADF3} - osu.Game.Modes.Catch + osu.Game.Rulesets.Catch - + {48F4582B-7687-4621-9CBE-5C24197CB536} - osu.Game.Modes.Mania + osu.Game.Rulesets.Mania - + {C92A607B-1FDD-4954-9F92-03FF547D9080} - osu.Game.Modes.Osu + osu.Game.Rulesets.Osu - + {F167E17A-7DE6-4AF5-B920-A5112296C695} - osu.Game.Modes.Taiko + osu.Game.Rulesets.Taiko {0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D} diff --git a/osu.Desktop.VisualTests/Program.cs b/osu.Desktop.VisualTests/Program.cs index fe1cdfd7f0..03d1588b78 100644 --- a/osu.Desktop.VisualTests/Program.cs +++ b/osu.Desktop.VisualTests/Program.cs @@ -4,11 +4,6 @@ using System; using osu.Framework.Desktop; using osu.Framework.Platform; -using osu.Game.Modes; -using osu.Game.Modes.Catch; -using osu.Game.Modes.Mania; -using osu.Game.Modes.Osu; -using osu.Game.Modes.Taiko; namespace osu.Desktop.VisualTests { @@ -21,11 +16,6 @@ namespace osu.Desktop.VisualTests using (GameHost host = Host.GetSuitableHost(@"osu")) { - Ruleset.Register(new OsuRuleset()); - Ruleset.Register(new TaikoRuleset()); - Ruleset.Register(new ManiaRuleset()); - Ruleset.Register(new CatchRuleset()); - if (benchmark) host.Run(new AutomatedVisualTestGame()); else diff --git a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs index 3129cade63..cb15558ec3 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs @@ -9,21 +9,30 @@ using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Database; -using osu.Game.Modes.Catch.UI; -using osu.Game.Modes.Mania.UI; -using osu.Game.Modes.Objects; -using osu.Game.Modes.Osu.Objects; -using osu.Game.Modes.Osu.UI; -using osu.Game.Modes.Taiko.UI; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Taiko.UI; using System.Collections.Generic; using osu.Desktop.VisualTests.Beatmaps; +using osu.Framework.Allocation; namespace osu.Desktop.VisualTests.Tests { internal class TestCaseGamefield : TestCase { + private RulesetDatabase rulesets; + public override string Description => @"Showing hitobjects and what not."; + [BackgroundDependencyLoader] + private void load(RulesetDatabase rulesets) + { + this.rulesets = rulesets; + } + public override void Reset() { base.Reset(); @@ -36,7 +45,7 @@ namespace osu.Desktop.VisualTests.Tests objects.Add(new HitCircle { StartTime = time, - Position = new Vector2(RNG.Next(0, 512), RNG.Next(0, 384)), + Position = new Vector2(RNG.Next(0, (int)OsuPlayfield.BASE_SIZE.X), RNG.Next(0, (int)OsuPlayfield.BASE_SIZE.Y)), Scale = RNG.NextSingle(0.5f, 1.0f), }); @@ -49,6 +58,7 @@ namespace osu.Desktop.VisualTests.Tests BeatmapInfo = new BeatmapInfo { Difficulty = new BeatmapDifficulty(), + Ruleset = rulesets.Query().First(), Metadata = new BeatmapMetadata { Artist = @"Unknown", diff --git a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs index 3d9f3aad79..15b38b3e83 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseHitObjects.cs @@ -10,11 +10,11 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Testing; using osu.Framework.Timing; -using osu.Game.Modes.Objects; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Judgements; -using osu.Game.Modes.Osu.Objects; -using osu.Game.Modes.Osu.Objects.Drawables; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; using System.Collections.Generic; namespace osu.Desktop.VisualTests.Tests diff --git a/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs b/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs index 44e52c237e..39010baf91 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseLeaderboard.cs @@ -4,9 +4,9 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Testing; -using osu.Game.Modes.Mods; -using osu.Game.Modes.Osu.Mods; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; diff --git a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs index 7677682ac8..d1c137191f 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs @@ -1,10 +1,11 @@ // Copyright (c) 2007-2017 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.Overlays.Mods; using osu.Framework.Testing; -using osu.Game.Modes; +using osu.Game.Database; namespace osu.Desktop.VisualTests.Tests { @@ -13,6 +14,13 @@ namespace osu.Desktop.VisualTests.Tests public override string Description => @"Tests the mod select overlay"; private ModSelectOverlay modSelect; + private RulesetDatabase rulesets; + + [BackgroundDependencyLoader] + private void load(RulesetDatabase rulesets) + { + this.rulesets = rulesets; + } public override void Reset() { @@ -26,10 +34,9 @@ namespace osu.Desktop.VisualTests.Tests }); AddStep("Toggle", modSelect.ToggleVisibility); - AddStep("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu); - AddStep("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko); - AddStep("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch); - AddStep("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania); + + foreach (var ruleset in rulesets.AllRulesets) + AddStep(ruleset.CreateInstance().Description, () => modSelect.Ruleset.Value = ruleset); } } } diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index 1a43425dda..35eb6d0ff9 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -6,7 +6,6 @@ using osu.Desktop.VisualTests.Platform; using osu.Framework.Testing; using osu.Framework.MathUtils; using osu.Game.Database; -using osu.Game.Modes; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Filter; @@ -20,13 +19,19 @@ namespace osu.Desktop.VisualTests.Tests public override string Description => @"with fake data"; + private RulesetDatabase rulesets; + public override void Reset() { base.Reset(); if (db == null) { storage = new TestStorage(@"TestCasePlaySongSelect"); - db = new BeatmapDatabase(storage); + + var backingDatabase = storage.GetDatabase(@"client"); + + rulesets = new RulesetDatabase(storage, backingDatabase); + db = new BeatmapDatabase(storage, backingDatabase, rulesets); var sets = new List(); @@ -72,7 +77,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1234 + i, - Mode = PlayMode.Osu, + Ruleset = rulesets.Query().First(), Path = "normal.osu", Version = "Normal", Difficulty = new BeatmapDifficulty @@ -83,7 +88,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1235 + i, - Mode = PlayMode.Osu, + Ruleset = rulesets.Query().First(), Path = "hard.osu", Version = "Hard", Difficulty = new BeatmapDifficulty @@ -94,7 +99,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1236 + i, - Mode = PlayMode.Osu, + Ruleset = rulesets.Query().First(), Path = "insane.osu", Version = "Insane", Difficulty = new BeatmapDifficulty diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index 624723ed35..f28cdd6a7e 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -9,12 +9,12 @@ using osu.Game.Beatmaps; using OpenTK; using osu.Framework.Graphics.Sprites; using osu.Game.Database; -using osu.Game.Modes; -using osu.Game.Modes.Objects; -using osu.Game.Modes.Osu.Objects; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Play; using OpenTK.Graphics; using osu.Desktop.VisualTests.Beatmaps; +using osu.Game.Rulesets.Osu.UI; namespace osu.Desktop.VisualTests.Tests { @@ -22,12 +22,14 @@ namespace osu.Desktop.VisualTests.Tests { protected Player Player; private BeatmapDatabase db; + private RulesetDatabase rulesets; public override string Description => @"Showing everything to play the game."; [BackgroundDependencyLoader] - private void load(BeatmapDatabase db) + private void load(BeatmapDatabase db, RulesetDatabase rulesets) { + this.rulesets = rulesets; this.db = db; } @@ -37,7 +39,7 @@ namespace osu.Desktop.VisualTests.Tests WorkingBeatmap beatmap = null; - var beatmapInfo = db.Query().FirstOrDefault(b => b.Mode == PlayMode.Osu); + var beatmapInfo = db.Query().FirstOrDefault(b => b.RulesetID == 0); if (beatmapInfo != null) beatmap = db.GetWorkingBeatmap(beatmapInfo); @@ -51,8 +53,8 @@ namespace osu.Desktop.VisualTests.Tests objects.Add(new HitCircle { StartTime = time, - Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : 512, - i % 4 < 2 ? 0 : 384), + Position = new Vector2(i % 4 == 0 || i % 4 == 2 ? 0 : OsuPlayfield.BASE_SIZE.X, + i % 4 < 2 ? 0 : OsuPlayfield.BASE_SIZE.Y), NewCombo = i % 4 == 0 }); @@ -65,6 +67,7 @@ namespace osu.Desktop.VisualTests.Tests BeatmapInfo = new BeatmapInfo { Difficulty = new BeatmapDifficulty(), + Ruleset = rulesets.Query().First(), Metadata = new BeatmapMetadata { Artist = @"Unknown", diff --git a/osu.Desktop.VisualTests/Tests/TestCaseReplay.cs b/osu.Desktop.VisualTests/Tests/TestCaseReplay.cs index ffdca25bb3..e00a912278 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseReplay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseReplay.cs @@ -2,8 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Modes.Mods; -using osu.Game.Modes.Osu.Mods; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Screens.Play; namespace osu.Desktop.VisualTests.Tests diff --git a/osu.Desktop.VisualTests/Tests/TestCaseResults.cs b/osu.Desktop.VisualTests/Tests/TestCaseResults.cs new file mode 100644 index 0000000000..aa3a117667 --- /dev/null +++ b/osu.Desktop.VisualTests/Tests/TestCaseResults.cs @@ -0,0 +1,68 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Testing; +using osu.Game.Beatmaps; +using osu.Game.Database; +using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Ranking; +using osu.Game.Users; + +namespace osu.Desktop.VisualTests.Tests +{ + internal class TestCaseResults : TestCase + { + private BeatmapDatabase db; + + public override string Description => @"Results after playing."; + + [BackgroundDependencyLoader] + private void load(BeatmapDatabase db) + { + this.db = db; + } + + private WorkingBeatmap beatmap; + + public override void Reset() + { + base.Reset(); + + if (beatmap == null) + { + var beatmapInfo = db.Query().FirstOrDefault(b => b.RulesetID == 0); + if (beatmapInfo != null) + beatmap = db.GetWorkingBeatmap(beatmapInfo); + } + + base.Reset(); + + Add(new Results(new Score + { + TotalScore = 2845370, + Accuracy = 0.98, + MaxCombo = 123, + Rank = ScoreRank.A, + Date = DateTime.Now, + Statistics = new Dictionary() + { + { "300", 50 }, + { "100", 20 }, + { "50", 50 }, + { "x", 1 } + }, + User = new User + { + Username = "peppy", + } + }) + { + Beatmap = beatmap + }); + } + } +} diff --git a/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs b/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs index f3cca16678..d8dac63980 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseScoreCounter.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; using osu.Framework.Testing; using osu.Game.Graphics.UserInterface; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.UI; namespace osu.Desktop.VisualTests.Tests { diff --git a/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs b/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs index 363b0b481e..7c40d21512 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseSongProgress.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.MathUtils; using osu.Framework.Testing; using osu.Framework.Timing; -using osu.Game.Modes.Objects; +using osu.Game.Rulesets.Objects; using osu.Game.Screens.Play; namespace osu.Desktop.VisualTests.Tests @@ -16,6 +16,7 @@ namespace osu.Desktop.VisualTests.Tests public override string Description => @"With fake data"; private SongProgress progress; + private SongProgressGraph graph; public override void Reset() { @@ -23,11 +24,20 @@ namespace osu.Desktop.VisualTests.Tests Add(progress = new SongProgress { + RelativeSizeAxes = Axes.X, AudioClock = new StopwatchClock(true), Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, }); + Add(graph = new SongProgressGraph + { + RelativeSizeAxes = Axes.X, + Height = 200, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, + }); + AddStep("Toggle Bar", progress.ToggleBar); AddWaitStep(5); AddStep("Toggle Bar", progress.ToggleBar); @@ -44,6 +54,7 @@ namespace osu.Desktop.VisualTests.Tests objects.Add(new HitObject { StartTime = i }); progress.Objects = objects; + graph.Objects = objects; } } } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs index b3cb8c3457..d769071bd9 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoHitObjects.cs @@ -6,7 +6,7 @@ using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; namespace osu.Desktop.VisualTests.Tests { diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs index 4e9ff4980e..259d0267db 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs @@ -7,11 +7,11 @@ using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; using osu.Framework.Testing; using osu.Framework.Timing; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects; -using osu.Game.Modes.Taiko.Objects.Drawables; -using osu.Game.Modes.Taiko.UI; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Objects.Drawables; +using osu.Game.Rulesets.Taiko.UI; using System; namespace osu.Desktop.VisualTests.Tests diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTooltip.cs b/osu.Desktop.VisualTests/Tests/TestCaseTooltip.cs new file mode 100644 index 0000000000..c536672314 --- /dev/null +++ b/osu.Desktop.VisualTests/Tests/TestCaseTooltip.cs @@ -0,0 +1,92 @@ +// Copyright (c) 2007-2017 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.Framework.Testing; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Framework.Configuration; +using OpenTK; +using osu.Game.Graphics; + +namespace osu.Desktop.VisualTests.Tests +{ + internal class TestCaseTooltip : TestCase + { + public override string Description => "tests tooltips on various elements"; + + public override void Reset() + { + base.Reset(); + OsuSliderBar slider; + OsuSliderBar sliderDouble; + + const float width = 400; + + Children = new Drawable[] + { + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + new TooltipTextContainer("text with a tooltip"), + new TooltipTextContainer("more text with another tooltip"), + new TooltipTextbox + { + Text = "a textbox with a tooltip", + Size = new Vector2(width,30), + }, + slider = new OsuSliderBar + { + Width = width, + }, + sliderDouble = new OsuSliderBar + { + Width = width, + }, + }, + }, + }; + + slider.Current.BindTo(new BindableInt(5) + { + MaxValue = 10, + MinValue = 0 + }); + + sliderDouble.Current.BindTo(new BindableDouble(0.5) + { + MaxValue = 1, + MinValue = 0 + }); + } + + private class TooltipTextContainer : Container, IHasTooltip + { + private readonly OsuSpriteText text; + + public string TooltipText => text.Text; + + public TooltipTextContainer(string tooltipText) + { + AutoSizeAxes = Axes.Both; + Children = new[] + { + text = new OsuSpriteText + { + Text = tooltipText, + } + }; + } + } + + private class TooltipTextbox : OsuTextBox, IHasTooltip + { + public string TooltipText => Text; + } + } +} diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj index d75bb94308..135e4596c7 100644 --- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj +++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj @@ -61,6 +61,7 @@ false false false + 6 none @@ -160,21 +161,21 @@ {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} osu.Game.Resources - + {c92a607b-1fdd-4954-9f92-03ff547d9080} - osu.Game.Modes.Osu + osu.Game.Rulesets.Osu - + {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} - osu.Game.Modes.Catch + osu.Game.Rulesets.Catch - + {48f4582b-7687-4621-9cbe-5c24197cb536} - osu.Game.Modes.Mania + osu.Game.Rulesets.Mania - + {f167e17a-7de6-4af5-b920-a5112296c695} - osu.Game.Modes.Taiko + osu.Game.Rulesets.Taiko {0d3fbf8a-7464-4cf7-8c90-3e7886df2d4d} @@ -197,12 +198,14 @@ + + diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index ddf58ac363..210f780078 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -7,11 +7,6 @@ using osu.Desktop.Beatmaps.IO; using osu.Framework.Desktop; using osu.Framework.Desktop.Platform; using osu.Game.IPC; -using osu.Game.Modes; -using osu.Game.Modes.Catch; -using osu.Game.Modes.Mania; -using osu.Game.Modes.Osu; -using osu.Game.Modes.Taiko; namespace osu.Desktop { @@ -41,11 +36,6 @@ namespace osu.Desktop } else { - Ruleset.Register(new OsuRuleset()); - Ruleset.Register(new TaikoRuleset()); - Ruleset.Register(new ManiaRuleset()); - Ruleset.Register(new CatchRuleset()); - host.Run(new OsuGameDesktop(args)); } return 0; diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index dbd26b4640..4f66dfd3eb 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -63,6 +63,7 @@ false + 6 none @@ -197,21 +198,21 @@ {d9a367c9-4c1a-489f-9b05-a0cea2b53b58} osu.Game.Resources - + {c92a607b-1fdd-4954-9f92-03ff547d9080} - osu.Game.Modes.Osu + osu.Game.Rulesets.Osu - + {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} - osu.Game.Modes.Catch + osu.Game.Rulesets.Catch - + {48f4582b-7687-4621-9cbe-5c24197cb536} - osu.Game.Modes.Mania + osu.Game.Rulesets.Mania - + {f167e17a-7de6-4af5-b920-a5112296c695} - osu.Game.Modes.Taiko + osu.Game.Rulesets.Taiko {0d3fbf8a-7464-4cf7-8c90-3e7886df2d4d} diff --git a/osu.Game.Modes.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Modes.Catch/Beatmaps/CatchBeatmapConverter.cs deleted file mode 100644 index 9791554f02..0000000000 --- a/osu.Game.Modes.Catch/Beatmaps/CatchBeatmapConverter.cs +++ /dev/null @@ -1,20 +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.Modes.Catch.Objects; -using System.Collections.Generic; - -namespace osu.Game.Modes.Catch.Beatmaps -{ - internal class CatchBeatmapConverter : IBeatmapConverter - { - public Beatmap Convert(Beatmap original) - { - return new Beatmap(original) - { - HitObjects = new List() // Todo: Convert HitObjects - }; - } - } -} diff --git a/osu.Game.Modes.Catch/Beatmaps/CatchBeatmapProcessor.cs b/osu.Game.Modes.Catch/Beatmaps/CatchBeatmapProcessor.cs deleted file mode 100644 index ef585e2675..0000000000 --- a/osu.Game.Modes.Catch/Beatmaps/CatchBeatmapProcessor.cs +++ /dev/null @@ -1,19 +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.Modes.Catch.Objects; - -namespace osu.Game.Modes.Catch.Beatmaps -{ - internal class CatchBeatmapProcessor : IBeatmapProcessor - { - public void SetDefaults(CatchBaseHit hitObject, Beatmap beatmap) - { - } - - public void PostProcess(Beatmap beatmap) - { - } - } -} diff --git a/osu.Game.Modes.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Modes.Mania/Beatmaps/ManiaBeatmapConverter.cs deleted file mode 100644 index 3ff210c1cc..0000000000 --- a/osu.Game.Modes.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ /dev/null @@ -1,20 +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.Modes.Mania.Objects; -using System.Collections.Generic; - -namespace osu.Game.Modes.Mania.Beatmaps -{ - internal class ManiaBeatmapConverter : IBeatmapConverter - { - public Beatmap Convert(Beatmap original) - { - return new Beatmap(original) - { - HitObjects = new List() // Todo: Implement - }; - } - } -} diff --git a/osu.Game.Modes.Mania/Beatmaps/ManiaBeatmapProcessor.cs b/osu.Game.Modes.Mania/Beatmaps/ManiaBeatmapProcessor.cs deleted file mode 100644 index 5e85a8f864..0000000000 --- a/osu.Game.Modes.Mania/Beatmaps/ManiaBeatmapProcessor.cs +++ /dev/null @@ -1,19 +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.Modes.Mania.Objects; - -namespace osu.Game.Modes.Mania.Beatmaps -{ - internal class ManiaBeatmapProcessor : IBeatmapProcessor - { - public void SetDefaults(ManiaBaseHit hitObject, Beatmap beatmap) - { - } - - public void PostProcess(Beatmap beatmap) - { - } - } -} diff --git a/osu.Game.Modes.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Modes.Osu/Beatmaps/OsuBeatmapProcessor.cs deleted file mode 100644 index 08c9d94141..0000000000 --- a/osu.Game.Modes.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ /dev/null @@ -1,32 +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.Modes.Osu.Objects; - -namespace osu.Game.Modes.Osu.Beatmaps -{ - internal class OsuBeatmapProcessor : IBeatmapProcessor - { - public void PostProcess(Beatmap beatmap) - { - if (beatmap.ComboColors.Count == 0) - return; - - int comboIndex = 0; - int colourIndex = 0; - - foreach (var obj in beatmap.HitObjects) - { - if (obj.NewCombo) - { - comboIndex = 0; - colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count; - } - - obj.ComboIndex = comboIndex++; - obj.ComboColour = beatmap.ComboColors[colourIndex]; - } - } - } -} diff --git a/osu.Game.Modes.Osu/Scoring/OsuScore.cs b/osu.Game.Modes.Osu/Scoring/OsuScore.cs deleted file mode 100644 index a0a639a59e..0000000000 --- a/osu.Game.Modes.Osu/Scoring/OsuScore.cs +++ /dev/null @@ -1,11 +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.Modes.Scoring; - -namespace osu.Game.Modes.Osu.Scoring -{ - internal class OsuScore : Score - { - } -} diff --git a/osu.Game.Modes.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Modes.Osu/Scoring/OsuScoreProcessor.cs deleted file mode 100644 index 3b798a2fad..0000000000 --- a/osu.Game.Modes.Osu/Scoring/OsuScoreProcessor.cs +++ /dev/null @@ -1,59 +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.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Judgements; -using osu.Game.Modes.Osu.Objects; -using osu.Game.Modes.Scoring; -using osu.Game.Modes.UI; - -namespace osu.Game.Modes.Osu.Scoring -{ - internal class OsuScoreProcessor : ScoreProcessor - { - public OsuScoreProcessor() - { - } - - public OsuScoreProcessor(HitRenderer hitRenderer) - : base(hitRenderer) - { - } - - protected override void Reset() - { - base.Reset(); - - Health.Value = 1; - Accuracy.Value = 1; - } - - protected override void OnNewJudgement(OsuJudgement judgement) - { - if (judgement != null) - { - switch (judgement.Result) - { - case HitResult.Hit: - Health.Value += 0.1f; - break; - case HitResult.Miss: - Health.Value -= 0.2f; - break; - } - } - - int score = 0; - int maxScore = 0; - - foreach (var j in Judgements) - { - score += j.ScoreValue; - maxScore += j.MaxScoreValue; - } - - TotalScore.Value = score; - Accuracy.Value = (double)score / maxScore; - } - } -} diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapProcessor.cs b/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapProcessor.cs deleted file mode 100644 index 84bc470e55..0000000000 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapProcessor.cs +++ /dev/null @@ -1,19 +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.Modes.Taiko.Objects; - -namespace osu.Game.Modes.Taiko.Beatmaps -{ - internal class TaikoBeatmapProcessor : IBeatmapProcessor - { - public void SetDefaults(TaikoHitObject hitObject, Beatmap beatmap) - { - } - - public void PostProcess(Beatmap beatmap) - { - } - } -} diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs new file mode 100644 index 0000000000..f9859cd244 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -0,0 +1,23 @@ +// 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.Catch.Objects; +using System.Collections.Generic; +using System; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Catch.Beatmaps +{ + internal class CatchBeatmapConverter : BeatmapConverter + { + protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; + + protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) + { + yield return null; + } + } +} diff --git a/osu.Game.Modes.Catch/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs similarity index 65% rename from osu.Game.Modes.Catch/CatchDifficultyCalculator.cs rename to osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs index 53c6f5c2ce..a865299cff 100644 --- a/osu.Game.Modes.Catch/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/CatchDifficultyCalculator.cs @@ -2,11 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Modes.Catch.Beatmaps; -using osu.Game.Modes.Catch.Objects; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Catch.Beatmaps; +using osu.Game.Rulesets.Catch.Objects; using System.Collections.Generic; -namespace osu.Game.Modes.Catch +namespace osu.Game.Rulesets.Catch { public class CatchDifficultyCalculator : DifficultyCalculator { @@ -19,6 +20,6 @@ namespace osu.Game.Modes.Catch return 0; } - protected override IBeatmapConverter CreateBeatmapConverter() => new CatchBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter() => new CatchBeatmapConverter(); } } \ No newline at end of file diff --git a/osu.Game.Modes.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs similarity index 88% rename from osu.Game.Modes.Catch/CatchRuleset.cs rename to osu.Game.Rulesets.Catch/CatchRuleset.cs index 09d8bdb9e5..a6faf13d51 100644 --- a/osu.Game.Modes.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -4,16 +4,16 @@ using OpenTK.Input; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Modes.Catch.Mods; -using osu.Game.Modes.Catch.UI; -using osu.Game.Modes.Mods; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Catch.Mods; +using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using System.Collections.Generic; -using osu.Game.Modes.Catch.Scoring; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Catch.Scoring; +using osu.Game.Rulesets.Scoring; -namespace osu.Game.Modes.Catch +namespace osu.Game.Rulesets.Catch { public class CatchRuleset : Ruleset { @@ -76,8 +76,6 @@ namespace osu.Game.Modes.Catch } } - protected override PlayMode PlayMode => PlayMode.Catch; - public override string Description => "osu!catch"; public override FontAwesome Icon => FontAwesome.fa_osu_fruits_o; @@ -92,5 +90,7 @@ namespace osu.Game.Modes.Catch public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap); public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(); + + public override int LegacyID => 2; } } diff --git a/osu.Game.Modes.Catch/Judgements/CatchJudgement.cs b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs similarity index 78% rename from osu.Game.Modes.Catch/Judgements/CatchJudgement.cs rename to osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs index eaacedd7e0..f0125b4c3a 100644 --- a/osu.Game.Modes.Catch/Judgements/CatchJudgement.cs +++ b/osu.Game.Rulesets.Catch/Judgements/CatchJudgement.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Judgements; +using osu.Game.Rulesets.Judgements; -namespace osu.Game.Modes.Catch.Judgements +namespace osu.Game.Rulesets.Catch.Judgements { public class CatchJudgement : Judgement { diff --git a/osu.Game.Modes.Catch/Mods/CatchMod.cs b/osu.Game.Rulesets.Catch/Mods/CatchMod.cs similarity index 91% rename from osu.Game.Modes.Catch/Mods/CatchMod.cs rename to osu.Game.Rulesets.Catch/Mods/CatchMod.cs index 97e4e58a5d..64a0c51b72 100644 --- a/osu.Game.Modes.Catch/Mods/CatchMod.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchMod.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Mods; +using osu.Game.Rulesets.Mods; -namespace osu.Game.Modes.Catch.Mods +namespace osu.Game.Rulesets.Catch.Mods { public class CatchModNoFail : ModNoFail { diff --git a/osu.Game.Modes.Catch/Objects/CatchBaseHit.cs b/osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs similarity index 75% rename from osu.Game.Modes.Catch/Objects/CatchBaseHit.cs rename to osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs index ee66894d31..de0547580f 100644 --- a/osu.Game.Modes.Catch/Objects/CatchBaseHit.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchBaseHit.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects; +using osu.Game.Rulesets.Objects; -namespace osu.Game.Modes.Catch.Objects +namespace osu.Game.Rulesets.Catch.Objects { public abstract class CatchBaseHit : HitObject { diff --git a/osu.Game.Modes.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs similarity index 93% rename from osu.Game.Modes.Catch/Objects/Drawable/DrawableFruit.cs rename to osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs index 885048b938..ae6585bdb2 100644 --- a/osu.Game.Modes.Catch/Objects/Drawable/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Transforms; using OpenTK; -namespace osu.Game.Modes.Catch.Objects.Drawable +namespace osu.Game.Rulesets.Catch.Objects.Drawable { internal class DrawableFruit : Sprite { diff --git a/osu.Game.Modes.Catch/Objects/Droplet.cs b/osu.Game.Rulesets.Catch/Objects/Droplet.cs similarity index 80% rename from osu.Game.Modes.Catch/Objects/Droplet.cs rename to osu.Game.Rulesets.Catch/Objects/Droplet.cs index dd58fec7e8..b1206e0d75 100644 --- a/osu.Game.Modes.Catch/Objects/Droplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Droplet.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Catch.Objects +namespace osu.Game.Rulesets.Catch.Objects { public class Droplet : CatchBaseHit { diff --git a/osu.Game.Modes.Catch/Objects/Fruit.cs b/osu.Game.Rulesets.Catch/Objects/Fruit.cs similarity index 80% rename from osu.Game.Modes.Catch/Objects/Fruit.cs rename to osu.Game.Rulesets.Catch/Objects/Fruit.cs index 15363a7031..fc55f83969 100644 --- a/osu.Game.Modes.Catch/Objects/Fruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Fruit.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Catch.Objects +namespace osu.Game.Rulesets.Catch.Objects { public class Fruit : CatchBaseHit { diff --git a/osu.Game.Modes.Catch/OpenTK.dll.config b/osu.Game.Rulesets.Catch/OpenTK.dll.config similarity index 100% rename from osu.Game.Modes.Catch/OpenTK.dll.config rename to osu.Game.Rulesets.Catch/OpenTK.dll.config diff --git a/osu.Game.Modes.Catch/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs similarity index 90% rename from osu.Game.Modes.Catch/Properties/AssemblyInfo.cs rename to osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs index 1d25411e73..42fbc7e082 100644 --- a/osu.Game.Modes.Catch/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Catch/Properties/AssemblyInfo.cs @@ -7,11 +7,11 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("osu.Game.Modes.Catch")] +[assembly: AssemblyTitle("osu.Game.Rulesets.Catch")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("osu.Game.Modes.Catch")] +[assembly: AssemblyProduct("osu.Game.Rulesets.Catch")] [assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/osu.Game.Modes.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs similarity index 72% rename from osu.Game.Modes.Catch/Scoring/CatchScoreProcessor.cs rename to osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 1b9bedf7fb..3f29547e46 100644 --- a/osu.Game.Modes.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -1,12 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Catch.Judgements; -using osu.Game.Modes.Catch.Objects; -using osu.Game.Modes.Scoring; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Catch.Judgements; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; -namespace osu.Game.Modes.Catch.Scoring +namespace osu.Game.Rulesets.Catch.Scoring { internal class CatchScoreProcessor : ScoreProcessor { diff --git a/osu.Game.Modes.Catch/UI/CatchHitRenderer.cs b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs similarity index 56% rename from osu.Game.Modes.Catch/UI/CatchHitRenderer.cs rename to osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs index 90bd61a39f..f34585be55 100644 --- a/osu.Game.Modes.Catch/UI/CatchHitRenderer.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchHitRenderer.cs @@ -2,15 +2,16 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Modes.Catch.Beatmaps; -using osu.Game.Modes.Catch.Judgements; -using osu.Game.Modes.Catch.Objects; -using osu.Game.Modes.Catch.Scoring; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Scoring; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Catch.Beatmaps; +using osu.Game.Rulesets.Catch.Judgements; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.Catch.Scoring; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; -namespace osu.Game.Modes.Catch.UI +namespace osu.Game.Rulesets.Catch.UI { public class CatchHitRenderer : HitRenderer { @@ -21,9 +22,7 @@ namespace osu.Game.Modes.Catch.UI public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this); - protected override IBeatmapConverter CreateBeatmapConverter() => new CatchBeatmapConverter(); - - protected override IBeatmapProcessor CreateBeatmapProcessor() => new CatchBeatmapProcessor(); + protected override BeatmapConverter CreateBeatmapConverter() => new CatchBeatmapConverter(); protected override Playfield CreatePlayfield() => new CatchPlayfield(); diff --git a/osu.Game.Modes.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs similarity index 77% rename from osu.Game.Modes.Catch/UI/CatchPlayfield.cs rename to osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index f8792a7fd5..4b1e6e93cd 100644 --- a/osu.Game.Modes.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -3,12 +3,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Modes.Catch.Objects; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Catch.Objects; +using osu.Game.Rulesets.UI; using OpenTK; -using osu.Game.Modes.Catch.Judgements; +using osu.Game.Rulesets.Catch.Judgements; -namespace osu.Game.Modes.Catch.UI +namespace osu.Game.Rulesets.Catch.UI { public class CatchPlayfield : Playfield { diff --git a/osu.Game.Modes.Catch/osu.Game.Modes.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj similarity index 91% rename from osu.Game.Modes.Catch/osu.Game.Modes.Catch.csproj rename to osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 50b1a095af..281d2b5a79 100644 --- a/osu.Game.Modes.Catch/osu.Game.Modes.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -7,8 +7,8 @@ {58F6C80C-1253-4A0E-A465-B8C85EBEADF3} Library Properties - osu.Game.Modes.Catch - osu.Game.Modes.Catch + osu.Game.Rulesets.Catch + osu.Game.Rulesets.Catch v4.5 512 @@ -21,6 +21,7 @@ prompt 4 false + 6 pdbonly @@ -47,7 +48,6 @@ - @@ -73,9 +73,9 @@ {C76BF5B3-985E-4D39-95FE-97C9C879B83A} osu.Framework - + {C92A607B-1FDD-4954-9F92-03FF547D9080} - osu.Game.Modes.Osu + osu.Game.Rulesets.Osu {0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D} diff --git a/osu.Game.Modes.Catch/packages.config b/osu.Game.Rulesets.Catch/packages.config similarity index 100% rename from osu.Game.Modes.Catch/packages.config rename to osu.Game.Rulesets.Catch/packages.config diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs new file mode 100644 index 0000000000..847af965cc --- /dev/null +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -0,0 +1,23 @@ +// 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.Mania.Objects; +using System.Collections.Generic; +using System; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Mania.Beatmaps +{ + internal class ManiaBeatmapConverter : BeatmapConverter + { + protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; + + protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) + { + yield return null; + } + } +} diff --git a/osu.Game.Modes.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs similarity index 78% rename from osu.Game.Modes.Mania/Judgements/ManiaJudgement.cs rename to osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index 3ef5b0f29b..8dafbd01a5 100644 --- a/osu.Game.Modes.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Judgements; +using osu.Game.Rulesets.Judgements; -namespace osu.Game.Modes.Mania.Judgements +namespace osu.Game.Rulesets.Mania.Judgements { public class ManiaJudgement : Judgement { diff --git a/osu.Game.Modes.Mania/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs similarity index 66% rename from osu.Game.Modes.Mania/ManiaDifficultyCalculator.cs rename to osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs index 02a5a3acdc..e9bcc60d2c 100644 --- a/osu.Game.Modes.Mania/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs @@ -2,11 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Modes.Mania.Beatmaps; -using osu.Game.Modes.Mania.Objects; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Objects; using System.Collections.Generic; -namespace osu.Game.Modes.Mania +namespace osu.Game.Rulesets.Mania { public class ManiaDifficultyCalculator : DifficultyCalculator { @@ -20,6 +21,6 @@ namespace osu.Game.Modes.Mania return 0; } - protected override IBeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(); } } \ No newline at end of file diff --git a/osu.Game.Modes.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs similarity index 90% rename from osu.Game.Modes.Mania/ManiaRuleset.cs rename to osu.Game.Rulesets.Mania/ManiaRuleset.cs index bd995d87d6..26614075b1 100644 --- a/osu.Game.Modes.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -3,16 +3,16 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Modes.Mania.Mods; -using osu.Game.Modes.Mania.UI; -using osu.Game.Modes.Mods; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using System.Collections.Generic; -using osu.Game.Modes.Mania.Scoring; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Scoring; -namespace osu.Game.Modes.Mania +namespace osu.Game.Rulesets.Mania { public class ManiaRuleset : Ruleset { @@ -96,8 +96,6 @@ namespace osu.Game.Modes.Mania } } - protected override PlayMode PlayMode => PlayMode.Mania; - public override string Description => "osu!mania"; public override FontAwesome Icon => FontAwesome.fa_osu_mania_o; @@ -107,5 +105,7 @@ namespace osu.Game.Modes.Mania public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap); public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); + + public override int LegacyID => 3; } } diff --git a/osu.Game.Modes.Mania/Mods/ManiaMod.cs b/osu.Game.Rulesets.Mania/Mods/ManiaMod.cs similarity index 94% rename from osu.Game.Modes.Mania/Mods/ManiaMod.cs rename to osu.Game.Rulesets.Mania/Mods/ManiaMod.cs index b330680550..68458caeac 100644 --- a/osu.Game.Modes.Mania/Mods/ManiaMod.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaMod.cs @@ -2,10 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Graphics; -using osu.Game.Modes.Mods; +using osu.Game.Rulesets.Mods; using System; -namespace osu.Game.Modes.Mania.Mods +namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModNoFail : ModNoFail { diff --git a/osu.Game.Modes.Mania/Objects/Drawable/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawable/DrawableNote.cs similarity index 93% rename from osu.Game.Modes.Mania/Objects/Drawable/DrawableNote.cs rename to osu.Game.Rulesets.Mania/Objects/Drawable/DrawableNote.cs index 76999cef21..07a27b1643 100644 --- a/osu.Game.Modes.Mania/Objects/Drawable/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawable/DrawableNote.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Transforms; using osu.Framework.Graphics; using OpenTK; -namespace osu.Game.Modes.Mania.Objects.Drawable +namespace osu.Game.Rulesets.Mania.Objects.Drawable { public class DrawableNote : Sprite { diff --git a/osu.Game.Modes.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs similarity index 79% rename from osu.Game.Modes.Mania/Objects/HoldNote.cs rename to osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 3d95e11118..e8ce1da77f 100644 --- a/osu.Game.Modes.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Mania.Objects +namespace osu.Game.Rulesets.Mania.Objects { public class HoldNote : Note { diff --git a/osu.Game.Modes.Mania/Objects/ManiaBaseHit.cs b/osu.Game.Rulesets.Mania/Objects/ManiaBaseHit.cs similarity index 74% rename from osu.Game.Modes.Mania/Objects/ManiaBaseHit.cs rename to osu.Game.Rulesets.Mania/Objects/ManiaBaseHit.cs index 8b3afc82d9..4c15b69eb7 100644 --- a/osu.Game.Modes.Mania/Objects/ManiaBaseHit.cs +++ b/osu.Game.Rulesets.Mania/Objects/ManiaBaseHit.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects; +using osu.Game.Rulesets.Objects; -namespace osu.Game.Modes.Mania.Objects +namespace osu.Game.Rulesets.Mania.Objects { public abstract class ManiaBaseHit : HitObject { diff --git a/osu.Game.Modes.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs similarity index 80% rename from osu.Game.Modes.Mania/Objects/Note.cs rename to osu.Game.Rulesets.Mania/Objects/Note.cs index c36ed8cf7e..5a6d6003db 100644 --- a/osu.Game.Modes.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Mania.Objects +namespace osu.Game.Rulesets.Mania.Objects { public class Note : ManiaBaseHit { diff --git a/osu.Game.Modes.Mania/OpenTK.dll.config b/osu.Game.Rulesets.Mania/OpenTK.dll.config similarity index 100% rename from osu.Game.Modes.Mania/OpenTK.dll.config rename to osu.Game.Rulesets.Mania/OpenTK.dll.config diff --git a/osu.Game.Modes.Mania/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs similarity index 90% rename from osu.Game.Modes.Mania/Properties/AssemblyInfo.cs rename to osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs index 11c8290f1b..790002acd7 100644 --- a/osu.Game.Modes.Mania/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Mania/Properties/AssemblyInfo.cs @@ -7,11 +7,11 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("osu.Game.Modes.Mania")] +[assembly: AssemblyTitle("osu.Game.Rulesets.Mania")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("osu.Game.Modes.Mania")] +[assembly: AssemblyProduct("osu.Game.Rulesets.Mania")] [assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/osu.Game.Modes.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs similarity index 72% rename from osu.Game.Modes.Mania/Scoring/ManiaScoreProcessor.cs rename to osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 0f87030e25..ba0304a44a 100644 --- a/osu.Game.Modes.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -1,12 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Mania.Judgements; -using osu.Game.Modes.Mania.Objects; -using osu.Game.Modes.Scoring; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Mania.Judgements; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; -namespace osu.Game.Modes.Mania.Scoring +namespace osu.Game.Rulesets.Mania.Scoring { internal class ManiaScoreProcessor : ScoreProcessor { diff --git a/osu.Game.Modes.Mania/UI/ManiaHitRenderer.cs b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs similarity index 59% rename from osu.Game.Modes.Mania/UI/ManiaHitRenderer.cs rename to osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs index 0415bc961a..7fb8f95b4c 100644 --- a/osu.Game.Modes.Mania/UI/ManiaHitRenderer.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaHitRenderer.cs @@ -2,15 +2,16 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Modes.Mania.Beatmaps; -using osu.Game.Modes.Mania.Judgements; -using osu.Game.Modes.Mania.Objects; -using osu.Game.Modes.Mania.Scoring; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Scoring; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Mania.Beatmaps; +using osu.Game.Rulesets.Mania.Judgements; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; -namespace osu.Game.Modes.Mania.UI +namespace osu.Game.Rulesets.Mania.UI { public class ManiaHitRenderer : HitRenderer { @@ -24,9 +25,7 @@ namespace osu.Game.Modes.Mania.UI public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(this); - protected override IBeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(); - - protected override IBeatmapProcessor CreateBeatmapProcessor() => new ManiaBeatmapProcessor(); + protected override BeatmapConverter CreateBeatmapConverter() => new ManiaBeatmapConverter(); protected override Playfield CreatePlayfield() => new ManiaPlayfield(columns); diff --git a/osu.Game.Modes.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs similarity index 84% rename from osu.Game.Modes.Mania/UI/ManiaPlayfield.cs rename to osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index deb4ebac25..5eea3d70c0 100644 --- a/osu.Game.Modes.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -3,13 +3,13 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Modes.Mania.Objects; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.UI; using OpenTK; using OpenTK.Graphics; -using osu.Game.Modes.Mania.Judgements; +using osu.Game.Rulesets.Mania.Judgements; -namespace osu.Game.Modes.Mania.UI +namespace osu.Game.Rulesets.Mania.UI { public class ManiaPlayfield : Playfield { diff --git a/osu.Game.Modes.Mania/osu.Game.Modes.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj similarity index 88% rename from osu.Game.Modes.Mania/osu.Game.Modes.Mania.csproj rename to osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index 896e9c68c6..facffa757c 100644 --- a/osu.Game.Modes.Mania/osu.Game.Modes.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -7,8 +7,8 @@ {48F4582B-7687-4621-9CBE-5C24197CB536} Library Properties - osu.Game.Modes.Mania - osu.Game.Modes.Mania + osu.Game.Rulesets.Mania + osu.Game.Rulesets.Mania v4.5 512 @@ -21,6 +21,7 @@ prompt 4 false + 6 pdbonly @@ -47,7 +48,6 @@ - @@ -66,13 +66,13 @@ {C76BF5B3-985E-4D39-95FE-97C9C879B83A} osu.Framework - + {C92A607B-1FDD-4954-9F92-03FF547D9080} - osu.Game.Modes.Osu + osu.Game.Rulesets.Osu - + {F167E17A-7DE6-4AF5-B920-A5112296C695} - osu.Game.Modes.Taiko + osu.Game.Rulesets.Taiko {0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D} diff --git a/osu.Game.Modes.Mania/packages.config b/osu.Game.Rulesets.Mania/packages.config similarity index 100% rename from osu.Game.Modes.Mania/packages.config rename to osu.Game.Rulesets.Mania/packages.config diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs new file mode 100644 index 0000000000..0eece7fc4c --- /dev/null +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -0,0 +1,61 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using System.Collections.Generic; +using osu.Game.Rulesets.Objects.Types; +using System; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.Beatmaps; + +namespace osu.Game.Rulesets.Osu.Beatmaps +{ + internal class OsuBeatmapConverter : BeatmapConverter + { + protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(IHasPosition) }; + + protected override IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap) + { + IHasCurve curveData = original as IHasCurve; + IHasEndTime endTimeData = original as IHasEndTime; + IHasPosition positionData = original as IHasPosition; + IHasCombo comboData = original as IHasCombo; + + if (curveData != null) + { + yield return new Slider + { + StartTime = original.StartTime, + Samples = original.Samples, + CurveObject = curveData, + Position = positionData?.Position ?? Vector2.Zero, + NewCombo = comboData?.NewCombo ?? false + }; + } + else if (endTimeData != null) + { + yield return new Spinner + { + StartTime = original.StartTime, + Samples = original.Samples, + EndTime = endTimeData.EndTime, + + Position = positionData?.Position ?? OsuPlayfield.BASE_SIZE / 2, + }; + } + else + { + yield return new HitCircle + { + StartTime = original.StartTime, + Samples = original.Samples, + Position = positionData?.Position ?? Vector2.Zero, + NewCombo = comboData?.NewCombo ?? false + }; + } + } + } +} diff --git a/osu.Game.Modes.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs similarity index 64% rename from osu.Game.Modes.Osu/Beatmaps/OsuBeatmapConverter.cs rename to osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index bae12a98e3..fce0188cda 100644 --- a/osu.Game.Modes.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -3,96 +3,58 @@ using OpenTK; using osu.Game.Beatmaps; -using osu.Game.Modes.Objects; -using osu.Game.Modes.Osu.Objects; -using osu.Game.Modes.Osu.Objects.Drawables; -using System.Collections.Generic; -using osu.Game.Modes.Objects.Types; -using System.Linq; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; -namespace osu.Game.Modes.Osu.Beatmaps +namespace osu.Game.Rulesets.Osu.Beatmaps { - internal class OsuBeatmapConverter : IBeatmapConverter + internal class OsuBeatmapProcessor : BeatmapProcessor { - public Beatmap Convert(Beatmap original) + public override void PostProcess(Beatmap beatmap) { - return new Beatmap(original) + applyStacking(beatmap); + + if (beatmap.ComboColors.Count == 0) + return; + + int comboIndex = 0; + int colourIndex = 0; + + foreach (var obj in beatmap.HitObjects) { - HitObjects = convertHitObjects(original.HitObjects, original.BeatmapInfo?.StackLeniency ?? 0.7f) - }; - } - - private List convertHitObjects(List hitObjects, float stackLeniency) - { - List converted = hitObjects.Select(convertHitObject).ToList(); - - updateStacking(converted, stackLeniency); - - return converted; - } - - private OsuHitObject convertHitObject(HitObject original) - { - IHasCurve curveData = original as IHasCurve; - IHasEndTime endTimeData = original as IHasEndTime; - IHasPosition positionData = original as IHasPosition; - IHasCombo comboData = original as IHasCombo; - - if (curveData != null) - { - return new Slider + if (obj.NewCombo) { - StartTime = original.StartTime, - Samples = original.Samples, - CurveObject = curveData, - Position = positionData?.Position ?? Vector2.Zero, - NewCombo = comboData?.NewCombo ?? false - }; - } + comboIndex = 0; + colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count; + } - if (endTimeData != null) - { - return new Spinner - { - StartTime = original.StartTime, - Samples = original.Samples, - Position = new Vector2(512, 384) / 2, - EndTime = endTimeData.EndTime - }; + obj.ComboIndex = comboIndex++; + obj.ComboColour = beatmap.ComboColors[colourIndex]; } - - return new HitCircle - { - StartTime = original.StartTime, - Samples = original.Samples, - Position = positionData?.Position ?? Vector2.Zero, - NewCombo = comboData?.NewCombo ?? false - }; } - private void updateStacking(List hitObjects, float stackLeniency, int startIndex = 0, int endIndex = -1) + private void applyStacking(Beatmap beatmap) { - if (endIndex == -1) - endIndex = hitObjects.Count - 1; - const int stack_distance = 3; - float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * stackLeniency; + float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; - // Reset stacking inside the update range - for (int i = startIndex; i <= endIndex; i++) - hitObjects[i].StackHeight = 0; + // Reset stacking + for (int i = 0; i <= beatmap.HitObjects.Count - 1; i++) + beatmap.HitObjects[i].StackHeight = 0; // Extend the end index to include objects they are stacked on - int extendedEndIndex = endIndex; - for (int i = endIndex; i >= startIndex; i--) + int extendedEndIndex = beatmap.HitObjects.Count - 1; + for (int i = beatmap.HitObjects.Count - 1; i >= 0; i--) { int stackBaseIndex = i; - for (int n = stackBaseIndex + 1; n < hitObjects.Count; n++) + for (int n = stackBaseIndex + 1; n < beatmap.HitObjects.Count; n++) { - OsuHitObject stackBaseObject = hitObjects[stackBaseIndex]; + OsuHitObject stackBaseObject = beatmap.HitObjects[stackBaseIndex]; if (stackBaseObject is Spinner) break; - OsuHitObject objectN = hitObjects[n]; + OsuHitObject objectN = beatmap.HitObjects[n]; if (objectN is Spinner) continue; @@ -115,14 +77,14 @@ namespace osu.Game.Modes.Osu.Beatmaps if (stackBaseIndex > extendedEndIndex) { extendedEndIndex = stackBaseIndex; - if (extendedEndIndex == hitObjects.Count - 1) + if (extendedEndIndex == beatmap.HitObjects.Count - 1) break; } } //Reverse pass for stack calculation. - int extendedStartIndex = startIndex; - for (int i = extendedEndIndex; i > startIndex; i--) + int extendedStartIndex = 0; + for (int i = extendedEndIndex; i > 0; i--) { int n = i; /* We should check every note which has not yet got a stack. @@ -136,7 +98,7 @@ namespace osu.Game.Modes.Osu.Beatmaps * 2 and 1 will be ignored in the i loop because they already have a stack value. */ - OsuHitObject objectI = hitObjects[i]; + OsuHitObject objectI = beatmap.HitObjects[i]; if (objectI.StackHeight != 0 || objectI is Spinner) continue; /* If this object is a hitcircle, then we enter this "special" case. @@ -147,7 +109,7 @@ namespace osu.Game.Modes.Osu.Beatmaps { while (--n >= 0) { - OsuHitObject objectN = hitObjects[n]; + OsuHitObject objectN = beatmap.HitObjects[n]; if (objectN is Spinner) continue; double endTime = (objectN as IHasEndTime)?.EndTime ?? objectN.StartTime; @@ -174,7 +136,7 @@ namespace osu.Game.Modes.Osu.Beatmaps for (int j = n + 1; j <= i; j++) { //For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above). - OsuHitObject objectJ = hitObjects[j]; + OsuHitObject objectJ = beatmap.HitObjects[j]; if (Vector2.Distance(objectN.EndPosition, objectJ.Position) < stack_distance) objectJ.StackHeight -= offset; } @@ -199,9 +161,9 @@ namespace osu.Game.Modes.Osu.Beatmaps /* We have hit the first slider in a possible stack. * From this point on, we ALWAYS stack positive regardless. */ - while (--n >= startIndex) + while (--n >= 0) { - OsuHitObject objectN = hitObjects[n]; + OsuHitObject objectN = beatmap.HitObjects[n]; if (objectN is Spinner) continue; if (objectI.StartTime - objectN.StartTime > stackThreshold) diff --git a/osu.Game.Modes.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs similarity index 89% rename from osu.Game.Modes.Osu/Judgements/OsuJudgement.cs rename to osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index e65d3dde3a..d61e179002 100644 --- a/osu.Game.Modes.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -2,11 +2,11 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Game.Modes.Judgements; -using osu.Game.Modes.Osu.Objects.Drawables; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Framework.Extensions; -namespace osu.Game.Modes.Osu.Judgements +namespace osu.Game.Rulesets.Osu.Judgements { public class OsuJudgement : Judgement { diff --git a/osu.Game.Modes.Osu/Mods/OsuMod.cs b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs similarity index 93% rename from osu.Game.Modes.Osu/Mods/OsuMod.cs rename to osu.Game.Rulesets.Osu/Mods/OsuMod.cs index db2ee26b7a..bdb5f386d0 100644 --- a/osu.Game.Modes.Osu/Mods/OsuMod.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs @@ -3,13 +3,13 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Modes.Mods; -using osu.Game.Modes.Osu.Objects; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Objects; using System; using System.Linq; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Scoring; -namespace osu.Game.Modes.Osu.Mods +namespace osu.Game.Rulesets.Osu.Mods { public class OsuModNoFail : ModNoFail { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs similarity index 83% rename from osu.Game.Modes.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs index a680c847ac..192ab0536e 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/ConnectionRenderer.cs @@ -2,10 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; -using osu.Game.Modes.Objects; +using osu.Game.Rulesets.Objects; using System.Collections.Generic; -namespace osu.Game.Modes.Osu.Objects.Drawables.Connections +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { /// /// Connects hit objects visually, for example with follow points. diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs similarity index 93% rename from osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs index 7815e3ba41..e1276f30c4 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPoint.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -namespace osu.Game.Modes.Osu.Objects.Drawables.Connections +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { public class FollowPoint : Container { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs similarity index 94% rename from osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index f45e4226dd..a4e032050e 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; using OpenTK; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; -namespace osu.Game.Modes.Osu.Objects.Drawables.Connections +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections { public class FollowPointRenderer : ConnectionRenderer { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs similarity index 93% rename from osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 68c5ec0a45..4c1a74c675 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -3,12 +3,12 @@ using System; using osu.Framework.Graphics; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using OpenTK; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; -namespace osu.Game.Modes.Osu.Objects.Drawables +namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs similarity index 89% rename from osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 816faa0d98..2baf651cc0 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -2,10 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.ComponentModel; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Judgements; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Judgements; -namespace osu.Game.Modes.Osu.Objects.Drawables +namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuHitObject : DrawableHitObject { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs similarity index 76% rename from osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuJudgement.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index 647c8faef8..eaa0bb7d27 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -2,12 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Judgements; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Judgements; using OpenTK; -using osu.Game.Modes.Judgements; +using osu.Game.Rulesets.Judgements; -namespace osu.Game.Modes.Osu.Objects.Drawables +namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuJudgement : DrawableJudgement { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs similarity index 95% rename from osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index be326751ba..ed698f5ad3 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -3,13 +3,13 @@ using OpenTK; using osu.Framework.Graphics; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics.Containers; -namespace osu.Game.Modes.Osu.Objects.Drawables +namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSlider : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs similarity index 92% rename from osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 188306c857..86baf9f235 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -4,12 +4,12 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Judgements; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Judgements; using OpenTK; using OpenTK.Graphics; -namespace osu.Game.Modes.Osu.Objects.Drawables +namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSliderTick : DrawableOsuHitObject { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs similarity index 92% rename from osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index d0136f717c..4623fe7f22 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -5,12 +5,13 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces; using OpenTK; using OpenTK.Graphics; +using osu.Game.Rulesets.Osu.UI; -namespace osu.Game.Modes.Osu.Objects.Drawables +namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableSpinner : DrawableOsuHitObject { @@ -29,7 +30,7 @@ namespace osu.Game.Modes.Osu.Objects.Drawables Position = s.Position; //take up full playfield. - Size = new Vector2(512); + Size = new Vector2(OsuPlayfield.BASE_SIZE.X); spinner = s; diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ApproachCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs similarity index 90% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/ApproachCircle.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs index fd4ef64350..323f5fb297 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ApproachCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ApproachCircle.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class ApproachCircle : Container { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs similarity index 93% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/CirclePiece.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs index 704a6b7490..9a90c07517 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Input; using OpenTK; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class CirclePiece : Container { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs similarity index 90% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs index 97228f610f..e5cf10b88a 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/ExplodePiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using OpenTK; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class ExplodePiece : Container { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/FlashPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs similarity index 89% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/FlashPiece.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs index cb60977dab..68ffb756d4 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/FlashPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using OpenTK; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class FlashPiece : Container { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/GlowPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs similarity index 91% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/GlowPiece.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs index 6cffa370cf..8a7b353da1 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/GlowPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/GlowPiece.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class GlowPiece : Container { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/NumberPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs similarity index 93% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/NumberPiece.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs index 0ebd274246..07b21657a5 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/NumberPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/NumberPiece.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; using OpenTK.Graphics; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class NumberPiece : Container { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs similarity index 90% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/RingPiece.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs index 3e172cdc09..a04d3e7a0a 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/RingPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class RingPiece : Container { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs similarity index 95% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBall.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index becbebf0c7..4cffc1def3 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using OpenTK.Graphics; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class SliderBall : CircularContainer, ISliderProgress { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs similarity index 96% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBody.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index e7837471ee..b23fdde4e8 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -15,7 +15,7 @@ using OpenTK; using OpenTK.Graphics.ES30; using OpenTK.Graphics; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class SliderBody : Container, ISliderProgress { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBouncer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBouncer.cs similarity index 93% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBouncer.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBouncer.cs index 196b9fb521..65679dd7d3 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SliderBouncer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBouncer.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class SliderBouncer : Container, ISliderProgress { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs similarity index 80% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs index 50dab933b0..72024bbe99 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerBackground.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class SpinnerBackground : SpinnerDisc { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs similarity index 95% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index a4fce3deb5..71adba74c7 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -15,7 +15,7 @@ using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class SpinnerDisc : CircularContainer { diff --git a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs similarity index 89% rename from osu.Game.Modes.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs rename to osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs index 26d44f3865..ea3ddb5051 100644 --- a/osu.Game.Modes.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/TrianglesPiece.cs @@ -3,7 +3,7 @@ using osu.Game.Graphics.Backgrounds; -namespace osu.Game.Modes.Osu.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces { public class TrianglesPiece : Triangles { diff --git a/osu.Game.Modes.Osu/Objects/HitCircle.cs b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs similarity index 81% rename from osu.Game.Modes.Osu/Objects/HitCircle.cs rename to osu.Game.Rulesets.Osu/Objects/HitCircle.cs index aa45ac7fb9..be969f1e18 100644 --- a/osu.Game.Modes.Osu/Objects/HitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/HitCircle.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Osu.Objects +namespace osu.Game.Rulesets.Osu.Objects { public class HitCircle : OsuHitObject { diff --git a/osu.Game.Modes.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs similarity index 88% rename from osu.Game.Modes.Osu/Objects/OsuHitObject.cs rename to osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index fa422834db..723a37ed7b 100644 --- a/osu.Game.Modes.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -1,15 +1,15 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects; +using osu.Game.Rulesets.Objects; using OpenTK; -using osu.Game.Modes.Osu.Objects.Drawables; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; using OpenTK.Graphics; using osu.Game.Beatmaps.Timing; using osu.Game.Database; -namespace osu.Game.Modes.Osu.Objects +namespace osu.Game.Rulesets.Osu.Objects { public abstract class OsuHitObject : HitObject, IHasCombo, IHasPosition { @@ -21,6 +21,8 @@ namespace osu.Game.Modes.Osu.Objects private const double hit_window_300 = 30; public Vector2 Position { get; set; } + public float X => Position.X; + public float Y => Position.Y; public Vector2 StackedPosition => Position + StackOffset; diff --git a/osu.Game.Modes.Osu/Objects/OsuHitObjectDifficulty.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObjectDifficulty.cs similarity index 97% rename from osu.Game.Modes.Osu/Objects/OsuHitObjectDifficulty.cs rename to osu.Game.Rulesets.Osu/Objects/OsuHitObjectDifficulty.cs index 322f6b077a..1786771dca 100644 --- a/osu.Game.Modes.Osu/Objects/OsuHitObjectDifficulty.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObjectDifficulty.cs @@ -6,7 +6,7 @@ using System; using System.Diagnostics; using System.Linq; -namespace osu.Game.Modes.Osu.Objects +namespace osu.Game.Rulesets.Osu.Objects { internal class OsuHitObjectDifficulty { diff --git a/osu.Game.Modes.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs similarity index 94% rename from osu.Game.Modes.Osu/Objects/Slider.cs rename to osu.Game.Rulesets.Osu/Objects/Slider.cs index a01c517cb2..167bf21670 100644 --- a/osu.Game.Modes.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -3,15 +3,15 @@ using OpenTK; using osu.Game.Beatmaps.Timing; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; using System; using System.Collections.Generic; -using osu.Game.Modes.Objects; +using osu.Game.Rulesets.Objects; using osu.Game.Database; using System.Linq; using osu.Game.Audio; -namespace osu.Game.Modes.Osu.Objects +namespace osu.Game.Rulesets.Osu.Objects { public class Slider : OsuHitObject, IHasCurve { diff --git a/osu.Game.Modes.Osu/Objects/SliderTick.cs b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs similarity index 83% rename from osu.Game.Modes.Osu/Objects/SliderTick.cs rename to osu.Game.Rulesets.Osu/Objects/SliderTick.cs index 67f393b126..7112a39f97 100644 --- a/osu.Game.Modes.Osu/Objects/SliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTick.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Osu.Objects +namespace osu.Game.Rulesets.Osu.Objects { public class SliderTick : OsuHitObject { diff --git a/osu.Game.Modes.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs similarity index 79% rename from osu.Game.Modes.Osu/Objects/Spinner.cs rename to osu.Game.Rulesets.Osu/Objects/Spinner.cs index dd9a6c386a..0a2c05833a 100644 --- a/osu.Game.Modes.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; -namespace osu.Game.Modes.Osu.Objects +namespace osu.Game.Rulesets.Osu.Objects { public class Spinner : OsuHitObject, IHasEndTime { diff --git a/osu.Game.Modes.Osu/OpenTK.dll.config b/osu.Game.Rulesets.Osu/OpenTK.dll.config similarity index 100% rename from osu.Game.Modes.Osu/OpenTK.dll.config rename to osu.Game.Rulesets.Osu/OpenTK.dll.config diff --git a/osu.Game.Modes.Osu/OsuAutoReplay.cs b/osu.Game.Rulesets.Osu/OsuAutoReplay.cs similarity index 94% rename from osu.Game.Modes.Osu/OsuAutoReplay.cs rename to osu.Game.Rulesets.Osu/OsuAutoReplay.cs index ae85bd72d8..da30cf4efb 100644 --- a/osu.Game.Modes.Osu/OsuAutoReplay.cs +++ b/osu.Game.Rulesets.Osu/OsuAutoReplay.cs @@ -4,16 +4,17 @@ using OpenTK; using osu.Framework.MathUtils; using osu.Game.Beatmaps; -using osu.Game.Modes.Osu.Objects; -using osu.Game.Modes.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; using System; using System.Collections.Generic; using System.Diagnostics; using osu.Framework.Graphics; -using osu.Game.Modes.Objects.Types; -using osu.Game.Modes.Replays; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Replays; +using osu.Game.Users; -namespace osu.Game.Modes.Osu +namespace osu.Game.Rulesets.Osu { public class OsuAutoReplay : Replay { @@ -27,6 +28,11 @@ namespace osu.Game.Modes.Osu { this.beatmap = beatmap; + User = new User + { + Username = @"Autoplay", + }; + createAutoReplay(); } @@ -132,8 +138,7 @@ namespace osu.Game.Modes.Osu if (h is Spinner) { - targetPosition.X = Frames[Frames.Count - 1].MouseX; - targetPosition.Y = Frames[Frames.Count - 1].MouseY; + targetPosition = Frames[Frames.Count - 1].Position; Vector2 difference = spinner_centre - targetPosition; @@ -187,7 +192,7 @@ namespace osu.Game.Modes.Osu addFrameToReplay(lastFrame); } - Vector2 lastPosition = new Vector2(lastFrame.MouseX, lastFrame.MouseY); + Vector2 lastPosition = lastFrame.Position; double timeDifference = applyModsToTime(h.StartTime - lastFrame.Time); @@ -213,7 +218,7 @@ namespace osu.Game.Modes.Osu ReplayButtonState button = buttonIndex % 2 == 0 ? ReplayButtonState.Left1 : ReplayButtonState.Right1; - double hEndTime = (h as IHasEndTime)?.EndTime ?? h.StartTime; + double hEndTime = ((h as IHasEndTime)?.EndTime ?? h.StartTime) + KEY_UP_DELAY; ReplayFrame newFrame = new ReplayFrame(h.StartTime, targetPosition.X, targetPosition.Y, button); ReplayFrame endFrame = new ReplayFrame(hEndTime + endDelay, h.EndPosition.X, h.EndPosition.Y, ReplayButtonState.None); diff --git a/osu.Game.Modes.Osu/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/OsuDifficultyCalculator.cs similarity index 95% rename from osu.Game.Modes.Osu/OsuDifficultyCalculator.cs rename to osu.Game.Rulesets.Osu/OsuDifficultyCalculator.cs index 7696638082..14b890a055 100644 --- a/osu.Game.Modes.Osu/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/OsuDifficultyCalculator.cs @@ -2,13 +2,14 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Modes.Objects.Types; -using osu.Game.Modes.Osu.Beatmaps; -using osu.Game.Modes.Osu.Objects; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Rulesets.Osu.Objects; using System; using System.Collections.Generic; -namespace osu.Game.Modes.Osu +namespace osu.Game.Rulesets.Osu { public class OsuDifficultyCalculator : DifficultyCalculator { @@ -180,7 +181,7 @@ namespace osu.Game.Modes.Osu return difficulty; } - protected override IBeatmapConverter CreateBeatmapConverter() => new OsuBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter() => new OsuBeatmapConverter(); // Those values are used as array indices. Be careful when changing them! public enum DifficultyType diff --git a/osu.Game.Modes.Osu/OsuKeyConversionInputManager.cs b/osu.Game.Rulesets.Osu/OsuKeyConversionInputManager.cs similarity index 95% rename from osu.Game.Modes.Osu/OsuKeyConversionInputManager.cs rename to osu.Game.Rulesets.Osu/OsuKeyConversionInputManager.cs index 567c7a35b1..e71f15cd65 100644 --- a/osu.Game.Modes.Osu/OsuKeyConversionInputManager.cs +++ b/osu.Game.Rulesets.Osu/OsuKeyConversionInputManager.cs @@ -11,7 +11,7 @@ using OpenTK.Input; using KeyboardState = osu.Framework.Input.KeyboardState; using MouseState = osu.Framework.Input.MouseState; -namespace osu.Game.Modes.Osu +namespace osu.Game.Rulesets.Osu { public class OsuKeyConversionInputManager : KeyConversionInputManager { diff --git a/osu.Game.Modes.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs similarity index 89% rename from osu.Game.Modes.Osu/OsuRuleset.cs rename to osu.Game.Rulesets.Osu/OsuRuleset.cs index 12df7d3f3c..39e911651a 100644 --- a/osu.Game.Modes.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -4,18 +4,18 @@ using OpenTK.Input; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Modes.Mods; -using osu.Game.Modes.Osu.Mods; -using osu.Game.Modes.Osu.Objects; -using osu.Game.Modes.Osu.UI; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.UI; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using System.Collections.Generic; using System.Linq; -using osu.Game.Modes.Osu.Scoring; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Rulesets.Scoring; -namespace osu.Game.Modes.Osu +namespace osu.Game.Rulesets.Osu { public class OsuRuleset : Ruleset { @@ -99,8 +99,6 @@ namespace osu.Game.Modes.Osu public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new OsuDifficultyCalculator(beatmap); - protected override PlayMode PlayMode => PlayMode.Osu; - public override string Description => "osu!"; public override IEnumerable CreateGameplayKeys() => new KeyCounter[] @@ -112,5 +110,7 @@ namespace osu.Game.Modes.Osu }; public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); + + public override int LegacyID => 0; } } diff --git a/osu.Game.Modes.Osu/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs similarity index 100% rename from osu.Game.Modes.Osu/Properties/AssemblyInfo.cs rename to osu.Game.Rulesets.Osu/Properties/AssemblyInfo.cs diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs new file mode 100644 index 0000000000..079ee928af --- /dev/null +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -0,0 +1,84 @@ +// 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.Framework.Extensions; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Osu.Scoring +{ + internal class OsuScoreProcessor : ScoreProcessor + { + public OsuScoreProcessor() + { + } + + public OsuScoreProcessor(HitRenderer hitRenderer) + : base(hitRenderer) + { + } + + protected override void Reset() + { + base.Reset(); + + Health.Value = 1; + Accuracy.Value = 1; + + scoreResultCounts.Clear(); + comboResultCounts.Clear(); + } + + private readonly Dictionary scoreResultCounts = new Dictionary(); + private readonly Dictionary comboResultCounts = new Dictionary(); + + public override void PopulateScore(Score score) + { + base.PopulateScore(score); + + score.Statistics[@"300"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Hit300); + score.Statistics[@"100"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Hit100); + score.Statistics[@"50"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Hit50); + score.Statistics[@"x"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Miss); + } + + protected override void OnNewJudgement(OsuJudgement judgement) + { + if (judgement != null) + { + if (judgement.Result != HitResult.None) + { + scoreResultCounts[judgement.Score] = scoreResultCounts.GetOrDefault(judgement.Score) + 1; + comboResultCounts[judgement.Combo] = comboResultCounts.GetOrDefault(judgement.Combo) + 1; + } + + switch (judgement.Result) + { + case HitResult.Hit: + Health.Value += 0.1f; + break; + case HitResult.Miss: + Health.Value -= 0.2f; + break; + } + } + + int score = 0; + int maxScore = 0; + + foreach (var j in Judgements) + { + score += j.ScoreValue; + maxScore += j.MaxScoreValue; + } + + TotalScore.Value = score; + Accuracy.Value = (double)score / maxScore; + } + } +} diff --git a/osu.Game.Modes.Osu/UI/OsuHitRenderer.cs b/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs similarity index 67% rename from osu.Game.Modes.Osu/UI/OsuHitRenderer.cs rename to osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs index 7e314c5ba1..687518e6d5 100644 --- a/osu.Game.Modes.Osu/UI/OsuHitRenderer.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuHitRenderer.cs @@ -3,17 +3,18 @@ using OpenTK; using osu.Game.Beatmaps; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Beatmaps; -using osu.Game.Modes.Osu.Judgements; -using osu.Game.Modes.Osu.Objects; -using osu.Game.Modes.Osu.Objects.Drawables; -using osu.Game.Modes.Osu.Scoring; -using osu.Game.Modes.Scoring; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Beatmaps; +using osu.Game.Rulesets.Osu.Judgements; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; -namespace osu.Game.Modes.Osu.UI +namespace osu.Game.Rulesets.Osu.UI { public class OsuHitRenderer : HitRenderer { @@ -24,9 +25,9 @@ namespace osu.Game.Modes.Osu.UI public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(this); - protected override IBeatmapConverter CreateBeatmapConverter() => new OsuBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter() => new OsuBeatmapConverter(); - protected override IBeatmapProcessor CreateBeatmapProcessor() => new OsuBeatmapProcessor(); + protected override BeatmapProcessor CreateBeatmapProcessor() => new OsuBeatmapProcessor(); protected override Playfield CreatePlayfield() => new OsuPlayfield(); diff --git a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs similarity index 84% rename from osu.Game.Modes.Osu/UI/OsuPlayfield.cs rename to osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 4164607b4d..53eedea073 100644 --- a/osu.Game.Modes.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -4,16 +4,16 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Osu.Objects; -using osu.Game.Modes.Osu.Objects.Drawables; -using osu.Game.Modes.Osu.Objects.Drawables.Connections; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables.Connections; +using osu.Game.Rulesets.UI; using System.Linq; using osu.Game.Graphics.Cursor; -using osu.Game.Modes.Osu.Judgements; +using osu.Game.Rulesets.Osu.Judgements; -namespace osu.Game.Modes.Osu.UI +namespace osu.Game.Rulesets.Osu.UI { public class OsuPlayfield : Playfield { @@ -23,6 +23,8 @@ namespace osu.Game.Modes.Osu.UI public override bool ProvidingUserCursor => true; + public static readonly Vector2 BASE_SIZE = new Vector2(512, 384); + public override Vector2 Size { get @@ -34,7 +36,7 @@ namespace osu.Game.Modes.Osu.UI } } - public OsuPlayfield() : base(512) + public OsuPlayfield() : base(BASE_SIZE.X) { Anchor = Anchor.Centre; Origin = Anchor.Centre; @@ -94,4 +96,4 @@ namespace osu.Game.Modes.Osu.UI judgementLayer.Add(explosion); } } -} \ No newline at end of file +} diff --git a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj similarity index 95% rename from osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj rename to osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 21f0f03d8c..fcad0061e4 100644 --- a/osu.Game.Modes.Osu/osu.Game.Modes.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -7,8 +7,8 @@ {C92A607B-1FDD-4954-9F92-03FF547D9080} Library Properties - osu.Game.Modes.Osu - osu.Game.Modes.Osu + osu.Game.Rulesets.Osu + osu.Game.Rulesets.Osu v4.5 512 @@ -22,6 +22,7 @@ prompt 4 false + 6 pdbonly @@ -71,7 +72,6 @@ - diff --git a/osu.Game.Modes.Osu/packages.config b/osu.Game.Rulesets.Osu/packages.config similarity index 100% rename from osu.Game.Modes.Osu/packages.config rename to osu.Game.Rulesets.Osu/packages.config diff --git a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs similarity index 80% rename from osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs rename to osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index aee06ad796..cf7b9ce710 100644 --- a/osu.Game.Modes.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -2,19 +2,20 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Modes.Objects; -using osu.Game.Modes.Objects.Types; -using osu.Game.Modes.Taiko.Objects; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Taiko.Objects; using System; using System.Collections.Generic; using System.Linq; using osu.Game.Database; using osu.Game.IO.Serialization; using osu.Game.Audio; +using osu.Game.Rulesets.Beatmaps; -namespace osu.Game.Modes.Taiko.Beatmaps +namespace osu.Game.Rulesets.Taiko.Beatmaps { - internal class TaikoBeatmapConverter : IBeatmapConverter + internal class TaikoBeatmapConverter : BeatmapConverter { /// /// osu! is generally slower than taiko, so a factor is added to increase @@ -38,25 +39,30 @@ namespace osu.Game.Modes.Taiko.Beatmaps /// private const float taiko_base_distance = 100; - public Beatmap Convert(Beatmap original) + protected override IEnumerable ValidConversionTypes { get; } = new[] { typeof(HitObject) }; + + protected override Beatmap ConvertBeatmap(Beatmap original) { + // Rewrite the beatmap info to add the slider velocity multiplier BeatmapInfo info = original.BeatmapInfo.DeepClone(); info.Difficulty.SliderMultiplier *= legacy_velocity_multiplier; - return new Beatmap(original) + Beatmap converted = base.ConvertBeatmap(original); + + // Post processing step to transform hit objects with the same start time into strong hits + converted.HitObjects = converted.HitObjects.GroupBy(t => t.StartTime).Select(x => { - BeatmapInfo = info, - HitObjects = original.HitObjects.SelectMany(h => convertHitObject(h, original)).ToList() - }; + TaikoHitObject first = x.First(); + if (x.Skip(1).Any()) + first.IsStrong = true; + return first; + }).ToList(); + + return converted; } - private IEnumerable convertHitObject(HitObject obj, Beatmap beatmap) + protected override IEnumerable ConvertHitObject(HitObject obj, Beatmap beatmap) { - // Check if this HitObject is already a TaikoHitObject, and return it if so - var originalTaiko = obj as TaikoHitObject; - if (originalTaiko != null) - yield return originalTaiko; - var distanceData = obj as IHasDistance; var repeatsData = obj as IHasRepeats; var endTimeData = obj as IHasEndTime; @@ -92,11 +98,11 @@ namespace osu.Game.Modes.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.Difficulty.SliderTickRate, taikoDuration / repeats) / 8; + double tickSpacing = Math.Min(speedAdjustedBeatLength / beatmap.BeatmapInfo.Difficulty.SliderTickRate, taikoDuration / repeats); if (tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength) { - for (double j = obj.StartTime; j <= distanceData.EndTime + tickSpacing; j += tickSpacing) + for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing) { // Todo: This should generate different type of hits (including strongs) // depending on hitobject sound additions (not implemented fully yet) diff --git a/osu.Game.Modes.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs similarity index 92% rename from osu.Game.Modes.Taiko/Judgements/TaikoDrumRollTickJudgement.cs rename to osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index 6ae476b265..78a5b29d36 100644 --- a/osu.Game.Modes.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Taiko.Judgements +namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoDrumRollTickJudgement : TaikoJudgement { diff --git a/osu.Game.Modes.Taiko/Judgements/TaikoHitResult.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoHitResult.cs similarity index 84% rename from osu.Game.Modes.Taiko/Judgements/TaikoHitResult.cs rename to osu.Game.Rulesets.Taiko/Judgements/TaikoHitResult.cs index cbc3919c4f..5fd850d6b0 100644 --- a/osu.Game.Modes.Taiko/Judgements/TaikoHitResult.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoHitResult.cs @@ -3,7 +3,7 @@ using System.ComponentModel; -namespace osu.Game.Modes.Taiko.Judgements +namespace osu.Game.Rulesets.Taiko.Judgements { public enum TaikoHitResult { diff --git a/osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs similarity index 93% rename from osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs rename to osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index 7676ef8c29..7bca59bf11 100644 --- a/osu.Game.Modes.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -1,11 +1,11 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Judgements; +using osu.Game.Rulesets.Judgements; using osu.Framework.Extensions; -using osu.Game.Modes.Objects.Drawables; +using osu.Game.Rulesets.Objects.Drawables; -namespace osu.Game.Modes.Taiko.Judgements +namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoJudgement : Judgement { diff --git a/osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs similarity index 84% rename from osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs rename to osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs index ee978d0026..4996cac39e 100644 --- a/osu.Game.Modes.Taiko/Judgements/TaikoStrongHitJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Judgements; +using osu.Game.Rulesets.Judgements; -namespace osu.Game.Modes.Taiko.Judgements +namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoStrongHitJudgement : TaikoJudgement, IPartialJudgement { diff --git a/osu.Game.Modes.Taiko/Mods/TaikoMod.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoMod.cs similarity index 87% rename from osu.Game.Modes.Taiko/Mods/TaikoMod.cs rename to osu.Game.Rulesets.Taiko/Mods/TaikoMod.cs index 422f0ec250..0b8492ef8c 100644 --- a/osu.Game.Modes.Taiko/Mods/TaikoMod.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoMod.cs @@ -2,13 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Modes.Mods; -using osu.Game.Modes.Scoring; -using osu.Game.Modes.Taiko.Objects; -using osu.Game.Modes.Taiko.Replays; +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.Modes.Taiko.Mods +namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModNoFail : ModNoFail { diff --git a/osu.Game.Modes.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs similarity index 80% rename from osu.Game.Modes.Taiko/Objects/BarLine.cs rename to osu.Game.Rulesets.Taiko/Objects/BarLine.cs index ae3c03de5e..0e6ff9f758 100644 --- a/osu.Game.Modes.Taiko/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Taiko.Objects +namespace osu.Game.Rulesets.Taiko.Objects { public class BarLine : TaikoHitObject { diff --git a/osu.Game.Modes.Taiko/Objects/CentreHit.cs b/osu.Game.Rulesets.Taiko/Objects/CentreHit.cs similarity index 79% rename from osu.Game.Modes.Taiko/Objects/CentreHit.cs rename to osu.Game.Rulesets.Taiko/Objects/CentreHit.cs index 258112f045..f82058fe01 100644 --- a/osu.Game.Modes.Taiko/Objects/CentreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/CentreHit.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Taiko.Objects +namespace osu.Game.Rulesets.Taiko.Objects { public class CentreHit : Hit { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs similarity index 94% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLine.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index 59f8aca867..4c83e08bab 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using OpenTK; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { /// /// A line that scrolls alongside hit objects in the playfield and visualises control points. diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLineMajor.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs similarity index 94% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLineMajor.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs index 73565e6948..e64682a1e4 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableBarLineMajor.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using OpenTK; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableBarLineMajor : DrawableBarLine { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs similarity index 83% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHit.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs index ff5ac859b4..8bb78669ca 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHit.cs @@ -3,10 +3,10 @@ using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableCentreHit : DrawableHit { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs similarity index 83% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs index bc24e2aa65..434fb9377f 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableCentreHitStrong.cs @@ -3,10 +3,10 @@ using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableCentreHitStrong : DrawableHitStrong { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs similarity index 92% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRoll.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index 0a0098dd34..4562501ed1 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -5,13 +5,13 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.MathUtils; using osu.Game.Graphics; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Taiko.Judgements; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Judgements; using OpenTK; using OpenTK.Graphics; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableDrumRoll : DrawableTaikoHitObject { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs similarity index 80% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRollTick.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 296affedaf..56a747467e 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -3,12 +3,12 @@ using System; using osu.Framework.Graphics; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Taiko.Judgements; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Judgements; using OpenTK.Input; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableDrumRollTick : DrawableTaikoHitObject { @@ -27,11 +27,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawables protected override void CheckJudgement(bool userTriggered) { if (!userTriggered) - { - if (Judgement.TimeOffset > HitObject.HitWindow) - Judgement.Result = HitResult.Miss; return; - } if (Math.Abs(Judgement.TimeOffset) < HitObject.HitWindow) { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs similarity index 91% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableHit.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 167fbebd7b..a4a46e3b48 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -4,12 +4,12 @@ using System; using System.Linq; using osu.Framework.Graphics; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public abstract class DrawableHit : DrawableTaikoHitObject { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs similarity index 90% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableHitStrong.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs index 4ab029acb3..1c6b12ea43 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs @@ -4,12 +4,12 @@ using System; using System.Linq; using osu.Framework.Input; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Taiko.Judgements; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Judgements; using OpenTK.Input; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public abstract class DrawableHitStrong : DrawableHit { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs similarity index 83% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHit.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs index 5a311d51ef..20e8d36105 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHit.cs @@ -3,10 +3,10 @@ using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableRimHit : DrawableHit { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs similarity index 83% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHitStrong.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs index 5789dfb140..4b1bb62bab 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableRimHitStrong.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableRimHitStrong.cs @@ -3,10 +3,10 @@ using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableRimHitStrong : DrawableHitStrong { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs similarity index 95% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableSwell.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 1e440df69a..57b2576a8b 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -9,14 +9,14 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK; using OpenTK.Graphics; using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public class DrawableSwell : DrawableTaikoHitObject { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs similarity index 91% rename from osu.Game.Modes.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs index f15f2bd152..24aa366944 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs @@ -5,13 +5,13 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using OpenTK; using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Objects.Drawables +namespace osu.Game.Rulesets.Taiko.Objects.Drawables { public abstract class DrawableTaikoHitObject : DrawableHitObject where TaikoHitType : TaikoHitObject diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs similarity index 90% rename from osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs index 0cf4e97b41..ddf1492ecc 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CentreHitSymbolPiece.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using OpenTK; -namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { /// /// The symbol used for centre hit pieces. diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs similarity index 95% rename from osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CirclePiece.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs index 216e05ebc4..9f91488fe3 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs @@ -8,7 +8,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Backgrounds; using OpenTK.Graphics; -namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { /// /// A circle piece which is used uniformly through osu!taiko to visualise hitobjects. diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs similarity index 88% rename from osu.Game.Modes.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs index 5431507614..bed54d358e 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/ElongatedCirclePiece.cs @@ -3,14 +3,13 @@ using System; using osu.Framework.Graphics.Primitives; -using osu.Game.Modes.Taiko.UI; -namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { public class ElongatedCirclePiece : CirclePiece { /// - /// As we are being used to define the absolute size of hits, we need to be given a relative reference of our containing . + /// As we are being used to define the absolute size of hits, we need to be given a relative reference of our containing playfield container. /// public Func PlayfieldLengthReference; @@ -38,4 +37,4 @@ namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces Width = (PlayfieldLengthReference?.Invoke() ?? 0) * Length + DrawHeight; } } -} \ No newline at end of file +} diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs similarity index 91% rename from osu.Game.Modes.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs index 6e19497978..4146edbdf7 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/RimHitSymbolPiece.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; -namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { /// /// The symbol used for rim hit pieces. diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs similarity index 88% rename from osu.Game.Modes.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs index e491793902..0f703837a9 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/SwellSymbolPiece.cs @@ -4,7 +4,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics; -namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { /// /// The symbol used for swell pieces. diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs similarity index 91% rename from osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs index 2220438a4a..83b2e59e44 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TaikoPiece.cs @@ -6,7 +6,7 @@ using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; -namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { public class TaikoPiece : Container, IHasAccentColour { diff --git a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TickPiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs similarity index 92% rename from osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TickPiece.cs rename to osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs index 53e795e2e2..1a0d0156e8 100644 --- a/osu.Game.Modes.Taiko/Objects/Drawables/Pieces/TickPiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/TickPiece.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; -namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces +namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces { public class TickPiece : TaikoPiece { @@ -20,7 +20,7 @@ namespace osu.Game.Modes.Taiko.Objects.Drawables.Pieces /// /// The size of a tick. /// - private const float tick_size = TaikoHitObject.DEFAULT_CIRCLE_DIAMETER / 4; + private const float tick_size = TaikoHitObject.DEFAULT_CIRCLE_DIAMETER / 6; private bool filled; public bool Filled diff --git a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs similarity index 94% rename from osu.Game.Modes.Taiko/Objects/DrumRoll.cs rename to osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 4f26ffd3a1..4f89fb8248 100644 --- a/osu.Game.Modes.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; using System; using System.Collections.Generic; using System.Linq; @@ -9,7 +9,7 @@ using osu.Game.Beatmaps.Timing; using osu.Game.Database; using osu.Game.Audio; -namespace osu.Game.Modes.Taiko.Objects +namespace osu.Game.Rulesets.Taiko.Objects { public class DrumRoll : TaikoHitObject, IHasEndTime { diff --git a/osu.Game.Modes.Taiko/Objects/DrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs similarity index 91% rename from osu.Game.Modes.Taiko/Objects/DrumRollTick.cs rename to osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs index 32e8851b66..01f9caf215 100644 --- a/osu.Game.Modes.Taiko/Objects/DrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRollTick.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Taiko.Objects +namespace osu.Game.Rulesets.Taiko.Objects { public class DrumRollTick : TaikoHitObject { diff --git a/osu.Game.Modes.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs similarity index 93% rename from osu.Game.Modes.Taiko/Objects/Hit.cs rename to osu.Game.Rulesets.Taiko/Objects/Hit.cs index ad8d07d901..136e89124c 100644 --- a/osu.Game.Modes.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -4,7 +4,7 @@ using osu.Game.Beatmaps.Timing; using osu.Game.Database; -namespace osu.Game.Modes.Taiko.Objects +namespace osu.Game.Rulesets.Taiko.Objects { public class Hit : TaikoHitObject { diff --git a/osu.Game.Modes.Taiko/Objects/RimHit.cs b/osu.Game.Rulesets.Taiko/Objects/RimHit.cs similarity index 79% rename from osu.Game.Modes.Taiko/Objects/RimHit.cs rename to osu.Game.Rulesets.Taiko/Objects/RimHit.cs index aae93ec10d..8e09842294 100644 --- a/osu.Game.Modes.Taiko/Objects/RimHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/RimHit.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Taiko.Objects +namespace osu.Game.Rulesets.Taiko.Objects { public class RimHit : Hit { diff --git a/osu.Game.Modes.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs similarity index 83% rename from osu.Game.Modes.Taiko/Objects/Swell.cs rename to osu.Game.Rulesets.Taiko/Objects/Swell.cs index 97101ea797..f74a543ca9 100644 --- a/osu.Game.Modes.Taiko/Objects/Swell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; -namespace osu.Game.Modes.Taiko.Objects +namespace osu.Game.Rulesets.Taiko.Objects { public class Swell : TaikoHitObject, IHasEndTime { diff --git a/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs similarity index 93% rename from osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs rename to osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index ebc9b19d3a..6a6353fde2 100644 --- a/osu.Game.Modes.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -3,10 +3,10 @@ using osu.Game.Beatmaps.Timing; using osu.Game.Database; -using osu.Game.Modes.Objects; -using osu.Game.Modes.Taiko.UI; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Taiko.UI; -namespace osu.Game.Modes.Taiko.Objects +namespace osu.Game.Rulesets.Taiko.Objects { public abstract class TaikoHitObject : HitObject { diff --git a/osu.Game.Modes.Taiko/OpenTK.dll.config b/osu.Game.Rulesets.Taiko/OpenTK.dll.config similarity index 100% rename from osu.Game.Modes.Taiko/OpenTK.dll.config rename to osu.Game.Rulesets.Taiko/OpenTK.dll.config diff --git a/osu.Game.Modes.Taiko/Properties/AssemblyInfo.cs b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs similarity index 90% rename from osu.Game.Modes.Taiko/Properties/AssemblyInfo.cs rename to osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs index 94ec895707..89c07517ca 100644 --- a/osu.Game.Modes.Taiko/Properties/AssemblyInfo.cs +++ b/osu.Game.Rulesets.Taiko/Properties/AssemblyInfo.cs @@ -7,11 +7,11 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("osu.Game.Modes.Taiko")] +[assembly: AssemblyTitle("osu.Game.Rulesets.Taiko")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("osu.Game.Modes.Taiko")] +[assembly: AssemblyProduct("osu.Game.Rulesets.Taiko")] [assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/osu.Game.Modes.Taiko/Replays/TaikoAutoReplay.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoReplay.cs similarity index 81% rename from osu.Game.Modes.Taiko/Replays/TaikoAutoReplay.cs rename to osu.Game.Rulesets.Taiko/Replays/TaikoAutoReplay.cs index 89d974baf9..df862a5cb0 100644 --- a/osu.Game.Modes.Taiko/Replays/TaikoAutoReplay.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoAutoReplay.cs @@ -3,11 +3,11 @@ using System; using osu.Game.Beatmaps; -using osu.Game.Modes.Objects.Types; -using osu.Game.Modes.Taiko.Objects; -using osu.Game.Modes.Replays; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Replays; -namespace osu.Game.Modes.Taiko.Replays +namespace osu.Game.Rulesets.Taiko.Replays { public class TaikoAutoReplay : Replay { @@ -24,8 +24,8 @@ namespace osu.Game.Modes.Taiko.Replays { bool hitButton = true; - Frames.Add(new ReplayFrame(-100000, 320, 240, ReplayButtonState.None)); - Frames.Add(new ReplayFrame(beatmap.HitObjects[0].StartTime - 1000, 320, 240, ReplayButtonState.None)); + Frames.Add(new ReplayFrame(-100000, null, null, ReplayButtonState.None)); + Frames.Add(new ReplayFrame(beatmap.HitObjects[0].StartTime - 1000, null, null, ReplayButtonState.None)); for (int i = 0; i < beatmap.HitObjects.Count; i++) { @@ -64,7 +64,7 @@ namespace osu.Game.Modes.Taiko.Replays break; } - Frames.Add(new ReplayFrame(j, 0, 0, button)); + Frames.Add(new ReplayFrame(j, null, null, button)); d = (d + 1) % 4; if (++count > req) break; @@ -74,7 +74,7 @@ namespace osu.Game.Modes.Taiko.Replays { foreach (var tick in drumRoll.Ticks) { - Frames.Add(new ReplayFrame(tick.StartTime, 0, 0, hitButton ? ReplayButtonState.Left1 : ReplayButtonState.Left2)); + Frames.Add(new ReplayFrame(tick.StartTime, null, null, hitButton ? ReplayButtonState.Left1 : ReplayButtonState.Left2)); hitButton = !hitButton; } } @@ -95,22 +95,22 @@ namespace osu.Game.Modes.Taiko.Replays button = hitButton ? ReplayButtonState.Left1 : ReplayButtonState.Left2; } - Frames.Add(new ReplayFrame(h.StartTime, 0, 0, button)); + Frames.Add(new ReplayFrame(h.StartTime, null, null, button)); } else throw new Exception("Unknown hit object type."); - Frames.Add(new ReplayFrame(endTime + 1, 0, 0, ReplayButtonState.None)); + Frames.Add(new ReplayFrame(endTime + KEY_UP_DELAY, null, null, ReplayButtonState.None)); if (i < beatmap.HitObjects.Count - 1) { double waitTime = beatmap.HitObjects[i + 1].StartTime - 1000; if (waitTime > endTime) - Frames.Add(new ReplayFrame(waitTime, 0, 0, ReplayButtonState.None)); + Frames.Add(new ReplayFrame(waitTime, null, null, ReplayButtonState.None)); } hitButton = !hitButton; } } } -} \ No newline at end of file +} diff --git a/osu.Game.Modes.Taiko/Replays/TaikoFramedReplayInputHandler.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs similarity index 90% rename from osu.Game.Modes.Taiko/Replays/TaikoFramedReplayInputHandler.cs rename to osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs index 44fca4abe7..f6425dd66f 100644 --- a/osu.Game.Modes.Taiko/Replays/TaikoFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoFramedReplayInputHandler.cs @@ -1,12 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Replays; +using osu.Game.Rulesets.Replays; using System.Collections.Generic; using osu.Framework.Input; using OpenTK.Input; -namespace osu.Game.Modes.Taiko.Replays +namespace osu.Game.Rulesets.Taiko.Replays { internal class TaikoFramedReplayInputHandler : FramedReplayInputHandler { diff --git a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs similarity index 95% rename from osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs rename to osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 987c3181a4..f5e2094cbf 100644 --- a/osu.Game.Modes.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -4,14 +4,14 @@ using System; using osu.Game.Beatmaps; using osu.Game.Database; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Scoring; -using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.UI; using OpenTK; -namespace osu.Game.Modes.Taiko.Scoring +namespace osu.Game.Rulesets.Taiko.Scoring { internal class TaikoScoreProcessor : ScoreProcessor { diff --git a/osu.Game.Modes.Taiko/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs similarity index 65% rename from osu.Game.Modes.Taiko/TaikoDifficultyCalculator.cs rename to osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs index 93dfc3d651..cd61709db8 100644 --- a/osu.Game.Modes.Taiko/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/TaikoDifficultyCalculator.cs @@ -2,11 +2,12 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Beatmaps; -using osu.Game.Modes.Taiko.Beatmaps; -using osu.Game.Modes.Taiko.Objects; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Taiko.Beatmaps; +using osu.Game.Rulesets.Taiko.Objects; using System.Collections.Generic; -namespace osu.Game.Modes.Taiko +namespace osu.Game.Rulesets.Taiko { public class TaikoDifficultyCalculator : DifficultyCalculator { @@ -19,6 +20,6 @@ namespace osu.Game.Modes.Taiko return 0; } - protected override IBeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); + protected override BeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); } } \ No newline at end of file diff --git a/osu.Game.Modes.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs similarity index 88% rename from osu.Game.Modes.Taiko/TaikoRuleset.cs rename to osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 1b3c3fc0eb..3fb2cf6c28 100644 --- a/osu.Game.Modes.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -4,16 +4,16 @@ using OpenTK.Input; using osu.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Modes.Mods; -using osu.Game.Modes.Taiko.Mods; -using osu.Game.Modes.Taiko.UI; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Rulesets.Taiko.UI; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using System.Collections.Generic; -using osu.Game.Modes.Scoring; -using osu.Game.Modes.Taiko.Scoring; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Scoring; -namespace osu.Game.Modes.Taiko +namespace osu.Game.Rulesets.Taiko { public class TaikoRuleset : Ruleset { @@ -76,8 +76,6 @@ namespace osu.Game.Modes.Taiko } } - protected override PlayMode PlayMode => PlayMode.Taiko; - public override string Description => "osu!taiko"; public override FontAwesome Icon => FontAwesome.fa_osu_taiko_o; @@ -93,5 +91,7 @@ namespace osu.Game.Modes.Taiko public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new TaikoDifficultyCalculator(beatmap); public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); + + public override int LegacyID => 1; } } diff --git a/osu.Game.Modes.Taiko/UI/DrawableTaikoJudgement.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs similarity index 88% rename from osu.Game.Modes.Taiko/UI/DrawableTaikoJudgement.cs rename to osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs index 78c9657b40..08fd8dbecc 100644 --- a/osu.Game.Modes.Taiko/UI/DrawableTaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs @@ -1,13 +1,13 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Game.Modes.Judgements; +using osu.Game.Rulesets.Judgements; -namespace osu.Game.Modes.Taiko.UI +namespace osu.Game.Rulesets.Taiko.UI { /// /// Text that is shown as judgement when a hit object is hit or missed. diff --git a/osu.Game.Modes.Taiko/UI/HitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs similarity index 91% rename from osu.Game.Modes.Taiko/UI/HitExplosion.cs rename to osu.Game.Rulesets.Taiko/UI/HitExplosion.cs index e4e329523f..2ebdeaa5b0 100644 --- a/osu.Game.Modes.Taiko/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs @@ -8,10 +8,10 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Taiko.Objects; -namespace osu.Game.Modes.Taiko.UI +namespace osu.Game.Rulesets.Taiko.UI { /// /// A circle explodes from the hit target to indicate a hitobject has been hit. diff --git a/osu.Game.Modes.Taiko/UI/HitTarget.cs b/osu.Game.Rulesets.Taiko/UI/HitTarget.cs similarity index 95% rename from osu.Game.Modes.Taiko/UI/HitTarget.cs rename to osu.Game.Rulesets.Taiko/UI/HitTarget.cs index b22dc1d647..fde2623246 100644 --- a/osu.Game.Modes.Taiko/UI/HitTarget.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitTarget.cs @@ -6,9 +6,9 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Game.Modes.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Objects; -namespace osu.Game.Modes.Taiko.UI +namespace osu.Game.Rulesets.Taiko.UI { /// /// A component that is displayed at the hit position in the taiko playfield. diff --git a/osu.Game.Modes.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs similarity index 96% rename from osu.Game.Modes.Taiko/UI/InputDrum.cs rename to osu.Game.Rulesets.Taiko/UI/InputDrum.cs index d238c38e74..999d76ab0b 100644 --- a/osu.Game.Modes.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Textures; using osu.Framework.Input; using osu.Game.Graphics; -namespace osu.Game.Modes.Taiko.UI +namespace osu.Game.Rulesets.Taiko.UI { /// /// A component of the playfield that captures input and displays input as a drum. diff --git a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs b/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs similarity index 57% rename from osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs rename to osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs index 32476dff7f..db15193ce5 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoHitRenderer.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoHitRenderer.cs @@ -2,24 +2,23 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Allocation; -using osu.Framework.MathUtils; using osu.Framework.Graphics; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Timing; -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Objects.Types; -using osu.Game.Modes.Replays; -using osu.Game.Modes.Scoring; -using osu.Game.Modes.Taiko.Beatmaps; -using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Taiko.Objects; -using osu.Game.Modes.Taiko.Objects.Drawables; -using osu.Game.Modes.Taiko.Scoring; -using osu.Game.Modes.UI; -using osu.Game.Modes.Taiko.Replays; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Beatmaps; +using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.Taiko.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Scoring; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.Taiko.Replays; using OpenTK; +using osu.Game.Rulesets.Beatmaps; -namespace osu.Game.Modes.Taiko.UI +namespace osu.Game.Rulesets.Taiko.UI { public class TaikoHitRenderer : HitRenderer { @@ -50,54 +49,36 @@ namespace osu.Game.Modes.Taiko.UI return; int currentIndex = 0; - - while (currentIndex < timingPoints.Count && Precision.AlmostEquals(timingPoints[currentIndex].BeatLength, 0)) - currentIndex++; - - double time = timingPoints[currentIndex].Time; - double measureLength = timingPoints[currentIndex].BeatLength * (int)timingPoints[currentIndex].TimeSignature; - - // Find the bar line time closest to 0 - time -= measureLength * (int)(time / measureLength); - - // Always start barlines from a positive time - while (time < 0) - time += measureLength; - int currentBeat = 0; + double time = timingPoints[currentIndex].Time; while (time <= lastHitTime) { - ControlPoint current = timingPoints[currentIndex]; - - if (time > current.Time || current.OmitFirstBarLine) + int nextIndex = currentIndex + 1; + if (nextIndex < timingPoints.Count && time > timingPoints[nextIndex].Time) { - bool isMajor = currentBeat % (int)current.TimeSignature == 0; - - var barLine = new BarLine - { - StartTime = time, - }; - - barLine.ApplyDefaults(Beatmap.TimingInfo, Beatmap.BeatmapInfo.Difficulty); - - taikoPlayfield.AddBarLine(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); - - currentBeat++; + currentIndex = nextIndex; + time = timingPoints[currentIndex].Time; + currentBeat = 0; } - double bl = current.BeatLength; + var currentPoint = timingPoints[currentIndex]; + var barLine = new BarLine + { + StartTime = time, + }; + + barLine.ApplyDefaults(Beatmap.TimingInfo, Beatmap.BeatmapInfo.Difficulty); + + bool isMajor = currentBeat % (int)currentPoint.TimeSignature == 0; + taikoPlayfield.AddBarLine(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); + + double bl = currentPoint.BeatLength; if (bl < 800) - bl *= (int)current.TimeSignature; + bl *= (int)currentPoint.TimeSignature; time += bl; - - if (currentIndex + 1 >= timingPoints.Count || time < timingPoints[currentIndex + 1].Time) - continue; - - currentBeat = 0; - currentIndex++; - time = timingPoints[currentIndex].Time; + currentBeat++; } } @@ -114,9 +95,7 @@ namespace osu.Game.Modes.Taiko.UI public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); - protected override IBeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); - - protected override IBeatmapProcessor CreateBeatmapProcessor() => new TaikoBeatmapProcessor(); + protected override BeatmapConverter CreateBeatmapConverter() => new TaikoBeatmapConverter(); protected override Playfield CreatePlayfield() => new TaikoPlayfield { diff --git a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs similarity index 95% rename from osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs rename to osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index db3a1bc84e..8e6f1c8556 100644 --- a/osu.Game.Modes.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -4,21 +4,21 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Game.Modes.Taiko.Objects; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Rulesets.UI; using OpenTK; using OpenTK.Graphics; -using osu.Game.Modes.Taiko.Judgements; -using osu.Game.Modes.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Judgements; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Primitives; using System.Linq; -using osu.Game.Modes.Taiko.Objects.Drawables; +using osu.Game.Rulesets.Taiko.Objects.Drawables; using System; -namespace osu.Game.Modes.Taiko.UI +namespace osu.Game.Rulesets.Taiko.UI { public class TaikoPlayfield : Playfield { diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj similarity index 95% rename from osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj rename to osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index 19ba5c77e4..c668b90ec4 100644 --- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -7,8 +7,8 @@ {F167E17A-7DE6-4AF5-B920-A5112296C695} Library Properties - osu.Game.Modes.Taiko - osu.Game.Modes.Taiko + osu.Game.Rulesets.Taiko + osu.Game.Rulesets.Taiko v4.5 512 @@ -21,6 +21,7 @@ prompt 4 false + 6 pdbonly @@ -47,7 +48,6 @@ - diff --git a/osu.Game.Modes.Taiko/packages.config b/osu.Game.Rulesets.Taiko/packages.config similarity index 100% rename from osu.Game.Modes.Taiko/packages.config rename to osu.Game.Rulesets.Taiko/packages.config diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs index 8183bc952e..4814af984e 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs @@ -6,12 +6,10 @@ using NUnit.Framework; using OpenTK; using OpenTK.Graphics; using osu.Game.Beatmaps.Formats; -using osu.Game.Modes; using osu.Game.Tests.Resources; -using osu.Game.Modes.Osu; -using osu.Game.Modes.Objects.Legacy; using System.Linq; using osu.Game.Audio; +using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Tests.Beatmaps.Formats { @@ -22,7 +20,6 @@ namespace osu.Game.Tests.Beatmaps.Formats public void SetUp() { OsuLegacyDecoder.Register(); - Ruleset.Register(new OsuRuleset()); } [Test] @@ -58,7 +55,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(false, beatmapInfo.Countdown); Assert.AreEqual(0.7f, beatmapInfo.StackLeniency); Assert.AreEqual(false, beatmapInfo.SpecialStyle); - Assert.AreEqual(PlayMode.Osu, beatmapInfo.Mode); + Assert.IsTrue(beatmapInfo.RulesetID == 0); Assert.AreEqual(false, beatmapInfo.LetterboxInBreaks); Assert.AreEqual(false, beatmapInfo.WidescreenStoryboard); } @@ -133,16 +130,22 @@ namespace osu.Game.Tests.Beatmaps.Formats using (var stream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) { var beatmap = decoder.Decode(new StreamReader(stream)); - var slider = beatmap.HitObjects[0] as LegacySlider; - Assert.IsNotNull(slider); - Assert.AreEqual(new Vector2(192, 168), slider.Position); - Assert.AreEqual(956, slider.StartTime); - Assert.IsTrue(slider.Samples.Any(s => s.Name == SampleInfo.HIT_NORMAL)); - var hit = beatmap.HitObjects[1] as LegacyHit; - Assert.IsNotNull(hit); - Assert.AreEqual(new Vector2(304, 56), hit.Position); - Assert.AreEqual(1285, hit.StartTime); - Assert.IsTrue(hit.Samples.Any(s => s.Name == SampleInfo.HIT_CLAP)); + + var curveData = beatmap.HitObjects[0] as IHasCurve; + var positionData = beatmap.HitObjects[0] as IHasPosition; + + Assert.IsNotNull(positionData); + Assert.IsNotNull(curveData); + Assert.AreEqual(new Vector2(192, 168), positionData.Position); + Assert.AreEqual(956, beatmap.HitObjects[0].StartTime); + Assert.IsTrue(beatmap.HitObjects[0].Samples.Any(s => s.Name == SampleInfo.HIT_NORMAL)); + + positionData = beatmap.HitObjects[1] as IHasPosition; + + Assert.IsNotNull(positionData); + Assert.AreEqual(new Vector2(304, 56), positionData.Position); + Assert.AreEqual(1285, beatmap.HitObjects[1].StartTime); + Assert.IsTrue(beatmap.HitObjects[1].Samples.Any(s => s.Name == SampleInfo.HIT_CLAP)); } } } diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 5d15b43761..b35f5901be 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -12,11 +12,6 @@ using osu.Framework.Desktop.Platform; using osu.Framework.Platform; using osu.Game.Database; using osu.Game.IPC; -using osu.Game.Modes; -using osu.Game.Modes.Catch; -using osu.Game.Modes.Mania; -using osu.Game.Modes.Osu; -using osu.Game.Modes.Taiko; namespace osu.Game.Tests.Beatmaps.IO { @@ -25,15 +20,6 @@ namespace osu.Game.Tests.Beatmaps.IO { private const string osz_path = @"../../../osu-resources/osu.Game.Resources/Beatmaps/241526 Soleily - Renatus.osz"; - [OneTimeSetUp] - public void SetUp() - { - Ruleset.Register(new OsuRuleset()); - Ruleset.Register(new TaikoRuleset()); - Ruleset.Register(new ManiaRuleset()); - Ruleset.Register(new CatchRuleset()); - } - [Test] public void TestImportWhenClosed() { @@ -119,6 +105,7 @@ namespace osu.Game.Tests.Beatmaps.IO Thread.Sleep(1); //reset beatmap database (sqlite and storage backing) + osu.Dependencies.Get().Reset(); osu.Dependencies.Get().Reset(); return osu; @@ -166,8 +153,16 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(set.Beatmaps.Count > 0); - var beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.Mode == PlayMode.Osu))?.Beatmap; + var beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap; + Assert.IsTrue(beatmap?.HitObjects.Count > 0); + beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.Beatmap; + Assert.IsTrue(beatmap?.HitObjects.Count > 0); + + beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.Beatmap; + Assert.IsTrue(beatmap?.HitObjects.Count > 0); + + beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Count > 0); } } diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index b9c4cf780a..03d09e24e0 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -4,8 +4,6 @@ using System.IO; using NUnit.Framework; using osu.Game.Beatmaps.IO; -using osu.Game.Modes; -using osu.Game.Modes.Osu; using osu.Game.Tests.Resources; using osu.Game.Beatmaps.Formats; using osu.Game.Database; @@ -19,7 +17,6 @@ namespace osu.Game.Tests.Beatmaps.IO public void SetUp() { OszArchiveReader.Register(); - Ruleset.Register(new OsuRuleset()); } [Test] diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 2844528d0c..b8fcb80aaf 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -19,6 +19,7 @@ 4 false false + 6 true @@ -62,21 +63,21 @@ {c76bf5b3-985e-4d39-95fe-97c9c879b83a} osu.Framework - + {c92a607b-1fdd-4954-9f92-03ff547d9080} - osu.Game.Modes.Osu + osu.Game.Rulesets.Osu - + {58f6c80c-1253-4a0e-a465-b8c85ebeadf3} - osu.Game.Modes.Catch + osu.Game.Rulesets.Catch - + {48f4582b-7687-4621-9cbe-5c24197cb536} - osu.Game.Modes.Mania + osu.Game.Rulesets.Mania - + {f167e17a-7de6-4af5-b920-a5112296c695} - osu.Game.Modes.Taiko + osu.Game.Rulesets.Taiko {0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D} diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 5709bdc8c5..3964fd25a7 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -4,8 +4,7 @@ using OpenTK.Graphics; using osu.Game.Beatmaps.Timing; using osu.Game.Database; -using osu.Game.Modes; -using osu.Game.Modes.Objects; +using osu.Game.Rulesets.Objects; using System.Collections.Generic; namespace osu.Game.Beatmaps @@ -50,12 +49,6 @@ namespace osu.Game.Beatmaps /// public class Beatmap : Beatmap { - /// - /// Calculates the star difficulty for this Beatmap. - /// - /// The star difficulty. - public double CalculateStarDifficulty() => Ruleset.GetRuleset(BeatmapInfo.Mode).CreateDifficultyCalculator(this).Calculate(); - /// /// Constructs a new beatmap. /// @@ -63,6 +56,7 @@ namespace osu.Game.Beatmaps public Beatmap(Beatmap original = null) : base(original) { + HitObjects = original?.HitObjects; } } } diff --git a/osu.Game/Beatmaps/DifficultyCalculator.cs b/osu.Game/Beatmaps/DifficultyCalculator.cs index a9da5c589c..727c89049f 100644 --- a/osu.Game/Beatmaps/DifficultyCalculator.cs +++ b/osu.Game/Beatmaps/DifficultyCalculator.cs @@ -1,7 +1,8 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects; +using osu.Game.Rulesets.Beatmaps; +using osu.Game.Rulesets.Objects; using System.Collections.Generic; namespace osu.Game.Beatmaps @@ -41,6 +42,6 @@ namespace osu.Game.Beatmaps { } - protected abstract IBeatmapConverter CreateBeatmapConverter(); + protected abstract BeatmapConverter CreateBeatmapConverter(); } } diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 47ae4d7985..8a9183819c 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Database; using osu.Game.Graphics; -using osu.Game.Modes; using OpenTK; using OpenTK.Graphics; @@ -45,7 +44,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, TextSize = Size.X, Colour = Color4.White, - Icon = Ruleset.GetRuleset(beatmap.Mode).Icon + Icon = beatmap.Ruleset.CreateInstance().Icon } }; } diff --git a/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs index 452bd595c7..cc9d367a59 100644 --- a/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.IO; -using osu.Game.Modes.Objects; +using osu.Game.Rulesets.Objects; using osu.Game.Database; namespace osu.Game.Beatmaps.Formats diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 35d81311d2..74a5be698e 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -7,9 +7,8 @@ using System.IO; using OpenTK.Graphics; using osu.Game.Beatmaps.Events; using osu.Game.Beatmaps.Timing; -using osu.Game.Modes; -using osu.Game.Modes.Objects; using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Objects.Legacy; namespace osu.Game.Beatmaps.Formats { @@ -30,6 +29,8 @@ namespace osu.Game.Beatmaps.Formats // TODO: Not sure how far back to go, or differences between versions } + private HitObjectParser parser; + private LegacySampleBank defaultSampleBank; private int defaultSampleVolume = 100; @@ -84,7 +85,23 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.StackLeniency = float.Parse(val, NumberFormatInfo.InvariantInfo); break; case @"Mode": - beatmap.BeatmapInfo.Mode = (PlayMode)int.Parse(val); + beatmap.BeatmapInfo.RulesetID = int.Parse(val); + + switch (beatmap.BeatmapInfo.RulesetID) + { + case 0: + parser = new Rulesets.Objects.Legacy.Osu.HitObjectParser(); + break; + case 1: + parser = new Rulesets.Objects.Legacy.Taiko.HitObjectParser(); + break; + case 2: + parser = new Rulesets.Objects.Legacy.Catch.HitObjectParser(); + break; + case 3: + parser = new Rulesets.Objects.Legacy.Mania.HitObjectParser(); + break; + } break; case @"LetterboxInBreaks": beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(val) == 1; @@ -304,8 +321,6 @@ namespace osu.Game.Beatmaps.Formats { beatmap.BeatmapInfo.BeatmapVersion = beatmapVersion; - HitObjectParser parser = new LegacyHitObjectParser(); - Section section = Section.None; bool hasCustomColours = false; diff --git a/osu.Game/Beatmaps/IBeatmapConverter.cs b/osu.Game/Beatmaps/IBeatmapConverter.cs deleted file mode 100644 index 72b248cfba..0000000000 --- a/osu.Game/Beatmaps/IBeatmapConverter.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 - -using osu.Game.Modes.Objects; - -namespace osu.Game.Beatmaps -{ - /// - /// Converts a Beatmap for another mode. - /// - /// The type of HitObject stored in the Beatmap. - public interface IBeatmapConverter where T : HitObject - { - /// - /// Converts a Beatmap to another mode. - /// - /// The original Beatmap. - /// The converted Beatmap. - Beatmap Convert(Beatmap original); - } -} diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 5bea1d0986..616128dab5 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -5,10 +5,10 @@ using osu.Framework.Audio.Track; using osu.Framework.Configuration; using osu.Framework.Graphics.Textures; using osu.Game.Database; -using osu.Game.Modes; -using osu.Game.Modes.Mods; +using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Beatmaps { @@ -18,15 +18,7 @@ namespace osu.Game.Beatmaps public readonly BeatmapSetInfo BeatmapSetInfo; - /// - /// A play mode that is preferred for this beatmap. PlayMode will become this mode where conversion is feasible, - /// or otherwise to the beatmap's default. - /// - public PlayMode? PreferredPlayMode; - - public PlayMode PlayMode => Beatmap?.BeatmapInfo?.Mode > PlayMode.Osu ? Beatmap.BeatmapInfo.Mode : PreferredPlayMode ?? PlayMode.Osu; - - public readonly Bindable> Mods = new Bindable>(); + public readonly Bindable> Mods = new Bindable>(new Mod[] { }); public readonly bool WithStoryboard; @@ -35,6 +27,18 @@ namespace osu.Game.Beatmaps BeatmapInfo = beatmapInfo; BeatmapSetInfo = beatmapSetInfo; WithStoryboard = withStoryboard; + + Mods.ValueChanged += mods => applyRateAdjustments(); + } + + private void applyRateAdjustments() + { + var t = track; + if (t == null) return; + + t.ResetSpeedAdjustments(); + foreach (var mod in Mods.Value.OfType()) + mod.ApplyToClock(t); } protected abstract Beatmap GetBeatmap(); @@ -75,7 +79,11 @@ namespace osu.Game.Beatmaps { lock (trackLock) { - return track ?? (track = GetTrack()); + if (track != null) return track; + + track = GetTrack(); + applyRateAdjustments(); + return track; } } } diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 38fe739a12..2e57806ce2 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Configuration; using osu.Framework.Platform; -using osu.Game.Modes; namespace osu.Game.Configuration { @@ -17,7 +16,7 @@ namespace osu.Game.Configuration Set(OsuConfig.Username, string.Empty); Set(OsuConfig.Token, string.Empty); - Set(OsuConfig.PlayMode, PlayMode.Osu); + Set(OsuConfig.Ruleset, 0, 0, int.MaxValue); Set(OsuConfig.AudioDevice, string.Empty); Set(OsuConfig.SavePassword, false); @@ -42,6 +41,8 @@ namespace osu.Game.Configuration Set(OsuConfig.KeyOverlay, false); //todo: implement all settings below this line (remove the Disabled set when doing so). + Set(OsuConfig.AudioOffset, 0, -500.0, 500.0); + Set(OsuConfig.MouseSpeed, 1.0).Disabled = true; Set(OsuConfig.BeatmapDirectory, @"Songs").Disabled = true; // TODO: use thi.Disabled = trues Set(OsuConfig.AllowPublicInvites, true).Disabled = true; @@ -107,7 +108,6 @@ namespace osu.Game.Configuration Set(OsuConfig.ManiaSpeedBPMScale, true).Disabled = true; Set(OsuConfig.MenuTip, 0).Disabled = true; Set(OsuConfig.MouseSpeed, 1, 0.4, 6).Disabled = true; - Set(OsuConfig.Offset, 0, -300, 300).Disabled = true; Set(OsuConfig.ScoreMeterScale, 1, 0.5, 2).Disabled = true; //Set(OsuConfig.ScoreMeterScale, 1, 0.5, OsuGame.Tournament ? 10 : 2).Disabled = true; Set(OsuConfig.DistanceSpacing, 0.8, 0.1, 6).Disabled = true; @@ -197,7 +197,7 @@ namespace osu.Game.Configuration public enum OsuConfig { // New osu: - PlayMode, + Ruleset, Token, // Imported from old osu: BeatmapDirectory, @@ -272,7 +272,7 @@ namespace osu.Game.Configuration MouseDisableButtons, MouseDisableWheel, MouseSpeed, - Offset, + AudioOffset, ScoreMeterScale, DistanceSpacing, EditorBeatDivisor, diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index 41ddd8df39..0e814dea82 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Linq.Expressions; using osu.Framework.Extensions; using osu.Framework.Logging; using osu.Framework.Platform; @@ -18,37 +17,21 @@ using SQLiteNetExtensions.Extensions; namespace osu.Game.Database { - public class BeatmapDatabase + public class BeatmapDatabase : Database { - private SQLiteConnection connection { get; } - private readonly Storage storage; + private readonly RulesetDatabase rulesets; + public event Action BeatmapSetAdded; public event Action BeatmapSetRemoved; // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) private BeatmapIPCChannel ipc; - public BeatmapDatabase(Storage storage, IIpcHost importHost = null) + public BeatmapDatabase(Storage storage, SQLiteConnection connection, RulesetDatabase rulesets, IIpcHost importHost = null) : base(storage, connection) { - this.storage = storage; - + this.rulesets = rulesets; if (importHost != null) ipc = new BeatmapIPCChannel(importHost, this); - - if (connection == null) - { - try - { - connection = prepareConnection(); - deletePending(); - } - catch (Exception e) - { - Logger.Error(e, @"Failed to initialise the beatmap database! Trying again with a clean database..."); - storage.DeleteDatabase(@"beatmaps"); - connection = prepareConnection(); - } - } } private void deletePending() @@ -57,20 +40,20 @@ namespace osu.Game.Database { try { - storage.Delete(b.Path); + Storage.Delete(b.Path); GetChildren(b, true); foreach (var i in b.Beatmaps) { - if (i.Metadata != null) connection.Delete(i.Metadata); - if (i.Difficulty != null) connection.Delete(i.Difficulty); + if (i.Metadata != null) Connection.Delete(i.Metadata); + if (i.Difficulty != null) Connection.Delete(i.Difficulty); - connection.Delete(i); + Connection.Delete(i); } - if (b.Metadata != null) connection.Delete(b.Metadata); - connection.Delete(b); + if (b.Metadata != null) Connection.Delete(b.Metadata); + Connection.Delete(b); } catch (Exception e) { @@ -80,42 +63,41 @@ namespace osu.Game.Database //this is required because sqlite migrations don't work, initially inserting nulls into this field. //see https://github.com/praeclarum/sqlite-net/issues/326 - connection.Query("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL"); + Connection.Query("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL"); } - private SQLiteConnection prepareConnection() + protected override void Prepare(bool reset = false) { - var conn = storage.GetDatabase(@"beatmaps"); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); - try + if (reset) { - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - } - catch - { - conn.Close(); - throw; + Storage.DeleteDatabase(@"beatmaps"); + + foreach (var setInfo in Query()) + { + if (Storage.Exists(setInfo.Path)) + Storage.Delete(setInfo.Path); + } + + Connection.DeleteAll(); + Connection.DeleteAll(); + Connection.DeleteAll(); + Connection.DeleteAll(); } - return conn; + deletePending(); } - public void Reset() - { - foreach (var setInfo in Query()) - { - if (storage.Exists(setInfo.Path)) - storage.Delete(setInfo.Path); - } - - connection.DeleteAll(); - connection.DeleteAll(); - connection.DeleteAll(); - connection.DeleteAll(); - } + protected override Type[] ValidTypes => new[] { + typeof(BeatmapSetInfo), + typeof(BeatmapInfo), + typeof(BeatmapMetadata), + typeof(BeatmapDifficulty), + }; /// /// Import multiple from . @@ -174,7 +156,7 @@ namespace osu.Game.Database BeatmapMetadata metadata; - using (var reader = ArchiveReader.GetReader(storage, path)) + using (var reader = ArchiveReader.GetReader(Storage, path)) { using (var stream = new StreamReader(reader.GetStream(reader.BeatmapFilenames[0]))) metadata = BeatmapDecoder.GetDecoder(stream).Decode(stream).Metadata; @@ -182,18 +164,18 @@ namespace osu.Game.Database if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader { - using (var input = storage.GetStream(path)) + using (var input = Storage.GetStream(path)) { hash = input.GetMd5Hash(); input.Seek(0, SeekOrigin.Begin); path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash); - if (!storage.Exists(path)) - using (var output = storage.GetStream(path, FileAccess.Write)) + if (!Storage.Exists(path)) + using (var output = Storage.GetStream(path, FileAccess.Write)) input.CopyTo(output); } } - var existing = connection.Table().FirstOrDefault(b => b.Hash == hash); + var existing = Connection.Table().FirstOrDefault(b => b.Hash == hash); if (existing != null) { @@ -216,7 +198,7 @@ namespace osu.Game.Database Metadata = metadata }; - using (var archive = ArchiveReader.GetReader(storage, path)) + using (var archive = ArchiveReader.GetReader(Storage, path)) { string[] mapNames = archive.BeatmapFilenames; foreach (var name in mapNames) @@ -236,7 +218,9 @@ namespace osu.Game.Database // TODO: Diff beatmap metadata with set metadata and leave it here if necessary beatmap.BeatmapInfo.Metadata = null; - beatmap.BeatmapInfo.StarDifficulty = beatmap.CalculateStarDifficulty(); + // TODO: this should be done in a better place once we actually need to dynamically update it. + beatmap.BeatmapInfo.Ruleset = rulesets.Query().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID); + beatmap.BeatmapInfo.StarDifficulty = rulesets.Query().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID)?.CreateInstance()?.CreateDifficultyCalculator(beatmap).Calculate() ?? 0; beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } @@ -248,17 +232,17 @@ namespace osu.Game.Database public void Import(IEnumerable beatmapSets) { - lock (connection) + lock (Connection) { - connection.BeginTransaction(); + Connection.BeginTransaction(); foreach (var s in beatmapSets) { - connection.InsertWithChildren(s, true); + Connection.InsertOrReplaceWithChildren(s, true); BeatmapSetAdded?.Invoke(s); } - connection.Commit(); + Connection.Commit(); } } @@ -275,7 +259,7 @@ namespace osu.Game.Database if (string.IsNullOrEmpty(beatmapSet.Path)) return null; - return ArchiveReader.GetReader(storage, beatmapSet.Path); + return ArchiveReader.GetReader(Storage, beatmapSet.Path); } public BeatmapSetInfo GetBeatmapSet(int id) @@ -287,12 +271,14 @@ namespace osu.Game.Database { var beatmapSetInfo = Query().FirstOrDefault(s => s.ID == beatmapInfo.BeatmapSetInfoID); - //we need metadata - GetChildren(beatmapSetInfo); - if (beatmapSetInfo == null) throw new InvalidOperationException($@"Beatmap set {beatmapInfo.BeatmapSetInfoID} is not in the local database."); + //we need metadata + GetChildren(beatmapSetInfo); + //we also need a ruleset + GetChildren(beatmapInfo); + if (beatmapInfo.Metadata == null) beatmapInfo.Metadata = beatmapSetInfo.Metadata; @@ -303,47 +289,6 @@ namespace osu.Game.Database return working; } - public TableQuery Query() where T : class - { - return connection.Table(); - } - - public T GetWithChildren(object id) where T : class - { - return connection.GetWithChildren(id); - } - - public List GetAllWithChildren(Expression> filter = null, bool recursive = true) - where T : class - { - return connection.GetAllWithChildren(filter, recursive); - } - - public T GetChildren(T item, bool recursive = false) - { - if (item == null) return default(T); - - connection.GetChildren(item, recursive); - return item; - } - - private readonly Type[] validTypes = { - typeof(BeatmapSetInfo), - typeof(BeatmapInfo), - typeof(BeatmapMetadata), - typeof(BeatmapDifficulty), - }; - - public void Update(T record, bool cascade = true) where T : class - { - if (validTypes.All(t => t != typeof(T))) - throw new ArgumentException("Must be a type managed by BeatmapDatabase", nameof(T)); - if (cascade) - connection.UpdateWithChildren(record); - else - connection.Update(record); - } - - public bool Exists(BeatmapSetInfo beatmapSet) => storage.Exists(beatmapSet.Path); + public bool Exists(BeatmapSetInfo beatmapSet) => Storage.Exists(beatmapSet.Path); } } diff --git a/osu.Game/Database/BeatmapInfo.cs b/osu.Game/Database/BeatmapInfo.cs index 3e84825919..5097622deb 100644 --- a/osu.Game/Database/BeatmapInfo.cs +++ b/osu.Game/Database/BeatmapInfo.cs @@ -3,7 +3,6 @@ using Newtonsoft.Json; using osu.Game.IO.Serialization; -using osu.Game.Modes; using SQLite.Net.Attributes; using SQLiteNetExtensions.Attributes; using System; @@ -54,7 +53,13 @@ namespace osu.Game.Database public bool Countdown { get; set; } public float StackLeniency { get; set; } public bool SpecialStyle { get; set; } - public PlayMode Mode { get; set; } + + [ForeignKey(typeof(RulesetInfo))] + public int RulesetID { get; set; } + + [OneToOne(CascadeOperations = CascadeOperation.All)] + public RulesetInfo Ruleset { get; set; } + public bool LetterboxInBreaks { get; set; } public bool WidescreenStoryboard { get; set; } diff --git a/osu.Game/Database/BeatmapSetInfo.cs b/osu.Game/Database/BeatmapSetInfo.cs index 0ef0ba4c63..0875d3c01f 100644 --- a/osu.Game/Database/BeatmapSetInfo.cs +++ b/osu.Game/Database/BeatmapSetInfo.cs @@ -26,6 +26,7 @@ namespace osu.Game.Database public double MaxStarDifficulty => Beatmaps.Max(b => b.StarDifficulty); + [Indexed] public bool DeletePending { get; set; } public string Hash { get; set; } diff --git a/osu.Game/Database/Database.cs b/osu.Game/Database/Database.cs new file mode 100644 index 0000000000..23851b3b2e --- /dev/null +++ b/osu.Game/Database/Database.cs @@ -0,0 +1,82 @@ +// 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 System.Linq.Expressions; +using osu.Framework.Logging; +using osu.Framework.Platform; +using SQLite.Net; +using SQLiteNetExtensions.Extensions; + +namespace osu.Game.Database +{ + public abstract class Database + { + protected SQLiteConnection Connection { get; } + protected Storage Storage { get; } + + protected Database(Storage storage, SQLiteConnection connection) + { + Storage = storage; + Connection = connection; + + try + { + Prepare(); + } + catch (Exception e) + { + Logger.Error(e, $@"Failed to initialise the {GetType()}! Trying again with a clean database..."); + Prepare(true); + } + } + + /// + /// Prepare this database for use. + /// + protected abstract void Prepare(bool reset = false); + + /// + /// Reset this database to a default state. Undo all changes to database and storage backings. + /// + public void Reset() => Prepare(true); + + public TableQuery Query() where T : class + { + return Connection.Table(); + } + + public T GetWithChildren(object id) where T : class + { + return Connection.GetWithChildren(id); + } + + public List GetAllWithChildren(Expression> filter = null, bool recursive = true) + where T : class + { + return Connection.GetAllWithChildren(filter, recursive); + } + + public T GetChildren(T item, bool recursive = false) + { + if (item == null) return default(T); + + Connection.GetChildren(item, recursive); + return item; + } + + protected abstract Type[] ValidTypes { get; } + + public void Update(T record, bool cascade = true) where T : class + { + if (ValidTypes.All(t => t != typeof(T))) + throw new ArgumentException("Must be a type managed by BeatmapDatabase", nameof(T)); + if (cascade) + Connection.UpdateWithChildren(record); + else + Connection.Update(record); + } + } +} \ No newline at end of file diff --git a/osu.Game/Database/RulesetDatabase.cs b/osu.Game/Database/RulesetDatabase.cs new file mode 100644 index 0000000000..b78ca5ffc6 --- /dev/null +++ b/osu.Game/Database/RulesetDatabase.cs @@ -0,0 +1,103 @@ +// 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.IO; +using System.Linq; +using System.Reflection; +using osu.Framework.Platform; +using osu.Game.Rulesets; +using SQLite.Net; + +namespace osu.Game.Database +{ + /// + /// Todo: All of this needs to be moved to a RulesetDatabase. + /// + public class RulesetDatabase : Database + { + public IEnumerable AllRulesets => Query().Where(r => r.Available); + + public RulesetDatabase(Storage storage, SQLiteConnection connection) + : base(storage, connection) + { + } + + protected override void Prepare(bool reset = false) + { + Connection.CreateTable(); + + if (reset) + { + Connection.DeleteAll(); + } + + List instances = new List(); + + foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, @"osu.Game.Rulesets.*.dll")) + { + try + { + var assembly = Assembly.LoadFile(file); + var rulesets = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Ruleset))); + + if (rulesets.Count() != 1) + continue; + + foreach (Type rulesetType in rulesets) + instances.Add((Ruleset)Activator.CreateInstance(rulesetType)); + } + catch (Exception) { } + } + + Connection.BeginTransaction(); + + //add all legacy modes in correct order + foreach (var r in instances.Where(r => r.LegacyID >= 0).OrderBy(r => r.LegacyID)) + { + Connection.InsertOrReplace(createRulesetInfo(r)); + } + + //add any other modes + foreach (var r in instances.Where(r => r.LegacyID < 0)) + { + var us = createRulesetInfo(r); + + var existing = Query().FirstOrDefault(ri => ri.InstantiationInfo == us.InstantiationInfo); + + if (existing == null) + Connection.Insert(us); + } + + //perform a consistency check + foreach (var r in Query()) + { + try + { + r.CreateInstance(); + r.Available = true; + } + catch + { + r.Available = false; + } + + Connection.Update(r); + } + + Connection.Commit(); + } + + private RulesetInfo createRulesetInfo(Ruleset ruleset) => new RulesetInfo + { + Name = ruleset.Description, + InstantiationInfo = ruleset.GetType().AssemblyQualifiedName, + ID = ruleset.LegacyID + }; + + protected override Type[] ValidTypes => new[] { typeof(RulesetInfo) }; + + public RulesetInfo GetRuleset(int id) => Query().First(r => r.ID == id); + } +} diff --git a/osu.Game/Database/RulesetInfo.cs b/osu.Game/Database/RulesetInfo.cs new file mode 100644 index 0000000000..322cb10c33 --- /dev/null +++ b/osu.Game/Database/RulesetInfo.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Rulesets; +using SQLite.Net.Attributes; + +namespace osu.Game.Database +{ + public class RulesetInfo + { + [PrimaryKey, AutoIncrement] + public int? ID { get; set; } + + [Indexed(Unique = true)] + public string Name { get; set; } + + [Indexed(Unique = true)] + public string InstantiationInfo { get; set; } + + [Indexed] + public bool Available { get; set; } + + public Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo)); + } +} \ No newline at end of file diff --git a/osu.Game/Database/ScoreDatabase.cs b/osu.Game/Database/ScoreDatabase.cs index 642bb4aff6..8ea836aceb 100644 --- a/osu.Game/Database/ScoreDatabase.cs +++ b/osu.Game/Database/ScoreDatabase.cs @@ -2,31 +2,36 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using System.IO; using System.Linq; using osu.Framework.Platform; using osu.Game.IO.Legacy; using osu.Game.IPC; -using osu.Game.Modes; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Scoring; using SharpCompress.Compressors.LZMA; +using SQLite.Net; namespace osu.Game.Database { - public class ScoreDatabase + public class ScoreDatabase : Database { private readonly Storage storage; + private readonly BeatmapDatabase beatmaps; + private readonly RulesetDatabase rulesets; private const string replay_folder = @"replays"; // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) private ScoreIPCChannel ipc; - public ScoreDatabase(Storage storage, IIpcHost importHost = null, BeatmapDatabase beatmaps = null) + public ScoreDatabase(Storage storage, SQLiteConnection connection, IIpcHost importHost = null, BeatmapDatabase beatmaps = null, RulesetDatabase rulesets = null) : base(storage, connection) { this.storage = storage; this.beatmaps = beatmaps; + this.rulesets = rulesets; if (importHost != null) ipc = new ScoreIPCChannel(importHost, this); @@ -39,8 +44,10 @@ namespace osu.Game.Database using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename))) using (SerializationReader sr = new SerializationReader(s)) { - var ruleset = Ruleset.GetRuleset((PlayMode)sr.ReadByte()); - score = ruleset.CreateScoreProcessor().CreateScore(); + score = new Score + { + Ruleset = rulesets.GetRuleset(sr.ReadByte()) + }; /* score.Pass = true;*/ var version = sr.ReadInt32(); @@ -101,11 +108,47 @@ namespace osu.Game.Database using (var lzma = new LzmaStream(properties, replayInStream, compressedSize, outSize)) using (var reader = new StreamReader(lzma)) - score.Replay = score.CreateReplay(reader); + score.Replay = createLegacyReplay(reader); } } return score; } + + /// + /// Creates a legacy replay which is read from a stream. + /// + /// The stream reader. + /// The legacy replay. + private Replay createLegacyReplay(StreamReader reader) + { + var frames = new List(); + + float lastTime = 0; + + foreach (var l in reader.ReadToEnd().Split(',')) + { + var split = l.Split('|'); + + if (split.Length < 4 || float.Parse(split[0]) < 0) continue; + + lastTime += float.Parse(split[0]); + + frames.Add(new ReplayFrame( + lastTime, + float.Parse(split[1]), + 384 - float.Parse(split[2]), + (ReplayButtonState)int.Parse(split[3]) + )); + } + + return new Replay { Frames = frames }; + } + + protected override void Prepare(bool reset = false) + { + } + + protected override Type[] ValidTypes => new[] { typeof(Score) }; } } diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index ceb3296bdf..8d5f95aad5 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -98,7 +98,7 @@ namespace osu.Game.Graphics.Cursor public Cursor() { - Size = new Vector2(42); + AutoSizeAxes = Axes.Both; } [BackgroundDependencyLoader] diff --git a/osu.Game/Graphics/Cursor/TooltipContainer.cs b/osu.Game/Graphics/Cursor/TooltipContainer.cs new file mode 100644 index 0000000000..5f0743746a --- /dev/null +++ b/osu.Game/Graphics/Cursor/TooltipContainer.cs @@ -0,0 +1,158 @@ +// Copyright (c) 2007-2017 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Input; +using osu.Framework.Threading; +using osu.Game.Graphics.Sprites; +using System.Linq; + +namespace osu.Game.Graphics.Cursor +{ + public class TooltipContainer : Container + { + private readonly CursorContainer cursor; + private readonly Tooltip tooltip; + + private ScheduledDelegate findTooltipTask; + private UserInputManager inputManager; + + private const int default_appear_delay = 220; + + private IHasTooltip currentlyDisplayed; + + public TooltipContainer(CursorContainer cursor) + { + this.cursor = cursor; + AlwaysPresent = true; + RelativeSizeAxes = Axes.Both; + Add(tooltip = new Tooltip { Alpha = 0 }); + } + + [BackgroundDependencyLoader] + private void load(UserInputManager input) + { + inputManager = input; + } + + protected override void Update() + { + if (tooltip.IsPresent) + { + if (currentlyDisplayed != null) + tooltip.TooltipText = currentlyDisplayed.TooltipText; + + //update the position of the displayed tooltip. + tooltip.Position = ToLocalSpace(cursor.ActiveCursor.ScreenSpaceDrawQuad.Centre) + new Vector2(10); + } + } + + protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) + { + updateTooltipState(state); + return base.OnMouseUp(state, args); + } + + protected override bool OnMouseMove(InputState state) + { + updateTooltipState(state); + return base.OnMouseMove(state); + } + + private void updateTooltipState(InputState state) + { + if (currentlyDisplayed?.Hovering != true) + { + if (currentlyDisplayed != null && !state.Mouse.HasMainButtonPressed) + { + tooltip.Delay(150); + tooltip.FadeOut(500, EasingTypes.OutQuint); + currentlyDisplayed = null; + } + + findTooltipTask?.Cancel(); + findTooltipTask = Scheduler.AddDelayed(delegate + { + var tooltipTarget = inputManager.HoveredDrawables.OfType().FirstOrDefault(); + + if (tooltipTarget == null) return; + + tooltip.TooltipText = tooltipTarget.TooltipText; + tooltip.FadeIn(500, EasingTypes.OutQuint); + + currentlyDisplayed = tooltipTarget; + }, (1 - tooltip.Alpha) * default_appear_delay); + } + } + + public class Tooltip : Container + { + private readonly Box background; + private readonly OsuSpriteText text; + + public string TooltipText + { + set + { + if (value == text.Text) return; + + text.Text = value; + if (Alpha > 0) + { + AutoSizeDuration = 250; + background.FlashColour(OsuColour.Gray(0.4f), 1000, EasingTypes.OutQuint); + } + else + AutoSizeDuration = 0; + } + } + + public override bool HandleInput => false; + + private const float text_size = 16; + + public Tooltip() + { + AutoSizeEasing = EasingTypes.OutQuint; + AutoSizeAxes = Axes.Both; + + CornerRadius = 5; + Masking = true; + EdgeEffect = new EdgeEffect + { + Type = EdgeEffectType.Shadow, + Colour = Color4.Black.Opacity(40), + Radius = 5, + }; + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.9f, + }, + text = new OsuSpriteText + { + TextSize = text_size, + Padding = new MarginPadding(5), + Font = @"Exo2.0-Regular", + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colour) + { + background.Colour = colour.Gray3; + } + } + } +} diff --git a/osu.Game/Graphics/IHasTooltip.cs b/osu.Game/Graphics/IHasTooltip.cs new file mode 100644 index 0000000000..dd51d68c41 --- /dev/null +++ b/osu.Game/Graphics/IHasTooltip.cs @@ -0,0 +1,15 @@ +// 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.Graphics +{ + public interface IHasTooltip : IDrawable + { + /// + /// Tooltip that shows when hovering the drawable + /// + string TooltipText { get; } + } +} diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index d8de4f6346..cd719431e7 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -80,6 +80,10 @@ namespace osu.Game.Graphics public Color4 GrayE = FromHex(@"eee"); public Color4 GrayF = FromHex(@"fff"); - public Color4 Red = FromHex(@"fc4549"); + public Color4 RedLighter = FromHex(@"ffeded"); + public Color4 RedLight = FromHex(@"ed7787"); + public Color4 Red = FromHex(@"ed1121"); + public Color4 RedDark = FromHex(@"ba0011"); + public Color4 RedDarker = FromHex(@"870000"); } } diff --git a/osu.Game/Graphics/TextAwesome.cs b/osu.Game/Graphics/TextAwesome.cs index 1bae165e45..69b0217444 100644 --- a/osu.Game/Graphics/TextAwesome.cs +++ b/osu.Game/Graphics/TextAwesome.cs @@ -817,13 +817,13 @@ namespace osu.Game.Graphics fa_youtube_play = 0xf16a, fa_youtube_square = 0xf166, - // gamemode icons in circles + // ruleset icons in circles fa_osu_osu_o = 0xe000, fa_osu_mania_o = 0xe001, fa_osu_fruits_o = 0xe002, fa_osu_taiko_o = 0xe003, - // gamemode icons without circles + // ruleset icons without circles fa_osu_filled_circle = 0xe004, fa_osu_cross_o = 0xe005, fa_osu_logo = 0xe006, diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index d339388aa5..e81db4954e 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -25,8 +25,6 @@ namespace osu.Game.Graphics.UserInterface { bindable = value; Current.BindTo(bindable); - if (value?.Disabled ?? true) - Alpha = 0.3f; } } @@ -84,6 +82,11 @@ 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/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 180cb88707..9b9a774049 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -5,6 +5,7 @@ using OpenTK; 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.Sprites; using osu.Framework.Graphics.UserInterface; @@ -12,15 +13,36 @@ using osu.Framework.Input; namespace osu.Game.Graphics.UserInterface { - public class OsuSliderBar : SliderBar where U : struct + public class OsuSliderBar : SliderBar, IHasTooltip where T : struct { private SampleChannel sample; private double lastSampleTime; + private T lastSampleValue; private readonly Nub nub; private readonly Box leftBox; private readonly Box rightBox; + public string TooltipText + { + get + { + var bindableDouble = CurrentNumber as BindableNumber; + if (bindableDouble != null) + { + if (bindableDouble.MaxValue == 1 && bindableDouble.MinValue == 0) + return bindableDouble.Value.ToString(@"P0"); + return bindableDouble.Value.ToString(@"n1"); + } + + var bindableInt = CurrentNumber as BindableNumber; + if (bindableInt != null) + return bindableInt.Value.ToString(@"n0"); + + return Current.Value.ToString(); + } + } + public OsuSliderBar() { Height = 12; @@ -52,6 +74,11 @@ namespace osu.Game.Graphics.UserInterface Expanded = true, } }; + + Current.DisabledChanged += disabled => + { + Alpha = disabled ? 0.3f : 1; + }; } [BackgroundDependencyLoader] @@ -84,6 +111,12 @@ namespace osu.Game.Graphics.UserInterface { if (Clock == null || Clock.CurrentTime - lastSampleTime <= 50) return; + + if (Current.Value.Equals(lastSampleValue)) + return; + + lastSampleValue = Current.Value; + lastSampleTime = Clock.CurrentTime; sample.Frequency.Value = 1 + NormalizedValue * 0.2f; diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index a54b122615..62b10b96ef 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -33,6 +33,11 @@ namespace osu.Game.Graphics.UserInterface Height = 40; TextContainer.Height = 0.5f; CornerRadius = 5; + + Current.DisabledChanged += disabled => + { + Alpha = disabled ? 0.3f : 1; + }; } [BackgroundDependencyLoader] diff --git a/osu.Game/Modes/Mods/Mod.cs b/osu.Game/Modes/Mods/Mod.cs deleted file mode 100644 index b6f09b8506..0000000000 --- a/osu.Game/Modes/Mods/Mod.cs +++ /dev/null @@ -1,175 +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.Modes.Objects; -using osu.Game.Modes.UI; -using System; -using osu.Game.Modes.Scoring; - -namespace osu.Game.Modes.Mods -{ - /// - /// The base class for gameplay modifiers. - /// - public abstract class Mod - { - /// - /// The name of this mod. - /// - public abstract string Name { get; } - - /// - /// The icon of this mod. - /// - public virtual FontAwesome Icon => FontAwesome.fa_question; - - /// - /// The user readable description of this mod. - /// - public virtual string Description => string.Empty; - - /// - /// The score multiplier of this mod. - /// - public abstract double ScoreMultiplier { get; } - - /// - /// Returns if this mod is ranked. - /// - public virtual bool Ranked => false; - - /// - /// The mods this mod cannot be enabled with. - /// - public virtual Type[] IncompatibleMods => new Type[] { }; - } - - public class MultiMod : Mod - { - public override string Name => string.Empty; - public override string Description => string.Empty; - public override double ScoreMultiplier => 0.0; - - public Mod[] Mods; - } - - public abstract class ModNoFail : Mod - { - public override string Name => "NoFail"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; - public override string Description => "You can't fail, no matter what."; - public override double ScoreMultiplier => 0.5; - public override bool Ranked => true; - public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModAutoplay) }; - } - - public abstract class ModEasy : Mod - { - public override string Name => "Easy"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_easy; - public override string Description => "Reduces overall difficulty - larger circles, more forgiving HP drain, less accuracy required."; - public override double ScoreMultiplier => 0.5; - public override bool Ranked => true; - public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; - } - - public abstract class ModHidden : Mod - { - public override string Name => "Hidden"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden; - public override bool Ranked => true; - } - - public abstract class ModHardRock : Mod - { - public override string Name => "Hard Rock"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_hardrock; - public override string Description => "Everything just got a bit harder..."; - public override Type[] IncompatibleMods => new[] { typeof(ModEasy) }; - } - - public abstract class ModSuddenDeath : Mod - { - public override string Name => "Sudden Death"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_suddendeath; - public override string Description => "Miss a note and fail."; - public override double ScoreMultiplier => 1; - public override bool Ranked => true; - public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; - } - - public abstract class ModDoubleTime : Mod - { - public override string Name => "Double Time"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_doubletime; - public override string Description => "Zoooooooooom"; - public override bool Ranked => true; - public override Type[] IncompatibleMods => new[] { typeof(ModHalfTime) }; - } - - public abstract class ModRelax : Mod - { - public override string Name => "Relax"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_relax; - public override double ScoreMultiplier => 0; - public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModNoFail), typeof(ModSuddenDeath) }; - } - - public abstract class ModHalfTime : Mod - { - public override string Name => "Half Time"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_halftime; - public override string Description => "Less zoom"; - public override bool Ranked => true; - public override Type[] IncompatibleMods => new[] { typeof(ModDoubleTime) }; - } - - public abstract class ModNightcore : ModDoubleTime - { - public override string Name => "Nightcore"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_nightcore; - public override string Description => "uguuuuuuuu"; - } - - public abstract class ModFlashlight : Mod - { - public override string Name => "Flashlight"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_flashlight; - public override string Description => "Restricted view area."; - public override bool Ranked => true; - } - - public class ModAutoplay : Mod - { - public override string Name => "Autoplay"; - 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 abstract class ModAutoplay : ModAutoplay, IApplicableMod - where T : HitObject - { - protected abstract Score CreateReplayScore(Beatmap beatmap); - - public void Apply(HitRenderer hitRenderer) - { - hitRenderer.SetReplay(CreateReplayScore(hitRenderer.Beatmap)?.Replay); - } - } - - public abstract class ModPerfect : ModSuddenDeath - { - public override string Name => "Perfect"; - public override string Description => "SS or quit."; - } - - public class ModCinema : ModAutoplay - { - public override string Name => "Cinema"; - public override FontAwesome Icon => FontAwesome.fa_osu_mod_cinema; - } -} diff --git a/osu.Game/Modes/Objects/Legacy/LegacyHit.cs b/osu.Game/Modes/Objects/Legacy/LegacyHit.cs deleted file mode 100644 index 239c8982da..0000000000 --- a/osu.Game/Modes/Objects/Legacy/LegacyHit.cs +++ /dev/null @@ -1,18 +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.Modes.Objects.Types; -using OpenTK; - -namespace osu.Game.Modes.Objects.Legacy -{ - /// - /// Legacy Hit-type, used for parsing Beatmaps. - /// - public sealed class LegacyHit : HitObject, IHasPosition, IHasCombo - { - public Vector2 Position { get; set; } - - public bool NewCombo { get; set; } - } -} diff --git a/osu.Game/Modes/PlayMode.cs b/osu.Game/Modes/PlayMode.cs deleted file mode 100644 index fa6d94a650..0000000000 --- a/osu.Game/Modes/PlayMode.cs +++ /dev/null @@ -1,13 +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.Modes -{ - public enum PlayMode - { - Osu = 0, - Taiko = 1, - Catch = 2, - Mania = 3 - } -} diff --git a/osu.Game/Modes/Ruleset.cs b/osu.Game/Modes/Ruleset.cs deleted file mode 100644 index c97420fbe3..0000000000 --- a/osu.Game/Modes/Ruleset.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.Beatmaps; -using osu.Game.Graphics; -using osu.Game.Modes.Mods; -using osu.Game.Modes.UI; -using osu.Game.Screens.Play; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using osu.Game.Modes.Scoring; - -namespace osu.Game.Modes -{ - public class BeatmapStatistic - { - public FontAwesome Icon; - public string Content; - public string Name; - } - - public abstract class Ruleset - { - private static readonly ConcurrentDictionary available_rulesets = new ConcurrentDictionary(); - - public static IEnumerable PlayModes => available_rulesets.Keys; - - public virtual IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { }; - - public abstract IEnumerable GetModsFor(ModType type); - - public abstract HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap); - - public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap); - - public abstract ScoreProcessor CreateScoreProcessor(); - - public static void Register(Ruleset ruleset) => available_rulesets.TryAdd(ruleset.PlayMode, ruleset.GetType()); - - protected abstract PlayMode PlayMode { get; } - - public virtual FontAwesome Icon => FontAwesome.fa_question_circle; - - public abstract string Description { get; } - - public abstract IEnumerable CreateGameplayKeys(); - - public static Ruleset GetRuleset(PlayMode mode) - { - Type type; - - if (!available_rulesets.TryGetValue(mode, out type)) - return null; - - return Activator.CreateInstance(type) as Ruleset; - } - - } -} diff --git a/osu.Game/Modes/Scoring/Score.cs b/osu.Game/Modes/Scoring/Score.cs deleted file mode 100644 index b0c123f438..0000000000 --- a/osu.Game/Modes/Scoring/Score.cs +++ /dev/null @@ -1,113 +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 Newtonsoft.Json; -using osu.Game.Database; -using osu.Game.Modes.Mods; -using osu.Game.Users; -using System.IO; -using osu.Game.Modes.Replays; - -namespace osu.Game.Modes.Scoring -{ - public class Score - { - [JsonProperty(@"rank")] - public ScoreRank Rank { get; set; } - - [JsonProperty(@"score")] - public double TotalScore { get; set; } - public double Accuracy { get; set; } - public double Health { get; set; } - - [JsonProperty(@"maxcombo")] - public int MaxCombo { get; set; } - public int Combo { get; set; } - public Mod[] Mods { get; set; } - - private User user; - - public User User - { - get - { - return user ?? new User - { - Username = LegacyUsername, - Id = LegacyUserID - }; - } - - set - { - user = value; - } - } - - [JsonProperty(@"replay_data")] - public Replay Replay; - - public BeatmapInfo Beatmap; - - [JsonProperty(@"score_id")] - public long OnlineScoreID; - - [JsonProperty(@"username")] - public string LegacyUsername; - - [JsonProperty(@"user_id")] - public long LegacyUserID; - - [JsonProperty(@"date")] - public DateTime Date; - - /// - /// Creates a replay which is read from a stream. - /// - /// The stream reader. - /// The replay. - public virtual Replay CreateReplay(StreamReader reader) - { - var frames = new List(); - - float lastTime = 0; - - foreach (var l in reader.ReadToEnd().Split(',')) - { - var split = l.Split('|'); - - if (split.Length < 4 || float.Parse(split[0]) < 0) continue; - - lastTime += float.Parse(split[0]); - - frames.Add(new ReplayFrame( - lastTime, - float.Parse(split[1]), - 384 - float.Parse(split[2]), - (ReplayButtonState)int.Parse(split[3]) - )); - } - - return new Replay { Frames = frames }; - } - - // [JsonProperty(@"count50")] 0, - //[JsonProperty(@"count100")] 0, - //[JsonProperty(@"count300")] 100, - //[JsonProperty(@"countmiss")] 0, - //[JsonProperty(@"countkatu")] 0, - //[JsonProperty(@"countgeki")] 31, - //[JsonProperty(@"perfect")] true, - //[JsonProperty(@"enabled_mods")] [ - // "DT", - // "FL", - // "HD", - // "HR" - //], - //[JsonProperty(@"rank")] "XH", - //[JsonProperty(@"pp")] 26.1816, - //[JsonProperty(@"replay")] true - } -} diff --git a/osu.Game/Modes/UI/StandardHealthDisplay.cs b/osu.Game/Modes/UI/StandardHealthDisplay.cs deleted file mode 100644 index 12d0f841a2..0000000000 --- a/osu.Game/Modes/UI/StandardHealthDisplay.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 OpenTK; -using OpenTK.Graphics; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; - -namespace osu.Game.Modes.UI -{ - public class StandardHealthDisplay : HealthDisplay, IHasAccentColour - { - private readonly Container fill; - - public Color4 AccentColour - { - get { return fill.Colour; } - set { fill.Colour = value; } - } - - private Color4 glowColour; - public Color4 GlowColour - { - get { return glowColour; } - set - { - if (glowColour == value) - return; - glowColour = value; - - fill.EdgeEffect = new EdgeEffect - { - Colour = glowColour, - Radius = 8, - Type = EdgeEffectType.Glow - }; - } - } - - public StandardHealthDisplay() - { - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - }, - fill = new Container - { - RelativeSizeAxes = Axes.Both, - Scale = new Vector2(0, 1), - Masking = true, - Children = new[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - } - } - }, - }; - } - - protected override void SetHealth(float value) => fill.ScaleTo(new Vector2(value, 1), 200, EasingTypes.OutQuint); - } -} diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 66c5e6c72d..5e6bf1ea9f 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.IO.Network; using osu.Game.Database; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Online.API.Requests { @@ -21,19 +21,16 @@ namespace osu.Game.Online.API.Requests protected override WebRequest CreateWebRequest() { var req = base.CreateWebRequest(); - req.AddParameter(@"c", beatmap.Hash); - req.AddParameter(@"f", beatmap.Path); + //req.AddParameter(@"c", beatmap.Hash); + //req.AddParameter(@"f", beatmap.Path); return req; } - protected override string Target => @"beatmaps/scores"; + protected override string Target => $@"beatmaps/{beatmap.OnlineBeatmapID}/scores"; } public class GetScoresResponse { - [JsonProperty(@"beatmap")] - public BeatmapInfo Beatmap; - [JsonProperty(@"scores")] public IEnumerable Scores; } diff --git a/osu.Game/Online/API/Requests/PostMessageRequest.cs b/osu.Game/Online/API/Requests/PostMessageRequest.cs new file mode 100644 index 0000000000..52269d9fe8 --- /dev/null +++ b/osu.Game/Online/API/Requests/PostMessageRequest.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Extensions; +using osu.Framework.IO.Network; +using osu.Game.Online.Chat; + +namespace osu.Game.Online.API.Requests +{ + public class PostMessageRequest : APIRequest + { + private readonly Message message; + + public PostMessageRequest(Message message) + { + this.message = message; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.Method = HttpMethod.POST; + req.AddParameter(@"target_type", message.TargetType.GetDescription()); + req.AddParameter(@"target_id", message.TargetId.ToString()); + req.AddParameter(@"message", message.Content); + + return req; + } + + protected override string Target => @"chat/messages"; + } +} \ No newline at end of file diff --git a/osu.Game/Online/Chat/Channel.cs b/osu.Game/Online/Chat/Channel.cs index d895b93336..04ebf0a389 100644 --- a/osu.Game/Online/Chat/Channel.cs +++ b/osu.Game/Online/Chat/Channel.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using System.Linq; using Newtonsoft.Json; +using osu.Framework.Lists; namespace osu.Game.Online.Chat { @@ -21,7 +23,7 @@ namespace osu.Game.Online.Chat [JsonProperty(@"channel_id")] public int Id; - public List Messages = new List(); + public SortedList Messages = new SortedList((m1, m2) => m1.Id.CompareTo(m2.Id)); //internal bool Joined; @@ -36,7 +38,10 @@ namespace osu.Game.Online.Chat public void AddNewMessages(IEnumerable messages) { + messages = messages.Except(Messages).ToList(); + Messages.AddRange(messages); + purgeOldMessages(); NewMessagesArrived?.Invoke(messages); diff --git a/osu.Game/Online/Chat/Drawables/ChatLine.cs b/osu.Game/Online/Chat/Drawables/ChatLine.cs index bfbcf3d707..6bfa25755f 100644 --- a/osu.Game/Online/Chat/Drawables/ChatLine.cs +++ b/osu.Game/Online/Chat/Drawables/ChatLine.cs @@ -55,6 +55,9 @@ namespace osu.Game.Online.Chat.Drawables private Color4 getUsernameColour(Message message) { + if (!string.IsNullOrEmpty(message.Sender?.Colour)) + return OsuColour.FromHex(message.Sender.Colour); + //todo: use User instead of Message when user_id is correctly populated. return username_colours[message.UserId % username_colours.Length]; } @@ -83,7 +86,7 @@ namespace osu.Game.Online.Chat.Drawables Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = @"Exo2.0-SemiBold", - Text = $@"{Message.Timestamp.LocalDateTime:hh:mm:ss}", + Text = $@"{Message.Timestamp.LocalDateTime:HH:mm:ss}", FixedWidth = true, TextSize = text_size * 0.75f, Alpha = 0.4f, @@ -91,7 +94,7 @@ namespace osu.Game.Online.Chat.Drawables new OsuSpriteText { Font = @"Exo2.0-BoldItalic", - Text = $@"{Message.User.Username}:", + Text = $@"{Message.Sender.Username}:", Colour = getUsernameColour(Message), TextSize = text_size, Origin = Anchor.TopRight, diff --git a/osu.Game/Online/Chat/Message.cs b/osu.Game/Online/Chat/Message.cs index b267cf63ac..372e43be38 100644 --- a/osu.Game/Online/Chat/Message.cs +++ b/osu.Game/Online/Chat/Message.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.ComponentModel; using Newtonsoft.Json; using osu.Game.Users; @@ -10,14 +11,17 @@ namespace osu.Game.Online.Chat public class Message { [JsonProperty(@"message_id")] - public long Id; + public readonly long Id; //todo: this should be inside sender. - [JsonProperty(@"user_id")] + [JsonProperty(@"sender_id")] public int UserId; - [JsonProperty(@"channel_id")] - public int ChannelId; + [JsonProperty(@"target_type")] + public TargetType TargetType; + + [JsonProperty(@"target_id")] + public int TargetId; [JsonProperty(@"timestamp")] public DateTimeOffset Timestamp; @@ -26,11 +30,31 @@ namespace osu.Game.Online.Chat public string Content; [JsonProperty(@"sender")] - public User User; + public User Sender; [JsonConstructor] public Message() { } + + public override bool Equals(object obj) + { + var objMessage = obj as Message; + + return Id == objMessage?.Id; + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } + } + + public enum TargetType + { + [Description(@"channel")] + Channel, + [Description(@"user")] + User } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ccea6ef458..c9f41de5f2 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -15,7 +15,6 @@ using osu.Framework.Logging; using osu.Game.Graphics.UserInterface.Volume; using osu.Framework.Allocation; using osu.Framework.Timing; -using osu.Game.Modes; using osu.Game.Overlays.Toolbar; using osu.Game.Screens; using osu.Game.Screens.Menu; @@ -24,8 +23,9 @@ using System.Linq; using osu.Framework.Graphics.Primitives; using System.Threading.Tasks; using osu.Framework.Threading; +using osu.Game.Database; using osu.Game.Graphics; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Scoring; using osu.Game.Overlays.Notifications; using osu.Game.Screens.Play; @@ -58,7 +58,8 @@ namespace osu.Game private VolumeControl volume; - public Bindable PlayMode; + private Bindable configRuleset; + public Bindable Ruleset = new Bindable(); private readonly string[] args; @@ -88,7 +89,9 @@ namespace osu.Game Dependencies.Cache(this); - PlayMode = LocalConfig.GetBindable(OsuConfig.PlayMode); + configRuleset = LocalConfig.GetBindable(OsuConfig.Ruleset); + Ruleset.Value = RulesetDatabase.GetRuleset(configRuleset.Value); + Ruleset.ValueChanged += r => configRuleset.Value = r.ID ?? 0; } private ScheduledDelegate scoreLoad; @@ -191,6 +194,7 @@ namespace osu.Game }; Dependencies.Cache(options); + Dependencies.Cache(chat); Dependencies.Cache(musicController); Dependencies.Cache(notificationManager); Dependencies.Cache(dialogOverlay); @@ -199,13 +203,7 @@ namespace osu.Game { Depth = -3, OnHome = delegate { intro?.ChildScreen?.MakeCurrent(); }, - OnPlayModeChange = m => PlayMode.Value = m, - }, t => - { - PlayMode.ValueChanged += delegate { Toolbar.SetGameMode(PlayMode.Value); }; - PlayMode.TriggerChange(); - overlayContent.Add(Toolbar); - }); + }, overlayContent.Add); options.StateChanged += delegate { @@ -276,7 +274,7 @@ namespace osu.Game return; } - //central game mode change logic. + //central game screen change logic. if (!currentScreen.ShowOverlays) { options.State = Visibility.Hidden; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index f95e8c3ac6..c9d7d856db 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -18,6 +18,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Processing; using osu.Game.Online.API; +using SQLite.Net; namespace osu.Game { @@ -27,6 +28,8 @@ namespace osu.Game protected BeatmapDatabase BeatmapDatabase; + protected RulesetDatabase RulesetDatabase; + protected ScoreDatabase ScoreDatabase; protected override string MainResourceFile => @"osu.Game.Resources.dll"; @@ -80,8 +83,12 @@ namespace osu.Game { Dependencies.Cache(this); Dependencies.Cache(LocalConfig); - Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, Host)); - Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, Host, BeatmapDatabase)); + + SQLiteConnection connection = Host.Storage.GetDatabase(@"client"); + + Dependencies.Cache(RulesetDatabase = new RulesetDatabase(Host.Storage, connection)); + Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, connection, RulesetDatabase, Host)); + Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, connection, Host, BeatmapDatabase)); Dependencies.Cache(new OsuColour()); //this completely overrides the framework default. will need to change once we make a proper FontStore. @@ -109,6 +116,7 @@ namespace osu.Game Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BlackItalic")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera")); + Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera-Light")); OszArchiveReader.Register(); @@ -137,9 +145,19 @@ namespace osu.Game AddInternal(ratioContainer = new RatioAdjust { - Children = new[] + Children = new Drawable[] { - Cursor = new MenuCursor { Depth = float.MinValue } + new Container + { + AlwaysReceiveInput = true, + RelativeSizeAxes = Axes.Both, + Depth = float.MinValue, + Children = new Drawable[] + { + Cursor = new MenuCursor(), + new TooltipContainer(Cursor) { Depth = -1 }, + } + }, } }); } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index fc12789b05..457611dfab 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -38,6 +38,10 @@ namespace osu.Game.Overlays private APIAccess api; + private const int transition_length = 500; + + private GetMessagesRequest fetchReq; + public ChatOverlay() { RelativeSizeAxes = Axes.X; @@ -82,94 +86,6 @@ namespace osu.Game.Overlays }); } - protected override bool OnFocus(InputState state) - { - //this is necessary as inputTextBox is masked away and therefore can't get focus :( - inputTextBox.TriggerFocus(); - return false; - } - - private void postMessage(TextBox sender, bool newText) - { - var postText = sender.Text; - - if (!string.IsNullOrEmpty(postText) && api.LocalUser.Value != null) - { - //todo: actually send to server - careChannels.FirstOrDefault()?.AddNewMessages(new[] - { - new Message - { - User = api.LocalUser.Value, - Timestamp = DateTimeOffset.Now, - Content = postText - } - }); - } - - sender.Text = string.Empty; - } - - [BackgroundDependencyLoader] - private void load(APIAccess api) - { - this.api = api; - api.Register(this); - } - - private long? lastMessageId; - - private List careChannels; - - private void addChannel(Channel channel) - { - Add(new DrawableChannel(channel)); - careChannels.Add(channel); - } - - private GetMessagesRequest fetchReq; - - public void FetchNewMessages(APIAccess api) - { - if (fetchReq != null) return; - - fetchReq = new GetMessagesRequest(careChannels, lastMessageId); - fetchReq.Success += delegate (List messages) - { - var ids = messages.Select(m => m.ChannelId).Distinct(); - - //batch messages per channel. - foreach (var id in ids) - careChannels.Find(c => c.Id == id)?.AddNewMessages(messages.Where(m => m.ChannelId == id)); - - lastMessageId = messages.LastOrDefault()?.Id ?? lastMessageId; - - Debug.Write("success!"); - fetchReq = null; - }; - fetchReq.Failure += delegate - { - Debug.Write("failure!"); - fetchReq = null; - }; - - api.Queue(fetchReq); - } - - private const int transition_length = 500; - - protected override void PopIn() - { - MoveToY(0, transition_length, EasingTypes.OutQuint); - FadeIn(transition_length, EasingTypes.OutQuint); - } - - protected override void PopOut() - { - MoveToY(DrawSize.Y, transition_length, EasingTypes.InSine); - FadeOut(transition_length, EasingTypes.InSine); - } - public void APIStateChanged(APIAccess api, APIState state) { switch (state) @@ -183,19 +99,46 @@ namespace osu.Game.Overlays } } + protected override bool OnFocus(InputState state) + { + //this is necessary as inputTextBox is masked away and therefore can't get focus :( + inputTextBox.TriggerFocus(); + return false; + } + + protected override void PopIn() + { + MoveToY(0, transition_length, EasingTypes.OutQuint); + FadeIn(transition_length, EasingTypes.OutQuint); + } + + protected override void PopOut() + { + MoveToY(DrawSize.Y, transition_length, EasingTypes.InSine); + FadeOut(transition_length, EasingTypes.InSine); + } + + [BackgroundDependencyLoader] + private void load(APIAccess api) + { + this.api = api; + api.Register(this); + } + + private long? lastMessageId; + + private List careChannels; + private void initializeChannels() { Clear(); careChannels = new List(); - //if (api.State != APIAccess.APIState.Online) - // return; - SpriteText loading; Add(loading = new OsuSpriteText { - Text = @"Loading available channels...", + Text = @"initialising chat...", Anchor = Anchor.Centre, Origin = Anchor.Centre, TextSize = 40, @@ -211,15 +154,85 @@ namespace osu.Game.Overlays Scheduler.Add(delegate { loading.FadeOut(100); - addChannel(channels.Find(c => c.Name == @"#osu")); + addChannel(channels.Find(c => c.Name == @"#lazer")); }); - //addChannel(channels.Find(c => c.Name == @"#lobby")); - //addChannel(channels.Find(c => c.Name == @"#english")); - - messageRequest = Scheduler.AddDelayed(() => FetchNewMessages(api), 1000, true); + messageRequest = Scheduler.AddDelayed(fetchNewMessages, 1000, true); }; api.Queue(req); } + + private void addChannel(Channel channel) + { + Add(new DrawableChannel(channel)); + careChannels.Add(channel); + } + + private void fetchNewMessages() + { + if (fetchReq != null) return; + + fetchReq = new GetMessagesRequest(careChannels, lastMessageId); + fetchReq.Success += delegate (List messages) + { + var ids = messages.Where(m => m.TargetType == TargetType.Channel).Select(m => m.TargetId).Distinct(); + + //batch messages per channel. + foreach (var id in ids) + careChannels.Find(c => c.Id == id)?.AddNewMessages(messages.Where(m => m.TargetId == id)); + + lastMessageId = messages.LastOrDefault()?.Id ?? lastMessageId; + + Debug.Write("success!"); + fetchReq = null; + }; + fetchReq.Failure += delegate + { + Debug.Write("failure!"); + fetchReq = null; + }; + + api.Queue(fetchReq); + } + + private void postMessage(TextBox textbox, bool newText) + { + var postText = textbox.Text; + + if (!string.IsNullOrEmpty(postText) && api.LocalUser.Value != null) + { + var currentChannel = careChannels.FirstOrDefault(); + + if (currentChannel == null) return; + + var message = new Message + { + Sender = api.LocalUser.Value, + Timestamp = DateTimeOffset.Now, + TargetType = TargetType.Channel, //TODO: read this from currentChannel + TargetId = currentChannel.Id, + Content = postText + }; + + textbox.ReadOnly = true; + var req = new PostMessageRequest(message); + + req.Failure += e => + { + textbox.FlashColour(Color4.Red, 1000); + textbox.ReadOnly = false; + }; + + req.Success += m => + { + currentChannel.AddNewMessages(new[] { m }); + + textbox.ReadOnly = false; + textbox.Text = string.Empty; + }; + + api.Queue(req); + } + } } } diff --git a/osu.Game/Overlays/Mods/AssistedSection.cs b/osu.Game/Overlays/Mods/AssistedSection.cs index a1ec7a3fdc..b4263fa309 100644 --- a/osu.Game/Overlays/Mods/AssistedSection.cs +++ b/osu.Game/Overlays/Mods/AssistedSection.cs @@ -4,7 +4,7 @@ using OpenTK.Input; using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Game.Modes.Mods; +using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { diff --git a/osu.Game/Overlays/Mods/DifficultyIncreaseSection.cs b/osu.Game/Overlays/Mods/DifficultyIncreaseSection.cs index 13df5aabfb..0a293416dc 100644 --- a/osu.Game/Overlays/Mods/DifficultyIncreaseSection.cs +++ b/osu.Game/Overlays/Mods/DifficultyIncreaseSection.cs @@ -4,7 +4,7 @@ using OpenTK.Input; using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Game.Modes.Mods; +using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { diff --git a/osu.Game/Overlays/Mods/DifficultyReductionSection.cs b/osu.Game/Overlays/Mods/DifficultyReductionSection.cs index f8ac4551ef..3a373e6f09 100644 --- a/osu.Game/Overlays/Mods/DifficultyReductionSection.cs +++ b/osu.Game/Overlays/Mods/DifficultyReductionSection.cs @@ -4,7 +4,7 @@ using OpenTK.Input; using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Game.Modes.Mods; +using osu.Game.Rulesets.Mods; namespace osu.Game.Overlays.Mods { diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index b787935d57..f380c19d8a 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -12,8 +12,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Game.Graphics.Sprites; -using osu.Game.Modes.Mods; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.UI; using System; using System.Linq; diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 0e93a5520d..c2af12f49e 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Input; using osu.Game.Graphics.Sprites; -using osu.Game.Modes.Mods; +using osu.Game.Rulesets.Mods; using System; namespace osu.Game.Overlays.Mods diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 2b9f8e86a9..dadfb808f7 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -13,11 +13,11 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; -using osu.Game.Modes; -using osu.Game.Modes.Mods; +using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; using System.Linq; +using osu.Game.Database; namespace osu.Game.Overlays.Mods { @@ -37,26 +37,30 @@ namespace osu.Game.Overlays.Mods public readonly Bindable> SelectedMods = new Bindable>(); - public readonly Bindable PlayMode = new Bindable(); + public readonly Bindable Ruleset = new Bindable(); - private void modeChanged(PlayMode newMode) + private void rulesetChanged(RulesetInfo newRuleset) { - var ruleset = Ruleset.GetRuleset(newMode); + var instance = newRuleset.CreateInstance(); + foreach (ModSection section in modSectionsContainer.Children) - section.Buttons = ruleset.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray(); + section.Buttons = instance.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray(); refreshSelectedMods(); } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, OsuGame osu) + private void load(OsuColour colours, OsuGame osu, RulesetDatabase rulesets) { lowMultiplierColour = colours.Red; highMultiplierColour = colours.Green; if (osu != null) - PlayMode.BindTo(osu.PlayMode); - PlayMode.ValueChanged += modeChanged; - PlayMode.TriggerChange(); + Ruleset.BindTo(osu.Ruleset); + else + Ruleset.Value = rulesets.AllRulesets.First(); + + Ruleset.ValueChanged += rulesetChanged; + Ruleset.TriggerChange(); } protected override void PopOut() diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 9d21a0341c..19e742facb 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -22,6 +22,7 @@ using osu.Game.Database; using osu.Game.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Graphics.Sprites; +using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Overlays @@ -293,7 +294,7 @@ namespace osu.Game.Overlays trackManager.SetExclusive(current.Track); current.Track.Start(); beatmapSource.Value = current; - }); + }).ContinueWith(task => Schedule(() => task.ThrowIfFaulted()), TaskContinuationOptions.OnlyOnFaulted); updateDisplay(current, isNext ? TransformDirection.Next : TransformDirection.Prev); } diff --git a/osu.Game/Overlays/Options/OptionDropdown.cs b/osu.Game/Overlays/Options/OptionDropdown.cs index ee12ba9b05..8642b132df 100644 --- a/osu.Game/Overlays/Options/OptionDropdown.cs +++ b/osu.Game/Overlays/Options/OptionDropdown.cs @@ -34,8 +34,6 @@ namespace osu.Game.Overlays.Options { bindable = value; dropdown.Current.BindTo(bindable); - if (value?.Disabled ?? true) - Alpha = 0.3f; } } @@ -75,6 +73,11 @@ namespace osu.Game.Overlays.Options Items = Items, } }; + + dropdown.Current.DisabledChanged += disabled => + { + Alpha = disabled ? 0.3f : 1; + }; } } } diff --git a/osu.Game/Overlays/Options/OptionSlider.cs b/osu.Game/Overlays/Options/OptionSlider.cs index 1c4b54a080..5c383c74a8 100644 --- a/osu.Game/Overlays/Options/OptionSlider.cs +++ b/osu.Game/Overlays/Options/OptionSlider.cs @@ -35,8 +35,6 @@ namespace osu.Game.Overlays.Options { bindable = value; slider.Current.BindTo(bindable); - if (value?.Disabled ?? true) - Alpha = 0.3f; } } diff --git a/osu.Game/Overlays/Options/OptionTextBox.cs b/osu.Game/Overlays/Options/OptionTextBox.cs index b5ef39c8b2..4927122181 100644 --- a/osu.Game/Overlays/Options/OptionTextBox.cs +++ b/osu.Game/Overlays/Options/OptionTextBox.cs @@ -16,9 +16,7 @@ namespace osu.Game.Overlays.Options { bindable = value; Current.BindTo(bindable); - if (value?.Disabled ?? true) - Alpha = 0.3f; } } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Options/OptionsFooter.cs b/osu.Game/Overlays/Options/OptionsFooter.cs index c42fe42428..c785f2d0c0 100644 --- a/osu.Game/Overlays/Options/OptionsFooter.cs +++ b/osu.Game/Overlays/Options/OptionsFooter.cs @@ -1,15 +1,14 @@ // 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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; +using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Modes; using OpenTK; using OpenTK.Graphics; @@ -18,7 +17,7 @@ namespace osu.Game.Overlays.Options public class OptionsFooter : FillFlowContainer { [BackgroundDependencyLoader] - private void load(OsuGameBase game, OsuColour colours) + private void load(OsuGameBase game, OsuColour colours, RulesetDatabase rulesets) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -27,13 +26,15 @@ namespace osu.Game.Overlays.Options var modes = new List(); - foreach (PlayMode m in Enum.GetValues(typeof(PlayMode))) + foreach (var ruleset in rulesets.AllRulesets) + { modes.Add(new TextAwesome { - Icon = Ruleset.GetRuleset(m).Icon, + Icon = ruleset.CreateInstance().Icon, Colour = Color4.Gray, TextSize = 20 }); + } Children = new Drawable[] { diff --git a/osu.Game/Overlays/Options/Sections/Audio/OffsetOptions.cs b/osu.Game/Overlays/Options/Sections/Audio/OffsetOptions.cs index 2602565c29..c1f5359585 100644 --- a/osu.Game/Overlays/Options/Sections/Audio/OffsetOptions.cs +++ b/osu.Game/Overlays/Options/Sections/Audio/OffsetOptions.cs @@ -18,10 +18,10 @@ namespace osu.Game.Overlays.Options.Sections.Audio { Children = new Drawable[] { - new OptionSlider + new OptionSlider { - LabelText = "Universal Offset", - Bindable = (BindableInt)config.GetBindable(OsuConfig.Offset) + LabelText = "Audio Offset", + Bindable = (BindableDouble)config.GetBindable(OsuConfig.AudioOffset) }, new OsuButton { diff --git a/osu.Game/Overlays/Options/Sections/Graphics/LayoutOptions.cs b/osu.Game/Overlays/Options/Sections/Graphics/LayoutOptions.cs index b04f853ec4..9f5e3458f3 100644 --- a/osu.Game/Overlays/Options/Sections/Graphics/LayoutOptions.cs +++ b/osu.Game/Overlays/Options/Sections/Graphics/LayoutOptions.cs @@ -12,8 +12,8 @@ namespace osu.Game.Overlays.Options.Sections.Graphics { protected override string Header => "Layout"; - private OptionSlider letterboxPositionX; - private OptionSlider letterboxPositionY; + private OptionSlider letterboxPositionX; + private OptionSlider letterboxPositionY; private Bindable letterboxing; @@ -35,15 +35,15 @@ namespace osu.Game.Overlays.Options.Sections.Graphics LabelText = "Letterboxing", Bindable = letterboxing, }, - letterboxPositionX = new OptionSlider + letterboxPositionX = new OptionSlider { LabelText = "Horizontal position", - Bindable = (BindableInt)config.GetBindable(FrameworkConfig.LetterboxPositionX) + Bindable = config.GetBindable(FrameworkConfig.LetterboxPositionX) }, - letterboxPositionY = new OptionSlider + letterboxPositionY = new OptionSlider { LabelText = "Vertical position", - Bindable = (BindableInt)config.GetBindable(FrameworkConfig.LetterboxPositionY) + Bindable = config.GetBindable(FrameworkConfig.LetterboxPositionY) }, }; diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 9e7b4f1519..43c3cd32f2 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; using osu.Game.Graphics; -using osu.Game.Modes; using OpenTK; namespace osu.Game.Overlays.Toolbar @@ -20,14 +19,12 @@ namespace osu.Game.Overlays.Toolbar public const float TOOLTIP_HEIGHT = 30; public Action OnHome; - public Action OnPlayModeChange; - private readonly ToolbarModeSelector modeSelector; private readonly ToolbarUserArea userArea; protected override bool HideOnEscape => false; - protected override bool BlockPassThroughInput => false; + protected override bool BlockPassThroughMouse => false; private const double transition_time = 500; @@ -53,13 +50,7 @@ namespace osu.Game.Overlays.Toolbar { Action = () => OnHome?.Invoke() }, - modeSelector = new ToolbarModeSelector - { - OnPlayModeChange = mode => - { - OnPlayModeChange?.Invoke(mode); - } - } + new ToolbarModeSelector() } }, new FillFlowContainer @@ -72,6 +63,7 @@ namespace osu.Game.Overlays.Toolbar AutoSizeAxes = Axes.X, Children = new Drawable[] { + new ToolbarChatButton(), new ToolbarMusicButton(), new ToolbarButton { @@ -129,8 +121,6 @@ namespace osu.Game.Overlays.Toolbar } } - public void SetGameMode(PlayMode mode) => modeSelector.SetGameMode(mode); - protected override void PopIn() { MoveToY(0, transition_time, EasingTypes.OutQuint); diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs new file mode 100644 index 0000000000..ca612662e1 --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs @@ -0,0 +1,23 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Game.Graphics; + +namespace osu.Game.Overlays.Toolbar +{ + internal class ToolbarChatButton : ToolbarOverlayToggleButton + { + public ToolbarChatButton() + { + Icon = FontAwesome.fa_comments; + } + + [BackgroundDependencyLoader] + private void load(ChatOverlay chat) + { + StateContainer = chat; + Action = chat.ToggleVisibility; + } + } +} \ No newline at end of file diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs index 62359b05ae..dd70289f7d 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs @@ -2,23 +2,26 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; -using osu.Game.Modes; +using osu.Game.Database; using OpenTK.Graphics; namespace osu.Game.Overlays.Toolbar { public class ToolbarModeButton : ToolbarButton { - private PlayMode mode; - public PlayMode Mode + private RulesetInfo ruleset; + public RulesetInfo Ruleset { - get { return mode; } + get { return ruleset; } set { - mode = value; - TooltipMain = Ruleset.GetRuleset(mode).Description; - TooltipSub = $"Play some {Ruleset.GetRuleset(mode).Description}"; - Icon = Ruleset.GetRuleset(mode).Icon; + ruleset = value; + + var rInstance = ruleset.CreateInstance(); + + TooltipMain = rInstance.Description; + TooltipSub = $"Play some {rInstance.Description}"; + Icon = rInstance.Icon; } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index e117089166..209b64e709 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -1,16 +1,17 @@ // 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.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; -using osu.Game.Modes; +using osu.Game.Database; using OpenTK; using OpenTK.Graphics; +using osu.Framework.Configuration; namespace osu.Game.Overlays.Toolbar { @@ -22,7 +23,7 @@ namespace osu.Game.Overlays.Toolbar private readonly Drawable modeButtonLine; private ToolbarModeButton activeButton; - public Action OnPlayModeChange; + private readonly Bindable ruleset = new Bindable(); public ToolbarModeSelector() { @@ -62,33 +63,43 @@ namespace osu.Game.Overlays.Toolbar } } }; + } - foreach (PlayMode m in Ruleset.PlayModes) + [BackgroundDependencyLoader] + private void load(RulesetDatabase rulesets, OsuGame game) + { + foreach (var r in rulesets.AllRulesets) { modeButtons.Add(new ToolbarModeButton { - Mode = m, + Ruleset = r, Action = delegate { - SetGameMode(m); - OnPlayModeChange?.Invoke(m); + ruleset.Value = r; } }); } + + ruleset.ValueChanged += rulesetChanged; + ruleset.DisabledChanged += disabledChanged; + ruleset.BindTo(game.Ruleset); } + public override bool HandleInput => !ruleset.Disabled; + + private void disabledChanged(bool isDisabled) => FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); + protected override void Update() { base.Update(); - Size = new Vector2(modeButtons.DrawSize.X, 1); } - public void SetGameMode(PlayMode mode) + private void rulesetChanged(RulesetInfo ruleset) { foreach (ToolbarModeButton m in modeButtons.Children.Cast()) { - bool isActive = m.Mode == mode; + bool isActive = m.Ruleset.ID == ruleset.ID; m.Active = isActive; if (isActive) activeButton = m; diff --git a/osu.Game/Rulesets/BeatmapStatistic.cs b/osu.Game/Rulesets/BeatmapStatistic.cs new file mode 100644 index 0000000000..11ac698851 --- /dev/null +++ b/osu.Game/Rulesets/BeatmapStatistic.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; + +namespace osu.Game.Rulesets +{ + public class BeatmapStatistic + { + public FontAwesome Icon; + public string Content; + public string Name; + } +} \ No newline at end of file diff --git a/osu.Game/Rulesets/Beatmaps/BeatmapConverter.cs b/osu.Game/Rulesets/Beatmaps/BeatmapConverter.cs new file mode 100644 index 0000000000..07aae6a26e --- /dev/null +++ b/osu.Game/Rulesets/Beatmaps/BeatmapConverter.cs @@ -0,0 +1,90 @@ +// 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 osu.Game.Rulesets.Objects; +using osu.Game.Beatmaps; + +namespace osu.Game.Rulesets.Beatmaps +{ + /// + /// Converts a Beatmap for another mode. + /// + /// The type of HitObject stored in the Beatmap. + public abstract class BeatmapConverter where T : HitObject + { + /// + /// Checks if a Beatmap can be converted using this Beatmap Converter. + /// + /// The Beatmap to check. + /// Whether the Beatmap can be converted using this Beatmap Converter. + public bool CanConvert(Beatmap beatmap) => ValidConversionTypes.All(t => beatmap.HitObjects.Any(t.IsInstanceOfType)); + + /// + /// Converts a Beatmap using this Beatmap Converter. + /// + /// The un-converted Beatmap. + /// The converted Beatmap. + public Beatmap Convert(Beatmap original) + { + // We always operate on a clone of the original beatmap, to not modify it game-wide + return ConvertBeatmap(new Beatmap(original)); + } + + /// + /// Performs the conversion of a Beatmap using this Beatmap Converter. + /// + /// The un-converted Beatmap. + /// The converted Beatmap. + protected virtual Beatmap ConvertBeatmap(Beatmap original) + { + return new Beatmap + { + BeatmapInfo = original.BeatmapInfo, + TimingInfo = original.TimingInfo, + HitObjects = original.HitObjects.SelectMany(h => convert(h, original)).ToList() + }; + } + + /// + /// Converts a hit object. + /// + /// The hit object to convert. + /// The un-converted Beatmap. + /// The converted hit object. + private IEnumerable convert(HitObject original, Beatmap beatmap) + { + // Check if the hitobject is already the converted type + T tObject = original as T; + if (tObject != null) + { + yield return tObject; + yield break; + } + + // Convert the hit object + foreach (var obj in ConvertHitObject(original, beatmap)) + { + if (obj == null) + continue; + + yield return obj; + } + } + + /// + /// The types of HitObjects that can be converted to be used for this Beatmap. + /// + protected abstract IEnumerable ValidConversionTypes { get; } + + /// + /// Performs the conversion of a hit object. + /// + /// The hit object to convert. + /// The un-converted Beatmap. + /// The converted hit object. + protected abstract IEnumerable ConvertHitObject(HitObject original, Beatmap beatmap); + } +} diff --git a/osu.Game/Beatmaps/IBeatmapProcessor.cs b/osu.Game/Rulesets/Beatmaps/BeatmapProcessor.cs similarity index 74% rename from osu.Game/Beatmaps/IBeatmapProcessor.cs rename to osu.Game/Rulesets/Beatmaps/BeatmapProcessor.cs index 9157a760b1..ee9fc30f7b 100644 --- a/osu.Game/Beatmaps/IBeatmapProcessor.cs +++ b/osu.Game/Rulesets/Beatmaps/BeatmapProcessor.cs @@ -1,15 +1,16 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Objects; -namespace osu.Game.Beatmaps +namespace osu.Game.Rulesets.Beatmaps { /// /// Processes a post-converted Beatmap. /// /// The type of HitObject contained in the Beatmap. - public interface IBeatmapProcessor + public class BeatmapProcessor where TObject : HitObject { /// @@ -19,6 +20,6 @@ namespace osu.Game.Beatmaps /// /// /// The Beatmap to process. - void PostProcess(Beatmap beatmap); + public virtual void PostProcess(Beatmap beatmap) { } } } diff --git a/osu.Game/Modes/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs similarity index 94% rename from osu.Game/Modes/Judgements/DrawableJudgement.cs rename to osu.Game/Rulesets/Judgements/DrawableJudgement.cs index eabcb5c161..3a82827497 100644 --- a/osu.Game/Modes/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -9,9 +9,9 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Modes.Objects.Drawables; +using osu.Game.Rulesets.Objects.Drawables; -namespace osu.Game.Modes.Judgements +namespace osu.Game.Rulesets.Judgements { /// /// A drawable object which visualises the hit result of a . diff --git a/osu.Game/Modes/Judgements/IPartialJudgement.cs b/osu.Game/Rulesets/Judgements/IPartialJudgement.cs similarity index 56% rename from osu.Game/Modes/Judgements/IPartialJudgement.cs rename to osu.Game/Rulesets/Judgements/IPartialJudgement.cs index 2ca1ffce4d..38080835e0 100644 --- a/osu.Game/Modes/Judgements/IPartialJudgement.cs +++ b/osu.Game/Rulesets/Judgements/IPartialJudgement.cs @@ -1,22 +1,15 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects.Drawables; -using osu.Game.Modes.Scoring; - -namespace osu.Game.Modes.Judgements +namespace osu.Game.Rulesets.Judgements { /// /// Inidicates that the judgement this is attached to is a partial judgement and the scoring value may change. - /// - /// This judgement will be continually processed by - /// unless the result is a miss and will trigger a full re-process of the when changed. - /// /// public interface IPartialJudgement { /// - /// Indicates that this partial judgement has changed and requires a full re-process of the . + /// Indicates that this partial judgement has changed and requires reprocessing. /// /// This is set to false once the judgement has been re-processed. /// diff --git a/osu.Game/Modes/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs similarity index 88% rename from osu.Game/Modes/Judgements/Judgement.cs rename to osu.Game/Rulesets/Judgements/Judgement.cs index 1bf898d25c..ed33cee5d4 100644 --- a/osu.Game/Modes/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -1,9 +1,9 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects.Drawables; +using osu.Game.Rulesets.Objects.Drawables; -namespace osu.Game.Modes.Judgements +namespace osu.Game.Rulesets.Judgements { public abstract class Judgement { diff --git a/osu.Game/Modes/Mods/IApplicableMod.cs b/osu.Game/Rulesets/Mods/IApplicableMod.cs similarity index 77% rename from osu.Game/Modes/Mods/IApplicableMod.cs rename to osu.Game/Rulesets/Mods/IApplicableMod.cs index 90547f4402..18e1ae4b3d 100644 --- a/osu.Game/Modes/Mods/IApplicableMod.cs +++ b/osu.Game/Rulesets/Mods/IApplicableMod.cs @@ -1,10 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects; -using osu.Game.Modes.UI; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI; -namespace osu.Game.Modes.Mods +namespace osu.Game.Rulesets.Mods { /// /// An interface for mods that are applied to a HitRenderer. @@ -17,6 +17,6 @@ namespace osu.Game.Modes.Mods /// Applies the mod to a HitRenderer. /// /// The HitRenderer to apply the mod to. - void Apply(HitRenderer hitRenderer); + void ApplyToHitRenderer(HitRenderer hitRenderer); } } diff --git a/osu.Game/Rulesets/Mods/IApplicableToClock.cs b/osu.Game/Rulesets/Mods/IApplicableToClock.cs new file mode 100644 index 0000000000..f0502cf346 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IApplicableToClock.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Timing; + +namespace osu.Game.Rulesets.Mods +{ + /// + /// An interface for mods that make adjustments to the track. + /// + public interface IApplicableToClock + { + void ApplyToClock(IAdjustableClock clock); + } +} \ No newline at end of file diff --git a/osu.Game/Rulesets/Mods/Mod.cs b/osu.Game/Rulesets/Mods/Mod.cs new file mode 100644 index 0000000000..a2846c1d2f --- /dev/null +++ b/osu.Game/Rulesets/Mods/Mod.cs @@ -0,0 +1,44 @@ +// 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 System; + +namespace osu.Game.Rulesets.Mods +{ + /// + /// The base class for gameplay modifiers. + /// + public abstract class Mod + { + /// + /// The name of this mod. + /// + public abstract string Name { get; } + + /// + /// The icon of this mod. + /// + public virtual FontAwesome Icon => FontAwesome.fa_question; + + /// + /// The user readable description of this mod. + /// + public virtual string Description => string.Empty; + + /// + /// The score multiplier of this mod. + /// + public abstract double ScoreMultiplier { get; } + + /// + /// Returns if this mod is ranked. + /// + public virtual bool Ranked => false; + + /// + /// The mods this mod cannot be enabled with. + /// + public virtual Type[] IncompatibleMods => new Type[] { }; + } +} diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs new file mode 100644 index 0000000000..1217bf835f --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2017 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.Scoring; +using osu.Game.Rulesets.UI; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModAutoplay : ModAutoplay, IApplicableMod + where T : HitObject + { + protected abstract Score CreateReplayScore(Beatmap beatmap); + + public void ApplyToHitRenderer(HitRenderer hitRenderer) + { + hitRenderer.SetReplay(CreateReplayScore(hitRenderer.Beatmap)?.Replay); + } + } + + public class ModAutoplay : Mod + { + public override string Name => "Autoplay"; + 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) }; + } +} \ No newline at end of file diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs new file mode 100644 index 0000000000..332bd2c5ac --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public class ModCinema : ModAutoplay + { + public override string Name => "Cinema"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_cinema; + } +} \ No newline at end of file diff --git a/osu.Game/Rulesets/Mods/ModDoubleTime.cs b/osu.Game/Rulesets/Mods/ModDoubleTime.cs new file mode 100644 index 0000000000..377a4c2180 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModDoubleTime.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Timing; +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public class ModDoubleTime : Mod, IApplicableToClock + { + public override string Name => "Double Time"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_doubletime; + public override string Description => "Zoooooooooom"; + public override bool Ranked => true; + public override Type[] IncompatibleMods => new[] { typeof(ModHalfTime) }; + + public override double ScoreMultiplier => 1.12; + + public virtual void ApplyToClock(IAdjustableClock clock) + { + 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 new file mode 100644 index 0000000000..bef3f04af3 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModEasy.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModEasy : Mod + { + public override string Name => "Easy"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_easy; + public override string Description => "Reduces overall difficulty - larger circles, more forgiving HP drain, less accuracy required."; + public override double ScoreMultiplier => 0.5; + public override bool Ranked => true; + public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; + } +} \ No newline at end of file diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs new file mode 100644 index 0000000000..63c534dc7d --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModFlashlight : Mod + { + public override string Name => "Flashlight"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_flashlight; + 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 new file mode 100644 index 0000000000..235fc7ad76 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModHalfTime.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Timing; +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModHalfTime : Mod, IApplicableToClock + { + public override string Name => "Half Time"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_halftime; + public override string Description => "Less zoom"; + public override bool Ranked => true; + public override Type[] IncompatibleMods => new[] { typeof(ModDoubleTime) }; + + public override double ScoreMultiplier => 1.12; + + public void ApplyToClock(IAdjustableClock clock) + { + 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 new file mode 100644 index 0000000000..b729b5ae15 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModHardRock.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModHardRock : Mod + { + public override string Name => "Hard Rock"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_hardrock; + public override string Description => "Everything just got a bit harder..."; + public override Type[] IncompatibleMods => new[] { typeof(ModEasy) }; + } +} \ No newline at end of file diff --git a/osu.Game/Rulesets/Mods/ModHidden.cs b/osu.Game/Rulesets/Mods/ModHidden.cs new file mode 100644 index 0000000000..12c788ce54 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModHidden.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModHidden : Mod + { + public override string Name => "Hidden"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden; + 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 new file mode 100644 index 0000000000..d04643fb8b --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModNightcore.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Audio; +using osu.Framework.Timing; +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModNightcore : ModDoubleTime + { + public override string Name => "Nightcore"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_nightcore; + public override string Description => "uguuuuuuuu"; + + public override void ApplyToClock(IAdjustableClock clock) + { + var pitchAdjust = clock as IHasPitchAdjust; + if (pitchAdjust != null) + pitchAdjust.PitchAdjust = 1.5; + else + 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 new file mode 100644 index 0000000000..0c8726bbc1 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModNoFail.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModNoFail : Mod + { + public override string Name => "NoFail"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; + public override string Description => "You can't fail, no matter what."; + public override double ScoreMultiplier => 0.5; + public override bool Ranked => true; + public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModAutoplay) }; + } +} \ No newline at end of file diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs new file mode 100644 index 0000000000..35217c8305 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModPerfect : ModSuddenDeath + { + public override string Name => "Perfect"; + public override string Description => "SS or quit."; + } +} \ No newline at end of file diff --git a/osu.Game/Rulesets/Mods/ModRelax.cs b/osu.Game/Rulesets/Mods/ModRelax.cs new file mode 100644 index 0000000000..5491f8fc58 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModRelax.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModRelax : Mod + { + public override string Name => "Relax"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_relax; + 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 new file mode 100644 index 0000000000..a7dcbbc9ed --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -0,0 +1,18 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Game.Graphics; + +namespace osu.Game.Rulesets.Mods +{ + public abstract class ModSuddenDeath : Mod + { + public override string Name => "Sudden Death"; + public override FontAwesome Icon => FontAwesome.fa_osu_mod_suddendeath; + public override string Description => "Miss a note and fail."; + public override double ScoreMultiplier => 1; + public override bool Ranked => true; + public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; + } +} \ No newline at end of file diff --git a/osu.Game/Modes/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs similarity index 85% rename from osu.Game/Modes/Mods/ModType.cs rename to osu.Game/Rulesets/Mods/ModType.cs index b1d0e781e1..15ffc4ad63 100644 --- a/osu.Game/Modes/Mods/ModType.cs +++ b/osu.Game/Rulesets/Mods/ModType.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Mods +namespace osu.Game.Rulesets.Mods { public enum ModType { diff --git a/osu.Game/Rulesets/Mods/MultiMod.cs b/osu.Game/Rulesets/Mods/MultiMod.cs new file mode 100644 index 0000000000..c5fac250d0 --- /dev/null +++ b/osu.Game/Rulesets/Mods/MultiMod.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mods +{ + public class MultiMod : Mod + { + public override string Name => string.Empty; + public override string Description => string.Empty; + public override double ScoreMultiplier => 0.0; + + public Mod[] Mods; + } +} \ No newline at end of file diff --git a/osu.Game/Modes/Objects/BezierApproximator.cs b/osu.Game/Rulesets/Objects/BezierApproximator.cs similarity index 97% rename from osu.Game/Modes/Objects/BezierApproximator.cs rename to osu.Game/Rulesets/Objects/BezierApproximator.cs index 6688e6b2ce..12be591aab 100644 --- a/osu.Game/Modes/Objects/BezierApproximator.cs +++ b/osu.Game/Rulesets/Objects/BezierApproximator.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using OpenTK; -namespace osu.Game.Modes.Objects +namespace osu.Game.Rulesets.Objects { public class BezierApproximator { diff --git a/osu.Game/Modes/Objects/CircularArcApproximator.cs b/osu.Game/Rulesets/Objects/CircularArcApproximator.cs similarity index 96% rename from osu.Game/Modes/Objects/CircularArcApproximator.cs rename to osu.Game/Rulesets/Objects/CircularArcApproximator.cs index 73db5fab29..642793fa3f 100644 --- a/osu.Game/Modes/Objects/CircularArcApproximator.cs +++ b/osu.Game/Rulesets/Objects/CircularArcApproximator.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using osu.Framework.MathUtils; using OpenTK; -namespace osu.Game.Modes.Objects +namespace osu.Game.Rulesets.Objects { public class CircularArcApproximator { diff --git a/osu.Game/Modes/Objects/CurvedHitObject.cs b/osu.Game/Rulesets/Objects/CurvedHitObject.cs similarity index 91% rename from osu.Game/Modes/Objects/CurvedHitObject.cs rename to osu.Game/Rulesets/Objects/CurvedHitObject.cs index ccb3d2497d..517c276242 100644 --- a/osu.Game/Modes/Objects/CurvedHitObject.cs +++ b/osu.Game/Rulesets/Objects/CurvedHitObject.cs @@ -2,10 +2,10 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; -namespace osu.Game.Modes.Objects +namespace osu.Game.Rulesets.Objects { public class CurvedHitObject : HitObject, IHasCurve { diff --git a/osu.Game/Modes/Objects/Drawables/ArmedState.cs b/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs similarity index 80% rename from osu.Game/Modes/Objects/Drawables/ArmedState.cs rename to osu.Game/Rulesets/Objects/Drawables/ArmedState.cs index 2f8d3ad07a..5e57c57f4d 100644 --- a/osu.Game/Modes/Objects/Drawables/ArmedState.cs +++ b/osu.Game/Rulesets/Objects/Drawables/ArmedState.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Objects.Drawables +namespace osu.Game.Rulesets.Objects.Drawables { public enum ArmedState { diff --git a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs similarity index 94% rename from osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs rename to osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e346a22813..a300eeab31 100644 --- a/osu.Game/Modes/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -7,13 +7,13 @@ using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; -using osu.Game.Modes.Judgements; +using osu.Game.Rulesets.Judgements; using Container = osu.Framework.Graphics.Containers.Container; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; using OpenTK.Graphics; using osu.Game.Audio; -namespace osu.Game.Modes.Objects.Drawables +namespace osu.Game.Rulesets.Objects.Drawables { public abstract class DrawableHitObject : Container, IStateful where TJudgement : Judgement diff --git a/osu.Game/Modes/Objects/Drawables/HitResult.cs b/osu.Game/Rulesets/Objects/Drawables/HitResult.cs similarity index 90% rename from osu.Game/Modes/Objects/Drawables/HitResult.cs rename to osu.Game/Rulesets/Objects/Drawables/HitResult.cs index e036610ae2..7492c0ab96 100644 --- a/osu.Game/Modes/Objects/Drawables/HitResult.cs +++ b/osu.Game/Rulesets/Objects/Drawables/HitResult.cs @@ -3,7 +3,7 @@ using System.ComponentModel; -namespace osu.Game.Modes.Objects.Drawables +namespace osu.Game.Rulesets.Objects.Drawables { public enum HitResult { diff --git a/osu.Game/Modes/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs b/osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs similarity index 83% rename from osu.Game/Modes/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs rename to osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs index 33a1f51414..0314ef3037 100644 --- a/osu.Game/Modes/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs +++ b/osu.Game/Rulesets/Objects/Drawables/IDrawableHitObjectWithProxiedApproach.cs @@ -3,7 +3,7 @@ using osu.Framework.Graphics; -namespace osu.Game.Modes.Objects.Drawables +namespace osu.Game.Rulesets.Objects.Drawables { public interface IDrawableHitObjectWithProxiedApproach { diff --git a/osu.Game/Modes/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs similarity index 95% rename from osu.Game/Modes/Objects/HitObject.cs rename to osu.Game/Rulesets/Objects/HitObject.cs index f362d6de63..240d110976 100644 --- a/osu.Game/Modes/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -6,7 +6,7 @@ using osu.Game.Beatmaps.Timing; using osu.Game.Database; using System.Collections.Generic; -namespace osu.Game.Modes.Objects +namespace osu.Game.Rulesets.Objects { /// /// A HitObject describes an object in a Beatmap. diff --git a/osu.Game/Modes/Objects/HitObjectParser.cs b/osu.Game/Rulesets/Objects/HitObjectParser.cs similarity index 85% rename from osu.Game/Modes/Objects/HitObjectParser.cs rename to osu.Game/Rulesets/Objects/HitObjectParser.cs index 5aa9f08589..ea0b5e0d2e 100644 --- a/osu.Game/Modes/Objects/HitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/HitObjectParser.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Objects +namespace osu.Game.Rulesets.Objects { public abstract class HitObjectParser { diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/Hit.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/Hit.cs new file mode 100644 index 0000000000..41dacd1265 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/Hit.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects.Legacy.Catch +{ + /// + /// Legacy osu!catch Hit-type, used for parsing Beatmaps. + /// + internal sealed class Hit : HitObject, IHasCombo, IHasXPosition + { + public float X { get; set; } + + public bool NewCombo { get; set; } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/HitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/HitObjectParser.cs new file mode 100644 index 0000000000..a27244e5bd --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/HitObjectParser.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Game.Rulesets.Objects.Types; +using System.Collections.Generic; + +namespace osu.Game.Rulesets.Objects.Legacy.Catch +{ + /// + /// A HitObjectParser to parse legacy osu!catch Beatmaps. + /// + internal class HitObjectParser : Legacy.HitObjectParser + { + protected override HitObject CreateHit(Vector2 position, bool newCombo) + { + return new Hit + { + X = position.X, + NewCombo = newCombo, + }; + } + + protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount) + { + return new Slider + { + X = position.X, + NewCombo = newCombo, + ControlPoints = controlPoints, + Distance = length, + CurveType = curveType, + RepeatCount = repeatCount + }; + } + + protected override HitObject CreateSpinner(Vector2 position, double endTime) + { + return new Spinner + { + EndTime = endTime + }; + } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/Slider.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/Slider.cs new file mode 100644 index 0000000000..865e56c847 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/Slider.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects.Legacy.Catch +{ + /// + /// Legacy osu!catch Slider-type, used for parsing Beatmaps. + /// + internal sealed class Slider : CurvedHitObject, IHasXPosition, IHasCombo + { + public float X { get; set; } + + public bool NewCombo { get; set; } + } +} diff --git a/osu.Game/Modes/Objects/Legacy/LegacySpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/Spinner.cs similarity index 57% rename from osu.Game/Modes/Objects/Legacy/LegacySpinner.cs rename to osu.Game/Rulesets/Objects/Legacy/Catch/Spinner.cs index 8f65d5e8a1..7690f42e76 100644 --- a/osu.Game/Modes/Objects/Legacy/LegacySpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/Spinner.cs @@ -1,14 +1,14 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; -namespace osu.Game.Modes.Objects.Legacy +namespace osu.Game.Rulesets.Objects.Legacy.Catch { /// - /// Legacy Spinner-type, used for parsing Beatmaps. + /// Legacy osu!catch Spinner-type, used for parsing Beatmaps. /// - internal class LegacySpinner : HitObject, IHasEndTime + internal sealed class Spinner : HitObject, IHasEndTime { public double EndTime { get; set; } diff --git a/osu.Game/Modes/Objects/LegacyHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/HitObjectParser.cs similarity index 64% rename from osu.Game/Modes/Objects/LegacyHitObjectParser.cs rename to osu.Game/Rulesets/Objects/Legacy/HitObjectParser.cs index 2316e5dc5d..c915e67ead 100644 --- a/osu.Game/Modes/Objects/LegacyHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/HitObjectParser.cs @@ -2,24 +2,26 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; using System; using System.Collections.Generic; using System.Globalization; -using osu.Game.Modes.Objects.Legacy; using osu.Game.Beatmaps.Formats; using osu.Game.Audio; -namespace osu.Game.Modes.Objects +namespace osu.Game.Rulesets.Objects.Legacy { - internal class LegacyHitObjectParser : HitObjectParser + /// + /// A HitObjectParser to parse legacy Beatmaps. + /// + internal abstract class HitObjectParser : Objects.HitObjectParser { public override HitObject Parse(string text) { string[] split = text.Split(','); - var type = (LegacyHitObjectType)int.Parse(split[3]) & ~LegacyHitObjectType.ColourHax; - bool combo = type.HasFlag(LegacyHitObjectType.NewCombo); - type &= ~LegacyHitObjectType.NewCombo; + var type = (HitObjectType)int.Parse(split[3]) & ~HitObjectType.ColourHax; + bool combo = type.HasFlag(HitObjectType.NewCombo); + type &= ~HitObjectType.NewCombo; int sampleVolume = 0; string normalSampleBank = null; @@ -27,22 +29,18 @@ namespace osu.Game.Modes.Objects HitObject result; - if ((type & LegacyHitObjectType.Circle) > 0) + if ((type & HitObjectType.Circle) > 0) { - result = new LegacyHit - { - Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])), - NewCombo = combo - }; + result = CreateHit(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo); if (split.Length > 5) readCustomSampleBanks(split[5], ref normalSampleBank, ref addSampleBank, ref sampleVolume); } - else if ((type & LegacyHitObjectType.Slider) > 0) + else if ((type & HitObjectType.Slider) > 0) { CurveType curveType = CurveType.Catmull; double length = 0; - List points = new List { new Vector2(int.Parse(split[0]), int.Parse(split[1])) }; + var points = new List { new Vector2(int.Parse(split[0]), int.Parse(split[1])) }; string[] pointsplit = split[5].Split('|'); foreach (string t in pointsplit) @@ -68,11 +66,7 @@ namespace osu.Game.Modes.Objects } string[] temp = t.Split(':'); - Vector2 v = new Vector2( - (int)Convert.ToDouble(temp[0], CultureInfo.InvariantCulture), - (int)Convert.ToDouble(temp[1], CultureInfo.InvariantCulture) - ); - points.Add(v); + points.Add(new Vector2((int)Convert.ToDouble(temp[0], CultureInfo.InvariantCulture), (int)Convert.ToDouble(temp[1], CultureInfo.InvariantCulture))); } int repeatCount = Convert.ToInt32(split[6], CultureInfo.InvariantCulture); @@ -83,37 +77,26 @@ namespace osu.Game.Modes.Objects if (split.Length > 7) length = Convert.ToDouble(split[7], CultureInfo.InvariantCulture); - result = new LegacySlider - { - ControlPoints = points, - Distance = length, - CurveType = curveType, - RepeatCount = repeatCount, - Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])), - NewCombo = combo - }; + result = CreateSlider(new Vector2(int.Parse(split[0]), int.Parse(split[1])), combo, points, length, curveType, repeatCount); if (split.Length > 10) readCustomSampleBanks(split[10], ref normalSampleBank, ref addSampleBank, ref sampleVolume); } - else if ((type & LegacyHitObjectType.Spinner) > 0) + else if ((type & HitObjectType.Spinner) > 0) { - result = new LegacySpinner - { - EndTime = Convert.ToDouble(split[5], CultureInfo.InvariantCulture) - }; + result = CreateSpinner(new Vector2(512, 384) / 2, Convert.ToDouble(split[5], CultureInfo.InvariantCulture)); if (split.Length > 6) readCustomSampleBanks(split[6], ref normalSampleBank, ref addSampleBank, ref sampleVolume); } - else if ((type & LegacyHitObjectType.Hold) > 0) + else if ((type & HitObjectType.Hold) > 0) { // Note: Hold is generated by BMS converts // Todo: Apparently end time is determined by samples?? // Shouldn't need implementation until mania - result = new LegacyHold + result = new Hold { Position = new Vector2(int.Parse(split[0]), int.Parse(split[1])), NewCombo = combo @@ -191,6 +174,34 @@ namespace osu.Game.Modes.Objects sampleVolume = split.Length > 3 ? int.Parse(split[3]) : 0; } + /// + /// Creates a legacy Hit-type hit object. + /// + /// The position of the hit object. + /// Whether the hit object creates a new combo. + /// The hit object. + protected abstract HitObject CreateHit(Vector2 position, bool newCombo); + + /// + /// Creats a legacy Slider-type hit object. + /// + /// The position of the hit object. + /// Whether the hit object creates a new combo. + /// The slider control points. + /// The slider length. + /// The slider curve type. + /// The slider repeat count. + /// The hit object. + protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount); + + /// + /// Creates a legacy Spinner-type hit object. + /// + /// The position of the hit object. + /// The spinner end time. + /// The hit object. + protected abstract HitObject CreateSpinner(Vector2 position, double endTime); + [Flags] private enum LegacySoundType { diff --git a/osu.Game/Modes/Objects/Legacy/LegacyHitObjectType.cs b/osu.Game/Rulesets/Objects/Legacy/HitObjectType.cs similarity index 78% rename from osu.Game/Modes/Objects/Legacy/LegacyHitObjectType.cs rename to osu.Game/Rulesets/Objects/Legacy/HitObjectType.cs index 416e1abe76..9111e6bd12 100644 --- a/osu.Game/Modes/Objects/Legacy/LegacyHitObjectType.cs +++ b/osu.Game/Rulesets/Objects/Legacy/HitObjectType.cs @@ -3,10 +3,10 @@ using System; -namespace osu.Game.Modes.Objects.Legacy +namespace osu.Game.Rulesets.Objects.Legacy { [Flags] - public enum LegacyHitObjectType + public enum HitObjectType { Circle = 1 << 0, Slider = 1 << 1, diff --git a/osu.Game/Modes/Objects/Legacy/LegacyHold.cs b/osu.Game/Rulesets/Objects/Legacy/Hold.cs similarity index 59% rename from osu.Game/Modes/Objects/Legacy/LegacyHold.cs rename to osu.Game/Rulesets/Objects/Legacy/Hold.cs index 4f858c16f1..a0a741e8e7 100644 --- a/osu.Game/Modes/Objects/Legacy/LegacyHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Hold.cs @@ -2,17 +2,21 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; -namespace osu.Game.Modes.Objects.Legacy +namespace osu.Game.Rulesets.Objects.Legacy { /// /// Legacy Hold-type, used for parsing "specials" in beatmaps. /// - public sealed class LegacyHold : HitObject, IHasPosition, IHasCombo, IHasHold + internal sealed class Hold : HitObject, IHasPosition, IHasCombo, IHasHold { public Vector2 Position { get; set; } + public float X => Position.X; + + public float Y => Position.Y; + public bool NewCombo { get; set; } } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/Hit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/Hit.cs new file mode 100644 index 0000000000..8e407fcf92 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/Hit.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects.Legacy.Mania +{ + /// + /// Legacy osu!mania Hit-type, used for parsing Beatmaps. + /// + internal sealed class Hit : HitObject, IHasXPosition, IHasCombo + { + public float X { get; set; } + + public bool NewCombo { get; set; } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/HitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/HitObjectParser.cs new file mode 100644 index 0000000000..98f0459e0a --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/HitObjectParser.cs @@ -0,0 +1,46 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Game.Rulesets.Objects.Types; +using System.Collections.Generic; + +namespace osu.Game.Rulesets.Objects.Legacy.Mania +{ + /// + /// A HitObjectParser to parse legacy osu!mania Beatmaps. + /// + internal class HitObjectParser : Legacy.HitObjectParser + { + protected override HitObject CreateHit(Vector2 position, bool newCombo) + { + return new Hit + { + X = position.X, + NewCombo = newCombo, + }; + } + + protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount) + { + return new Slider + { + X = position.X, + NewCombo = newCombo, + ControlPoints = controlPoints, + Distance = length, + CurveType = curveType, + RepeatCount = repeatCount + }; + } + + protected override HitObject CreateSpinner(Vector2 position, double endTime) + { + return new Spinner + { + X = position.X, + EndTime = endTime + }; + } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/Slider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/Slider.cs new file mode 100644 index 0000000000..c884ed324b --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/Slider.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects.Legacy.Mania +{ + /// + /// Legacy osu!mania Slider-type, used for parsing Beatmaps. + /// + internal sealed class Slider : CurvedHitObject, IHasXPosition, IHasCombo + { + public float X { get; set; } + + public bool NewCombo { get; set; } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/Spinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/Spinner.cs new file mode 100644 index 0000000000..3937eb003e --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/Spinner.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects.Legacy.Mania +{ + /// + /// Legacy osu!mania Spinner-type, used for parsing Beatmaps. + /// + internal sealed class Spinner : HitObject, IHasEndTime, IHasXPosition + { + public double EndTime { get; set; } + + public double Duration => EndTime - StartTime; + + public float X { get; set; } + } +} diff --git a/osu.Game/Modes/Objects/Legacy/LegacySlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/Hit.cs similarity index 50% rename from osu.Game/Modes/Objects/Legacy/LegacySlider.cs rename to osu.Game/Rulesets/Objects/Legacy/Osu/Hit.cs index bdfebb1983..a30ba9b265 100644 --- a/osu.Game/Modes/Objects/Legacy/LegacySlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/Hit.cs @@ -1,18 +1,22 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; using OpenTK; -namespace osu.Game.Modes.Objects.Legacy +namespace osu.Game.Rulesets.Objects.Legacy.Osu { /// - /// Legacy Slider-type, used for parsing Beatmaps. + /// Legacy osu! Hit-type, used for parsing Beatmaps. /// - public sealed class LegacySlider : CurvedHitObject, IHasPosition, IHasCombo + internal sealed class Hit : HitObject, IHasPosition, IHasCombo { public Vector2 Position { get; set; } + public float X => Position.X; + + public float Y => Position.Y; + public bool NewCombo { get; set; } } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/HitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/HitObjectParser.cs new file mode 100644 index 0000000000..227a4412c4 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/HitObjectParser.cs @@ -0,0 +1,46 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Game.Rulesets.Objects.Types; +using System.Collections.Generic; + +namespace osu.Game.Rulesets.Objects.Legacy.Osu +{ + /// + /// A HitObjectParser to parse legacy osu! Beatmaps. + /// + internal class HitObjectParser : Legacy.HitObjectParser + { + protected override HitObject CreateHit(Vector2 position, bool newCombo) + { + return new Hit + { + Position = position, + NewCombo = newCombo, + }; + } + + protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount) + { + return new Slider + { + Position = position, + NewCombo = newCombo, + ControlPoints = controlPoints, + Distance = length, + CurveType = curveType, + RepeatCount = repeatCount + }; + } + + protected override HitObject CreateSpinner(Vector2 position, double endTime) + { + return new Spinner + { + Position = position, + EndTime = endTime + }; + } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/Slider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/Slider.cs new file mode 100644 index 0000000000..7d90c6d41e --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/Slider.cs @@ -0,0 +1,22 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; +using OpenTK; + +namespace osu.Game.Rulesets.Objects.Legacy.Osu +{ + /// + /// Legacy osu! Slider-type, used for parsing Beatmaps. + /// + internal sealed class Slider : CurvedHitObject, IHasPosition, IHasCombo + { + public Vector2 Position { get; set; } + + public float X => Position.X; + + public float Y => Position.Y; + + public bool NewCombo { get; set; } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/Spinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/Spinner.cs new file mode 100644 index 0000000000..ad3f9637a7 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/Spinner.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; +using OpenTK; + +namespace osu.Game.Rulesets.Objects.Legacy.Osu +{ + /// + /// Legacy osu! Spinner-type, used for parsing Beatmaps. + /// + internal sealed class Spinner : HitObject, IHasEndTime, IHasPosition + { + public double EndTime { get; set; } + + public double Duration => EndTime - StartTime; + + public Vector2 Position { get; set; } + + public float X => Position.X; + + public float Y => Position.Y; + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/Hit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/Hit.cs new file mode 100644 index 0000000000..0a9a8ac64c --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/Hit.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects.Legacy.Taiko +{ + /// + /// Legacy osu!taiko Hit-type, used for parsing Beatmaps. + /// + internal sealed class Hit : HitObject, IHasCombo + { + public bool NewCombo { get; set; } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/HitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/HitObjectParser.cs new file mode 100644 index 0000000000..669ee34910 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/HitObjectParser.cs @@ -0,0 +1,43 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Game.Rulesets.Objects.Types; +using System.Collections.Generic; + +namespace osu.Game.Rulesets.Objects.Legacy.Taiko +{ + /// + /// A HitObjectParser to parse legacy osu!taiko Beatmaps. + /// + internal class HitObjectParser : Legacy.HitObjectParser + { + protected override HitObject CreateHit(Vector2 position, bool newCombo) + { + return new Hit + { + NewCombo = newCombo, + }; + } + + protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount) + { + return new Slider + { + NewCombo = newCombo, + ControlPoints = controlPoints, + Distance = length, + CurveType = curveType, + RepeatCount = repeatCount + }; + } + + protected override HitObject CreateSpinner(Vector2 position, double endTime) + { + return new Spinner + { + EndTime = endTime + }; + } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/Slider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/Slider.cs new file mode 100644 index 0000000000..18d2d4039d --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/Slider.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects.Legacy.Taiko +{ + /// + /// Legacy osu!taiko Slider-type, used for parsing Beatmaps. + /// + internal sealed class Slider : CurvedHitObject, IHasCombo + { + public bool NewCombo { get; set; } + } +} diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/Spinner.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/Spinner.cs new file mode 100644 index 0000000000..1b296b9533 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/Spinner.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects.Legacy.Taiko +{ + /// + /// Legacy osu!taiko Spinner-type, used for parsing Beatmaps. + /// + internal sealed class Spinner : HitObject, IHasEndTime + { + public double EndTime { get; set; } + + public double Duration => EndTime - StartTime; + } +} diff --git a/osu.Game/Modes/Objects/SliderCurve.cs b/osu.Game/Rulesets/Objects/SliderCurve.cs similarity index 96% rename from osu.Game/Modes/Objects/SliderCurve.cs rename to osu.Game/Rulesets/Objects/SliderCurve.cs index 642a65af21..8bf85e498c 100644 --- a/osu.Game/Modes/Objects/SliderCurve.cs +++ b/osu.Game/Rulesets/Objects/SliderCurve.cs @@ -4,10 +4,10 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.MathUtils; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects.Types; using OpenTK; -namespace osu.Game.Modes.Objects +namespace osu.Game.Rulesets.Objects { public class SliderCurve { diff --git a/osu.Game/Modes/Objects/Types/CurveType.cs b/osu.Game/Rulesets/Objects/Types/CurveType.cs similarity index 82% rename from osu.Game/Modes/Objects/Types/CurveType.cs rename to osu.Game/Rulesets/Objects/Types/CurveType.cs index ba5d3f37ac..18db712a65 100644 --- a/osu.Game/Modes/Objects/Types/CurveType.cs +++ b/osu.Game/Rulesets/Objects/Types/CurveType.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Objects.Types +namespace osu.Game.Rulesets.Objects.Types { public enum CurveType { diff --git a/osu.Game/Modes/Objects/Types/IHasCombo.cs b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs similarity index 87% rename from osu.Game/Modes/Objects/Types/IHasCombo.cs rename to osu.Game/Rulesets/Objects/Types/IHasCombo.cs index 1ca381372d..f053fdcf49 100644 --- a/osu.Game/Modes/Objects/Types/IHasCombo.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasCombo.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Objects.Types +namespace osu.Game.Rulesets.Objects.Types { /// /// A HitObject that is part of a combo. diff --git a/osu.Game/Modes/Objects/Types/IHasCurve.cs b/osu.Game/Rulesets/Objects/Types/IHasCurve.cs similarity index 95% rename from osu.Game/Modes/Objects/Types/IHasCurve.cs rename to osu.Game/Rulesets/Objects/Types/IHasCurve.cs index 0db799a15f..5ff6d03f6d 100644 --- a/osu.Game/Modes/Objects/Types/IHasCurve.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasCurve.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using OpenTK; -namespace osu.Game.Modes.Objects.Types +namespace osu.Game.Rulesets.Objects.Types { /// /// A HitObject that has a curve. diff --git a/osu.Game/Modes/Objects/Types/IHasDistance.cs b/osu.Game/Rulesets/Objects/Types/IHasDistance.cs similarity index 88% rename from osu.Game/Modes/Objects/Types/IHasDistance.cs rename to osu.Game/Rulesets/Objects/Types/IHasDistance.cs index 87863e64e6..a5e487a0ba 100644 --- a/osu.Game/Modes/Objects/Types/IHasDistance.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasDistance.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Objects.Types +namespace osu.Game.Rulesets.Objects.Types { /// /// A HitObject that has a positional length. diff --git a/osu.Game/Modes/Objects/Types/IHasEndTime.cs b/osu.Game/Rulesets/Objects/Types/IHasEndTime.cs similarity index 89% rename from osu.Game/Modes/Objects/Types/IHasEndTime.cs rename to osu.Game/Rulesets/Objects/Types/IHasEndTime.cs index e96258812c..ac30afe5fb 100644 --- a/osu.Game/Modes/Objects/Types/IHasEndTime.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasEndTime.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Objects.Types +namespace osu.Game.Rulesets.Objects.Types { /// /// A HitObject that ends at a different time than its start time. diff --git a/osu.Game/Modes/Objects/Types/IHasHold.cs b/osu.Game/Rulesets/Objects/Types/IHasHold.cs similarity index 85% rename from osu.Game/Modes/Objects/Types/IHasHold.cs rename to osu.Game/Rulesets/Objects/Types/IHasHold.cs index b9f4939091..82ec790524 100644 --- a/osu.Game/Modes/Objects/Types/IHasHold.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasHold.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Objects.Types +namespace osu.Game.Rulesets.Objects.Types { /// /// A special type of HitObject, mostly used for legacy conversion of "holds". diff --git a/osu.Game/Modes/Objects/Types/IHasPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasPosition.cs similarity index 76% rename from osu.Game/Modes/Objects/Types/IHasPosition.cs rename to osu.Game/Rulesets/Objects/Types/IHasPosition.cs index 8138bf6662..6eca86656d 100644 --- a/osu.Game/Modes/Objects/Types/IHasPosition.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasPosition.cs @@ -3,12 +3,12 @@ using OpenTK; -namespace osu.Game.Modes.Objects.Types +namespace osu.Game.Rulesets.Objects.Types { /// /// A HitObject that has a starting position. /// - public interface IHasPosition + public interface IHasPosition : IHasXPosition, IHasYPosition { /// /// The starting position of the HitObject. diff --git a/osu.Game/Modes/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs similarity index 88% rename from osu.Game/Modes/Objects/Types/IHasRepeats.cs rename to osu.Game/Rulesets/Objects/Types/IHasRepeats.cs index a34774d0ef..f7058fd3c9 100644 --- a/osu.Game/Modes/Objects/Types/IHasRepeats.cs +++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -namespace osu.Game.Modes.Objects.Types +namespace osu.Game.Rulesets.Objects.Types { /// /// A HitObject that spans some length. diff --git a/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs new file mode 100644 index 0000000000..b0ad3af7d2 --- /dev/null +++ b/osu.Game/Rulesets/Objects/Types/IHasXPosition.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + + +namespace osu.Game.Rulesets.Objects.Types +{ + /// + /// A HitObject that has a starting X-position. + /// + public interface IHasXPosition + { + /// + /// The starting X-position of this HitObject. + /// + float X { get; } + } +} diff --git a/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs b/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs new file mode 100644 index 0000000000..222e8f762f --- /dev/null +++ b/osu.Game/Rulesets/Objects/Types/IHasYPosition.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + + +namespace osu.Game.Rulesets.Objects.Types +{ + /// + /// A HitObject that has a starting Y-position. + /// + public interface IHasYPosition + { + /// + /// The starting Y-position of this HitObject. + /// + float Y { get; } + } +} diff --git a/osu.Game/Modes/Replays/FramedReplayInputHandler.cs b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs similarity index 96% rename from osu.Game/Modes/Replays/FramedReplayInputHandler.cs rename to osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs index 0c1e140ce4..60da35fd91 100644 --- a/osu.Game/Modes/Replays/FramedReplayInputHandler.cs +++ b/osu.Game/Rulesets/Replays/FramedReplayInputHandler.cs @@ -12,7 +12,7 @@ using OpenTK.Input; using KeyboardState = osu.Framework.Input.KeyboardState; using MouseState = osu.Framework.Input.MouseState; -namespace osu.Game.Modes.Replays +namespace osu.Game.Rulesets.Replays { /// /// The ReplayHandler will take a replay and handle the propagation of updates to the input stack. diff --git a/osu.Game/Modes/Replays/Replay.cs b/osu.Game/Rulesets/Replays/Replay.cs similarity index 65% rename from osu.Game/Modes/Replays/Replay.cs rename to osu.Game/Rulesets/Replays/Replay.cs index 62f60358e0..36e1b24e73 100644 --- a/osu.Game/Modes/Replays/Replay.cs +++ b/osu.Game/Rulesets/Replays/Replay.cs @@ -2,11 +2,16 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Game.Users; -namespace osu.Game.Modes.Replays +namespace osu.Game.Rulesets.Replays { public class Replay { + protected const double KEY_UP_DELAY = 50; + + public User User; + public List Frames = new List(); } -} \ No newline at end of file +} diff --git a/osu.Game/Modes/Replays/ReplayButtonState.cs b/osu.Game/Rulesets/Replays/ReplayButtonState.cs similarity index 86% rename from osu.Game/Modes/Replays/ReplayButtonState.cs rename to osu.Game/Rulesets/Replays/ReplayButtonState.cs index d49139226c..be55a153cb 100644 --- a/osu.Game/Modes/Replays/ReplayButtonState.cs +++ b/osu.Game/Rulesets/Replays/ReplayButtonState.cs @@ -3,7 +3,7 @@ using System; -namespace osu.Game.Modes.Replays +namespace osu.Game.Rulesets.Replays { [Flags] public enum ReplayButtonState diff --git a/osu.Game/Modes/Replays/ReplayFrame.cs b/osu.Game/Rulesets/Replays/ReplayFrame.cs similarity index 78% rename from osu.Game/Modes/Replays/ReplayFrame.cs rename to osu.Game/Rulesets/Replays/ReplayFrame.cs index 4cd681beaf..b0f62e5271 100644 --- a/osu.Game/Modes/Replays/ReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/ReplayFrame.cs @@ -3,16 +3,16 @@ using OpenTK; -namespace osu.Game.Modes.Replays +namespace osu.Game.Rulesets.Replays { public class ReplayFrame { - public Vector2 Position => new Vector2(MouseX, MouseY); + public Vector2 Position => new Vector2(MouseX ?? 0, MouseY ?? 0); - public bool IsImportant => MouseLeft || MouseRight; + public bool IsImportant => MouseX.HasValue && MouseY.HasValue && (MouseLeft || MouseRight); - public float MouseX; - public float MouseY; + public float? MouseX; + public float? MouseY; public bool MouseLeft => MouseLeft1 || MouseLeft2; public bool MouseRight => MouseRight1 || MouseRight2; @@ -55,10 +55,10 @@ namespace osu.Game.Modes.Replays } - public ReplayFrame(double time, float posX, float posY, ReplayButtonState buttonState) + public ReplayFrame(double time, float? mouseX, float? mouseY, ReplayButtonState buttonState) { - MouseX = posX; - MouseY = posY; + MouseX = mouseX; + MouseY = mouseY; ButtonState = buttonState; Time = time; } diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs new file mode 100644 index 0000000000..ea35e61b36 --- /dev/null +++ b/osu.Game/Rulesets/Ruleset.cs @@ -0,0 +1,43 @@ +// 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.Mods; +using osu.Game.Rulesets.UI; +using osu.Game.Screens.Play; +using System.Collections.Generic; +using osu.Game.Rulesets.Scoring; + +namespace osu.Game.Rulesets +{ + public abstract class Ruleset + { + public virtual IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { }; + + public abstract IEnumerable GetModsFor(ModType type); + + /// + /// Attempt to create a HitRenderer for the provided beatmap. + /// + /// + /// Unable to successfully load the beatmap to be usable with this ruleset. + /// + public abstract HitRenderer CreateHitRendererWith(WorkingBeatmap beatmap); + + public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap); + + public abstract ScoreProcessor CreateScoreProcessor(); + + public virtual FontAwesome Icon => FontAwesome.fa_question_circle; + + public abstract string Description { get; } + + public abstract IEnumerable CreateGameplayKeys(); + + /// + /// Do not override this unless you are a legacy mode. + /// + public virtual int LegacyID => -1; + } +} diff --git a/osu.Game/Rulesets/Scoring/Score.cs b/osu.Game/Rulesets/Scoring/Score.cs new file mode 100644 index 0000000000..15d8690322 --- /dev/null +++ b/osu.Game/Rulesets/Scoring/Score.cs @@ -0,0 +1,84 @@ +// 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 Newtonsoft.Json; +using osu.Game.Database; +using osu.Game.Rulesets.Mods; +using osu.Game.Users; +using osu.Game.Rulesets.Replays; + +namespace osu.Game.Rulesets.Scoring +{ + public class Score + { + public ScoreRank Rank { get; set; } + + [JsonProperty(@"score")] + public double TotalScore { get; set; } + + public double Accuracy { get; set; } + + public double Health { get; set; } = 1; + + [JsonProperty(@"max_combo")] + public int MaxCombo { get; set; } + + public int Combo { get; set; } + + [JsonProperty(@"mods")] + protected string[] ModStrings { get; set; } //todo: parse to Mod objects + + public RulesetInfo Ruleset { get; set; } + + public Mod[] Mods { get; set; } + + [JsonProperty(@"user")] + public User User; + + [JsonProperty(@"replay_data")] + public Replay Replay; + + public BeatmapInfo Beatmap; + + [JsonProperty(@"score_id")] + public long OnlineScoreID; + + [JsonProperty(@"created_at")] + public DateTime Date; + + [JsonProperty(@"statistics")] + private Dictionary jsonStats + { + set + { + foreach (var kvp in value) + { + string key = kvp.Key; + switch (key) + { + case @"count_300": + key = @"300"; + break; + case @"count_100": + key = @"100"; + break; + case @"count_50": + key = @"50"; + break; + case @"count_miss": + key = @"x"; + break; + default: + continue; + } + + Statistics.Add(key, kvp.Value); + } + } + } + + public Dictionary Statistics = new Dictionary(); + } +} diff --git a/osu.Game/Modes/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs similarity index 75% rename from osu.Game/Modes/Scoring/ScoreProcessor.cs rename to osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ba845b84dc..11c1c273e2 100644 --- a/osu.Game/Modes/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -5,12 +5,12 @@ using System; using System.Collections.Generic; using osu.Framework.Configuration; using osu.Game.Beatmaps; -using osu.Game.Modes.Judgements; -using osu.Game.Modes.Objects; -using osu.Game.Modes.UI; -using osu.Game.Modes.Objects.Drawables; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.UI; +using osu.Game.Rulesets.Objects.Drawables; -namespace osu.Game.Modes.Scoring +namespace osu.Game.Rulesets.Scoring { public abstract class ScoreProcessor { @@ -19,6 +19,11 @@ namespace osu.Game.Modes.Scoring /// public event Action Failed; + /// + /// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by the . + /// + public event Action NewJudgement; + /// /// The current total score. /// @@ -61,18 +66,20 @@ namespace osu.Game.Modes.Scoring Reset(); } - /// - /// Creates a Score applicable to the game mode in which this ScoreProcessor resides. - /// - /// The Score. - public virtual Score CreateScore() => new Score + private ScoreRank rankFrom(double acc) { - TotalScore = TotalScore, - Combo = Combo, - MaxCombo = HighestCombo, - Accuracy = Accuracy, - Health = Health, - }; + if (acc == 1) + return ScoreRank.X; + if (acc > 0.95) + return ScoreRank.S; + if (acc > 0.9) + return ScoreRank.A; + if (acc > 0.8) + return ScoreRank.B; + if (acc > 0.7) + return ScoreRank.C; + return ScoreRank.D; + } /// /// Resets this ScoreProcessor to a default state. @@ -102,6 +109,29 @@ namespace osu.Game.Modes.Scoring alreadyFailed = true; Failed?.Invoke(); } + + /// + /// Notifies subscribers of that a new judgement has occurred. + /// + /// The judgement to notify subscribers of. + protected void NotifyNewJudgement(Judgement judgement) + { + NewJudgement?.Invoke(judgement); + } + + /// + /// Retrieve a score populated with data for the current play this processor is responsible for. + /// + public virtual void PopulateScore(Score score) + { + score.TotalScore = TotalScore; + score.Combo = Combo; + score.MaxCombo = HighestCombo; + score.Accuracy = Accuracy; + score.Rank = rankFrom(Accuracy); + score.Date = DateTime.Now; + score.Health = Health; + } } public abstract class ScoreProcessor : ScoreProcessor @@ -161,6 +191,8 @@ namespace osu.Game.Modes.Scoring Judgements.Add(judgement); OnNewJudgement(judgement); + + NotifyNewJudgement(judgement); } else OnJudgementChanged(judgement); @@ -193,4 +225,4 @@ namespace osu.Game.Modes.Scoring /// The judgement that triggered this calculation. protected virtual void OnJudgementChanged(TJudgement judgement) { } } -} \ No newline at end of file +} diff --git a/osu.Game/Modes/Scoring/ScoreRank.cs b/osu.Game/Rulesets/Scoring/ScoreRank.cs similarity index 90% rename from osu.Game/Modes/Scoring/ScoreRank.cs rename to osu.Game/Rulesets/Scoring/ScoreRank.cs index 743f24ecd6..f4a6a1e03c 100644 --- a/osu.Game/Modes/Scoring/ScoreRank.cs +++ b/osu.Game/Rulesets/Scoring/ScoreRank.cs @@ -3,7 +3,7 @@ using System.ComponentModel; -namespace osu.Game.Modes.Scoring +namespace osu.Game.Rulesets.Scoring { public enum ScoreRank { diff --git a/osu.Game/Modes/UI/ComboCounter.cs b/osu.Game/Rulesets/UI/ComboCounter.cs similarity index 96% rename from osu.Game/Modes/UI/ComboCounter.cs rename to osu.Game/Rulesets/UI/ComboCounter.cs index 8c0327fa04..d21059cbdb 100644 --- a/osu.Game/Modes/UI/ComboCounter.cs +++ b/osu.Game/Rulesets/UI/ComboCounter.cs @@ -10,7 +10,7 @@ using osu.Framework.Graphics.Transforms; using osu.Framework.MathUtils; using osu.Game.Graphics.Sprites; -namespace osu.Game.Modes.UI +namespace osu.Game.Rulesets.UI { public abstract class ComboCounter : Container { diff --git a/osu.Game/Modes/UI/ComboResultCounter.cs b/osu.Game/Rulesets/UI/ComboResultCounter.cs similarity index 95% rename from osu.Game/Modes/UI/ComboResultCounter.cs rename to osu.Game/Rulesets/UI/ComboResultCounter.cs index 63009c5351..4b19b2c1ff 100644 --- a/osu.Game/Modes/UI/ComboResultCounter.cs +++ b/osu.Game/Rulesets/UI/ComboResultCounter.cs @@ -7,7 +7,7 @@ using osu.Framework.MathUtils; using osu.Game.Graphics.UserInterface; using System; -namespace osu.Game.Modes.UI +namespace osu.Game.Rulesets.UI { /// /// Used to display combo with a roll-up animation in results screen. diff --git a/osu.Game/Modes/UI/HealthDisplay.cs b/osu.Game/Rulesets/UI/HealthDisplay.cs similarity index 91% rename from osu.Game/Modes/UI/HealthDisplay.cs rename to osu.Game/Rulesets/UI/HealthDisplay.cs index 4c8d7e4ab8..5c6b9d2fe3 100644 --- a/osu.Game/Modes/UI/HealthDisplay.cs +++ b/osu.Game/Rulesets/UI/HealthDisplay.cs @@ -4,7 +4,7 @@ using osu.Framework.Configuration; using osu.Framework.Graphics.Containers; -namespace osu.Game.Modes.UI +namespace osu.Game.Rulesets.UI { public abstract class HealthDisplay : Container { diff --git a/osu.Game/Modes/UI/HitRenderer.cs b/osu.Game/Rulesets/UI/HitRenderer.cs similarity index 84% rename from osu.Game/Modes/UI/HitRenderer.cs rename to osu.Game/Rulesets/UI/HitRenderer.cs index 6962c80d87..a3a806b6a7 100644 --- a/osu.Game/Modes/UI/HitRenderer.cs +++ b/osu.Game/Rulesets/UI/HitRenderer.cs @@ -5,20 +5,21 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; -using osu.Game.Modes.Judgements; -using osu.Game.Modes.Mods; -using osu.Game.Modes.Objects; -using osu.Game.Modes.Objects.Drawables; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Screens.Play; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using osu.Game.Modes.Replays; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Scoring; using OpenTK; +using osu.Game.Rulesets.Beatmaps; -namespace osu.Game.Modes.UI +namespace osu.Game.Rulesets.UI { /// /// Base HitRenderer. Doesn't hold objects. @@ -90,11 +91,17 @@ namespace osu.Game.Modes.UI protected virtual FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new FramedReplayInputHandler(replay); + public Replay Replay { get; private set; } + /// /// Sets a replay to be used, overriding local input. /// /// The replay, null for local input. - public void SetReplay(Replay replay) => InputManager.ReplayInputHandler = replay != null ? CreateReplayInputHandler(replay) : null; + public void SetReplay(Replay replay) + { + Replay = replay; + InputManager.ReplayInputHandler = replay != null ? CreateReplayInputHandler(replay) : null; + } } /// @@ -119,8 +126,12 @@ namespace osu.Game.Modes.UI RelativeSizeAxes = Axes.Both; - IBeatmapConverter converter = CreateBeatmapConverter(); - IBeatmapProcessor processor = CreateBeatmapProcessor(); + BeatmapConverter converter = CreateBeatmapConverter(); + BeatmapProcessor processor = CreateBeatmapProcessor(); + + // Check if the beatmap can be converted + if (!converter.CanConvert(beatmap.Beatmap)) + throw new BeatmapInvalidForRulesetException($"{nameof(Beatmap)} can't be converted for the current ruleset."); // Convert the beatmap Beatmap = converter.Convert(beatmap.Beatmap); @@ -136,7 +147,6 @@ namespace osu.Game.Modes.UI applyMods(beatmap.Mods.Value); } - /// /// Applies the active mods to this HitRenderer. /// @@ -147,21 +157,21 @@ namespace osu.Game.Modes.UI return; foreach (var mod in mods.OfType>()) - mod.Apply(this); + mod.ApplyToHitRenderer(this); } - /// - /// Creates a converter to convert Beatmap to a specific mode. - /// - /// The Beatmap converter. - protected abstract IBeatmapConverter CreateBeatmapConverter(); - /// /// Creates a processor to perform post-processing operations /// on HitObjects in converted Beatmaps. /// /// The Beatmap processor. - protected abstract IBeatmapProcessor CreateBeatmapProcessor(); + protected virtual BeatmapProcessor CreateBeatmapProcessor() => new BeatmapProcessor(); + + /// + /// Creates a converter to convert Beatmap to a specific mode. + /// + /// The Beatmap converter. + protected abstract BeatmapConverter CreateBeatmapConverter(); } /// @@ -268,4 +278,12 @@ namespace osu.Game.Modes.UI /// The Playfield. protected abstract Playfield CreatePlayfield(); } + + public class BeatmapInvalidForRulesetException : Exception + { + public BeatmapInvalidForRulesetException(string text) + : base(text) + { + } + } } diff --git a/osu.Game/Modes/UI/HudOverlay.cs b/osu.Game/Rulesets/UI/HudOverlay.cs similarity index 92% rename from osu.Game/Modes/UI/HudOverlay.cs rename to osu.Game/Rulesets/UI/HudOverlay.cs index 4902baf9b9..47cf157732 100644 --- a/osu.Game/Modes/UI/HudOverlay.cs +++ b/osu.Game/Rulesets/UI/HudOverlay.cs @@ -8,13 +8,13 @@ using osu.Framework.Graphics.Containers; using osu.Game.Configuration; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Scoring; using osu.Framework.Input; using OpenTK.Input; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; -namespace osu.Game.Modes.UI +namespace osu.Game.Rulesets.UI { public abstract class HudOverlay : Container { @@ -94,7 +94,7 @@ namespace osu.Game.Modes.UI } } - public void BindProcessor(ScoreProcessor processor) + public virtual void BindProcessor(ScoreProcessor processor) { ScoreCounter?.Current.BindTo(processor.TotalScore); AccuracyCounter?.Current.BindTo(processor.Accuracy); @@ -102,7 +102,7 @@ namespace osu.Game.Modes.UI HealthDisplay?.Current.BindTo(processor.Health); } - public void BindHitRenderer(HitRenderer hitRenderer) + public virtual void BindHitRenderer(HitRenderer hitRenderer) { hitRenderer.InputManager.Add(KeyCounter.GetReceptor()); } diff --git a/osu.Game/Modes/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs similarity index 94% rename from osu.Game/Modes/UI/ModIcon.cs rename to osu.Game/Rulesets/UI/ModIcon.cs index 1e0aa89a41..8301796c1f 100644 --- a/osu.Game/Modes/UI/ModIcon.cs +++ b/osu.Game/Rulesets/UI/ModIcon.cs @@ -6,7 +6,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; -namespace osu.Game.Modes.UI +namespace osu.Game.Rulesets.UI { public class ModIcon : Container { diff --git a/osu.Game/Modes/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs similarity index 93% rename from osu.Game/Modes/UI/Playfield.cs rename to osu.Game/Rulesets/UI/Playfield.cs index 1e7cf6579c..44d15e42c4 100644 --- a/osu.Game/Modes/UI/Playfield.cs +++ b/osu.Game/Rulesets/UI/Playfield.cs @@ -4,13 +4,13 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Modes.Objects; -using osu.Game.Modes.Objects.Drawables; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Drawables; using OpenTK; -using osu.Game.Modes.Judgements; +using osu.Game.Rulesets.Judgements; using osu.Framework.Allocation; -namespace osu.Game.Modes.UI +namespace osu.Game.Rulesets.UI { public abstract class Playfield : Container where TObject : HitObject diff --git a/osu.Game/Modes/UI/StandardComboCounter.cs b/osu.Game/Rulesets/UI/StandardComboCounter.cs similarity index 96% rename from osu.Game/Modes/UI/StandardComboCounter.cs rename to osu.Game/Rulesets/UI/StandardComboCounter.cs index 08bb3add84..ad05c83839 100644 --- a/osu.Game/Modes/UI/StandardComboCounter.cs +++ b/osu.Game/Rulesets/UI/StandardComboCounter.cs @@ -3,7 +3,7 @@ using OpenTK; -namespace osu.Game.Modes.UI +namespace osu.Game.Rulesets.UI { /// /// Uses the 'x' symbol and has a pop-out effect while rolling over. diff --git a/osu.Game/Rulesets/UI/StandardHealthDisplay.cs b/osu.Game/Rulesets/UI/StandardHealthDisplay.cs new file mode 100644 index 0000000000..3d9a5489dc --- /dev/null +++ b/osu.Game/Rulesets/UI/StandardHealthDisplay.cs @@ -0,0 +1,107 @@ +// Copyright (c) 2007-2017 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.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Objects.Drawables; +using System; + +namespace osu.Game.Rulesets.UI +{ + public class StandardHealthDisplay : HealthDisplay, IHasAccentColour + { + /// + /// The base opacity of the glow. + /// + private const float base_glow_opacity = 0.6f; + + /// + /// The number of sequential hits required within to reach the maximum glow opacity. + /// + private const int glow_max_hits = 8; + + /// + /// The amount of time to delay before fading the glow opacity back to . + /// + /// This is calculated to require a stream snapped to 1/4 at 150bpm to reach the maximum glow opacity with hits. + /// + /// + private const float glow_fade_delay = 100; + + /// + /// The amount of time to fade the glow to after . + /// + private const double glow_fade_time = 500; + + private readonly Container fill; + + public Color4 AccentColour + { + get { return fill.Colour; } + set { fill.Colour = value; } + } + + private Color4 glowColour; + public Color4 GlowColour + { + get { return glowColour; } + set + { + if (glowColour == value) + return; + glowColour = value; + + fill.EdgeEffect = new EdgeEffect + { + Colour = glowColour.Opacity(base_glow_opacity), + Radius = 8, + Roundness = 4, + Type = EdgeEffectType.Glow, + }; + } + } + + public StandardHealthDisplay() + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + fill = new Container + { + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0, 1), + Masking = true, + Children = new[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + } + } + }, + }; + } + + public void Flash(Judgement judgement) + { + if (judgement.Result == HitResult.Miss) + return; + + fill.FadeEdgeEffectTo(Math.Min(1, fill.EdgeEffect.Colour.Linear.A + (1f - base_glow_opacity) / glow_max_hits), 50, EasingTypes.OutQuint); + fill.Delay(glow_fade_delay); + fill.FadeEdgeEffectTo(base_glow_opacity, glow_fade_time, EasingTypes.OutQuint); + } + + protected override void SetHealth(float value) => fill.ResizeTo(new Vector2(value, 1), 200, EasingTypes.OutQuint); + } +} diff --git a/osu.Game/Modes/UI/StandardHudOverlay.cs b/osu.Game/Rulesets/UI/StandardHudOverlay.cs similarity index 83% rename from osu.Game/Modes/UI/StandardHudOverlay.cs rename to osu.Game/Rulesets/UI/StandardHudOverlay.cs index 161a700bef..c68e29f98a 100644 --- a/osu.Game/Modes/UI/StandardHudOverlay.cs +++ b/osu.Game/Rulesets/UI/StandardHudOverlay.cs @@ -3,14 +3,14 @@ using OpenTK; using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Primitives; using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; -namespace osu.Game.Modes.UI +namespace osu.Game.Rulesets.UI { public class StandardHudOverlay : HudOverlay { @@ -57,7 +57,7 @@ namespace osu.Game.Modes.UI Position = new Vector2(0, 30), }; - protected override SongProgress CreateProgress() => new SongProgress() + protected override SongProgress CreateProgress() => new SongProgress { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -75,8 +75,17 @@ namespace osu.Game.Modes.UI if (shd != null) { shd.AccentColour = colours.BlueLighter; - shd.GlowColour = colours.BlueDarker.Opacity(0.6f); + shd.GlowColour = colours.BlueDarker; } } + + public override void BindProcessor(ScoreProcessor processor) + { + base.BindProcessor(processor); + + var shd = HealthDisplay as StandardHealthDisplay; + if (shd != null) + processor.NewJudgement += shd.Flash; + } } } diff --git a/osu.Game/Screens/BackgroundScreen.cs b/osu.Game/Screens/BackgroundScreen.cs index fd40141fcb..a9cb93876c 100644 --- a/osu.Game/Screens/BackgroundScreen.cs +++ b/osu.Game/Screens/BackgroundScreen.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens public override bool Push(Screen screen) { - // When trying to push a non-loaded GameMode, load it asynchronously and re-invoke Push + // When trying to push a non-loaded screen, load it asynchronously and re-invoke Push // once it's done. if (screen.LoadState == LoadState.NotLoaded) { @@ -36,7 +36,7 @@ namespace osu.Game.Screens return true; } - // Make sure the in-progress loading is complete before pushing the GameMode. + // Make sure the in-progress loading is complete before pushing the screen. while (screen.LoadState < LoadState.Loaded) Thread.Sleep(1); diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 3e832b36fa..0b3ecb4f5a 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -5,6 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Screens; using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.Graphics.Containers; namespace osu.Game.Screens @@ -14,7 +15,7 @@ namespace osu.Game.Screens internal BackgroundScreen Background { get; private set; } /// - /// Override to create a BackgroundMode for the current GameMode. + /// Override to create a BackgroundMode for the current screen. /// Note that the instance created may not be the used instance if it matches the BackgroundMode equality clause. /// protected virtual BackgroundScreen CreateBackground() => null; @@ -25,8 +26,12 @@ namespace osu.Game.Screens internal virtual bool HasLocalCursorDisplayed => false; + internal virtual bool AllowRulesetChange => true; + private readonly Bindable beatmap = new Bindable(); + private readonly Bindable ruleset = new Bindable(); + public WorkingBeatmap Beatmap { get @@ -40,7 +45,7 @@ namespace osu.Game.Screens } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuGameBase game) + private void load(OsuGameBase game, OsuGame osuGame) { if (game != null) { @@ -52,11 +57,23 @@ namespace osu.Game.Screens } beatmap.ValueChanged += OnBeatmapChanged; + + if (osuGame != null) + ruleset.BindTo(osuGame.Ruleset); } + /// + /// The global Beatmap was changed. + /// protected virtual void OnBeatmapChanged(WorkingBeatmap beatmap) { + } + protected override void Update() + { + if (!IsCurrentScreen) return; + + ruleset.Disabled = !AllowRulesetChange; } protected override void OnEntering(Screen last) @@ -99,7 +116,7 @@ namespace osu.Game.Screens if (Background != null && !Background.Equals(nextOsu?.Background)) { if (nextOsu != null) - //We need to use MakeCurrent in case we are jumping up multiple game modes. + //We need to use MakeCurrent in case we are jumping up multiple game screens. nextOsu.Background?.MakeCurrent(); else Background.Exit(); diff --git a/osu.Game/Screens/Play/MenuOverlay.cs b/osu.Game/Screens/Play/MenuOverlay.cs index 738e5cc35d..fa522956f7 100644 --- a/osu.Game/Screens/Play/MenuOverlay.cs +++ b/osu.Game/Screens/Play/MenuOverlay.cs @@ -25,6 +25,8 @@ namespace osu.Game.Screens.Play protected override bool HideOnEscape => false; + protected override bool BlockPassThroughKeyboard => true; + public Action OnRetry; public Action OnQuit; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fa564cdd61..a31ac25d60 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -14,14 +14,15 @@ using osu.Framework.Screens; using osu.Framework.Timing; using osu.Game.Configuration; using osu.Game.Database; -using osu.Game.Modes; -using osu.Game.Modes.UI; +using osu.Game.Rulesets; +using osu.Game.Rulesets.UI; using osu.Game.Screens.Backgrounds; -using osu.Game.Screens.Ranking; using System; using System.Linq; using osu.Framework.Threading; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Play { @@ -35,8 +36,12 @@ namespace osu.Game.Screens.Play public BeatmapInfo BeatmapInfo; + public Action RestartRequested; + public bool IsPaused => !interpolatedSourceClock.IsRunning; + internal override bool AllowRulesetChange => false; + public bool HasFailed { get; private set; } public int RestartCount; @@ -47,32 +52,36 @@ namespace osu.Game.Screens.Play private bool canPause => ValidForResume && !HasFailed && Time.Current >= lastPauseActionTime + pause_cooldown; private IAdjustableClock sourceClock; + private OffsetClock offsetClock; private IFrameBasedClock interpolatedSourceClock; - private Ruleset ruleset; + private RulesetInfo ruleset; private ScoreProcessor scoreProcessor; protected HitRenderer HitRenderer; + + #region User Settings + private Bindable dimLevel; + private Bindable mouseWheelDisabled; + private Bindable userAudioOffset; + + #endregion + private SkipButton skipButton; private HudOverlay hudOverlay; private PauseOverlay pauseOverlay; private FailOverlay failOverlay; - [BackgroundDependencyLoader] - private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager config) + [BackgroundDependencyLoader(permitNulls: true)] + private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager config, OsuGame osu) { - if (Beatmap.Beatmap.BeatmapInfo?.Mode > PlayMode.Taiko) - { - //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor. - Exit(); - return; - } - dimLevel = config.GetBindable(OsuConfig.DimLevel); mouseWheelDisabled = config.GetBindable(OsuConfig.MouseDisableWheel); + Ruleset rulesetInstance; + try { if (Beatmap == null) @@ -83,6 +92,22 @@ namespace osu.Game.Screens.Play if (Beatmap == null) throw new Exception("Beatmap was not loaded"); + + ruleset = osu?.Ruleset.Value ?? Beatmap.BeatmapInfo.Ruleset; + rulesetInstance = ruleset.CreateInstance(); + + try + { + HitRenderer = rulesetInstance.CreateHitRendererWith(Beatmap); + } + catch (BeatmapInvalidForRulesetException) + { + // we may fail to create a HitRenderer if the beatmap cannot be loaded with the user's preferred ruleset + // let's try again forcing the beatmap's ruleset. + ruleset = Beatmap.BeatmapInfo.Ruleset; + rulesetInstance = ruleset.CreateInstance(); + HitRenderer = rulesetInstance.CreateHitRendererWith(Beatmap); + } } catch (Exception e) { @@ -102,16 +127,21 @@ namespace osu.Game.Screens.Play } sourceClock = (IAdjustableClock)track ?? new StopwatchClock(); - interpolatedSourceClock = new InterpolatingFramedClock(sourceClock); + offsetClock = new OffsetClock(sourceClock); + + userAudioOffset = config.GetBindable(OsuConfig.AudioOffset); + userAudioOffset.ValueChanged += v => offsetClock.Offset = v; + userAudioOffset.TriggerChange(); + + interpolatedSourceClock = new InterpolatingFramedClock(offsetClock); Schedule(() => { sourceClock.Reset(); + foreach (var mod in Beatmap.Mods.Value.OfType()) + mod.ApplyToClock(sourceClock); }); - ruleset = Ruleset.GetRuleset(Beatmap.PlayMode); - HitRenderer = ruleset.CreateHitRendererWith(Beatmap); - scoreProcessor = HitRenderer.CreateScoreProcessor(); hudOverlay = new StandardHudOverlay() @@ -120,7 +150,7 @@ namespace osu.Game.Screens.Play Origin = Anchor.Centre }; - hudOverlay.KeyCounter.Add(ruleset.CreateGameplayKeys()); + hudOverlay.KeyCounter.Add(rulesetInstance.CreateGameplayKeys()); hudOverlay.BindProcessor(scoreProcessor); hudOverlay.BindHitRenderer(HitRenderer); @@ -243,20 +273,9 @@ namespace osu.Game.Screens.Play public void Restart() { - sourceClock.Stop(); // If the clock is running and Restart is called the game will lag until relaunch - - var newPlayer = new Player(); - ValidForResume = false; - - LoadComponentAsync(newPlayer, delegate - { - newPlayer.RestartCount = RestartCount + 1; - if (!Push(newPlayer)) - { - // Error(?) - } - }); + RestartRequested?.Invoke(); + Exit(); } private ScheduledDelegate onCompletionEvent; @@ -272,10 +291,14 @@ namespace osu.Game.Screens.Play Delay(1000); onCompletionEvent = Schedule(delegate { - Push(new Results + var score = new Score { - Score = scoreProcessor.CreateScore() - }); + Beatmap = Beatmap.BeatmapInfo, + Ruleset = ruleset + }; + scoreProcessor.PopulateScore(score); + score.User = HitRenderer.Replay?.User ?? (Game as OsuGame)?.API?.LocalUser?.Value; + Push(new Results(score)); }); } @@ -321,24 +344,23 @@ namespace osu.Game.Screens.Play protected override void OnSuspending(Screen next) { fadeOut(); - base.OnSuspending(next); } protected override bool OnExiting(Screen next) { - if (HasFailed || !ValidForResume) - return false; - - if (pauseOverlay != null && !HitRenderer.HasReplayLoaded) + if (!HasFailed && ValidForResume) { - //pause screen override logic. - if (pauseOverlay?.State == Visibility.Hidden && !canPause) return true; - - if (!IsPaused) // For if the user presses escape quickly when entering the map + if (pauseOverlay != null && !HitRenderer.HasReplayLoaded) { - Pause(); - return true; + //pause screen override logic. + if (pauseOverlay?.State == Visibility.Hidden && !canPause) return true; + + if (!IsPaused) // For if the user presses escape quickly when entering the map + { + Pause(); + return true; + } } } @@ -358,8 +380,6 @@ namespace osu.Game.Screens.Play Background?.FadeTo(1f, fade_out_duration); } - private Bindable mouseWheelDisabled; - protected override bool OnWheel(InputState state) => mouseWheelDisabled.Value && !IsPaused; } } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 64d17fd5bb..765abd9873 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -19,17 +19,27 @@ namespace osu.Game.Screens.Play { public class PlayerLoader : OsuScreen { - private readonly Player player; + private Player player; + private readonly OsuLogo logo; private BeatmapMetadataDisplay info; + private bool showOverlays = true; + internal override bool ShowOverlays => showOverlays; + + internal override bool AllowRulesetChange => false; + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); public PlayerLoader(Player player) { - ValidForResume = false; this.player = player; + player.RestartRequested = () => { + showOverlays = false; + ValidForResume = true; + }; + Children = new Drawable[] { logo = new OsuLogo @@ -53,6 +63,37 @@ namespace osu.Game.Screens.Play LoadComponentAsync(player); } + protected override void OnResuming(Screen last) + { + base.OnResuming(last); + + contentIn(); + + //we will only be resumed if the player has requested a re-run (see ValidForResume setting above) + LoadComponentAsync(player = new Player + { + RestartCount = player.RestartCount + 1, + RestartRequested = player.RestartRequested, + Beatmap = player.Beatmap, + }); + + Delay(400); + + Schedule(pushWhenLoaded); + } + + private void contentIn() + { + Content.ScaleTo(1, 650, EasingTypes.OutQuint); + Content.FadeInFromZero(400); + } + + private void contentOut() + { + Content.ScaleTo(0.7f, 300, EasingTypes.InQuint); + Content.FadeOut(250); + } + protected override void OnEntering(Screen last) { base.OnEntering(last); @@ -60,20 +101,27 @@ namespace osu.Game.Screens.Play Background.FadeTo(0.4f, 250); Content.ScaleTo(0.7f); - Content.ScaleTo(1, 750, EasingTypes.OutQuint); - Content.FadeInFromZero(500); - Delay(1000, true); + contentIn(); + + Delay(500, true); logo.MoveToOffset(new Vector2(0, -180), 500, EasingTypes.InOutExpo); Delay(250, true); info.FadeIn(500); - Delay(2000, true); + Delay(1400, true); - Content.ScaleTo(0.7f, 300, EasingTypes.InQuint); - Content.FadeOut(250); + Schedule(pushWhenLoaded); + } + + private void pushWhenLoaded() + { + if (!player.IsLoaded) + Schedule(pushWhenLoaded); + + contentOut(); Delay(250); @@ -83,6 +131,12 @@ namespace osu.Game.Screens.Play if (!Push(player)) Exit(); + else + { + //By default, we want to load the player and never be returned to. + //Note that this may change if the player we load requested a re-run. + ValidForResume = false; + } }); } diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index 4593656a2e..860675b62a 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -1,7 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Game.Modes.Replays; +using osu.Game.Rulesets.Replays; namespace osu.Game.Screens.Play { diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index 52f3b9e1ae..6ad76ae361 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -4,21 +4,21 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Primitives; using System; using System.Collections.Generic; using osu.Game.Graphics; using osu.Framework.Allocation; using System.Linq; using osu.Framework.Timing; -using osu.Game.Modes.Objects; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; +using osu.Framework.Graphics.Primitives; namespace osu.Game.Screens.Play { public class SongProgress : OverlayContainer { - private const int progress_height = 5; + private const int bottom_bar_height = 5; protected override bool HideOnEscape => false; @@ -41,25 +41,7 @@ namespace osu.Game.Screens.Play { set { - objects = value; - - const int granularity = 200; - - var interval = lastHitTime / granularity; - - var values = new int[granularity]; - - foreach (var h in objects) - { - IHasEndTime end = h as IHasEndTime; - - int startRange = (int)(h.StartTime / interval); - int endRange = (int)((end?.EndTime ?? h.StartTime) / interval); - for (int i = startRange; i <= endRange; i++) - values[i]++; - } - - graph.Values = values; + graph.Objects = objects = value; } } @@ -71,9 +53,10 @@ namespace osu.Game.Screens.Play public SongProgress() { - RelativeSizeAxes = Axes.X; - Height = progress_height + SongProgressGraph.Column.HEIGHT + handle_size.Y; - Y = progress_height; + const float graph_height = SquareGraph.Column.WIDTH * 6; + + Height = bottom_bar_height + graph_height + handle_size.Y; + Y = bottom_bar_height; Children = new Drawable[] { @@ -82,10 +65,10 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.X, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, - Height = SongProgressGraph.Column.HEIGHT, - Margin = new MarginPadding { Bottom = progress_height }, + Height = graph_height, + Margin = new MarginPadding { Bottom = bottom_bar_height }, }, - bar = new SongProgressBar(progress_height, SongProgressGraph.Column.HEIGHT, handle_size) + bar = new SongProgressBar(bottom_bar_height, graph_height, handle_size) { Alpha = 0, Anchor = Anchor.BottomLeft, @@ -114,7 +97,7 @@ namespace osu.Game.Screens.Play private void updateBarVisibility() { bar.FadeTo(barVisible ? 1 : 0, transition_duration, EasingTypes.In); - MoveTo(new Vector2(0, barVisible ? 0 : progress_height), transition_duration, EasingTypes.In); + MoveTo(new Vector2(0, barVisible ? 0 : bottom_bar_height), transition_duration, EasingTypes.In); } protected override void PopIn() @@ -132,11 +115,13 @@ namespace osu.Game.Screens.Play { base.Update(); + if (objects == null) + return; + double progress = (AudioClock?.CurrentTime ?? Time.Current) / lastHitTime; bar.UpdatePosition((float)progress); graph.Progress = (int)(graph.ColumnCount * progress); - } } } diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index 4f0cdbf67a..20548970e5 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -1,235 +1,46 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; -using OpenTK.Graphics; using System.Linq; using System.Collections.Generic; -using osu.Framework; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Containers; -using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Objects; namespace osu.Game.Screens.Play { - public class SongProgressGraph : BufferedContainer + public class SongProgressGraph : SquareGraph { - private Column[] columns = { }; + private IEnumerable objects; - public int ColumnCount => columns.Length; - - public override bool HandleInput => false; - - private int progress; - public int Progress + public IEnumerable Objects { - get { return progress; } set { - if (value == progress) return; - progress = value; + objects = value; - redrawProgress(); - } - } + const int granularity = 200; - private int[] calculatedValues = { }; // values but adjusted to fit the amount of columns - private int[] values; - public int[] Values - { - get { return values; } - set - { - if (value == values) return; - values = value; - recreateGraph(); - } - } + var lastHit = (objects.Last() as IHasEndTime)?.EndTime ?? 0; - private Color4 fillColour; - public Color4 FillColour - { - get { return fillColour; } - set - { - if (value == fillColour) return; - fillColour = value; + if (lastHit == 0) + lastHit = objects.Last().StartTime; - redrawFilled(); - } - } + var interval = (lastHit + 1) / granularity; - public SongProgressGraph() - { - CacheDrawnFrameBuffer = true; - PixelSnapping = true; - } + var values = new int[granularity]; - private float lastDrawWidth; - protected override void Update() - { - base.Update(); - - // todo: Recreating in update is probably not the best idea - if (DrawWidth == lastDrawWidth) return; - recreateGraph(); - lastDrawWidth = DrawWidth; - } - - /// - /// Redraws all the columns to match their lit/dimmed state. - /// - private void redrawProgress() - { - for (int i = 0; i < columns.Length; i++) - { - columns[i].State = i <= progress ? ColumnState.Lit : ColumnState.Dimmed; - } - - ForceRedraw(); - } - - /// - /// Redraws the filled amount of all the columns. - /// - private void redrawFilled() - { - for (int i = 0; i < ColumnCount; i++) - { - columns[i].Filled = calculatedValues.ElementAtOrDefault(i); - } - } - - /// - /// Takes and adjusts it to fit the amount of columns. - /// - private void recalculateValues() - { - var newValues = new List(); - - if (values == null) - { - for (float i = 0; i < ColumnCount; i++) - newValues.Add(0); - - return; - } - - float step = values.Length / (float)ColumnCount; - for (float i = 0; i < values.Length; i += step) - { - newValues.Add(values[(int)i]); - } - - calculatedValues = newValues.ToArray(); - } - - /// - /// Recreates the entire graph. - /// - private void recreateGraph() - { - var newColumns = new List(); - - for (float x = 0; x < DrawWidth; x += Column.WIDTH) - { - newColumns.Add(new Column(fillColour) + foreach (var h in objects) { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Position = new Vector2(x, 0), - State = ColumnState.Dimmed, - }); - } + IHasEndTime end = h as IHasEndTime; - columns = newColumns.ToArray(); - Children = columns; - - recalculateValues(); - redrawFilled(); - redrawProgress(); - } - - public class Column : Container, IStateful - { - private readonly Color4 emptyColour = Color4.White.Opacity(100); - private readonly Color4 litColour; - private readonly Color4 dimmedColour = Color4.White.Opacity(175); - - private const float cube_count = 6; - private const float cube_size = 4; - private const float padding = 2; - public const float WIDTH = cube_size + padding; - public const float HEIGHT = cube_count * WIDTH + padding; - - private readonly List drawableRows = new List(); - - private int filled; - public int Filled - { - get { return filled; } - set - { - if (value == filled) return; - filled = value; - - fillActive(); - } - } - - private ColumnState state; - public ColumnState State - { - get { return state; } - set - { - if (value == state) return; - state = value; - - fillActive(); - } - } - - public Column(Color4 litColour) - { - Size = new Vector2(WIDTH, HEIGHT); - this.litColour = litColour; - - for (int r = 0; r < cube_count; r++) - { - drawableRows.Add(new Box - { - EdgeSmoothness = new Vector2(padding / 4), - Size = new Vector2(cube_size), - Position = new Vector2(0, r * WIDTH + padding), - }); + int startRange = (int)(h.StartTime / interval); + int endRange = (int)((end?.EndTime > 0 ? end.EndTime : h.StartTime) / interval); + for (int i = startRange; i <= endRange; i++) + values[i]++; } - Children = drawableRows; - - // Reverse drawableRows so when iterating through them they start at the bottom - drawableRows.Reverse(); + Values = values; } - - private void fillActive() - { - Color4 colour = State == ColumnState.Lit ? litColour : dimmedColour; - - for (int i = 0; i < drawableRows.Count; i++) - { - if (Filled == 0) // i <= Filled doesn't work for zero fill - drawableRows[i].Colour = emptyColour; - else - drawableRows[i].Colour = i <= Filled ? colour : emptyColour; - } - } - } - - public enum ColumnState - { - Lit, - Dimmed } } } diff --git a/osu.Game/Screens/Play/SquareGraph.cs b/osu.Game/Screens/Play/SquareGraph.cs new file mode 100644 index 0000000000..43a8253b53 --- /dev/null +++ b/osu.Game/Screens/Play/SquareGraph.cs @@ -0,0 +1,238 @@ +// 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.Framework; +using osu.Framework.Caching; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Screens.Play +{ + public class SquareGraph : BufferedContainer + { + private Column[] columns = { }; + + public int ColumnCount => columns.Length; + + public override bool HandleInput => false; + + private int progress; + public int Progress + { + get { return progress; } + set + { + if (value == progress) return; + progress = value; + redrawProgress(); + } + } + + private float[] calculatedValues = { }; // values but adjusted to fit the amount of columns + + private int[] values; + public int[] Values + { + get { return values; } + set + { + if (value == values) return; + values = value; + layout.Invalidate(); + } + } + + private Color4 fillColour; + public Color4 FillColour + { + get { return fillColour; } + set + { + if (value == fillColour) return; + fillColour = value; + redrawFilled(); + } + } + + public SquareGraph() + { + CacheDrawnFrameBuffer = true; + } + + private Cached layout = new Cached(); + + public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) + { + if ((invalidation & Invalidation.SizeInParentSpace) > 0) + layout.Invalidate(); + return base.Invalidate(invalidation, source, shallPropagate); + } + + protected override void Update() + { + base.Update(); + layout.Refresh(recreateGraph); + } + + /// + /// Redraws all the columns to match their lit/dimmed state. + /// + private void redrawProgress() + { + for (int i = 0; i < columns.Length; i++) + columns[i].State = i <= progress ? ColumnState.Lit : ColumnState.Dimmed; + ForceRedraw(); + } + + /// + /// Redraws the filled amount of all the columns. + /// + private void redrawFilled() + { + for (int i = 0; i < ColumnCount; i++) + columns[i].Filled = calculatedValues.ElementAtOrDefault(i); + ForceRedraw(); + } + + /// + /// Takes and adjusts it to fit the amount of columns. + /// + private void recalculateValues() + { + var newValues = new List(); + + if (values == null) + { + for (float i = 0; i < ColumnCount; i++) + newValues.Add(0); + + return; + } + + var max = values.Max(); + + float step = values.Length / (float)ColumnCount; + for (float i = 0; i < values.Length; i += step) + { + newValues.Add((float)values[(int)i] / max); + } + + calculatedValues = newValues.ToArray(); + } + + /// + /// Recreates the entire graph. + /// + private void recreateGraph() + { + var newColumns = new List(); + + for (float x = 0; x < DrawWidth; x += Column.WIDTH) + { + newColumns.Add(new Column + { + LitColour = fillColour, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Height = DrawHeight, + Position = new Vector2(x, 0), + State = ColumnState.Dimmed, + }); + } + + columns = newColumns.ToArray(); + Children = columns; + + recalculateValues(); + redrawFilled(); + redrawProgress(); + } + + public class Column : Container, IStateful + { + protected readonly Color4 EmptyColour = Color4.White.Opacity(20); + public Color4 LitColour = Color4.LightBlue; + protected readonly Color4 DimmedColour = Color4.White.Opacity(140); + + private float cubeCount => DrawHeight / WIDTH; + private const float cube_size = 4; + private const float padding = 2; + public const float WIDTH = cube_size + padding; + + private readonly List drawableRows = new List(); + + private float filled; + public float Filled + { + get { return filled; } + set + { + if (value == filled) return; + filled = value; + + fillActive(); + } + } + + private ColumnState state; + public ColumnState State + { + get { return state; } + set + { + if (value == state) return; + state = value; + + if (IsLoaded) + fillActive(); + } + } + + public Column() + { + Width = WIDTH; + } + + protected override void LoadComplete() + { + for (int r = 0; r < cubeCount; r++) + { + drawableRows.Add(new Box + { + Size = new Vector2(cube_size), + Position = new Vector2(0, r * WIDTH + padding), + }); + } + + Children = drawableRows; + + // Reverse drawableRows so when iterating through them they start at the bottom + drawableRows.Reverse(); + + fillActive(); + } + + private void fillActive() + { + Color4 colour = State == ColumnState.Lit ? LitColour : DimmedColour; + + int countFilled = (int)MathHelper.Clamp(filled * drawableRows.Count, 0, drawableRows.Count); + + for (int i = 0; i < drawableRows.Count; i++) + drawableRows[i].Colour = i < countFilled ? colour : EmptyColour; + } + } + + public enum ColumnState + { + Lit, + Dimmed + } + } +} diff --git a/osu.Game/Screens/Ranking/AspectContainer.cs b/osu.Game/Screens/Ranking/AspectContainer.cs new file mode 100644 index 0000000000..4699b4ab92 --- /dev/null +++ b/osu.Game/Screens/Ranking/AspectContainer.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2007-2017 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; + +namespace osu.Game.Screens.Ranking +{ + public class AspectContainer : Container + { + protected override void Update() + { + base.Update(); + if (RelativeSizeAxes == Axes.X) + Height = DrawWidth; + else + Width = DrawHeight; + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Ranking/ResultMode.cs b/osu.Game/Screens/Ranking/ResultMode.cs new file mode 100644 index 0000000000..eeb04033ea --- /dev/null +++ b/osu.Game/Screens/Ranking/ResultMode.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Screens.Ranking +{ + public enum ResultMode + { + Summary, + Ranking, + Share + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Ranking/ResultModeButton.cs b/osu.Game/Screens/Ranking/ResultModeButton.cs new file mode 100644 index 0000000000..fc62342860 --- /dev/null +++ b/osu.Game/Screens/Ranking/ResultModeButton.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Screens.Ranking +{ + public class ResultModeButton : TabItem + { + private readonly FontAwesome icon; + private Color4 activeColour; + private Color4 inactiveColour; + private CircularContainer colouredPart; + + public ResultModeButton(ResultMode mode) : base(mode) + { + switch (mode) + { + case ResultMode.Summary: + icon = FontAwesome.fa_asterisk; + break; + case ResultMode.Ranking: + icon = FontAwesome.fa_list; + break; + case ResultMode.Share: + icon = FontAwesome.fa_camera; + break; + } + } + + public override bool Active + { + get + { + return base.Active; + } + set + { + base.Active = value; + colouredPart.FadeColour(Active ? activeColour : inactiveColour, 200, EasingTypes.OutQuint); + } + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Size = new Vector2(50); + + Masking = true; + CornerRadius = 25; + + activeColour = colours.PinkDarker; + inactiveColour = OsuColour.Gray(0.8f); + + EdgeEffect = new EdgeEffect + { + Colour = Color4.Black.Opacity(0.4f), + Type = EdgeEffectType.Shadow, + Radius = 5, + }; + + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + colouredPart = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.8f), + BorderThickness = 4, + BorderColour = Color4.White, + Colour = inactiveColour, + Children = new Drawable[] + { + new Box + { + AlwaysPresent = true, //for border rendering + RelativeSizeAxes = Axes.Both, + Colour = Color4.Transparent, + }, + new TextAwesome + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Shadow = false, + Colour = OsuColour.Gray(0.95f), + Icon = icon, + TextSize = 20, + } + } + } + }; + } + } +} diff --git a/osu.Game/Screens/Ranking/ResultModeTabControl.cs b/osu.Game/Screens/Ranking/ResultModeTabControl.cs new file mode 100644 index 0000000000..346bff5720 --- /dev/null +++ b/osu.Game/Screens/Ranking/ResultModeTabControl.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.UserInterface; +using OpenTK; + +namespace osu.Game.Screens.Ranking +{ + public class ResultModeTabControl : TabControl + { + public ResultModeTabControl() + { + TabContainer.Anchor = Anchor.BottomCentre; + TabContainer.Origin = Anchor.BottomCentre; + TabContainer.Spacing = new Vector2(15); + + TabContainer.Masking = false; + TabContainer.Padding = new MarginPadding(5); + } + + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(ResultMode value) => new ResultModeButton(value) + { + Anchor = TabContainer.Anchor, + 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 37770bea3e..ffe72966f5 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -1,93 +1,283 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Screens; +using System.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Modes.Scoring; +using osu.Framework.Graphics.Primitives; +using osu.Game.Rulesets.Scoring; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Screens; +using osu.Game.Graphics.Containers; using osu.Game.Screens.Backgrounds; using OpenTK; using OpenTK.Graphics; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Ranking { - internal class Results : OsuScreen + public class Results : OsuScreen { - protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); + private readonly Score score; + private Container circleOuterBackground; + private Container circleOuter; + private Container circleInner; + + private ParallaxContainer backgroundParallax; + + private ResultModeTabControl modeChangeButtons; + + internal override bool AllowRulesetChange => false; + + private Container currentPage; private static readonly Vector2 background_blur = new Vector2(20); - private ScoreDisplay scoreDisplay; + protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); + + private const float overscan = 1.3f; + + private const float circle_outer_scale = 0.96f; + + public Results(Score score) + { + this.score = score; + } + + private const float transition_time = 800; + + private IEnumerable allCircles => new Drawable[] { circleOuterBackground, circleInner, circleOuter }; protected override void OnEntering(Screen last) { base.OnEntering(last); - Background.Schedule(() => (Background as BackgroundScreenBeatmap)?.BlurTo(background_blur, 1000)); + (Background as BackgroundScreenBeatmap)?.BlurTo(background_blur, 2500, EasingTypes.OutQuint); + + allCircles.ForEach(c => + { + c.FadeOut(); + c.ScaleTo(0); + }); + + backgroundParallax.FadeOut(); + modeChangeButtons.FadeOut(); + currentPage.FadeOut(); + + circleOuterBackground.ScaleTo(1, transition_time, EasingTypes.OutQuint); + circleOuterBackground.FadeTo(1, transition_time, EasingTypes.OutQuint); + + Content.Delay(transition_time * 0.25f, true); + + circleOuter.ScaleTo(1, transition_time, EasingTypes.OutQuint); + circleOuter.FadeTo(1, transition_time, EasingTypes.OutQuint); + + Content.Delay(transition_time * 0.3f, true); + + backgroundParallax.FadeIn(transition_time, EasingTypes.OutQuint); + + circleInner.ScaleTo(1, transition_time, EasingTypes.OutQuint); + circleInner.FadeTo(1, transition_time, EasingTypes.OutQuint); + + Content.Delay(transition_time * 0.4f, true); + + modeChangeButtons.FadeIn(transition_time, EasingTypes.OutQuint); + currentPage.FadeIn(transition_time, EasingTypes.OutQuint); + + Content.DelayReset(); } protected override bool OnExiting(Screen next) { - Background.Schedule(() => Background.FadeColour(Color4.White, 500)); + allCircles.ForEach(c => + { + c.ScaleTo(0, transition_time, EasingTypes.OutSine); + }); + + Content.FadeOut(transition_time / 4); + return base.OnExiting(next); } - public Score Score + [BackgroundDependencyLoader] + private void load(OsuColour colours) { - set - { - scoreDisplay?.FadeOut(500); - scoreDisplay?.Expire(); - - scoreDisplay = new ScoreDisplay(value) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }; - - Add(scoreDisplay); - - scoreDisplay.FadeIn(500); - scoreDisplay.ScaleTo(0.1f); - scoreDisplay.ScaleTo(1, 1000, EasingTypes.OutElastic); - scoreDisplay.RotateTo(360 * 5, 1000, EasingTypes.OutElastic); - - } - } - } - - internal class ScoreDisplay : Container - { - public ScoreDisplay(Score s) - { - AutoSizeAxes = Axes.Both; - Children = new Drawable[] { - new FillFlowContainer + new AspectContainer { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.Y, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Height = overscan, Children = new Drawable[] { - new OsuSpriteText + circleOuterBackground = new CircularContainer { - TextSize = 40, - Text = $@"Accuracy: {s.Accuracy:#0.00%}", + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + Children = new Drawable[] + { + new Box + { + Alpha = 0.2f, + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + } + } }, - new OsuSpriteText + circleOuter = new CircularContainer { - TextSize = 40, - Text = $@"Score: {s.TotalScore}", + Size = new Vector2(circle_outer_scale), + EdgeEffect = new EdgeEffect + { + Colour = Color4.Black.Opacity(0.4f), + Type = EdgeEffectType.Shadow, + Radius = 15, + }, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + backgroundParallax = new ParallaxContainer + { + RelativeSizeAxes = Axes.Both, + ParallaxAmount = 0.01f, + Scale = new Vector2(1 / circle_outer_scale / overscan), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Sprite + { + Alpha = 0.2f, + Texture = Beatmap?.Background, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill + } + } + }, + modeChangeButtons = new ResultModeTabControl + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + Height = 50, + Margin = new MarginPadding { Bottom = 110 }, + }, + new SpriteText + { + Text = $"{score.MaxCombo}x", + TextSize = 40, + RelativePositionAxes = Axes.X, + Font = @"Exo2.0-Bold", + X = 0.1f, + Colour = colours.BlueDarker, + Anchor = Anchor.CentreLeft, + Origin = Anchor.BottomCentre, + }, + new SpriteText + { + Text = "max combo", + TextSize = 20, + RelativePositionAxes = Axes.X, + X = 0.1f, + Colour = colours.Gray6, + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopCentre, + }, + new SpriteText + { + Text = $"{score.Accuracy:P2}", + TextSize = 40, + RelativePositionAxes = Axes.X, + Font = @"Exo2.0-Bold", + X = 0.9f, + Colour = colours.BlueDarker, + Anchor = Anchor.CentreLeft, + Origin = Anchor.BottomCentre, + }, + new SpriteText + { + Text = "accuracy", + TextSize = 20, + RelativePositionAxes = Axes.X, + X = 0.9f, + Colour = colours.Gray6, + Anchor = Anchor.CentreLeft, + Origin = Anchor.TopCentre, + }, + } }, - new OsuSpriteText + circleInner = new CircularContainer { - TextSize = 40, - Text = $@"MaxCombo: {s.MaxCombo}", + Size = new Vector2(0.6f), + EdgeEffect = new EdgeEffect + { + Colour = Color4.Black.Opacity(0.4f), + Type = EdgeEffectType.Shadow, + Radius = 15, + }, + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + } } } - } + }, + new BackButton + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Action = Exit + }, }; + + modeChangeButtons.AddItem(ResultMode.Summary); + modeChangeButtons.AddItem(ResultMode.Ranking); + //modeChangeButtons.AddItem(ResultMode.Share); + + modeChangeButtons.Current.ValueChanged += mode => + { + currentPage?.FadeOut(); + currentPage?.Expire(); + + switch (mode) + { + case ResultMode.Summary: + currentPage = new ResultsPageScore(score, Beatmap); + break; + case ResultMode.Ranking: + currentPage = new ResultsPageRanking(score, Beatmap); + break; + } + + if (currentPage != null) + circleInner.Add(currentPage); + }; + + modeChangeButtons.Current.TriggerChange(); } } } diff --git a/osu.Game/Screens/Ranking/ResultsPage.cs b/osu.Game/Screens/Ranking/ResultsPage.cs new file mode 100644 index 0000000000..02eae3643b --- /dev/null +++ b/osu.Game/Screens/Ranking/ResultsPage.cs @@ -0,0 +1,92 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Scoring; +using OpenTK; +using OpenTK.Graphics; + +namespace osu.Game.Screens.Ranking +{ + internal class ResultsPage : Container + { + protected readonly Score Score; + protected readonly WorkingBeatmap Beatmap; + private CircularContainer content; + private Box fill; + + protected override Container Content => content; + + public ResultsPage(Score score, WorkingBeatmap beatmap) + { + Score = score; + Beatmap = beatmap; + RelativeSizeAxes = Axes.Both; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + fill.Delay(400); + fill.FadeInFromZero(600); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AddInternal(new Drawable[] + { + fill = new Box + { + Alpha = 0, + RelativeSizeAxes = Axes.Both, + Colour = colours.Gray6 + }, + new CircularContainer + { + EdgeEffect = new EdgeEffect + { + Colour = colours.GrayF.Opacity(0.8f), + Type = EdgeEffectType.Shadow, + Radius = 1, + }, + RelativeSizeAxes = Axes.Both, + Masking = true, + BorderThickness = 20, + BorderColour = Color4.White, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box{ + RelativeSizeAxes = Axes.Both, + Alpha = 0, + AlwaysPresent = true + }, + } + }, + content = new CircularContainer + { + EdgeEffect = new EdgeEffect + { + Colour = Color4.Black.Opacity(0.2f), + Type = EdgeEffectType.Shadow, + Radius = 15, + }, + RelativeSizeAxes = Axes.Both, + Masking = true, + Size = new Vector2(0.88f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }); + } + + } +} diff --git a/osu.Game/Screens/Ranking/ResultsPageRanking.cs b/osu.Game/Screens/Ranking/ResultsPageRanking.cs new file mode 100644 index 0000000000..827abd556e --- /dev/null +++ b/osu.Game/Screens/Ranking/ResultsPageRanking.cs @@ -0,0 +1,42 @@ +// Copyright (c) 2007-2017 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.Sprites; +using osu.Game.Beatmaps; +using osu.Game.Graphics; +using osu.Game.Rulesets.Scoring; +using osu.Game.Screens.Select.Leaderboards; +using OpenTK; + +namespace osu.Game.Screens.Ranking +{ + internal class ResultsPageRanking : ResultsPage + { + public ResultsPageRanking(Score score, WorkingBeatmap beatmap = null) : base(score, beatmap) + { + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + new Box + { + Colour = colours.GrayE, + RelativeSizeAxes = Axes.Both, + }, + new Leaderboard + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Beatmap = Beatmap.BeatmapInfo ?? Score.Beatmap, + Scale = new Vector2(0.7f) + } + }; + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs new file mode 100644 index 0000000000..1c2a126211 --- /dev/null +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -0,0 +1,393 @@ +// Copyright (c) 2007-2017 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.Containers; +using osu.Framework.Graphics.Primitives; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Game.Configuration; +using osu.Game.Database; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Screens.Select.Leaderboards; +using osu.Game.Users; +using OpenTK; +using OpenTK.Graphics; +using System; +using System.Collections.Generic; +using osu.Framework.Extensions.Color4Extensions; +using osu.Game.Beatmaps; +using osu.Game.Screens.Play; +using osu.Game.Rulesets.Scoring; +using osu.Framework.Graphics.Colour; +using System.Linq; + +namespace osu.Game.Screens.Ranking +{ + internal class ResultsPageScore : ResultsPage + { + private ScoreCounter scoreCounter; + + public ResultsPageScore(Score score, WorkingBeatmap beatmap) : base(score, beatmap) { } + + private FillFlowContainer statisticsContainer; + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + const float user_header_height = 120; + + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = user_header_height }, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }, + } + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new UserHeader(Score.User) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Height = user_header_height, + }, + new DrawableRank(Score.Rank) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Size = new Vector2(150, 60), + Margin = new MarginPadding(20), + }, + new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Height = 60, + Children = new Drawable[] + { + new SongProgressGraph + { + RelativeSizeAxes = Axes.Both, + Alpha = 0.5f, + Objects = Beatmap.Beatmap.HitObjects, + }, + scoreCounter = new SlowScoreCounter(6) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Colour = colours.PinkDarker, + Y = 10, + TextSize = 56, + }, + } + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Colour = colours.PinkDarker, + Shadow = false, + Font = @"Exo2.0-Bold", + TextSize = 16, + Text = "total score", + Margin = new MarginPadding { Bottom = 15 }, + }, + new BeatmapDetails(Beatmap.BeatmapInfo) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding { Bottom = 10 }, + }, + new DateDisplay(Score.Date) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }, + new Container + { + RelativeSizeAxes = Axes.X, + Size = new Vector2(0.75f, 1), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding { Top = 10, Bottom = 10 }, + Children = new Drawable[] + { + new Box + { + ColourInfo = ColourInfo.GradientHorizontal( + colours.GrayC.Opacity(0), + colours.GrayC.Opacity(0.9f)), + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f, 1), + }, + new Box + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + ColourInfo = ColourInfo.GradientHorizontal( + colours.GrayC.Opacity(0.9f), + colours.GrayC.Opacity(0)), + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.5f, 1), + }, + } + }, + statisticsContainer = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Direction = FillDirection.Horizontal, + LayoutDuration = 200, + LayoutEasing = EasingTypes.OutQuint + } + } + } + }; + + statisticsContainer.Children = Score.Statistics.Select(s => new DrawableScoreStatistic(s)); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Schedule(() => + { + scoreCounter.Increment(Score.TotalScore); + + int delay = 0; + foreach (var s in statisticsContainer.Children) + { + s.FadeOut(); + s.Delay(delay += 200); + s.FadeIn(300 + delay, EasingTypes.Out); + } + }); + } + + private class DrawableScoreStatistic : Container + { + private readonly KeyValuePair statistic; + + public DrawableScoreStatistic(KeyValuePair statistic) + { + this.statistic = statistic; + + AutoSizeAxes = Axes.Both; + Margin = new MarginPadding { Left = 5, Right = 5 }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + new SpriteText { + Text = statistic.Value.ToString().PadLeft(4, '0'), + Colour = colours.Gray7, + TextSize = 30, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }, + new SpriteText { + Text = statistic.Key, + Colour = colours.Gray7, + Font = @"Exo2.0-Bold", + Y = 26, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }, + }; + } + } + + private class DateDisplay : Container + { + private DateTime date; + + public DateDisplay(DateTime date) + { + this.date = date; + + AutoSizeAxes = Axes.Y; + + Width = 140; + + Masking = true; + CornerRadius = 5; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colours.Gray6, + }, + new OsuSpriteText + { + Origin = Anchor.CentreLeft, + Anchor = Anchor.CentreLeft, + Text = date.ToString("HH:mm"), + Padding = new MarginPadding { Left = 10, Right = 10, Top = 5, Bottom = 5 }, + Colour = Color4.White, + }, + new OsuSpriteText + { + Origin = Anchor.CentreRight, + Anchor = Anchor.CentreRight, + Text = date.ToString("yyyy/MM/dd"), + Padding = new MarginPadding { Left = 10, Right = 10, Top = 5, Bottom = 5 }, + Colour = Color4.White, + } + }; + } + } + + private class BeatmapDetails : Container + { + private readonly BeatmapInfo beatmap; + + private Bindable preferUnicode; + + private readonly OsuSpriteText title; + private readonly OsuSpriteText artist; + private readonly OsuSpriteText versionMapper; + + public BeatmapDetails(BeatmapInfo beatmap) + { + this.beatmap = beatmap; + + AutoSizeAxes = Axes.Both; + + Children = new Drawable[] + { + new FillFlowContainer + { + Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + title = new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Shadow = false, + TextSize = 24, + Font = @"Exo2.0-BoldItalic", + }, + artist = new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Shadow = false, + TextSize = 20, + Font = @"Exo2.0-BoldItalic", + }, + versionMapper = new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Shadow = false, + TextSize = 16, + Font = @"Exo2.0-Bold", + }, + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, OsuConfigManager config) + { + title.Colour = artist.Colour = colours.BlueDarker; + versionMapper.Colour = colours.Gray8; + + versionMapper.Text = $"{beatmap.Version} - mapped by {beatmap.Metadata.Author}"; + + preferUnicode = config.GetBindable(OsuConfig.ShowUnicode); + preferUnicode.ValueChanged += unicode => + { + title.Text = unicode ? beatmap.Metadata.TitleUnicode : beatmap.Metadata.Title; + artist.Text = unicode ? beatmap.Metadata.ArtistUnicode : beatmap.Metadata.Artist; + }; + preferUnicode.TriggerChange(); + } + } + + private class UserHeader : Container + { + private readonly User user; + private readonly Sprite cover; + + public UserHeader(User user) + { + this.user = user; + Children = new Drawable[] + { + cover = new Sprite + { + FillMode = FillMode.Fill, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }, + new OsuSpriteText + { + Font = @"Exo2.0-RegularItalic", + Text = user.Username, + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + TextSize = 30, + Padding = new MarginPadding { Bottom = 10 }, + } + }; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + if (!string.IsNullOrEmpty(user.CoverUrl)) + cover.Texture = textures.Get(user.CoverUrl); + } + } + + private class SlowScoreCounter : ScoreCounter + { + protected override double RollingDuration => 3000; + + protected override EasingTypes RollingEasing => EasingTypes.OutPow10; + + public SlowScoreCounter(uint leading = 0) : base(leading) + { + DisplayedCountSpriteText.Shadow = false; + DisplayedCountSpriteText.Font = @"Venera-Light"; + UseCommaSeparator = true; + } + } + } +} diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index bebdbb8c2a..04432058dc 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -7,12 +7,15 @@ using osu.Framework.Screens; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.Sprites; using osu.Game.Screens.Backgrounds; using osu.Game.Graphics.UserInterface; using OpenTK; using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Game.Graphics; +using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Screens { @@ -24,8 +27,8 @@ namespace osu.Game.Screens protected virtual IEnumerable PossibleChildren => null; - private readonly Container textContainer; - private readonly Box box; + private readonly FillFlowContainer textContainer; + private readonly Container boxContainer; protected override BackgroundScreen CreateBackground() => new BackgroundScreenCustom(@"Backgrounds/bg2"); @@ -33,20 +36,20 @@ namespace osu.Game.Screens { base.OnEntering(last); - //only show the pop button if we are entered form another gamemode. + //only show the pop button if we are entered form another screen. if (last != null) popButton.Alpha = 1; Content.Alpha = 0; textContainer.Position = new Vector2(DrawSize.X / 16, 0); - box.ScaleTo(0.2f); - box.RotateTo(-20); + boxContainer.ScaleTo(0.2f); + boxContainer.RotateTo(-20); Content.Delay(300, true); - box.ScaleTo(1, transition_time, EasingTypes.OutElastic); - box.RotateTo(0, transition_time / 2, EasingTypes.OutQuint); + boxContainer.ScaleTo(1, transition_time, EasingTypes.OutElastic); + boxContainer.RotateTo(0, transition_time / 2, EasingTypes.OutQuint); textContainer.MoveTo(Vector2.Zero, transition_time, EasingTypes.OutExpo); Content.FadeIn(transition_time, EasingTypes.OutExpo); @@ -82,36 +85,62 @@ namespace osu.Game.Screens Children = new Drawable[] { - box = new Box + boxContainer = new Container { - RelativeSizeAxes = Axes.Both, Size = new Vector2(0.3f), + RelativeSizeAxes = Axes.Both, + CornerRadius = 20, + Masking = true, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Colour = getColourFor(GetType()), - Alpha = 1, - BlendingMode = BlendingMode.Additive, - }, - textContainer = new Container - { - AutoSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Children = new[] + Children = new Drawable[] { - new OsuSpriteText + new Box { - Text = GetType().Name, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - TextSize = 50, + RelativeSizeAxes = Axes.Both, + + Colour = getColourFor(GetType()), + Alpha = 0.2f, + BlendingMode = BlendingMode.Additive, }, - new OsuSpriteText + textContainer = new FillFlowContainer { - Text = GetType().Namespace, + AutoSizeAxes = Axes.Both, Anchor = Anchor.Centre, Origin = Anchor.Centre, - Position = new Vector2(0, 30) + Direction = FillDirection.Vertical, + Children = new[] + { + new TextAwesome + { + Icon = FontAwesome.fa_universal_access, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextSize = 50, + }, + new OsuSpriteText + { + Text = GetType().Name, + Colour = getColourFor(GetType()).Lighten(0.8f), + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + TextSize = 50, + }, + new OsuSpriteText + { + Text = "is not yet ready for use!", + TextSize = 20, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }, + new OsuSpriteText + { + Text = "please check back a bit later.", + TextSize = 14, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }, + } }, } }, @@ -120,17 +149,15 @@ namespace osu.Game.Screens Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Alpha = 0, - Action = delegate { - Exit(); - } + Action = Exit }, childModeButtons = new FillFlowContainer { Direction = FillDirection.Vertical, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.1f, 1) + RelativeSizeAxes = Axes.Y, + Size = new Vector2(TwoLayerButton.SIZE_RETRACTED.X, 1) } }; @@ -138,14 +165,11 @@ namespace osu.Game.Screens { foreach (Type t in PossibleChildren) { - childModeButtons.Add(new Button + childModeButtons.Add(new ChildModeButton { Text = $@"{t.Name}", - RelativeSizeAxes = Axes.X, - Size = new Vector2(1, 40), - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, BackgroundColour = getColourFor(t), + HoverColour = getColourFor(t).Lighten(0.2f), Action = delegate { Push(Activator.CreateInstance(t) as Screen); @@ -163,5 +187,21 @@ namespace osu.Game.Screens byte b = (byte)MathHelper.Clamp((hash & 0x0000FF) * 0.8f, 20, 255); return new Color4(r, g, b, 255); } + + public class ChildModeButton : TwoLayerButton + { + public ChildModeButton() + { + Icon = FontAwesome.fa_osu_right_o; + Anchor = Anchor.BottomRight; + Origin = Anchor.BottomRight; + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + ActivationSound = audio.Sample.Get(@"Menu/menuhit"); + } + } } } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index f104bf9a37..06aaea041a 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -145,7 +145,7 @@ namespace osu.Game.Screens.Select } } - int startIndex = groups.IndexOf(selectedGroup); + int startIndex = Math.Max(0, groups.IndexOf(selectedGroup)); int index = startIndex; do @@ -221,7 +221,12 @@ namespace osu.Game.Screens.Select private BeatmapGroup createGroup(BeatmapSetInfo beatmapSet) { database.GetChildren(beatmapSet); - beatmapSet.Beatmaps.ForEach(b => { if (b.Metadata == null) b.Metadata = beatmapSet.Metadata; }); + beatmapSet.Beatmaps.ForEach(b => + { + database.GetChildren(b); + if (b.Metadata == null) + b.Metadata = beatmapSet.Metadata; + }); return new BeatmapGroup(beatmapSet, database) { diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 768cef4645..a87d5f58a1 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -18,9 +18,9 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Modes; -using osu.Game.Modes.Objects; -using osu.Game.Modes.Objects.Types; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Screens.Select { @@ -47,6 +47,8 @@ namespace osu.Game.Screens.Select protected override bool HideOnEscape => false; + protected override bool BlockPassThroughMouse => false; + protected override void PopIn() { MoveToX(0, 800, EasingTypes.OutQuint); @@ -100,7 +102,7 @@ namespace osu.Game.Screens.Select })); //get statistics fromt he current ruleset. - labels.AddRange(Ruleset.GetRuleset(beatmap.BeatmapInfo.Mode).GetBeatmapStatistics(beatmap).Select(s => new InfoLabel(s))); + labels.AddRange(beatmap.BeatmapInfo.Ruleset.CreateInstance().GetBeatmapStatistics(beatmap).Select(s => new InfoLabel(s))); } AlwaysPresent = true; diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 7596af1484..e0b197e9ca 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -16,7 +16,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Select.Filter; using Container = osu.Framework.Graphics.Containers.Container; using osu.Framework.Input; -using osu.Game.Modes; +using osu.Game.Database; namespace osu.Game.Screens.Select { @@ -61,7 +61,7 @@ namespace osu.Game.Screens.Select Group = group, Sort = sort, SearchText = searchTextBox.Text, - Mode = playMode + Ruleset = ruleset }; public Action Exit; @@ -163,16 +163,17 @@ namespace osu.Game.Screens.Select searchTextBox.HoldFocus = true; } - private readonly Bindable playMode = new Bindable(); + private readonly Bindable ruleset = new Bindable(); [BackgroundDependencyLoader(permitNulls:true)] private void load(OsuColour colours, OsuGame osu) { sortTabs.AccentColour = colours.GreenLight; - if (osu != null) playMode.BindTo(osu.PlayMode); - playMode.ValueChanged += val => FilterChanged?.Invoke(CreateCriteria()); - playMode.TriggerChange(); + if (osu != null) + ruleset.BindTo(osu.Ruleset); + ruleset.ValueChanged += val => FilterChanged?.Invoke(CreateCriteria()); + ruleset.TriggerChange(); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 2654129a44..d49c7296ba 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps.Drawables; -using osu.Game.Modes; +using osu.Game.Database; using osu.Game.Screens.Select.Filter; namespace osu.Game.Screens.Select @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Select public GroupMode Group; public SortMode Sort; public string SearchText; - public PlayMode Mode; + public RulesetInfo Ruleset; public void Filter(List groups) { @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Select { var set = g.BeatmapSet; - bool hasCurrentMode = set.Beatmaps.Any(bm => bm.Mode == Mode); + bool hasCurrentMode = set.Beatmaps.Any(bm => bm.RulesetID == (Ruleset?.ID ?? 0)); bool match = hasCurrentMode; diff --git a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs index 1e9d6dc831..647398db9e 100644 --- a/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs +++ b/osu.Game/Screens/Select/Leaderboards/DrawableRank.cs @@ -7,7 +7,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Extensions; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Screens.Select.Leaderboards { diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index 315611a60c..2c51429d4c 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -12,7 +12,7 @@ using osu.Framework.Graphics.Primitives; using System; using osu.Framework.Allocation; using osu.Game.Database; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Scoring; using osu.Game.Online.API; using osu.Game.Online.API.Requests; @@ -23,6 +23,8 @@ namespace osu.Game.Screens.Select.Leaderboards private readonly ScrollContainer scrollContainer; private readonly FillFlowContainer scrollFlow; + public Action ScoreSelected; + private IEnumerable scores; public IEnumerable Scores { @@ -52,6 +54,7 @@ namespace osu.Game.Screens.Select.Leaderboards var ls = new LeaderboardScore(s, 1 + i) { AlwaysPresent = true, + Action = () => ScoreSelected?.Invoke(s), State = Visibility.Hidden, }; scrollFlow.Add(ls); diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs index 493f351b75..8df95f6913 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs @@ -10,14 +10,14 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Framework.Extensions.Color4Extensions; -using osu.Game.Modes.Mods; +using osu.Game.Rulesets.Mods; using osu.Game.Users; using osu.Framework; -using osu.Game.Modes.Scoring; +using osu.Game.Rulesets.Scoring; namespace osu.Game.Screens.Select.Leaderboards { - public class LeaderboardScore : Container, IStateful + public class LeaderboardScore : ClickableContainer, IStateful { public static readonly float HEIGHT = 60; @@ -204,7 +204,7 @@ namespace osu.Game.Screens.Select.Leaderboards Children = new Drawable[] { maxCombo = new ScoreComponentLabel(FontAwesome.fa_link, Score.MaxCombo.ToString()), - accuracy = new ScoreComponentLabel(FontAwesome.fa_crosshairs, string.Format(Score.Accuracy % 1 == 0 ? @"{0:0}" : @"{0:0.00}", Score.Accuracy)), + accuracy = new ScoreComponentLabel(FontAwesome.fa_crosshairs, string.Format(Score.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", Score.Accuracy)), }, }, }, diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 78a8e4c177..c15900eb6d 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -12,6 +12,7 @@ using osu.Game.Graphics; using osu.Game.Overlays.Mods; using osu.Game.Screens.Edit; using osu.Game.Screens.Play; +using osu.Game.Screens.Ranking; namespace osu.Game.Screens.Select { @@ -35,6 +36,8 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = 10, Right = 5 }, }); + + beatmapDetails.Leaderboard.ScoreSelected += s => Push(new Results(s)); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 3e8ddc0f64..182158fa5d 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -20,7 +20,6 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Modes; using osu.Game.Overlays; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Select.Options; @@ -29,7 +28,7 @@ namespace osu.Game.Screens.Select { public abstract class SongSelect : OsuScreen { - private readonly Bindable playMode = new Bindable(); + private readonly Bindable ruleset = new Bindable(); private BeatmapDatabase database; protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); @@ -170,8 +169,8 @@ namespace osu.Game.Screens.Select if (database == null) database = beatmaps; - playMode.ValueChanged += val => { if (Beatmap != null) Beatmap.PreferredPlayMode = val; }; - if (osu != null) playMode.BindTo(osu.PlayMode); + if (osu != null) + ruleset.BindTo(osu.Ruleset); database.BeatmapSetAdded += onBeatmapSetAdded; database.BeatmapSetRemoved += onBeatmapSetRemoved; @@ -200,7 +199,6 @@ namespace osu.Game.Screens.Select { if (Beatmap == null) return; - Beatmap.PreferredPlayMode = playMode.Value; OnSelected(); } diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs index 960b452682..729629bdb8 100644 --- a/osu.Game/Users/Country.cs +++ b/osu.Game/Users/Country.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -14,6 +15,7 @@ namespace osu.Game.Users /// /// The name of this country. /// + [JsonProperty(@"name")] public string FullName; /// @@ -24,6 +26,7 @@ namespace osu.Game.Users /// /// Two-letter flag acronym (ISO 3166 standard) /// + [JsonProperty(@"code")] public string FlagName; } diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 6e1de7e3ac..1361eefcff 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -13,11 +13,36 @@ namespace osu.Game.Users [JsonProperty(@"username")] public string Username; + [JsonProperty(@"country_code")] + public string CountryCode; + + [JsonProperty(@"country")] public Country Country; - public Team Team; + //public Team Team; - [JsonProperty(@"colour")] + [JsonProperty(@"profile_colour")] public string Colour; + + [JsonProperty(@"avatar_url")] + public string AvatarUrl; + + [JsonProperty(@"cover_url")] + public string CoverUrl; + + //[JsonProperty(@"cover")] + //public UserCover Cover; + + public class UserCover + { + [JsonProperty(@"custom_url")] + public string CustomUrl; + + [JsonProperty(@"url")] + public string Url; + + [JsonProperty(@"id")] + public int? Id; + } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f810eeec96..49cc32a6b6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,6 +24,7 @@ prompt 4 false + 6 pdbonly @@ -56,6 +57,7 @@ $(SolutionDir)\packages\SQLite.Net-PCL.3.1.1\lib\net4\SQLite.Net.Platform.Win32.dll True + @@ -71,17 +73,22 @@ - - + + + + + + + @@ -94,49 +101,82 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -148,8 +188,8 @@ - - + + @@ -181,6 +221,10 @@ + + + + @@ -203,7 +247,11 @@ - + + + + + @@ -216,17 +264,16 @@ - - + - - + + - - + + @@ -343,9 +390,9 @@ - + - + @@ -364,7 +411,7 @@ - + diff --git a/osu.sln b/osu.sln index c200d2e586..317cfe7da4 100644 --- a/osu.sln +++ b/osu.sln @@ -21,13 +21,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Desktop.VisualTests", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Tests", "osu.Game.Tests\osu.Game.Tests.csproj", "{54377672-20B1-40AF-8087-5CF73BF3953A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Modes.Osu", "osu.Game.Modes.Osu\osu.Game.Modes.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Osu", "osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj", "{C92A607B-1FDD-4954-9F92-03FF547D9080}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Modes.Catch", "osu.Game.Modes.Catch\osu.Game.Modes.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Catch", "osu.Game.Rulesets.Catch\osu.Game.Rulesets.Catch.csproj", "{58F6C80C-1253-4A0E-A465-B8C85EBEADF3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Modes.Taiko", "osu.Game.Modes.Taiko\osu.Game.Modes.Taiko.csproj", "{F167E17A-7DE6-4AF5-B920-A5112296C695}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Taiko", "osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj", "{F167E17A-7DE6-4AF5-B920-A5112296C695}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Modes.Mania", "osu.Game.Modes.Mania\osu.Game.Modes.Mania.csproj", "{48F4582B-7687-4621-9CBE-5C24197CB536}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Mania", "osu.Game.Rulesets.Mania\osu.Game.Rulesets.Mania.csproj", "{48F4582B-7687-4621-9CBE-5C24197CB536}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Desktop.Tests", "osu.Desktop.Tests\osu.Desktop.Tests.csproj", "{230AC4F3-7783-49FB-9AEC-B83CDA3B9F3D}" EndProject