diff --git a/osu-framework b/osu-framework index 6b44a9f807..2204764944 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 6b44a9f807fadcb3b3f044780d7e27d62ffe80ac +Subproject commit 2204764944ff693e857649253547054cc91764a0 diff --git a/osu.Desktop.VisualTests/Tests/TestCaseBeatSyncedContainer.cs b/osu.Desktop.VisualTests/Tests/TestCaseBeatSyncedContainer.cs index 5e9b976c8a..50d1df9964 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseBeatSyncedContainer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseBeatSyncedContainer.cs @@ -177,9 +177,7 @@ namespace osu.Desktop.VisualTests.Tests beatsPerMinute.Value = 60000 / timingPoint.BeatLength; adjustedBeatLength.Value = timingPoint.BeatLength; - flashLayer.ClearTransforms(); - flashLayer.FadeTo(1); - flashLayer.FadeTo(0, timingPoint.BeatLength); + flashLayer.FadeOutFromOne(timingPoint.BeatLength); } } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs index 9335938265..111bc03377 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseBeatmapDetails.cs @@ -3,9 +3,9 @@ using osu.Framework.Graphics; using osu.Framework.Testing; -using osu.Game.Database; using osu.Game.Screens.Select; using System.Linq; +using osu.Game.Beatmaps; namespace osu.Desktop.VisualTests.Tests { diff --git a/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs b/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs index f9dc424153..0b4e8a5799 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseContextMenu.cs @@ -59,20 +59,13 @@ namespace osu.Desktop.VisualTests.Tests { base.LoadComplete(); - using (container.BeginLoopedSequence()) - { - container.MoveTo(new Vector2(0, 100), duration); - using (container.BeginDelayedSequence(duration)) - { - container.MoveTo(new Vector2(100, 100), duration); - using (container.BeginDelayedSequence(duration)) - { - container.MoveTo(new Vector2(100, 0), duration); - using (container.BeginDelayedSequence(duration)) - container.MoveTo(Vector2.Zero, duration); - } - } - } + // Move box along a square trajectory + container.Loop(c => c + .MoveTo(new Vector2(0, 100), duration).Then() + .MoveTo(new Vector2(100, 100), duration).Then() + .MoveTo(new Vector2(100, 0), duration).Then() + .MoveTo(Vector2.Zero, duration) + ); } private class MyContextMenuContainer : Container, IHasContextMenu @@ -95,10 +88,10 @@ namespace osu.Desktop.VisualTests.Tests { new OsuContextMenuItem(@"Simple option"), new OsuContextMenuItem(@"Simple very very long option"), - new OsuContextMenuItem(@"Change width", MenuItemType.Highlighted) { Action = () => ResizeWidthTo(Width * 2, 100, EasingTypes.OutQuint) }, - new OsuContextMenuItem(@"Change height", MenuItemType.Highlighted) { Action = () => ResizeHeightTo(Height * 2, 100, EasingTypes.OutQuint) }, - new OsuContextMenuItem(@"Change width back", MenuItemType.Destructive) { Action = () => ResizeWidthTo(Width / 2, 100, EasingTypes.OutQuint) }, - new OsuContextMenuItem(@"Change height back", MenuItemType.Destructive) { Action = () => ResizeHeightTo(Height / 2, 100, EasingTypes.OutQuint) }, + new OsuContextMenuItem(@"Change width", MenuItemType.Highlighted) { Action = () => this.ResizeWidthTo(Width * 2, 100, Easing.OutQuint) }, + new OsuContextMenuItem(@"Change height", MenuItemType.Highlighted) { Action = () => this.ResizeHeightTo(Height * 2, 100, Easing.OutQuint) }, + new OsuContextMenuItem(@"Change width back", MenuItemType.Destructive) { Action = () => this.ResizeWidthTo(Width / 2, 100, Easing.OutQuint) }, + new OsuContextMenuItem(@"Change height back", MenuItemType.Destructive) { Action = () => this.ResizeHeightTo(Height / 2, 100, Easing.OutQuint) }, }; } } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs b/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs index 2a20bca836..4a5ff1b576 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs @@ -4,8 +4,9 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Testing; -using osu.Game.Database; +using osu.Game.Beatmaps; using osu.Game.Overlays; +using osu.Game.Rulesets; namespace osu.Desktop.VisualTests.Tests { @@ -14,7 +15,7 @@ namespace osu.Desktop.VisualTests.Tests public override string Description => @"osu!direct overlay"; private DirectOverlay direct; - private RulesetDatabase rulesets; + private RulesetStore rulesets; protected override void LoadComplete() { @@ -28,7 +29,7 @@ namespace osu.Desktop.VisualTests.Tests } [BackgroundDependencyLoader] - private void load(RulesetDatabase rulesets) + private void load(RulesetStore rulesets) { this.rulesets = rulesets; } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs b/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs index 4f4ef9bbb5..38cf03d60e 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs @@ -7,8 +7,9 @@ using osu.Framework.Testing; using osu.Game.Screens.Multiplayer; using osu.Game.Online.Multiplayer; using osu.Game.Users; -using osu.Game.Database; using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; namespace osu.Desktop.VisualTests.Tests { @@ -16,7 +17,7 @@ namespace osu.Desktop.VisualTests.Tests { public override string Description => @"Select your favourite room"; - private RulesetDatabase rulesets; + private RulesetStore rulesets; protected override void LoadComplete() { @@ -124,7 +125,7 @@ namespace osu.Desktop.VisualTests.Tests } [BackgroundDependencyLoader] - private void load(RulesetDatabase rulesets) + private void load(RulesetStore rulesets) { this.rulesets = rulesets; } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs index 0c5f21a185..0b08065241 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs @@ -8,7 +8,6 @@ using osu.Framework.MathUtils; using osu.Framework.Testing; using osu.Framework.Timing; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Objects; @@ -19,17 +18,18 @@ using System.Collections.Generic; using osu.Desktop.VisualTests.Beatmaps; using osu.Framework.Allocation; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets; namespace osu.Desktop.VisualTests.Tests { internal class TestCaseGamefield : TestCase { - private RulesetDatabase rulesets; + private RulesetStore rulesets; public override string Description => @"Showing hitobjects and what not."; [BackgroundDependencyLoader] - private void load(RulesetDatabase rulesets) + private void load(RulesetStore rulesets) { this.rulesets = rulesets; } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs b/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs index 87a40a76ca..f65dbe7a64 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseKeyCounter.cs @@ -96,7 +96,7 @@ namespace osu.Desktop.VisualTests.Tests { SelectionBox.ScaleTo( new Vector2(value, 1), - 300, EasingTypes.OutQuint); + 300, Easing.OutQuint); } } } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs b/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs index bab471ed6a..ea2f0464c4 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseMenuButtonSystem.cs @@ -17,7 +17,7 @@ namespace osu.Desktop.VisualTests.Tests { Add(new Box { - ColourInfo = ColourInfo.GradientVertical(Color4.Gray, Color4.WhiteSmoke), + Colour = ColourInfo.GradientVertical(Color4.Gray, Color4.WhiteSmoke), RelativeSizeAxes = Framework.Graphics.Axes.Both, }); Add(new ButtonSystem()); diff --git a/osu.Desktop.VisualTests/Tests/TestCaseMods.cs b/osu.Desktop.VisualTests/Tests/TestCaseMods.cs index e626a70e5f..1604be603a 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseMods.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseMods.cs @@ -5,7 +5,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Overlays.Mods; using osu.Framework.Testing; -using osu.Game.Database; +using osu.Game.Rulesets; using osu.Game.Screens.Play.HUD; using OpenTK; @@ -18,11 +18,11 @@ namespace osu.Desktop.VisualTests.Tests private ModSelectOverlay modSelect; private ModDisplay modDisplay; - private RulesetDatabase rulesets; + private RulesetStore rulesets; [BackgroundDependencyLoader] - private void load(RulesetDatabase rulesets) + private void load(RulesetStore rulesets) { this.rulesets = rulesets; } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs b/osu.Desktop.VisualTests/Tests/TestCaseNotificationOverlay.cs similarity index 88% rename from osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs rename to osu.Desktop.VisualTests/Tests/TestCaseNotificationOverlay.cs index 4ba50c8220..3b9c251670 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseNotificationManager.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseNotificationOverlay.cs @@ -12,17 +12,17 @@ using osu.Framework.Graphics.Containers; namespace osu.Desktop.VisualTests.Tests { - internal class TestCaseNotificationManager : TestCase + internal class TestCaseNotificationOverlay : TestCase { public override string Description => @"I handle notifications"; - private readonly NotificationManager manager; + private readonly NotificationOverlay manager; - public TestCaseNotificationManager() + public TestCaseNotificationOverlay() { progressingNotifications.Clear(); - Content.Add(manager = new NotificationManager + Content.Add(manager = new NotificationOverlay { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, @@ -56,10 +56,7 @@ namespace osu.Desktop.VisualTests.Tests } if (remaining > 0) - { - Delay(80); - Schedule(() => sendBarrage(remaining - 1)); - } + Scheduler.AddDelayed(() => sendBarrage(remaining - 1), 80); } protected override void Update() diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index 83a1436357..51c78ff442 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using osu.Desktop.VisualTests.Platform; using osu.Framework.Testing; using osu.Framework.MathUtils; +using osu.Game.Beatmaps; using osu.Game.Database; +using osu.Game.Rulesets; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Filter; @@ -13,31 +15,28 @@ namespace osu.Desktop.VisualTests.Tests { internal class TestCasePlaySongSelect : TestCase { - private readonly BeatmapDatabase db; + private readonly BeatmapManager manager; public override string Description => @"with fake data"; - private readonly RulesetDatabase rulesets; + private readonly RulesetStore rulesets; public TestCasePlaySongSelect() { PlaySongSelect songSelect; - if (db == null) + if (manager == null) { var storage = new TestStorage(@"TestCasePlaySongSelect"); var backingDatabase = storage.GetDatabase(@"client"); + backingDatabase.CreateTable(); - rulesets = new RulesetDatabase(storage, backingDatabase); - db = new BeatmapDatabase(storage, backingDatabase, rulesets); - - var sets = new List(); + rulesets = new RulesetStore(backingDatabase); + manager = new BeatmapManager(storage, null, backingDatabase, rulesets); for (int i = 0; i < 100; i += 10) - sets.Add(createTestBeatmapSet(i)); - - db.Import(sets); + manager.Import(createTestBeatmapSet(i)); } Add(songSelect = new PlaySongSelect()); @@ -48,21 +47,12 @@ namespace osu.Desktop.VisualTests.Tests AddStep(@"Sort by Difficulty", delegate { songSelect.FilterControl.Sort = SortMode.Difficulty; }); } - //protected override void Dispose(bool isDisposing) - //{ - // if (oldDb != null) - // db = null; - - // base.Dispose(isDisposing); - //} - private BeatmapSetInfo createTestBeatmapSet(int i) { return new BeatmapSetInfo { OnlineBeatmapSetID = 1234 + i, Hash = "d8e8fca2dc0f896fd7cb4cb0031ba249", - Path = string.Empty, Metadata = new BeatmapMetadata { OnlineBeatmapSetID = 1234 + i, diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index 088ccb2aa3..f38cabd618 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Game.Beatmaps; using OpenTK; -using osu.Game.Database; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Screens.Play; @@ -14,18 +13,19 @@ using OpenTK.Graphics; using osu.Desktop.VisualTests.Beatmaps; using osu.Game.Rulesets.Osu.UI; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets; namespace osu.Desktop.VisualTests.Tests { internal class TestCasePlayer : TestCase { protected Player Player; - private RulesetDatabase rulesets; + private RulesetStore rulesets; public override string Description => @"Showing everything to play the game."; [BackgroundDependencyLoader] - private void load(RulesetDatabase rulesets) + private void load(RulesetStore rulesets) { this.rulesets = rulesets; } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseResults.cs b/osu.Desktop.VisualTests/Tests/TestCaseResults.cs index 4a980068b9..288fff346f 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseResults.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseResults.cs @@ -3,11 +3,9 @@ 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; @@ -16,14 +14,14 @@ namespace osu.Desktop.VisualTests.Tests { internal class TestCaseResults : TestCase { - private BeatmapDatabase db; + private BeatmapManager beatmaps; public override string Description => @"Results after playing."; [BackgroundDependencyLoader] - private void load(BeatmapDatabase db) + private void load(BeatmapManager beatmaps) { - this.db = db; + this.beatmaps = beatmaps; } private WorkingBeatmap beatmap; @@ -34,9 +32,9 @@ namespace osu.Desktop.VisualTests.Tests if (beatmap == null) { - var beatmapInfo = db.Query().FirstOrDefault(b => b.RulesetID == 0); + var beatmapInfo = beatmaps.QueryBeatmap(b => b.RulesetID == 0); if (beatmapInfo != null) - beatmap = db.GetWorkingBeatmap(beatmapInfo); + beatmap = beatmaps.GetWorkingBeatmap(beatmapInfo); } Add(new Results(new Score diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs index 4d650afed5..043f072b25 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs @@ -4,10 +4,11 @@ using osu.Framework.Testing; using osu.Framework.Graphics; using osu.Game.Screens.Multiplayer; -using osu.Game.Database; using osu.Game.Online.Multiplayer; using osu.Game.Users; using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; namespace osu.Desktop.VisualTests.Tests { @@ -15,7 +16,7 @@ namespace osu.Desktop.VisualTests.Tests { public override string Description => @"from the multiplayer lobby"; - private RulesetDatabase rulesets; + private RulesetStore rulesets; protected override void LoadComplete() { @@ -135,7 +136,7 @@ namespace osu.Desktop.VisualTests.Tests } [BackgroundDependencyLoader] - private void load(RulesetDatabase rulesets) + private void load(RulesetStore rulesets) { this.rulesets = rulesets; } diff --git a/osu.Desktop.VisualTests/Tests/TestCaseScrollingHitObjects.cs b/osu.Desktop.VisualTests/Tests/TestCaseScrollingHitObjects.cs index 8e5cf8687c..43f30a96b0 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseScrollingHitObjects.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseScrollingHitObjects.cs @@ -196,7 +196,7 @@ namespace osu.Desktop.VisualTests.Tests protected override void LoadComplete() { base.LoadComplete(); - FadeInFromZero(250, EasingTypes.OutQuint); + this.FadeInFromZero(250, Easing.OutQuint); } protected override void Update() diff --git a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs index 00929c06c2..8ca129eb91 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseTaikoPlayfield.cs @@ -67,6 +67,8 @@ namespace osu.Desktop.VisualTests.Tests private void changePlayfieldSize(int step) { + double delay = 0; + // Add new hits switch (step) { @@ -84,7 +86,7 @@ namespace osu.Desktop.VisualTests.Tests break; case 5: addSwell(1000); - playfieldContainer.Delay(scroll_time - 100); + delay = scroll_time - 100; break; } @@ -92,10 +94,10 @@ namespace osu.Desktop.VisualTests.Tests switch (step) { default: - playfieldContainer.ResizeTo(new Vector2(1, rng.Next(25, 400)), 500); + playfieldContainer.Delay(delay).ResizeTo(new Vector2(1, rng.Next(25, 400)), 500); break; case 6: - playfieldContainer.ResizeTo(new Vector2(1, TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT), 500); + playfieldContainer.Delay(delay).ResizeTo(new Vector2(1, TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT), 500); break; } } diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj index 4974f0c0d1..1f4fd80ca6 100644 --- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj +++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj @@ -198,7 +198,7 @@ - + diff --git a/osu.Desktop/Beatmaps/IO/LegacyFilesystemReader.cs b/osu.Desktop/Beatmaps/IO/LegacyFilesystemReader.cs deleted file mode 100644 index 8772fc9f28..0000000000 --- a/osu.Desktop/Beatmaps/IO/LegacyFilesystemReader.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.IO; -using System.Linq; -using osu.Game.Beatmaps.IO; - -namespace osu.Desktop.Beatmaps.IO -{ - /// - /// Reads an extracted legacy beatmap from disk. - /// - public class LegacyFilesystemReader : ArchiveReader - { - public static void Register() => AddReader((storage, path) => Directory.Exists(path)); - - private readonly string basePath; - - public LegacyFilesystemReader(string path) - { - basePath = path; - - BeatmapFilenames = Directory.GetFiles(basePath, @"*.osu").Select(Path.GetFileName).ToArray(); - - if (BeatmapFilenames.Length == 0) - throw new FileNotFoundException(@"This directory contains no beatmaps"); - - StoryboardFilename = Directory.GetFiles(basePath, @"*.osb").Select(Path.GetFileName).FirstOrDefault(); - } - - public override Stream GetStream(string name) - { - return File.OpenRead(Path.Combine(basePath, name)); - } - - public override void Dispose() - { - // no-op - } - - public override Stream GetUnderlyingStream() => null; - } -} diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs index a2bfe6bf2e..bd5c6c6790 100644 --- a/osu.Desktop/OsuGameDesktop.cs +++ b/osu.Desktop/OsuGameDesktop.cs @@ -65,11 +65,11 @@ namespace osu.Desktop var filePaths = dropData.Select(f => f.ToString()).ToArray(); if (filePaths.All(f => Path.GetExtension(f) == @".osz")) - Task.Run(() => BeatmapDatabase.Import(filePaths)); + Task.Run(() => BeatmapManager.Import(filePaths)); else if (filePaths.All(f => Path.GetExtension(f) == @".osr")) Task.Run(() => { - var score = ScoreDatabase.ReadReplayFile(filePaths.First()); + var score = ScoreStore.ReadReplayFile(filePaths.First()); Schedule(() => LoadScore(score)); }); } diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs index a8ab97ce37..6983c51c7d 100644 --- a/osu.Desktop/Overlays/VersionManager.cs +++ b/osu.Desktop/Overlays/VersionManager.cs @@ -25,16 +25,16 @@ namespace osu.Desktop.Overlays public class VersionManager : OverlayContainer { private UpdateManager updateManager; - private NotificationManager notificationManager; + private NotificationOverlay notificationOverlay; protected override bool HideOnEscape => false; public override bool HandleInput => false; [BackgroundDependencyLoader] - private void load(NotificationManager notification, OsuColour colours, TextureStore textures, OsuGameBase game) + private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game) { - notificationManager = notification; + notificationOverlay = notification; AutoSizeAxes = Axes.Both; Anchor = Anchor.BottomCentre; @@ -116,7 +116,7 @@ namespace osu.Desktop.Overlays if (notification == null) { notification = new UpdateProgressNotification { State = ProgressNotificationState.Active }; - Schedule(() => notificationManager.Post(notification)); + Schedule(() => notificationOverlay.Post(notification)); } Schedule(() => @@ -175,7 +175,7 @@ namespace osu.Desktop.Overlays protected override void PopIn() { - FadeIn(1000); + this.FadeIn(1000); } protected override void PopOut() @@ -207,7 +207,7 @@ namespace osu.Desktop.Overlays new Box { RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientVertical(colours.YellowDark, colours.Yellow) + Colour = ColourInfo.GradientVertical(colours.YellowDark, colours.Yellow) }, new TextAwesome { diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 210f780078..3b63239525 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -3,7 +3,6 @@ using System; using System.IO; -using osu.Desktop.Beatmaps.IO; using osu.Framework.Desktop; using osu.Framework.Desktop.Platform; using osu.Game.IPC; @@ -15,8 +14,6 @@ namespace osu.Desktop [STAThread] public static int Main(string[] args) { - LegacyFilesystemReader.Register(); - // Back up the cwd before DesktopGameHost changes it var cwd = Environment.CurrentDirectory; diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index e69603602c..82fbefec7a 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -228,7 +228,6 @@ - diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs index 0ed2a0ba6f..b55b9fdb37 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Mania.Beatmaps.Patterns; using osu.Game.Rulesets.Mania.MathUtils; -using osu.Game.Database; using osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy; using OpenTK; using osu.Game.Audio; diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs index e6e3f1d07f..b72618c36c 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/PatternGenerator.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Objects; using OpenTK; diff --git a/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs b/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs index 674d83f6f2..52b55a4ff5 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HitWindows.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HitWindows.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.Database; +using osu.Game.Beatmaps; namespace osu.Game.Rulesets.Mania.Judgements { diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index fa32d46a88..c3a29b39a8 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -2,8 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Database; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Mania.Objects diff --git a/osu.Game.Rulesets.Mania/Objects/Note.cs b/osu.Game.Rulesets.Mania/Objects/Note.cs index 6c0cacd277..3c4ff4216f 100644 --- a/osu.Game.Rulesets.Mania/Objects/Note.cs +++ b/osu.Game.Rulesets.Mania/Objects/Note.cs @@ -1,8 +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.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Database; using osu.Game.Rulesets.Mania.Judgements; namespace osu.Game.Rulesets.Mania.Objects diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 798d4b8c5b..f575342486 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Objects.Drawables; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 12b6f61a12..94cf6a4337 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Mania.UI { Name = "Key gradient", RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientVertical(Color4.Black, Color4.Black.Opacity(0)), + Colour = ColourInfo.GradientVertical(Color4.Black, Color4.Black.Opacity(0)), Alpha = 0.5f }, keyIcon = new Container @@ -206,8 +206,8 @@ namespace osu.Game.Rulesets.Mania.UI if (args.Key == Key) { - background.FadeTo(background.Alpha + 0.2f, 50, EasingTypes.OutQuint); - keyIcon.ScaleTo(1.4f, 50, EasingTypes.OutQuint); + background.FadeTo(background.Alpha + 0.2f, 50, Easing.OutQuint); + keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint); } return false; @@ -217,8 +217,8 @@ namespace osu.Game.Rulesets.Mania.UI { if (args.Key == Key) { - background.FadeTo(0.2f, 800, EasingTypes.OutQuart); - keyIcon.ScaleTo(1f, 400, EasingTypes.OutQuart); + background.FadeTo(0.2f, 800, Easing.OutQuart); + keyIcon.ScaleTo(1f, 400, Easing.OutQuart); } return false; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 3feb448752..03b6e18856 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -16,8 +16,6 @@ using System.Linq; using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Input; -using osu.Framework.Graphics.Transforms; -using osu.Framework.MathUtils; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Timing; using osu.Framework.Configuration; @@ -222,10 +220,10 @@ namespace osu.Game.Rulesets.Mania.UI switch (args.Key) { case Key.Minus: - transformVisibleTimeRangeTo(visibleTimeRange + time_span_step, 200, EasingTypes.OutQuint); + transformVisibleTimeRangeTo(visibleTimeRange + time_span_step, 200, Easing.OutQuint); break; case Key.Plus: - transformVisibleTimeRangeTo(visibleTimeRange - time_span_step, 200, EasingTypes.OutQuint); + transformVisibleTimeRangeTo(visibleTimeRange - time_span_step, 200, Easing.OutQuint); break; } } @@ -233,9 +231,9 @@ namespace osu.Game.Rulesets.Mania.UI return false; } - private void transformVisibleTimeRangeTo(double newTimeRange, double duration = 0, EasingTypes easing = EasingTypes.None) + private void transformVisibleTimeRangeTo(double newTimeRange, double duration = 0, Easing easing = Easing.None) { - TransformTo(newTimeRange, duration, easing, new TransformTimeSpan()); + this.TransformTo(nameof(visibleTimeRange), newTimeRange, duration, easing); } protected override void Update() @@ -244,23 +242,5 @@ namespace osu.Game.Rulesets.Mania.UI // While masking on effectively only the Y-axis, so we need to set the width of the bar line container manually barLineContainer.Width = columns.Width; } - - private class TransformTimeSpan : Transform - { - public double CurrentValue - { - get - { - double time = Time?.Current ?? 0; - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - } - - public override void Apply(Drawable d) => ((ManiaPlayfield)d).visibleTimeRange.Value = (float)CurrentValue; - public override void ReadIntoStartValue(Drawable d) => StartValue = ((ManiaPlayfield)d).visibleTimeRange.Value; - } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index 925767b851..2396e5d129 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -94,12 +94,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections using (fp.BeginAbsoluteSequence(fadeInTime)) { fp.FadeIn(DrawableOsuHitObject.TIME_FADEIN); - fp.ScaleTo(1, DrawableOsuHitObject.TIME_FADEIN, EasingTypes.Out); + fp.ScaleTo(1, DrawableOsuHitObject.TIME_FADEIN, Easing.Out); - fp.MoveTo(pointEndPosition, DrawableOsuHitObject.TIME_FADEIN, EasingTypes.Out); + fp.MoveTo(pointEndPosition, DrawableOsuHitObject.TIME_FADEIN, Easing.Out); - fp.Delay(fadeOutTime - fadeInTime); - fp.FadeOut(DrawableOsuHitObject.TIME_FADEIN); + fp.Delay(fadeOutTime - fadeInTime).FadeOut(DrawableOsuHitObject.TIME_FADEIN); } fp.Expire(true); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 75b2dc0a32..f68a7a765b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -112,29 +112,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { double duration = ((HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime) - HitObject.StartTime; - using (glow.BeginDelayedSequence(duration)) - glow.FadeOut(400); + glow.Delay(duration).FadeOut(400); switch (state) { case ArmedState.Idle: - using (BeginDelayedSequence(duration + TIME_PREEMPT)) - FadeOut(TIME_FADEOUT); + this.Delay(duration + TIME_PREEMPT).FadeOut(TIME_FADEOUT); Expire(true); break; case ArmedState.Miss: ApproachCircle.FadeOut(50); - FadeOut(TIME_FADEOUT / 5); + this.FadeOut(TIME_FADEOUT / 5); Expire(); break; case ArmedState.Hit: ApproachCircle.FadeOut(50); const double flash_in = 40; - - flash.FadeTo(0.8f, flash_in); - using (flash.BeginDelayedSequence(flash_in)) - flash.FadeOut(100); + flash.FadeTo(0.8f, flash_in) + .Then() + .FadeOut(100); explode.FadeIn(flash_in); @@ -145,8 +142,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.FadeOut(); number.FadeOut(); - FadeOut(800); - ScaleTo(Scale * 1.5f, 400, EasingTypes.OutQuad); + this.FadeOut(800) + .ScaleTo(Scale * 1.5f, 400, Easing.OutQuad); } Expire(); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 2711ec1a62..ca1b44e1c7 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Judgements; +using osu.Framework.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -24,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected sealed override void UpdateState(ArmedState state) { - Flush(); + FinishTransforms(); using (BeginAbsoluteSequence(HitObject.StartTime - TIME_PREEMPT, true)) { @@ -44,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected virtual void UpdatePreemptState() { - FadeIn(TIME_FADEIN); + this.FadeIn(TIME_FADEIN); } protected virtual void UpdateCurrentState(ArmedState state) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index eaa0bb7d27..892d106b02 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void LoadComplete() { if (Judgement.Result != HitResult.Miss) - JudgementText.TransformSpacingTo(new Vector2(14, 0), 1800, EasingTypes.OutQuint); + JudgementText.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint); base.LoadComplete(); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index c6c009e8f2..d5583b0d9d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -158,14 +158,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { ball.FadeIn(); - Delay(slider.Duration, true); + using (BeginDelayedSequence(slider.Duration, true)) + { + body.FadeOut(160); + ball.FadeOut(160); - body.FadeOut(160); - ball.FadeOut(160); - - FadeOut(800); - - Expire(); + this.FadeOut(800) + .Expire(); + } } public Drawable ProxiedLayer => initialCircle.ApproachCircle; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 28fbf46a92..2a50b23047 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -62,14 +62,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { var animIn = Math.Min(150, sliderTick.StartTime - FadeInTime); - ScaleTo(0.5f); - ScaleTo(1.2f, animIn); - FadeIn(animIn); - - Delay(animIn); - ScaleTo(1, 150, EasingTypes.Out); - - Delay(-animIn); + this.Animate( + d => d.FadeIn(animIn), + d => d.ScaleTo(0.5f).ScaleTo(1.2f, animIn) + ).Then( + d => d.ScaleTo(1, 150, Easing.Out) + ); } protected override void UpdateCurrentState(ArmedState state) @@ -77,16 +75,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (state) { case ArmedState.Idle: - Delay(FadeOutTime - sliderTick.StartTime); - FadeOut(); + this.Delay(FadeOutTime - sliderTick.StartTime).FadeOut(); break; case ArmedState.Miss: - FadeOut(160); - FadeColour(Color4.Red, 80); + this.FadeOut(160) + .FadeColour(Color4.Red, 80); break; case ArmedState.Hit: - FadeOut(120, EasingTypes.OutQuint); - ScaleTo(Scale * 1.5f, 120, EasingTypes.OutQuint); + this.FadeOut(120, Easing.OutQuint) + .ScaleTo(Scale * 1.5f, 120, Easing.OutQuint); break; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 840acb8221..2aae1bb24e 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -174,9 +174,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ticks.Rotation = disc.Rotation; float relativeCircleScale = spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight; - disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, EasingTypes.OutQuint); + disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint); - symbol.RotateTo(disc.Rotation / 2, 500, EasingTypes.OutQuint); + symbol.RotateTo(disc.Rotation / 2, 500, Easing.OutQuint); } protected override void UpdatePreemptState() @@ -184,35 +184,33 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.UpdatePreemptState(); circleContainer.ScaleTo(spinner.Scale * 0.3f); - circleContainer.ScaleTo(spinner.Scale, TIME_PREEMPT / 1.4f, EasingTypes.OutQuint); + circleContainer.ScaleTo(spinner.Scale, TIME_PREEMPT / 1.4f, Easing.OutQuint); disc.RotateTo(-720); symbol.RotateTo(-720); - mainContainer.ScaleTo(0); - mainContainer.ScaleTo(spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, TIME_PREEMPT - 150, EasingTypes.OutQuint); - - mainContainer.Delay(TIME_PREEMPT - 150); - mainContainer.ScaleTo(1, 500, EasingTypes.OutQuint); + mainContainer + .ScaleTo(0) + .ScaleTo(spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, TIME_PREEMPT - 150, Easing.OutQuint) + .Then() + .ScaleTo(1, 500, Easing.OutQuint); } protected override void UpdateCurrentState(ArmedState state) { - Delay(spinner.Duration, true); - - FadeOut(160); + var sequence = this.Delay(spinner.Duration).FadeOut(160); switch (state) { case ArmedState.Hit: - ScaleTo(Scale * 1.2f, 320, EasingTypes.Out); - Expire(); + sequence.ScaleTo(Scale * 1.2f, 320, Easing.Out); break; case ArmedState.Miss: - ScaleTo(Scale * 0.8f, 320, EasingTypes.In); - Expire(); + sequence.ScaleTo(Scale * 0.8f, 320, Easing.In); break; } + + Expire(); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs index 9a114aa72c..dbfd9b291b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs @@ -106,8 +106,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces tracking = value; - follow.ScaleTo(tracking ? 2.8f : 1, 300, EasingTypes.OutQuint); - follow.FadeTo(tracking ? 0.2f : 0, 300, EasingTypes.OutQuint); + follow.ScaleTo(tracking ? 2.8f : 1, 300, Easing.OutQuint); + follow.FadeTo(tracking ? 0.2f : 0, 300, Easing.OutQuint); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBouncer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBouncer.cs index a34ff30a43..10d14b5485 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBouncer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBouncer.cs @@ -37,8 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces protected override void LoadComplete() { base.LoadComplete(); - using (icon.BeginLoopedSequence()) - icon.RotateTo(360, 1000); + icon.Spin(1000, RotationDirection.Clockwise); } public void UpdateProgress(double progress, int repeat) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs index f3ddf683d2..cd808abe9d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Transforms; using osu.Framework.Input; using osu.Game.Graphics; using OpenTK; @@ -127,13 +126,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces if (Complete && updateCompleteTick()) { - background.Flush(flushType: typeof(TransformAlpha)); - background.FadeTo(tracking_alpha + 0.2f, 60, EasingTypes.OutExpo); - background.Delay(60); - background.FadeTo(tracking_alpha, 250, EasingTypes.OutQuint); + background.FinishTransforms(false, nameof(Alpha)); + background + .FadeTo(tracking_alpha + 0.2f, 60, Easing.OutExpo) + .Then() + .FadeTo(tracking_alpha, 250, Easing.OutQuint); } - RotateTo(currentRotation / 2, validAndTracking ? 500 : 1500, EasingTypes.OutExpo); + this.RotateTo(currentRotation / 2, validAndTracking ? 500 : 1500, Easing.OutExpo); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index e6fd82e6c8..7a311f1467 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.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.Beatmaps; using osu.Game.Rulesets.Objects; using OpenTK; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; using OpenTK.Graphics; -using osu.Game.Database; using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Rulesets.Osu.Objects diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs index 3b44e38d5e..4d8c030ede 100644 --- a/osu.Game.Rulesets.Osu/Objects/Slider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs @@ -6,9 +6,9 @@ using osu.Game.Rulesets.Objects.Types; using System; using System.Collections.Generic; using osu.Game.Rulesets.Objects; -using osu.Game.Database; using System.Linq; using osu.Game.Audio; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Rulesets.Osu.Objects diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 6ba499739a..c4f5dfe97a 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -1,8 +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.Beatmaps; using osu.Game.Rulesets.Objects.Types; -using osu.Game.Database; using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Rulesets.Osu.Objects diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index 5ede3f56f5..b92f1bc60a 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Replays /// /// What easing to use when moving between hitobjects /// - private EasingTypes preferredEasing => DelayedMovements ? EasingTypes.InOutCubic : EasingTypes.Out; + private Easing preferredEasing => DelayedMovements ? Easing.InOutCubic : Easing.Out; #endregion @@ -110,7 +110,7 @@ namespace osu.Game.Rulesets.Osu.Replays { // Default values for circles/sliders Vector2 startPosition = h.StackedPosition; - EasingTypes easing = preferredEasing; + Easing easing = preferredEasing; float spinnerDirection = -1; // The startPosition for the slider should not be its .Position, but the point on the circle whose tangent crosses the current cursor position @@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.Osu.Replays if (spinCentreOffset.Length > SPIN_RADIUS) { // If moving in from the outside, don't ease out (default eases out). This means auto will "start" spinning immediately after moving into position. - easing = EasingTypes.In; + easing = Easing.In; } } @@ -190,7 +190,7 @@ namespace osu.Game.Rulesets.Osu.Replays } } - private void moveToHitObject(double targetTime, Vector2 targetPos, double hitObjectRadius, EasingTypes easing) + private void moveToHitObject(double targetTime, Vector2 targetPos, double hitObjectRadius, Easing easing) { ReplayFrame lastFrame = Frames[Frames.Count - 1]; diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs index 5d44da78f9..44f61e2074 100644 --- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs +++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs @@ -8,7 +8,6 @@ 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; diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index 5d627f2b50..7507ee600e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -64,11 +64,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void LoadComplete() { base.LoadComplete(); - Delay(BarLine.StartTime - Time.Current); - FadeOut(base_fadeout_time * BarLine.ScrollTime / 1000); + this.Delay(BarLine.StartTime - Time.Current).FadeOut(base_fadeout_time * BarLine.ScrollTime / 1000); } - private void updateScrollPosition(double time) => MoveToX((float)((BarLine.StartTime - time) / BarLine.ScrollTime)); + private void updateScrollPosition(double time) => this.MoveToX((float)((BarLine.StartTime - time) / BarLine.ScrollTime)); protected override void Update() { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index 56a747467e..b64bc64d9b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (state) { case ArmedState.Hit: - Content.ScaleTo(0, 100, EasingTypes.OutQuint); + Content.ScaleTo(0, 100, Easing.OutQuint); break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index a4a46e3b48..0d5c8d2a25 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -65,45 +65,42 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void UpdateState(ArmedState state) { - Delay(HitObject.StartTime - Time.Current + Judgement.TimeOffset, true); - var circlePiece = MainPiece as CirclePiece; + circlePiece?.FlashBox.FinishTransforms(); - circlePiece?.FlashBox.Flush(); - - switch (State) + using (BeginDelayedSequence(HitObject.StartTime - Time.Current + Judgement.TimeOffset, true)) { - case ArmedState.Idle: - Delay(HitObject.HitWindowMiss); - break; - case ArmedState.Miss: - FadeOut(100); - break; - case ArmedState.Hit: - FadeOut(600); + switch (State) + { + case ArmedState.Idle: + this.Delay(HitObject.HitWindowMiss).Expire(); + break; + case ArmedState.Miss: + this.FadeOut(100) + .Expire(); + break; + case ArmedState.Hit: + var flash = circlePiece?.FlashBox; + if (flash != null) + { + flash.FadeTo(0.9f); + flash.FadeOut(300); + } - var flash = circlePiece?.FlashBox; - if (flash != null) - { - flash.FadeTo(0.9f); - flash.FadeOut(300); - } + const float gravity_time = 300; + const float gravity_travel_height = 200; + Content.ScaleTo(0.8f, gravity_time * 2, Easing.OutQuad); - FadeOut(800); + this.FadeOut(800) + .MoveToY(-gravity_travel_height, gravity_time, Easing.Out) + .Then() + .MoveToY(gravity_travel_height * 2, gravity_time * 2, Easing.In); - const float gravity_time = 300; - const float gravity_travel_height = 200; - - Content.ScaleTo(0.8f, gravity_time * 2, EasingTypes.OutQuad); - - MoveToY(-gravity_travel_height, gravity_time, EasingTypes.Out); - Delay(gravity_time, true); - MoveToY(gravity_travel_height * 2, gravity_time * 2, EasingTypes.In); - break; + Expire(); + break; + } } - - Expire(); } } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 1c72f2a7dd..a565f92fac 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -147,13 +147,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables var completion = (float)userHits / HitObject.RequiredHits; - expandingRing.FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50); - using (expandingRing.BeginDelayedSequence(50)) - expandingRing.FadeTo(completion / 8, 2000, EasingTypes.OutQuint); + expandingRing + .FadeTo(expandingRing.Alpha + MathHelper.Clamp(completion / 16, 0.1f, 0.6f), 50) + .Then() + .FadeTo(completion / 8, 2000, Easing.OutQuint); - symbol.RotateTo((float)(completion * HitObject.Duration / 8), 4000, EasingTypes.OutQuint); + symbol.RotateTo((float)(completion * HitObject.Duration / 8), 4000, Easing.OutQuint); - expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, EasingTypes.OutQuint); + expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint); if (userHits == HitObject.RequiredHits) { @@ -180,26 +181,21 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void UpdateState(ArmedState state) { const float preempt = 100; - - Delay(HitObject.StartTime - Time.Current - preempt, true); - - targetRing.ScaleTo(target_ring_scale, preempt * 4, EasingTypes.OutQuint); - - Delay(preempt, true); - - Delay(Judgement.TimeOffset + HitObject.Duration, true); - const float out_transition_time = 300; + double untilStartTime = HitObject.StartTime - Time.Current; + double untilJudgement = untilStartTime + Judgement.TimeOffset + HitObject.Duration; + + targetRing.Delay(untilStartTime - preempt).ScaleTo(target_ring_scale, preempt * 4, Easing.OutQuint); + this.Delay(untilJudgement).FadeOut(out_transition_time, Easing.Out); + switch (state) { case ArmedState.Hit: - bodyContainer.ScaleTo(1.4f, out_transition_time); + bodyContainer.Delay(untilJudgement).ScaleTo(1.4f, out_transition_time); break; } - FadeOut(out_transition_time, EasingTypes.Out); - Expire(); } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs index 3f8249f5a9..698939e278 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/Pieces/CirclePiece.cs @@ -166,9 +166,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces double duration = timingPoint.BeatLength * 2; - background.FadeEdgeEffectTo(1, pre_beat_transition_time, EasingTypes.OutQuint); - using (background.BeginDelayedSequence(pre_beat_transition_time)) - background.FadeEdgeEffectTo(edge_alpha_kiai, duration, EasingTypes.OutQuint); + background + .FadeEdgeEffectTo(1, pre_beat_transition_time, Easing.OutQuint) + .Then() + .FadeEdgeEffectTo(edge_alpha_kiai, duration, Easing.OutQuint); } } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs index 18e3016fc3..fd9daa269c 100644 --- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs @@ -5,8 +5,8 @@ using osu.Game.Rulesets.Objects.Types; using System; using System.Collections.Generic; using System.Linq; -using osu.Game.Database; using osu.Game.Audio; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Rulesets.Taiko.Objects diff --git a/osu.Game.Rulesets.Taiko/Objects/Hit.cs b/osu.Game.Rulesets.Taiko/Objects/Hit.cs index f31472d0fd..03b9be4157 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Hit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Hit.cs @@ -1,8 +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.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Database; namespace osu.Game.Rulesets.Taiko.Objects { diff --git a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs index 79bb901112..db368cb112 100644 --- a/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs +++ b/osu.Game.Rulesets.Taiko/Objects/TaikoHitObject.cs @@ -1,8 +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.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Database; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Taiko.UI; diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index f5e2094cbf..70df3d8317 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -3,7 +3,6 @@ using System; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs index 08fd8dbecc..779471b8dc 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoJudgement.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Allocation; using osu.Game.Graphics; using osu.Game.Rulesets.Judgements; +using osu.Framework.Graphics; namespace osu.Game.Rulesets.Taiko.UI { @@ -47,7 +48,7 @@ namespace osu.Game.Rulesets.Taiko.UI switch (Judgement.Result) { case HitResult.Hit: - MoveToY(-100, 500); + this.MoveToY(-100, 500); break; } diff --git a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs index 4d39ba0ead..c372ac1809 100644 --- a/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/HitExplosion.cs @@ -62,8 +62,8 @@ namespace osu.Game.Rulesets.Taiko.UI { base.LoadComplete(); - ScaleTo(3f, 1000, EasingTypes.OutQuint); - FadeOut(500); + this.ScaleTo(3f, 1000, Easing.OutQuint); + this.FadeOut(500); Expire(); } @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Taiko.UI /// public void VisualiseSecondHit() { - ResizeTo(new Vector2(TaikoPlayfield.HIT_TARGET_OFFSET + TaikoHitObject.DEFAULT_STRONG_CIRCLE_DIAMETER), 50); + this.ResizeTo(new Vector2(TaikoPlayfield.HIT_TARGET_OFFSET + TaikoHitObject.DEFAULT_STRONG_CIRCLE_DIAMETER), 50); } } } diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs index 999d76ab0b..60881f3c24 100644 --- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs +++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs @@ -149,15 +149,17 @@ namespace osu.Game.Rulesets.Taiko.UI const float down_time = 40; const float up_time = 1000; - back.ScaleTo(target.Scale.X - scale_amount, down_time, EasingTypes.OutQuint); - back.Delay(down_time); - back.ScaleTo(1, up_time, EasingTypes.OutQuint); + back.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint) + .Then() + .ScaleTo(1, up_time, Easing.OutQuint); - target.ScaleTo(target.Scale.X - scale_amount, down_time, EasingTypes.OutQuint); - target.FadeTo(Math.Min(target.Alpha + alpha_amount, 1), down_time, EasingTypes.OutQuint); - target.Delay(down_time); - target.ScaleTo(1, up_time, EasingTypes.OutQuint); - target.FadeOut(up_time, EasingTypes.OutQuint); + target.Animate( + t => t.ScaleTo(target.Scale.X - scale_amount, down_time, Easing.OutQuint), + t => t.FadeTo(Math.Min(target.Alpha + alpha_amount, 1), down_time, Easing.OutQuint) + ).Then( + t => t.ScaleTo(1, up_time, Easing.OutQuint), + t => t.FadeOut(up_time, Easing.OutQuint) + ); } return false; diff --git a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs index b4aec7057b..524490fac3 100644 --- a/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs +++ b/osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs @@ -59,8 +59,8 @@ namespace osu.Game.Rulesets.Taiko.UI { base.LoadComplete(); - ScaleTo(new Vector2(1, 3f), 500, EasingTypes.OutQuint); - FadeOut(250); + this.ScaleTo(new Vector2(1, 3f), 500, Easing.OutQuint); + this.FadeOut(250); Expire(); } diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index bb679e5150..b0fb9d7f28 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -158,7 +158,7 @@ namespace osu.Game.Rulesets.Taiko.UI Anchor = Anchor.TopRight, RelativeSizeAxes = Axes.Y, Width = 10, - ColourInfo = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)), + Colour = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)), }, } }, diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs index 4814af984e..da3b448f74 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs @@ -16,12 +16,6 @@ namespace osu.Game.Tests.Beatmaps.Formats [TestFixture] public class OsuLegacyDecoderTest { - [OneTimeSetUpAttribute] - public void SetUp() - { - OsuLegacyDecoder.Register(); - } - [Test] public void TestDecodeMetadata() { diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index e467df0c53..ecaf0db096 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -10,8 +10,10 @@ using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Desktop.Platform; using osu.Framework.Platform; -using osu.Game.Database; using osu.Game.IPC; +using osu.Framework.Allocation; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; namespace osu.Game.Tests.Beatmaps.IO { @@ -26,15 +28,15 @@ namespace osu.Game.Tests.Beatmaps.IO //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new HeadlessGameHost()) { - loadOsu(host); + var osu = loadOsu(host); var temp = prepareTempCopy(osz_path); Assert.IsTrue(File.Exists(temp)); - host.Dependencies.Get().Import(temp); + osu.Dependencies.Get().Import(temp); - ensureLoaded(host); + ensureLoaded(osu); Assert.IsFalse(File.Exists(temp)); } @@ -49,7 +51,7 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(host.IsPrimaryInstance); Assert.IsTrue(!client.IsPrimaryInstance); - loadOsu(host); + var osu = loadOsu(host); var temp = prepareTempCopy(osz_path); @@ -59,7 +61,7 @@ namespace osu.Game.Tests.Beatmaps.IO if (!importer.ImportAsync(temp).Wait(10000)) Assert.Fail(@"IPC took too long to send"); - ensureLoaded(host); + ensureLoaded(osu); Assert.IsFalse(File.Exists(temp)); } @@ -71,16 +73,16 @@ namespace osu.Game.Tests.Beatmaps.IO //unfortunately for the time being we need to reference osu.Framework.Desktop for a game host here. using (HeadlessGameHost host = new HeadlessGameHost()) { - loadOsu(host); + var osu = loadOsu(host); var temp = prepareTempCopy(osz_path); Assert.IsTrue(File.Exists(temp), "Temporary file copy never substantiated"); using (File.OpenRead(temp)) - host.Dependencies.Get().Import(temp); + osu.Dependencies.Get().Import(temp); - ensureLoaded(host); + ensureLoaded(osu); File.Delete(temp); @@ -103,20 +105,21 @@ namespace osu.Game.Tests.Beatmaps.IO Thread.Sleep(1); //reset beatmap database (sqlite and storage backing) - host.Dependencies.Get().Reset(); - host.Dependencies.Get().Reset(); + osu.Dependencies.Get().Reset(); + osu.Dependencies.Get().Reset(); return osu; } - private void ensureLoaded(GameHost host, int timeout = 60000) + private void ensureLoaded(OsuGameBase osu, int timeout = 60000) { IEnumerable resultSets = null; + var store = osu.Dependencies.Get(); + Action waitAction = () => { - while (!(resultSets = host.Dependencies.Get() - .Query().Where(s => s.OnlineBeatmapSetID == 241526)).Any()) + while (!(resultSets = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526)).Any()) Thread.Sleep(50); }; @@ -132,15 +135,14 @@ namespace osu.Game.Tests.Beatmaps.IO //if we don't re-check here, the set will be inserted but the beatmaps won't be present yet. waitAction = () => { - while ((resultBeatmaps = host.Dependencies.Get() - .GetAllWithChildren(s => s.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0)).Count() != 12) + while ((resultBeatmaps = store.QueryBeatmaps(s => s.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0)).Count() != 12) Thread.Sleep(50); }; Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout), @"Beatmaps did not import to the database in allocated time"); - var set = host.Dependencies.Get().GetChildren(resultSets.First()); + var set = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526).First(); Assert.IsTrue(set.Beatmaps.Count == resultBeatmaps.Count(), $@"Incorrect database beatmap count post-import ({resultBeatmaps.Count()} but should be {set.Beatmaps.Count})."); @@ -150,16 +152,16 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(set.Beatmaps.Count > 0); - var beatmap = host.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap; + var beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Count > 0); - beatmap = host.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.Beatmap; + beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Count > 0); - beatmap = host.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.Beatmap; + beatmap = store.GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Count > 0); - beatmap = host.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap; + beatmap = store.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 c9b3b1b922..7a7a8a58bc 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -2,23 +2,18 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.IO; +using System.Linq; using NUnit.Framework; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.IO; using osu.Game.Tests.Resources; using osu.Game.Beatmaps.Formats; -using osu.Game.Database; namespace osu.Game.Tests.Beatmaps.IO { [TestFixture] public class OszArchiveReaderTest { - [OneTimeSetUpAttribute] - public void SetUp() - { - OszArchiveReader.Register(); - } - [Test] public void TestReadBeatmaps() { @@ -40,7 +35,7 @@ namespace osu.Game.Tests.Beatmaps.IO "Soleily - Renatus (MMzz) [Muzukashii].osu", "Soleily - Renatus (MMzz) [Oni].osu" }; - var maps = reader.BeatmapFilenames; + var maps = reader.Filenames.ToArray(); foreach (var map in expected) Assert.Contains(map, maps); } diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 0368455b92..8668b0c995 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -3,7 +3,6 @@ using OpenTK.Graphics; using osu.Game.Beatmaps.Timing; -using osu.Game.Database; using osu.Game.Rulesets.Objects; using System.Collections.Generic; using System.Linq; diff --git a/osu.Game/Database/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs similarity index 96% rename from osu.Game/Database/BeatmapDifficulty.cs rename to osu.Game/Beatmaps/BeatmapDifficulty.cs index 87c651aa88..7c2294cae9 100644 --- a/osu.Game/Database/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -3,7 +3,7 @@ using SQLite.Net.Attributes; -namespace osu.Game.Database +namespace osu.Game.Beatmaps { public class BeatmapDifficulty { diff --git a/osu.Game/Database/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs similarity index 92% rename from osu.Game/Database/BeatmapInfo.cs rename to osu.Game/Beatmaps/BeatmapInfo.cs index 9f253f6055..6f4a4a8a69 100644 --- a/osu.Game/Database/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -1,14 +1,15 @@ // 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.Game.IO.Serialization; -using SQLite.Net.Attributes; -using SQLiteNetExtensions.Attributes; using System; using System.Linq; +using Newtonsoft.Json; +using osu.Game.IO.Serialization; +using osu.Game.Rulesets; +using SQLite.Net.Attributes; +using SQLiteNetExtensions.Attributes; -namespace osu.Game.Database +namespace osu.Game.Beatmaps { public class BeatmapInfo : IEquatable, IJsonSerializable { @@ -60,7 +61,7 @@ namespace osu.Game.Database [ForeignKey(typeof(RulesetInfo))] public int RulesetID { get; set; } - [OneToOne(CascadeOperations = CascadeOperation.All)] + [OneToOne(CascadeOperations = CascadeOperation.CascadeRead)] public RulesetInfo Ruleset { get; set; } public bool LetterboxInBreaks { get; set; } @@ -94,11 +95,11 @@ namespace osu.Game.Database } public bool AudioEquals(BeatmapInfo other) => other != null && BeatmapSet != null && other.BeatmapSet != null && - BeatmapSet.Path == other.BeatmapSet.Path && + BeatmapSet.Hash == other.BeatmapSet.Hash && (Metadata ?? BeatmapSet.Metadata).AudioFile == (other.Metadata ?? other.BeatmapSet.Metadata).AudioFile; public bool BackgroundEquals(BeatmapInfo other) => other != null && BeatmapSet != null && other.BeatmapSet != null && - BeatmapSet.Path == other.BeatmapSet.Path && + BeatmapSet.Hash == other.BeatmapSet.Hash && (Metadata ?? BeatmapSet.Metadata).BackgroundFile == (other.Metadata ?? other.BeatmapSet.Metadata).BackgroundFile; } } diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs new file mode 100644 index 0000000000..5cc2a2a430 --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -0,0 +1,499 @@ +// 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.Linq.Expressions; +using Ionic.Zip; +using osu.Framework.Audio.Track; +using osu.Framework.Extensions; +using osu.Framework.Graphics.Textures; +using osu.Framework.IO.Stores; +using osu.Framework.Logging; +using osu.Framework.Platform; +using osu.Game.Beatmaps.Formats; +using osu.Game.Beatmaps.IO; +using osu.Game.IO; +using osu.Game.IPC; +using osu.Game.Overlays.Notifications; +using osu.Game.Rulesets; +using SQLite.Net; + +namespace osu.Game.Beatmaps +{ + /// + /// Handles the storage and retrieval of Beatmaps/WorkingBeatmaps. + /// + public class BeatmapManager + { + /// + /// Fired when a new becomes available in the database. + /// + public event Action BeatmapSetAdded; + + /// + /// Fired when a is removed from the database. + /// + public event Action BeatmapSetRemoved; + + /// + /// A default representation of a WorkingBeatmap to use when no beatmap is available. + /// + public WorkingBeatmap DefaultBeatmap { private get; set; } + + private readonly Storage storage; + + private readonly FileStore files; + + private readonly RulesetStore rulesets; + + private readonly BeatmapStore beatmaps; + + // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) + private BeatmapIPCChannel ipc; + + /// + /// Set an endpoint for notifications to be posted to. + /// + public Action PostNotification { private get; set; } + + public BeatmapManager(Storage storage, FileStore files, SQLiteConnection connection, RulesetStore rulesets, IIpcHost importHost = null) + { + beatmaps = new BeatmapStore(connection); + beatmaps.BeatmapSetAdded += s => BeatmapSetAdded?.Invoke(s); + beatmaps.BeatmapSetRemoved += s => BeatmapSetRemoved?.Invoke(s); + + this.storage = storage; + this.files = files; + this.rulesets = rulesets; + + if (importHost != null) + ipc = new BeatmapIPCChannel(importHost, this); + } + + /// + /// Import one or more from filesystem . + /// This will post a notification tracking import progress. + /// + /// One or more beatmap locations on disk. + public void Import(params string[] paths) + { + var notification = new ProgressNotification + { + Text = "Beatmap import is initialising...", + Progress = 0, + State = ProgressNotificationState.Active, + }; + + PostNotification?.Invoke(notification); + + int i = 0; + foreach (string path in paths) + { + if (notification.State == ProgressNotificationState.Cancelled) + // user requested abort + return; + + try + { + notification.Text = $"Importing ({i} of {paths.Length})\n{Path.GetFileName(path)}"; + using (ArchiveReader reader = getReaderFrom(path)) + Import(reader); + + notification.Progress = (float)++i / paths.Length; + + // We may or may not want to delete the file depending on where it is stored. + // e.g. reconstructing/repairing database with beatmaps from default storage. + // Also, not always a single file, i.e. for LegacyFilesystemReader + // TODO: Add a check to prevent files from storage to be deleted. + try + { + if (File.Exists(path)) + File.Delete(path); + } + catch (Exception e) + { + Logger.Error(e, $@"Could not delete original file after import ({Path.GetFileName(path)})"); + } + } + catch (Exception e) + { + e = e.InnerException ?? e; + Logger.Error(e, @"Could not import beatmap set"); + } + } + + notification.State = ProgressNotificationState.Completed; + } + + private readonly object importLock = new object(); + + /// + /// Import a beatmap from an . + /// + /// The beatmap to be imported. + public BeatmapSetInfo Import(ArchiveReader archiveReader) + { + // let's only allow one concurrent import at a time for now. + lock (importLock) + { + BeatmapSetInfo set = importToStorage(archiveReader); + Import(set); + return set; + } + } + + /// + /// Import a beatmap from a . + /// + /// The beatmap to be imported. + public void Import(BeatmapSetInfo beatmapSetInfo) + { + // If we have an ID then we already exist in the database. + if (beatmapSetInfo.ID != 0) return; + + lock (beatmaps) + beatmaps.Add(beatmapSetInfo); + } + + /// + /// Delete a beatmap from the manager. + /// Is a no-op for already deleted beatmaps. + /// + /// The beatmap to delete. + public void Delete(BeatmapSetInfo beatmapSet) + { + lock (beatmaps) + if (!beatmaps.Delete(beatmapSet)) return; + + if (!beatmapSet.Protected) + files.Dereference(beatmapSet.Files.Select(f => f.FileInfo)); + } + + /// + /// Returns a to a usable state if it has previously been deleted but not yet purged. + /// Is a no-op for already usable beatmaps. + /// + /// The beatmap to restore. + public void Undelete(BeatmapSetInfo beatmapSet) + { + lock (beatmaps) + if (!beatmaps.Undelete(beatmapSet)) return; + + if (!beatmapSet.Protected) + files.Reference(beatmapSet.Files.Select(f => f.FileInfo)); + } + + /// + /// Retrieve a instance for the provided + /// + /// The beatmap to lookup. + /// The currently loaded . Allows for optimisation where elements are shared with the new beatmap. + /// A instance correlating to the provided . + public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo, WorkingBeatmap previous = null) + { + if (beatmapInfo == null || beatmapInfo == DefaultBeatmap?.BeatmapInfo) + return DefaultBeatmap; + + lock (beatmaps) + beatmaps.Populate(beatmapInfo); + + if (beatmapInfo.BeatmapSet == null) + throw new InvalidOperationException($@"Beatmap set {beatmapInfo.BeatmapSetInfoID} is not in the local database."); + + if (beatmapInfo.Metadata == null) + beatmapInfo.Metadata = beatmapInfo.BeatmapSet.Metadata; + + WorkingBeatmap working = new BeatmapManagerWorkingBeatmap(files.Store, beatmapInfo); + + previous?.TransferTo(working); + + return working; + } + + /// + /// Reset the manager to an empty state. + /// + public void Reset() + { + lock (beatmaps) + beatmaps.Reset(); + } + + /// + /// Perform a lookup query on available s. + /// + /// The query. + /// The first result for the provided query, or null if no results were found. + public BeatmapSetInfo QueryBeatmapSet(Func query) + { + lock (beatmaps) + { + BeatmapSetInfo set = beatmaps.Query().FirstOrDefault(query); + + if (set != null) + beatmaps.Populate(set); + + return set; + } + } + + /// + /// Perform a lookup query on available s. + /// + /// The query. + /// Results from the provided query. + public List QueryBeatmapSets(Expression> query) + { + lock (beatmaps) return beatmaps.QueryAndPopulate(query); + } + + /// + /// Perform a lookup query on available s. + /// + /// The query. + /// The first result for the provided query, or null if no results were found. + public BeatmapInfo QueryBeatmap(Func query) + { + lock (beatmaps) + { + BeatmapInfo set = beatmaps.Query().FirstOrDefault(query); + + if (set != null) + beatmaps.Populate(set); + + return set; + } + } + + /// + /// Perform a lookup query on available s. + /// + /// The query. + /// Results from the provided query. + public List QueryBeatmaps(Expression> query) + { + lock (beatmaps) return beatmaps.QueryAndPopulate(query); + } + + /// + /// Creates an from a valid storage path. + /// + /// A file or folder path resolving the beatmap content. + /// A reader giving access to the beatmap's content. + private ArchiveReader getReaderFrom(string path) + { + if (ZipFile.IsZipFile(path)) + return new OszArchiveReader(storage.GetStream(path)); + else + return new LegacyFilesystemReader(path); + } + + /// + /// Import a beamap into our local storage. + /// If the beatmap is already imported, the existing instance will be returned. + /// + /// The beatmap archive to be read. + /// The imported beatmap, or an existing instance if it is already present. + private BeatmapSetInfo importToStorage(ArchiveReader reader) + { + // for now, concatenate all .osu files in the set to create a unique hash. + MemoryStream hashable = new MemoryStream(); + foreach (string file in reader.Filenames.Where(f => f.EndsWith(".osu"))) + using (Stream s = reader.GetStream(file)) + s.CopyTo(hashable); + + var hash = hashable.ComputeSHA2Hash(); + + // check if this beatmap has already been imported and exit early if so. + BeatmapSetInfo beatmapSet; + lock (beatmaps) + beatmapSet = beatmaps.QueryAndPopulate(b => b.Hash == hash).FirstOrDefault(); + + if (beatmapSet != null) + { + Undelete(beatmapSet); + return beatmapSet; + } + + List fileInfos = new List(); + + // import files to manager + foreach (string file in reader.Filenames) + using (Stream s = reader.GetStream(file)) + fileInfos.Add(new BeatmapSetFileInfo + { + Filename = file, + FileInfo = files.Add(s) + }); + + BeatmapMetadata metadata; + + using (var stream = new StreamReader(reader.GetStream(reader.Filenames.First(f => f.EndsWith(".osu"))))) + metadata = BeatmapDecoder.GetDecoder(stream).Decode(stream).Metadata; + + beatmapSet = new BeatmapSetInfo + { + OnlineBeatmapSetID = metadata.OnlineBeatmapSetID, + Beatmaps = new List(), + Hash = hash, + Files = fileInfos, + Metadata = metadata + }; + + var mapNames = reader.Filenames.Where(f => f.EndsWith(".osu")); + + foreach (var name in mapNames) + { + using (var raw = reader.GetStream(name)) + using (var ms = new MemoryStream()) //we need a memory stream so we can seek and shit + using (var sr = new StreamReader(ms)) + { + raw.CopyTo(ms); + ms.Position = 0; + + var decoder = BeatmapDecoder.GetDecoder(sr); + Beatmap beatmap = decoder.Decode(sr); + + beatmap.BeatmapInfo.Path = name; + beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash(); + + // TODO: Diff beatmap metadata with set metadata and leave it here if necessary + beatmap.BeatmapInfo.Metadata = null; + + // 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); + } + } + + return beatmapSet; + } + + /// + /// Returns a list of all usable s. + /// + /// Whether returned objects should be pre-populated with all data. + /// A list of available . + public List GetAllUsableBeatmapSets(bool populate = true) + { + lock (beatmaps) + { + if (populate) + return beatmaps.QueryAndPopulate(b => !b.DeletePending).ToList(); + else + return beatmaps.Query(b => !b.DeletePending).ToList(); + } + } + + protected class BeatmapManagerWorkingBeatmap : WorkingBeatmap + { + private readonly IResourceStore store; + + public BeatmapManagerWorkingBeatmap(IResourceStore store, BeatmapInfo beatmapInfo) + : base(beatmapInfo) + { + this.store = store; + } + + protected override Beatmap GetBeatmap() + { + try + { + Beatmap beatmap; + + BeatmapDecoder decoder; + using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapInfo.Path)))) + { + decoder = BeatmapDecoder.GetDecoder(stream); + beatmap = decoder.Decode(stream); + } + + if (beatmap == null || BeatmapSetInfo.StoryboardFile == null) + return beatmap; + + using (var stream = new StreamReader(store.GetStream(getPathForFile(BeatmapSetInfo.StoryboardFile)))) + decoder.Decode(stream, beatmap); + + + return beatmap; + } + catch { return null; } + } + + private string getPathForFile(string filename) => BeatmapSetInfo.Files.First(f => f.Filename == filename).FileInfo.StoragePath; + + protected override Texture GetBackground() + { + if (Metadata?.BackgroundFile == null) + return null; + + try + { + return new TextureStore(new RawTextureLoaderStore(store), false).Get(getPathForFile(Metadata.BackgroundFile)); + } + catch { return null; } + } + + protected override Track GetTrack() + { + try + { + var trackData = store.GetStream(getPathForFile(Metadata.AudioFile)); + return trackData == null ? null : new TrackBass(trackData); + } + catch { return new TrackVirtual(); } + } + } + + public void ImportFromStable() + { + string stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!", "Songs"); + if (!Directory.Exists(stableInstallPath)) + stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu", "Songs"); + + if (!Directory.Exists(stableInstallPath)) + { + Logger.Log("Couldn't find an osu!stable installation!", LoggingTarget.Information, LogLevel.Error); + return; + } + + Import(Directory.GetDirectories(stableInstallPath)); + } + + public void DeleteAll() + { + var maps = GetAllUsableBeatmapSets().ToArray(); + + if (maps.Length == 0) return; + + var notification = new ProgressNotification + { + Progress = 0, + State = ProgressNotificationState.Active, + }; + + PostNotification?.Invoke(notification); + + int i = 0; + + foreach (var b in maps) + { + if (notification.State == ProgressNotificationState.Cancelled) + // user requested abort + return; + + notification.Text = $"Deleting ({i} of {maps.Length})"; + notification.Progress = (float)++i / maps.Length; + Delete(b); + } + + notification.State = ProgressNotificationState.Completed; + } + } +} diff --git a/osu.Game/Database/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs similarity index 94% rename from osu.Game/Database/BeatmapMetadata.cs rename to osu.Game/Beatmaps/BeatmapMetadata.cs index ccf1a99c2c..cc9a51b4e2 100644 --- a/osu.Game/Database/BeatmapMetadata.cs +++ b/osu.Game/Beatmaps/BeatmapMetadata.cs @@ -5,7 +5,7 @@ using System.Linq; using Newtonsoft.Json; using SQLite.Net.Attributes; -namespace osu.Game.Database +namespace osu.Game.Beatmaps { public class BeatmapMetadata { diff --git a/osu.Game/Database/BeatmapMetrics.cs b/osu.Game/Beatmaps/BeatmapMetrics.cs similarity index 94% rename from osu.Game/Database/BeatmapMetrics.cs rename to osu.Game/Beatmaps/BeatmapMetrics.cs index 25de0f0a8d..730cf635da 100644 --- a/osu.Game/Database/BeatmapMetrics.cs +++ b/osu.Game/Beatmaps/BeatmapMetrics.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using Newtonsoft.Json; -namespace osu.Game.Database +namespace osu.Game.Beatmaps { /// /// Beatmap metrics based on acculumated online data from community plays. diff --git a/osu.Game/Database/BeatmapOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapOnlineInfo.cs similarity index 93% rename from osu.Game/Database/BeatmapOnlineInfo.cs rename to osu.Game/Beatmaps/BeatmapOnlineInfo.cs index f4e70388f5..e8f40a7e07 100644 --- a/osu.Game/Database/BeatmapOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapOnlineInfo.cs @@ -3,7 +3,7 @@ using Newtonsoft.Json; -namespace osu.Game.Database +namespace osu.Game.Beatmaps { /// /// Beatmap info retrieved for previewing locally without having the beatmap downloaded. diff --git a/osu.Game/Beatmaps/BeatmapSetFileInfo.cs b/osu.Game/Beatmaps/BeatmapSetFileInfo.cs new file mode 100644 index 0000000000..a05362b32d --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapSetFileInfo.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.IO; +using SQLite.Net.Attributes; +using SQLiteNetExtensions.Attributes; + +namespace osu.Game.Beatmaps +{ + public class BeatmapSetFileInfo + { + [PrimaryKey, AutoIncrement] + public int ID { get; set; } + + [ForeignKey(typeof(BeatmapSetInfo)), NotNull] + public int BeatmapSetInfoID { get; set; } + + [ForeignKey(typeof(FileInfo)), NotNull] + public int FileInfoID { get; set; } + + [OneToOne(CascadeOperations = CascadeOperation.CascadeRead)] + public FileInfo FileInfo { get; set; } + + [NotNull] + public string Filename { get; set; } + } +} \ No newline at end of file diff --git a/osu.Game/Database/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs similarity index 75% rename from osu.Game/Database/BeatmapSetInfo.cs rename to osu.Game/Beatmaps/BeatmapSetInfo.cs index 017a489d9e..f47affcab8 100644 --- a/osu.Game/Database/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -6,7 +6,7 @@ using System.Linq; using SQLite.Net.Attributes; using SQLiteNetExtensions.Attributes; -namespace osu.Game.Database +namespace osu.Game.Beatmaps { public class BeatmapSetInfo { @@ -34,8 +34,11 @@ namespace osu.Game.Database public string Hash { get; set; } - public string Path { get; set; } + public string StoryboardFile => Files.FirstOrDefault(f => f.Filename.EndsWith(".osb"))?.Filename; - public string StoryboardFile { get; set; } + [OneToMany(CascadeOperations = CascadeOperation.All)] + public List Files { get; set; } + + public bool Protected { get; set; } } } diff --git a/osu.Game/Database/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs similarity index 94% rename from osu.Game/Database/BeatmapSetOnlineInfo.cs rename to osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs index 61d408c94a..e5a1984f50 100644 --- a/osu.Game/Database/BeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs @@ -3,7 +3,7 @@ using Newtonsoft.Json; -namespace osu.Game.Database +namespace osu.Game.Beatmaps { /// /// Beatmap set info retrieved for previewing locally without having the set downloaded. diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs new file mode 100644 index 0000000000..97cfdcf31b --- /dev/null +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -0,0 +1,152 @@ +// 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.Logging; +using osu.Game.Database; +using SQLite.Net; +using SQLiteNetExtensions.Extensions; + +namespace osu.Game.Beatmaps +{ + /// + /// Handles the storage and retrieval of Beatmaps/BeatmapSets to the database backing + /// + public class BeatmapStore : DatabaseBackedStore + { + public event Action BeatmapSetAdded; + public event Action BeatmapSetRemoved; + + /// + /// The current version of this store. Used for migrations (see ). + /// The initial version is 1. + /// + protected override int StoreVersion => 2; + + public BeatmapStore(SQLiteConnection connection) + : base(connection) + { + } + + protected override Type[] ValidTypes => new[] + { + typeof(BeatmapSetInfo), + typeof(BeatmapInfo), + typeof(BeatmapMetadata), + typeof(BeatmapDifficulty), + }; + + protected override void Prepare(bool reset = false) + { + if (reset) + { + Connection.DropTable(); + Connection.DropTable(); + Connection.DropTable(); + Connection.DropTable(); + Connection.DropTable(); + } + + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + } + + protected override void StartupTasks() + { + base.StartupTasks(); + cleanupPendingDeletions(); + } + + /// + /// Perform migrations between two store versions. + /// + /// The current store version. This will be zero on a fresh database initialisation. + /// The target version which we are migrating to (equal to the current ). + protected override void PerformMigration(int currentVersion, int targetVersion) + { + base.PerformMigration(currentVersion, targetVersion); + + while (currentVersion++ < targetVersion) + { + switch (currentVersion) + { + case 1: + case 2: + // cannot migrate; breaking underlying changes. + Reset(); + break; + } + } + } + + /// + /// Add a to the database. + /// + /// The beatmap to add. + public void Add(BeatmapSetInfo beatmapSet) + { + Connection.RunInTransaction(() => + { + Connection.InsertOrReplaceWithChildren(beatmapSet, true); + }); + + BeatmapSetAdded?.Invoke(beatmapSet); + } + + /// + /// Delete a to the database. + /// + /// The beatmap to delete. + /// Whether the beatmap's was changed. + public bool Delete(BeatmapSetInfo beatmapSet) + { + if (beatmapSet.DeletePending) return false; + + beatmapSet.DeletePending = true; + Connection.Update(beatmapSet); + + BeatmapSetRemoved?.Invoke(beatmapSet); + return true; + } + + /// + /// Restore a previously deleted . + /// + /// The beatmap to restore. + /// Whether the beatmap's was changed. + public bool Undelete(BeatmapSetInfo beatmapSet) + { + if (!beatmapSet.DeletePending) return false; + + beatmapSet.DeletePending = false; + Connection.Update(beatmapSet); + + BeatmapSetAdded?.Invoke(beatmapSet); + return true; + } + + private void cleanupPendingDeletions() + { + foreach (var b in QueryAndPopulate(b => b.DeletePending && !b.Protected)) + { + try + { + // many-to-many join table entries are not automatically tidied. + Connection.Table().Delete(f => f.BeatmapSetInfoID == b.ID); + Connection.Delete(b, true); + } + catch (Exception e) + { + Logger.Error(e, $@"Could not delete beatmap {b}"); + } + } + + //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"); + } + } +} diff --git a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs index 11cc6122ac..ad9a0a787b 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Linq; using osu.Framework; using osu.Framework.Graphics; -using osu.Game.Database; namespace osu.Game.Beatmaps.Drawables { @@ -59,10 +58,10 @@ namespace osu.Game.Beatmaps.Drawables } } - public BeatmapGroup(BeatmapSetInfo beatmapSet, BeatmapDatabase database) + public BeatmapGroup(BeatmapSetInfo beatmapSet, BeatmapManager manager) { BeatmapSet = beatmapSet; - WorkingBeatmap beatmap = database.GetWorkingBeatmap(BeatmapSet.Beatmaps.FirstOrDefault()); + WorkingBeatmap beatmap = manager.GetWorkingBeatmap(BeatmapSet.Beatmaps.FirstOrDefault()); Header = new BeatmapSetHeader(beatmap) { diff --git a/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs b/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs index cfa98da3c8..429ecaf416 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.UserInterface; @@ -34,7 +33,7 @@ namespace osu.Game.Beatmaps.Drawables GainedSelection?.Invoke(this); - background.ColourInfo = ColourInfo.GradientVertical( + background.Colour = ColourInfo.GradientVertical( new Color4(20, 43, 51, 255), new Color4(40, 86, 102, 255)); diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs index 4e41424ae8..df7e0905d0 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetCover.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Game.Database; namespace osu.Game.Beatmaps.Drawables { diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs index b59dbac722..a2457ba78e 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs @@ -35,7 +35,7 @@ namespace osu.Game.Beatmaps.Drawables new PanelBackground(beatmap) { RelativeSizeAxes = Axes.Both, - OnLoadComplete = d => d.FadeInFromZero(400, EasingTypes.Out), + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), } ) { @@ -119,21 +119,21 @@ namespace osu.Game.Beatmaps.Drawables new Box { RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientHorizontal( + Colour = ColourInfo.GradientHorizontal( Color4.Black, new Color4(0f, 0f, 0f, 0.9f)), Width = 0.05f, }, new Box { RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientHorizontal( + Colour = ColourInfo.GradientHorizontal( new Color4(0f, 0f, 0f, 0.9f), new Color4(0f, 0f, 0f, 0.1f)), Width = 0.2f, }, new Box { RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientHorizontal( + Colour = ColourInfo.GradientHorizontal( new Color4(0f, 0f, 0f, 0.1f), new Color4(0, 0, 0, 0)), Width = 0.05f, }, diff --git a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs index e91b52565a..2614baa116 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyColouredContainer.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; -using osu.Game.Database; using osu.Game.Graphics; using OpenTK.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 14298c4172..f61380bfb8 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Game.Database; using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; diff --git a/osu.Game/Beatmaps/Drawables/Panel.cs b/osu.Game/Beatmaps/Drawables/Panel.cs index 3dac50732c..d07be88392 100644 --- a/osu.Game/Beatmaps/Drawables/Panel.cs +++ b/osu.Game/Beatmaps/Drawables/Panel.cs @@ -64,9 +64,9 @@ namespace osu.Game.Beatmaps.Drawables } if (state == PanelSelectedState.Hidden) - FadeOut(300, EasingTypes.OutQuint); + this.FadeOut(300, Easing.OutQuint); else - FadeIn(250); + this.FadeIn(250); } private PanelSelectedState state = PanelSelectedState.NotSelected; diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 970a3dbd35..0885fb05e5 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; -using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; diff --git a/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs index 21a3ab9842..1c3eadc91e 100644 --- a/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.IO; using osu.Game.Rulesets.Objects; -using osu.Game.Database; namespace osu.Game.Beatmaps.Formats { @@ -13,6 +12,11 @@ namespace osu.Game.Beatmaps.Formats { private static readonly Dictionary decoders = new Dictionary(); + static BeatmapDecoder() + { + OsuLegacyDecoder.Register(); + } + public static BeatmapDecoder GetDecoder(StreamReader stream) { string line = stream.ReadLine()?.Trim(); diff --git a/osu.Game/Beatmaps/IO/ArchiveReader.cs b/osu.Game/Beatmaps/IO/ArchiveReader.cs index 7ff5668b6f..3af2a7ea2a 100644 --- a/osu.Game/Beatmaps/IO/ArchiveReader.cs +++ b/osu.Game/Beatmaps/IO/ArchiveReader.cs @@ -5,45 +5,11 @@ using System; using System.Collections.Generic; using System.IO; using osu.Framework.IO.Stores; -using osu.Framework.Platform; namespace osu.Game.Beatmaps.IO { public abstract class ArchiveReader : IDisposable, IResourceStore { - private class Reader - { - public Func Test; - public Type Type; - } - - private static readonly List readers = new List(); - - public static ArchiveReader GetReader(Storage storage, string path) - { - foreach (var reader in readers) - { - if (reader.Test(storage, path)) - return (ArchiveReader)Activator.CreateInstance(reader.Type, storage.GetStream(path)); - } - throw new IOException(@"Unknown file format"); - } - - protected static void AddReader(Func test) where T : ArchiveReader - { - readers.Add(new Reader { Test = test, Type = typeof(T) }); - } - - /// - /// Gets a list of beatmap file names. - /// - public string[] BeatmapFilenames { get; protected set; } - - /// - /// The storyboard filename. Null if no storyboard is present. - /// - public string StoryboardFilename { get; protected set; } - /// /// Opens a stream for reading a specific file from this archive. /// @@ -51,6 +17,8 @@ namespace osu.Game.Beatmaps.IO public abstract void Dispose(); + public abstract IEnumerable Filenames { get; } + public virtual byte[] Get(string name) { using (Stream input = GetStream(name)) diff --git a/osu.Game/Beatmaps/IO/LegacyFilesystemReader.cs b/osu.Game/Beatmaps/IO/LegacyFilesystemReader.cs new file mode 100644 index 0000000000..dc38181717 --- /dev/null +++ b/osu.Game/Beatmaps/IO/LegacyFilesystemReader.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 System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace osu.Game.Beatmaps.IO +{ + /// + /// Reads an extracted legacy beatmap from disk. + /// + public class LegacyFilesystemReader : ArchiveReader + { + private readonly string path; + + public LegacyFilesystemReader(string path) + { + this.path = path; + } + + public override Stream GetStream(string name) => File.OpenRead(Path.Combine(path, name)); + + public override void Dispose() + { + // no-op + } + + public override IEnumerable Filenames => Directory.GetFiles(path).Select(Path.GetFileName).ToArray(); + + public override Stream GetUnderlyingStream() => null; + } +} diff --git a/osu.Game/Beatmaps/IO/OszArchiveReader.cs b/osu.Game/Beatmaps/IO/OszArchiveReader.cs index a22a5f4cce..4e0c40d28e 100644 --- a/osu.Game/Beatmaps/IO/OszArchiveReader.cs +++ b/osu.Game/Beatmaps/IO/OszArchiveReader.cs @@ -1,25 +1,15 @@ // 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.IO; using System.Linq; using Ionic.Zip; -using osu.Game.Beatmaps.Formats; namespace osu.Game.Beatmaps.IO { public sealed class OszArchiveReader : ArchiveReader { - public static void Register() - { - AddReader((storage, path) => - { - using (var stream = storage.GetStream(path)) - return stream != null && ZipFile.IsZipFile(stream, false); - }); - OsuLegacyDecoder.Register(); - } - private readonly Stream archiveStream; private readonly ZipFile archive; @@ -27,13 +17,6 @@ namespace osu.Game.Beatmaps.IO { this.archiveStream = archiveStream; archive = ZipFile.Read(archiveStream); - - BeatmapFilenames = archive.Entries.Where(e => e.FileName.EndsWith(@".osu")).Select(e => e.FileName).ToArray(); - - if (BeatmapFilenames.Length == 0) - throw new FileNotFoundException(@"This directory contains no beatmaps"); - - StoryboardFilename = archive.Entries.Where(e => e.FileName.EndsWith(@".osb")).Select(e => e.FileName).FirstOrDefault(); } public override Stream GetStream(string name) @@ -41,7 +24,16 @@ namespace osu.Game.Beatmaps.IO ZipEntry entry = archive.Entries.SingleOrDefault(e => e.FileName == name); if (entry == null) throw new FileNotFoundException(); - return entry.OpenReader(); + + // allow seeking + MemoryStream copy = new MemoryStream(); + + using (Stream s = entry.OpenReader()) + s.CopyTo(copy); + + copy.Position = 0; + + return copy; } public override void Dispose() @@ -50,6 +42,8 @@ namespace osu.Game.Beatmaps.IO archiveStream.Dispose(); } + public override IEnumerable Filenames => archive.Entries.Select(e => e.FileName).ToArray(); + public override Stream GetUnderlyingStream() => archiveStream; } } \ No newline at end of file diff --git a/osu.Game/Database/RankStatus.cs b/osu.Game/Beatmaps/RankStatus.cs similarity index 91% rename from osu.Game/Database/RankStatus.cs rename to osu.Game/Beatmaps/RankStatus.cs index f2a7d67a40..17a4a4aa3f 100644 --- a/osu.Game/Database/RankStatus.cs +++ b/osu.Game/Beatmaps/RankStatus.cs @@ -3,7 +3,7 @@ using System.ComponentModel; -namespace osu.Game.Database +namespace osu.Game.Beatmaps { public enum RankStatus { diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 0e8d8a9546..a6a3b23d5d 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -4,7 +4,6 @@ using osu.Framework.Audio.Track; using osu.Framework.Configuration; using osu.Framework.Graphics.Textures; -using osu.Game.Database; using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; @@ -22,14 +21,11 @@ namespace osu.Game.Beatmaps public readonly Bindable> Mods = new Bindable>(new Mod[] { }); - public readonly bool WithStoryboard; - - protected WorkingBeatmap(BeatmapInfo beatmapInfo, bool withStoryboard = false) + protected WorkingBeatmap(BeatmapInfo beatmapInfo) { BeatmapInfo = beatmapInfo; BeatmapSetInfo = beatmapInfo.BeatmapSet; Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo.Metadata; - WithStoryboard = withStoryboard; Mods.ValueChanged += mods => applyRateAdjustments(); } diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs deleted file mode 100644 index b31b71a728..0000000000 --- a/osu.Game/Database/BeatmapDatabase.cs +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using osu.Framework.Extensions; -using osu.Framework.Logging; -using osu.Framework.Platform; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Formats; -using osu.Game.Beatmaps.IO; -using osu.Game.IPC; -using osu.Game.Screens.Menu; -using SQLite.Net; -using SQLiteNetExtensions.Extensions; - -namespace osu.Game.Database -{ - public class BeatmapDatabase : Database - { - 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; - - /// - /// A default representation of a WorkingBeatmap to use when no beatmap is available. - /// - public WorkingBeatmap DefaultBeatmap { private get; set; } - - public BeatmapDatabase(Storage storage, SQLiteConnection connection, RulesetDatabase rulesets, IIpcHost importHost = null) : base(storage, connection) - { - this.rulesets = rulesets; - if (importHost != null) - ipc = new BeatmapIPCChannel(importHost, this); - } - - private void deletePending() - { - foreach (var b in GetAllWithChildren(b => b.DeletePending)) - { - if (b.Hash == Intro.MENU_MUSIC_BEATMAP_HASH) - // this is a bit hacky, but will do for now. - continue; - - try - { - Storage.Delete(b.Path); - - foreach (var i in b.Beatmaps) - { - if (i.Metadata != null) Connection.Delete(i.Metadata); - if (i.Difficulty != null) Connection.Delete(i.Difficulty); - - Connection.Delete(i); - } - - if (b.Metadata != null) Connection.Delete(b.Metadata); - Connection.Delete(b); - } - catch (Exception e) - { - Logger.Error(e, $@"Could not delete beatmap {b}"); - } - } - - //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"); - } - - protected override void Prepare(bool reset = false) - { - Connection.CreateTable(); - Connection.CreateTable(); - Connection.CreateTable(); - Connection.CreateTable(); - - if (reset) - { - 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(); - } - - deletePending(); - } - - protected override Type[] ValidTypes => new[] { - typeof(BeatmapSetInfo), - typeof(BeatmapInfo), - typeof(BeatmapMetadata), - typeof(BeatmapDifficulty), - }; - - public void Import(string path) - { - try - { - Import(ArchiveReader.GetReader(Storage, path)); - - // We may or may not want to delete the file depending on where it is stored. - // e.g. reconstructing/repairing database with beatmaps from default storage. - // Also, not always a single file, i.e. for LegacyFilesystemReader - // TODO: Add a check to prevent files from storage to be deleted. - try - { - File.Delete(path); - } - catch (Exception e) - { - Logger.Error(e, $@"Could not delete file at {path}"); - } - } - catch (Exception e) - { - e = e.InnerException ?? e; - Logger.Error(e, @"Could not import beatmap set"); - } - } - - public void Import(ArchiveReader archiveReader) - { - BeatmapSetInfo set = getBeatmapSet(archiveReader); - - //If we have an ID then we already exist in the database. - if (set.ID == 0) - Import(new[] { set }); - } - - /// - /// Import multiple from . - /// - /// Multiple locations on disk - public void Import(params string[] paths) - { - foreach (string p in paths) - { - //In case the file was imported twice and deleted after the first time - if (File.Exists(p)) - Import(p); - } - } - - /// - /// Duplicates content from to storage and returns a representing . - /// - /// Content location - /// - private BeatmapSetInfo getBeatmapSet(string path) => getBeatmapSet(ArchiveReader.GetReader(Storage, path)); - - private BeatmapSetInfo getBeatmapSet(ArchiveReader archiveReader) - { - BeatmapMetadata metadata; - - using (var stream = new StreamReader(archiveReader.GetStream(archiveReader.BeatmapFilenames[0]))) - metadata = BeatmapDecoder.GetDecoder(stream).Decode(stream).Metadata; - - string hash; - string path; - - using (var input = archiveReader.GetUnderlyingStream()) - { - 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)) - input.CopyTo(output); - } - - var existing = Connection.Table().FirstOrDefault(b => b.Hash == hash); - - if (existing != null) - { - GetChildren(existing); - - if (existing.DeletePending) - { - existing.DeletePending = false; - Update(existing, false); - BeatmapSetAdded?.Invoke(existing); - } - - return existing; - } - - var beatmapSet = new BeatmapSetInfo - { - OnlineBeatmapSetID = metadata.OnlineBeatmapSetID, - Beatmaps = new List(), - Path = path, - Hash = hash, - Metadata = metadata - }; - - using (var archive = ArchiveReader.GetReader(Storage, path)) - { - string[] mapNames = archive.BeatmapFilenames; - foreach (var name in mapNames) - using (var raw = archive.GetStream(name)) - using (var ms = new MemoryStream()) //we need a memory stream so we can seek and shit - using (var sr = new StreamReader(ms)) - { - raw.CopyTo(ms); - ms.Position = 0; - - var decoder = BeatmapDecoder.GetDecoder(sr); - Beatmap beatmap = decoder.Decode(sr); - - beatmap.BeatmapInfo.Path = name; - beatmap.BeatmapInfo.Hash = ms.GetMd5Hash(); - - // TODO: Diff beatmap metadata with set metadata and leave it here if necessary - beatmap.BeatmapInfo.Metadata = null; - - // 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); - } - beatmapSet.StoryboardFile = archive.StoryboardFilename; - } - - return beatmapSet; - } - - public void Import(IEnumerable beatmapSets) - { - lock (Connection) - { - Connection.BeginTransaction(); - - foreach (var s in beatmapSets) - { - Connection.InsertOrReplaceWithChildren(s, true); - BeatmapSetAdded?.Invoke(s); - } - - Connection.Commit(); - } - } - - public void Delete(BeatmapSetInfo beatmapSet) - { - beatmapSet.DeletePending = true; - Update(beatmapSet, false); - - BeatmapSetRemoved?.Invoke(beatmapSet); - } - - public ArchiveReader GetReader(BeatmapSetInfo beatmapSet) - { - if (string.IsNullOrEmpty(beatmapSet.Path)) - return null; - - return ArchiveReader.GetReader(Storage, beatmapSet.Path); - } - - public BeatmapSetInfo GetBeatmapSet(int id) - { - return Query().FirstOrDefault(s => s.OnlineBeatmapSetID == id); - } - - public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo, WorkingBeatmap previous = null, bool withStoryboard = false) - { - if (beatmapInfo == null || beatmapInfo == DefaultBeatmap?.BeatmapInfo) - return DefaultBeatmap; - - if (beatmapInfo.BeatmapSet == null || beatmapInfo.Ruleset == null) - beatmapInfo = GetChildren(beatmapInfo, true); - - if (beatmapInfo.BeatmapSet == null) - throw new InvalidOperationException($@"Beatmap set {beatmapInfo.BeatmapSetInfoID} is not in the local database."); - - if (beatmapInfo.Metadata == null) - beatmapInfo.Metadata = beatmapInfo.BeatmapSet.Metadata; - - WorkingBeatmap working = new DatabaseWorkingBeatmap(this, beatmapInfo, withStoryboard); - - previous?.TransferTo(working); - - return working; - } - - public bool Exists(BeatmapSetInfo beatmapSet) => Storage.Exists(beatmapSet.Path); - } -} diff --git a/osu.Game/Database/Database.cs b/osu.Game/Database/Database.cs deleted file mode 100644 index a55c0f570b..0000000000 --- a/osu.Game/Database/Database.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System; -using System.Collections.Generic; -using System.Linq; -using 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(); - } - - /// - /// This is expensive. Use with caution. - /// - 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/DatabaseBackedStore.cs b/osu.Game/Database/DatabaseBackedStore.cs new file mode 100644 index 0000000000..e3afd9688a --- /dev/null +++ b/osu.Game/Database/DatabaseBackedStore.cs @@ -0,0 +1,131 @@ +// 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 DatabaseBackedStore + { + protected readonly Storage Storage; + protected readonly SQLiteConnection Connection; + + protected virtual int StoreVersion => 1; + + protected DatabaseBackedStore(SQLiteConnection connection, Storage storage = null) + { + 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); + } + + checkMigrations(); + } + + private void checkMigrations() + { + var storeName = GetType().Name; + + var reportedVersion = Connection.Table().FirstOrDefault(s => s.StoreName == storeName) ?? new StoreVersion + { + StoreName = storeName, + Version = 0 + }; + + if (reportedVersion.Version != StoreVersion) + PerformMigration(reportedVersion.Version, reportedVersion.Version = StoreVersion); + + Connection.InsertOrReplace(reportedVersion); + + StartupTasks(); + } + + /// + /// Called when the database version of this store doesn't match the local version. + /// Any manual migration operations should be performed in this. + /// + /// The current store version. This will be zero on a fresh database initialisation. + /// The target version which we are migrating to (equal to the current ). + protected virtual void PerformMigration(int currentVersion, int targetVersion) + { + } + + /// + /// Perform any common startup tasks. Runs after and . + /// + protected virtual void StartupTasks() + { + + } + + /// + /// Prepare this database for use. Tables should be created here. + /// + 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(Expression> filter = null) where T : class + { + checkType(typeof(T)); + + var query = Connection.Table(); + + if (filter != null) + query = query.Where(filter); + + return query; + } + + /// + /// Query and populate results. + /// + /// An filter to refine results. + /// + public List QueryAndPopulate(Expression> filter) + where T : class + { + checkType(typeof(T)); + + return Connection.GetAllWithChildren(filter, true); + } + + /// + /// Populate a database-backed item. + /// + /// + /// Whether population should recurse beyond a single level. + public void Populate(T item, bool recursive = true) + { + checkType(item.GetType()); + Connection.GetChildren(item, recursive); + } + + private void checkType(Type type) + { + if (!ValidTypes.Contains(type)) + throw new InvalidOperationException($"The requested operation specified a type of {type}, which is invalid for this {nameof(DatabaseBackedStore)}."); + } + + protected abstract Type[] ValidTypes { get; } + } +} diff --git a/osu.Game/Database/DatabaseWorkingBeatmap.cs b/osu.Game/Database/DatabaseWorkingBeatmap.cs deleted file mode 100644 index 2acae9c340..0000000000 --- a/osu.Game/Database/DatabaseWorkingBeatmap.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.IO; -using osu.Framework.Audio.Track; -using osu.Framework.Graphics.Textures; -using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Formats; -using osu.Game.Beatmaps.IO; - -namespace osu.Game.Database -{ - internal class DatabaseWorkingBeatmap : WorkingBeatmap - { - private readonly BeatmapDatabase database; - - public DatabaseWorkingBeatmap(BeatmapDatabase database, BeatmapInfo beatmapInfo, bool withStoryboard = false) - : base(beatmapInfo, withStoryboard) - { - this.database = database; - } - - private ArchiveReader getReader() => database?.GetReader(BeatmapSetInfo); - - protected override Beatmap GetBeatmap() - { - try - { - Beatmap beatmap; - - using (var reader = getReader()) - { - BeatmapDecoder decoder; - using (var stream = new StreamReader(reader.GetStream(BeatmapInfo.Path))) - { - decoder = BeatmapDecoder.GetDecoder(stream); - beatmap = decoder.Decode(stream); - } - - if (beatmap == null || !WithStoryboard || BeatmapSetInfo.StoryboardFile == null) - return beatmap; - - using (var stream = new StreamReader(reader.GetStream(BeatmapSetInfo.StoryboardFile))) - decoder.Decode(stream, beatmap); - } - - return beatmap; - } - catch { return null; } - } - - protected override Texture GetBackground() - { - if (Metadata?.BackgroundFile == null) - return null; - - try - { - using (var reader = getReader()) - return new TextureStore(new RawTextureLoaderStore(reader), false).Get(Metadata.BackgroundFile); - } - catch { return null; } - } - - protected override Track GetTrack() - { - try - { - var trackData = getReader()?.GetStream(Metadata.AudioFile); - return trackData == null ? null : new TrackBass(trackData); - } - catch { return new TrackVirtual(); } - } - } -} diff --git a/osu.Game/Database/StoreVersion.cs b/osu.Game/Database/StoreVersion.cs new file mode 100644 index 0000000000..00314875a6 --- /dev/null +++ b/osu.Game/Database/StoreVersion.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 SQLite.Net.Attributes; + +namespace osu.Game.Database +{ + public class StoreVersion + { + [PrimaryKey] + public string StoreName { get; set; } + + public int Version { get; set; } + } +} diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 19475b00c9..ec9d30f244 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -42,7 +42,7 @@ namespace osu.Game.Graphics.Containers { if (!parallaxEnabled) { - content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, EasingTypes.OutQuint); + content.MoveTo(Vector2.Zero, firstUpdate ? 0 : 1000, Easing.OutQuint); content.Scale = new Vector2(1 + ParallaxAmount); } }; @@ -57,7 +57,7 @@ namespace osu.Game.Graphics.Containers if (parallaxEnabled) { Vector2 offset = input.CurrentState.Mouse == null ? Vector2.Zero : ToLocalSpace(input.CurrentState.Mouse.NativeState.Position) - DrawSize / 2; - content.MoveTo(offset * ParallaxAmount, firstUpdate ? 0 : 1000, EasingTypes.OutQuint); + content.MoveTo(offset * ParallaxAmount, firstUpdate ? 0 : 1000, Easing.OutQuint); content.Scale = new Vector2(1 + ParallaxAmount); } diff --git a/osu.Game/Graphics/Cursor/GameplayCursor.cs b/osu.Game/Graphics/Cursor/GameplayCursor.cs index da3975f606..9f771ae56d 100644 --- a/osu.Game/Graphics/Cursor/GameplayCursor.cs +++ b/osu.Game/Graphics/Cursor/GameplayCursor.cs @@ -13,7 +13,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Input; using osu.Game.Beatmaps; using osu.Game.Configuration; -using osu.Game.Database; namespace osu.Game.Graphics.Cursor { @@ -29,14 +28,14 @@ namespace osu.Game.Graphics.Cursor protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { ActiveCursor.Scale = new Vector2(1); - ActiveCursor.ScaleTo(1.2f, 100, EasingTypes.OutQuad); + ActiveCursor.ScaleTo(1.2f, 100, Easing.OutQuad); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { if (!state.Mouse.HasMainButtonPressed) - ActiveCursor.ScaleTo(1, 200, EasingTypes.OutQuad); + ActiveCursor.ScaleTo(1, 200, Easing.OutQuad); return base.OnMouseUp(state, args); } diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 82ae424ab0..9658cfdb09 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -34,7 +34,7 @@ namespace osu.Game.Graphics.Cursor if (diff > 180) diff -= 360; degrees = ActiveCursor.Rotation + diff; - ActiveCursor.RotateTo(degrees, 600, EasingTypes.OutQuint); + ActiveCursor.RotateTo(degrees, 600, Easing.OutQuint); } return base.OnMouseMove(state); @@ -49,10 +49,10 @@ namespace osu.Game.Graphics.Cursor protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { ActiveCursor.Scale = new Vector2(1); - ActiveCursor.ScaleTo(0.90f, 800, EasingTypes.OutQuint); + ActiveCursor.ScaleTo(0.90f, 800, Easing.OutQuint); ((Cursor)ActiveCursor).AdditiveLayer.Alpha = 0; - ((Cursor)ActiveCursor).AdditiveLayer.FadeInFromZero(800, EasingTypes.OutQuint); + ((Cursor)ActiveCursor).AdditiveLayer.FadeInFromZero(800, Easing.OutQuint); return base.OnMouseDown(state, args); } @@ -62,9 +62,9 @@ namespace osu.Game.Graphics.Cursor { dragging = false; - ((Cursor)ActiveCursor).AdditiveLayer.FadeOut(500, EasingTypes.OutQuint); - ActiveCursor.RotateTo(0, 600 * (1 + Math.Abs(ActiveCursor.Rotation / 720)), EasingTypes.OutElasticHalf); - ActiveCursor.ScaleTo(1, 500, EasingTypes.OutElastic); + ((Cursor)ActiveCursor).AdditiveLayer.FadeOut(500, Easing.OutQuint); + ActiveCursor.RotateTo(0, 600 * (1 + Math.Abs(ActiveCursor.Rotation / 720)), Easing.OutElasticHalf); + ActiveCursor.ScaleTo(1, 500, Easing.OutElastic); } return base.OnMouseUp(state, args); @@ -72,21 +72,21 @@ namespace osu.Game.Graphics.Cursor protected override bool OnClick(InputState state) { - ((Cursor)ActiveCursor).AdditiveLayer.FadeOutFromOne(500, EasingTypes.OutQuint); + ((Cursor)ActiveCursor).AdditiveLayer.FadeOutFromOne(500, Easing.OutQuint); return base.OnClick(state); } protected override void PopIn() { - ActiveCursor.FadeTo(1, 250, EasingTypes.OutQuint); - ActiveCursor.ScaleTo(1, 400, EasingTypes.OutQuint); + ActiveCursor.FadeTo(1, 250, Easing.OutQuint); + ActiveCursor.ScaleTo(1, 400, Easing.OutQuint); } protected override void PopOut() { - ActiveCursor.FadeTo(0, 900, EasingTypes.OutQuint); - ActiveCursor.ScaleTo(0, 500, EasingTypes.In); + ActiveCursor.FadeTo(0, 900, Easing.OutQuint); + ActiveCursor.ScaleTo(0, 500, Easing.In); } public class Cursor : Container diff --git a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs index 44d176f4d9..e9d84b28a3 100644 --- a/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs +++ b/osu.Game/Graphics/Cursor/OsuTooltipContainer.cs @@ -37,7 +37,7 @@ namespace osu.Game.Graphics.Cursor if (IsPresent) { AutoSizeDuration = 250; - background.FlashColour(OsuColour.Gray(0.4f), 1000, EasingTypes.OutQuint); + background.FlashColour(OsuColour.Gray(0.4f), 1000, Easing.OutQuint); } else AutoSizeDuration = 0; @@ -48,7 +48,7 @@ namespace osu.Game.Graphics.Cursor public OsuTooltip() { - AutoSizeEasing = EasingTypes.OutQuint; + AutoSizeEasing = Easing.OutQuint; CornerRadius = 5; Masking = true; @@ -83,16 +83,10 @@ namespace osu.Game.Graphics.Cursor protected override void PopIn() { instantMovement |= !IsPresent; - - ClearTransforms(); - FadeIn(500, EasingTypes.OutQuint); + this.FadeIn(500, Easing.OutQuint); } - protected override void PopOut() - { - using (BeginDelayedSequence(150)) - FadeOut(500, EasingTypes.OutQuint); - } + protected override void PopOut() => this.Delay(150).FadeOut(500, Easing.OutQuint); public override void Move(Vector2 pos) { @@ -103,7 +97,7 @@ namespace osu.Game.Graphics.Cursor } else { - MoveTo(pos, 200, EasingTypes.OutQuint); + this.MoveTo(pos, 200, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/IHasAccentColour.cs b/osu.Game/Graphics/IHasAccentColour.cs index 9eb66d8fac..ac2117c517 100644 --- a/osu.Game/Graphics/IHasAccentColour.cs +++ b/osu.Game/Graphics/IHasAccentColour.cs @@ -4,7 +4,6 @@ using OpenTK.Graphics; using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; -using osu.Game.Graphics.Transforms; namespace osu.Game.Graphics { @@ -27,10 +26,8 @@ namespace osu.Game.Graphics /// The new accent colour. /// The tween duration. /// The tween easing. - public static void FadeAccent(this T accentedDrawable, Color4 newColour, double duration = 0, EasingTypes easing = EasingTypes.None) - where T : Transformable, IHasAccentColour - { - accentedDrawable.TransformTo(newColour, duration, easing, new TransformAccent()); - } + public static TransformSequence FadeAccent(this T accentedDrawable, Color4 newColour, double duration = 0, Easing easing = Easing.None) + where T : IHasAccentColour + => accentedDrawable.TransformTo(nameof(accentedDrawable.AccentColour), newColour, duration, easing); } } diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index d2f4d4768c..70017d3c6e 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -13,6 +13,9 @@ namespace osu.Game.Graphics public static Color4 FromHex(string hex) { + if (hex[0] == '#') + hex = hex.Substring(1); + switch (hex.Length) { default: diff --git a/osu.Game/Graphics/Transforms/TransformAccent.cs b/osu.Game/Graphics/Transforms/TransformAccent.cs deleted file mode 100644 index 53a452ad8a..0000000000 --- a/osu.Game/Graphics/Transforms/TransformAccent.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using OpenTK.Graphics; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Transforms; -using osu.Framework.MathUtils; - -namespace osu.Game.Graphics.Transforms -{ - public class TransformAccent : Transform - { - /// - /// Current value of the transformed colour in linear colour space. - /// - public virtual Color4 CurrentValue - { - get - { - double time = Time?.Current ?? 0; - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - } - - public override void Apply(Drawable d) => ((IHasAccentColour)d).AccentColour = CurrentValue; - public override void ReadIntoStartValue(Drawable d) => StartValue = ((IHasAccentColour)d).AccentColour; - } -} diff --git a/osu.Game/Graphics/UserInterface/Bar.cs b/osu.Game/Graphics/UserInterface/Bar.cs index 1da73a60a2..20df553142 100644 --- a/osu.Game/Graphics/UserInterface/Bar.cs +++ b/osu.Game/Graphics/UserInterface/Bar.cs @@ -17,7 +17,7 @@ namespace osu.Game.Graphics.UserInterface private const int resize_duration = 250; - private const EasingTypes easing = EasingTypes.InOutCubic; + private const Easing easing = Easing.InOutCubic; private float length; /// diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs index 155b08fde8..f61192a1a6 100644 --- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs +++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs @@ -28,7 +28,7 @@ namespace osu.Game.Graphics.UserInterface var tabIndex = TabContainer.IndexOf(TabMap[tab]); t.State = tIndex < tabIndex ? Visibility.Hidden : Visibility.Visible; - t.Chevron.FadeTo(tIndex <= tabIndex ? 0f : 1f, 500, EasingTypes.OutQuint); + t.Chevron.FadeTo(tIndex <= tabIndex ? 0f : 1f, 500, Easing.OutQuint); } }; } @@ -54,13 +54,13 @@ namespace osu.Game.Graphics.UserInterface if (State == Visibility.Visible) { - FadeIn(transition_duration, EasingTypes.OutQuint); - ScaleTo(new Vector2(1f), transition_duration, EasingTypes.OutQuint); + this.FadeIn(transition_duration, Easing.OutQuint); + this.ScaleTo(new Vector2(1f), transition_duration, Easing.OutQuint); } else { - FadeOut(transition_duration, EasingTypes.OutQuint); - ScaleTo(new Vector2(0.8f, 1f), transition_duration, EasingTypes.OutQuint); + this.FadeOut(transition_duration, Easing.OutQuint); + this.ScaleTo(new Vector2(0.8f, 1f), transition_duration, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs index 3f1b81893d..1cbf77d8f2 100644 --- a/osu.Game/Graphics/UserInterface/DialogButton.cs +++ b/osu.Game/Graphics/UserInterface/DialogButton.cs @@ -96,11 +96,10 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnClick(Framework.Input.InputState state) { didClick = true; - colourContainer.ResizeTo(new Vector2(1.5f, 1f), click_duration, EasingTypes.In); + colourContainer.ResizeTo(new Vector2(1.5f, 1f), click_duration, Easing.In); flash(); - Delay(click_duration); - Schedule(delegate { + this.Delay(click_duration).Schedule(delegate { colourContainer.ResizeTo(new Vector2(0.8f, 1f)); spriteText.Spacing = Vector2.Zero; glowContainer.FadeOut(); @@ -111,10 +110,10 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(Framework.Input.InputState state) { - spriteText.TransformSpacingTo(hoverSpacing, hover_duration, EasingTypes.OutElastic); + spriteText.TransformSpacingTo(hoverSpacing, hover_duration, Easing.OutElastic); - colourContainer.ResizeTo(new Vector2(hover_width, 1f), hover_duration, EasingTypes.OutElastic); - glowContainer.FadeIn(glow_fade_duration, EasingTypes.Out); + colourContainer.ResizeTo(new Vector2(hover_width, 1f), hover_duration, Easing.OutElastic); + glowContainer.FadeIn(glow_fade_duration, Easing.Out); base.OnHover(state); return true; } @@ -123,9 +122,9 @@ namespace osu.Game.Graphics.UserInterface { if (!didClick) { - colourContainer.ResizeTo(new Vector2(0.8f, 1f), hover_duration, EasingTypes.OutElastic); - spriteText.TransformSpacingTo(Vector2.Zero, hover_duration, EasingTypes.OutElastic); - glowContainer.FadeOut(glow_fade_duration, EasingTypes.Out); + colourContainer.ResizeTo(new Vector2(0.8f, 1f), hover_duration, Easing.OutElastic); + spriteText.TransformSpacingTo(Vector2.Zero, hover_duration, Easing.OutElastic); + glowContainer.FadeOut(glow_fade_duration, Easing.Out); } didClick = false; @@ -149,9 +148,9 @@ namespace osu.Game.Graphics.UserInterface private void updateGlow() { - leftGlow.ColourInfo = ColourInfo.GradientHorizontal(new Color4(ButtonColour.R, ButtonColour.G, ButtonColour.B, 0f), ButtonColour); + leftGlow.Colour = ColourInfo.GradientHorizontal(new Color4(ButtonColour.R, ButtonColour.G, ButtonColour.B, 0f), ButtonColour); centerGlow.Colour = ButtonColour; - rightGlow.ColourInfo = ColourInfo.GradientHorizontal(ButtonColour, new Color4(ButtonColour.R, ButtonColour.G, ButtonColour.B, 0f)); + rightGlow.Colour = ColourInfo.GradientHorizontal(ButtonColour, new Color4(ButtonColour.R, ButtonColour.G, ButtonColour.B, 0f)); } public DialogButton() diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs index a9210c69fb..110a955780 100644 --- a/osu.Game/Graphics/UserInterface/IconButton.cs +++ b/osu.Game/Graphics/UserInterface/IconButton.cs @@ -86,31 +86,31 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(InputState state) { - hover.FadeIn(500, EasingTypes.OutQuint); + hover.FadeIn(500, Easing.OutQuint); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - hover.FadeOut(500, EasingTypes.OutQuint); + hover.FadeOut(500, Easing.OutQuint); base.OnHoverLost(state); } protected override bool OnClick(InputState state) { - hover.FlashColour(flashColour, 800, EasingTypes.OutQuint); + hover.FlashColour(flashColour, 800, Easing.OutQuint); return base.OnClick(state); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - content.ScaleTo(0.75f, 2000, EasingTypes.OutQuint); + content.ScaleTo(0.75f, 2000, Easing.OutQuint); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - content.ScaleTo(1, 1000, EasingTypes.OutElastic); + content.ScaleTo(1, 1000, Easing.OutElastic); return base.OnMouseUp(state, args); } } diff --git a/osu.Game/Graphics/UserInterface/LineGraph.cs b/osu.Game/Graphics/UserInterface/LineGraph.cs index cd8ba96dc8..aa9256e576 100644 --- a/osu.Game/Graphics/UserInterface/LineGraph.cs +++ b/osu.Game/Graphics/UserInterface/LineGraph.cs @@ -49,7 +49,7 @@ namespace osu.Game.Graphics.UserInterface values = value.ToArray(); applyPath(); maskingContainer.Width = 0; - maskingContainer.ResizeWidthTo(1, transform_duration, EasingTypes.OutQuint); + maskingContainer.ResizeWidthTo(1, transform_duration, Easing.OutQuint); } } diff --git a/osu.Game/Graphics/UserInterface/LoadingAnimation.cs b/osu.Game/Graphics/UserInterface/LoadingAnimation.cs index eed5061abd..56ee47a7e6 100644 --- a/osu.Game/Graphics/UserInterface/LoadingAnimation.cs +++ b/osu.Game/Graphics/UserInterface/LoadingAnimation.cs @@ -34,14 +34,13 @@ namespace osu.Game.Graphics.UserInterface { base.LoadComplete(); - using (spinner.BeginLoopedSequence()) - spinner.RotateTo(360, 2000); + spinner.Spin(2000, RotationDirection.Clockwise); } private const float transition_duration = 500; - protected override void PopIn() => FadeIn(transition_duration * 5, EasingTypes.OutQuint); + protected override void PopIn() => this.FadeIn(transition_duration * 5, Easing.OutQuint); - protected override void PopOut() => FadeOut(transition_duration, EasingTypes.OutQuint); + protected override void PopOut() => this.FadeOut(transition_duration, Easing.OutQuint); } } diff --git a/osu.Game/Graphics/UserInterface/Nub.cs b/osu.Game/Graphics/UserInterface/Nub.cs index d5059945c6..f7df6cd4f4 100644 --- a/osu.Game/Graphics/UserInterface/Nub.cs +++ b/osu.Game/Graphics/UserInterface/Nub.cs @@ -43,9 +43,9 @@ namespace osu.Game.Graphics.UserInterface Current.ValueChanged += newValue => { if (newValue) - fill.FadeIn(200, EasingTypes.OutQuint); + fill.FadeIn(200, Easing.OutQuint); else - fill.FadeTo(0.01f, 200, EasingTypes.OutQuint); //todo: remove once we figure why containers aren't drawing at all times + fill.FadeTo(0.01f, 200, Easing.OutQuint); //todo: remove once we figure why containers aren't drawing at all times }; } @@ -80,13 +80,13 @@ namespace osu.Game.Graphics.UserInterface if (value) { - FadeColour(GlowingAccentColour, 500, EasingTypes.OutQuint); - FadeEdgeEffectTo(1, 500, EasingTypes.OutQuint); + this.FadeColour(GlowingAccentColour, 500, Easing.OutQuint); + FadeEdgeEffectTo(1, 500, Easing.OutQuint); } else { FadeEdgeEffectTo(0, 500); - FadeColour(AccentColour, 500); + this.FadeColour(AccentColour, 500); } } } @@ -95,7 +95,7 @@ namespace osu.Game.Graphics.UserInterface { set { - ResizeTo(new Vector2(value ? EXPANDED_SIZE : COLLAPSED_SIZE, 12), 500, EasingTypes.OutQuint); + this.ResizeTo(new Vector2(value ? EXPANDED_SIZE : COLLAPSED_SIZE, 12), 500, Easing.OutQuint); } } diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 18156f8e76..3c454f2af2 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -68,6 +68,14 @@ namespace osu.Game.Graphics.UserInterface sampleClick = audio.Sample.Get(@"UI/generic-click"); sampleHover = audio.Sample.Get(@"UI/generic-hover"); + + Enabled.ValueChanged += enabled_ValueChanged; + Enabled.TriggerChange(); + } + + private void enabled_ValueChanged(bool enabled) + { + this.FadeColour(enabled ? Color4.White : Color4.Gray, 200, Easing.OutQuint); } protected override bool OnClick(InputState state) @@ -91,13 +99,13 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - Content.ScaleTo(0.9f, 4000, EasingTypes.OutQuint); + Content.ScaleTo(0.9f, 4000, Easing.OutQuint); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - Content.ScaleTo(1, 1000, EasingTypes.OutElastic); + Content.ScaleTo(1, 1000, Easing.OutElastic); return base.OnMouseUp(state, args); } } diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs index e17ce2a5b2..d4882cce1e 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenu.cs @@ -39,13 +39,13 @@ namespace osu.Game.Graphics.UserInterface Background.Colour = colours.ContextMenuGray; } - protected override void AnimateOpen() => FadeIn(fade_duration, EasingTypes.OutQuint); - protected override void AnimateClose() => FadeOut(fade_duration, EasingTypes.OutQuint); + protected override void AnimateOpen() => this.FadeIn(fade_duration, Easing.OutQuint); + protected override void AnimateClose() => this.FadeOut(fade_duration, Easing.OutQuint); protected override void UpdateContentHeight() { var actualHeight = (RelativeSizeAxes & Axes.Y) > 0 ? 1 : ContentHeight; - ResizeTo(new Vector2(1, State == MenuState.Opened ? actualHeight : 0), 300, EasingTypes.OutQuint); + this.ResizeTo(new Vector2(1, State == MenuState.Opened ? actualHeight : 0), 300, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/OsuContextMenuItem.cs b/osu.Game/Graphics/UserInterface/OsuContextMenuItem.cs index 5d12dadf5f..196e905bdc 100644 --- a/osu.Game/Graphics/UserInterface/OsuContextMenuItem.cs +++ b/osu.Game/Graphics/UserInterface/OsuContextMenuItem.cs @@ -93,15 +93,15 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(InputState state) { sampleHover.Play(); - textBold.FadeIn(transition_length, EasingTypes.OutQuint); - text.FadeOut(transition_length, EasingTypes.OutQuint); + textBold.FadeIn(transition_length, Easing.OutQuint); + text.FadeOut(transition_length, Easing.OutQuint); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - textBold.FadeOut(transition_length, EasingTypes.OutQuint); - text.FadeIn(transition_length, EasingTypes.OutQuint); + textBold.FadeOut(transition_length, Easing.OutQuint); + text.FadeIn(transition_length, Easing.OutQuint); base.OnHoverLost(state); } diff --git a/osu.Game/Graphics/UserInterface/OsuMenu.cs b/osu.Game/Graphics/UserInterface/OsuMenu.cs index 84b88da96e..e597bc44b5 100644 --- a/osu.Game/Graphics/UserInterface/OsuMenu.cs +++ b/osu.Game/Graphics/UserInterface/OsuMenu.cs @@ -19,14 +19,14 @@ namespace osu.Game.Graphics.UserInterface ItemsContainer.Padding = new MarginPadding(5); } - protected override void AnimateOpen() => FadeIn(300, EasingTypes.OutQuint); + protected override void AnimateOpen() => this.FadeIn(300, Easing.OutQuint); - protected override void AnimateClose() => FadeOut(300, EasingTypes.OutQuint); + protected override void AnimateClose() => this.FadeOut(300, Easing.OutQuint); protected override void UpdateContentHeight() { var actualHeight = (RelativeSizeAxes & Axes.Y) > 0 ? 1 : ContentHeight; - ResizeTo(new Vector2(1, State == MenuState.Opened ? actualHeight : 0), 300, EasingTypes.OutQuint); + this.ResizeTo(new Vector2(1, State == MenuState.Opened ? actualHeight : 0), 300, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs index dc52fd0f62..b7ca25b95a 100644 --- a/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuPasswordTextBox.cs @@ -47,8 +47,8 @@ namespace osu.Game.Graphics.UserInterface protected override void LoadComplete() { base.LoadComplete(); - circle.FadeIn(500, EasingTypes.OutQuint); - circle.ResizeTo(new Vector2(0.8f), 500, EasingTypes.OutQuint); + circle.FadeIn(500, Easing.OutQuint); + circle.ResizeTo(new Vector2(0.8f), 500, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs index 673a23afac..3dd3596c30 100644 --- a/osu.Game/Graphics/UserInterface/OsuSliderBar.cs +++ b/osu.Game/Graphics/UserInterface/OsuSliderBar.cs @@ -166,7 +166,7 @@ namespace osu.Game.Graphics.UserInterface protected override void UpdateValue(float value) { - Nub.MoveToX(RangePadding + UsableWidth * value, 250, EasingTypes.OutQuint); + Nub.MoveToX(RangePadding + UsableWidth * value, 250, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs index 602aee3c58..8c16c048ea 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs @@ -77,14 +77,14 @@ namespace osu.Game.Graphics.UserInterface private void fadeActive() { - box.FadeIn(transition_length, EasingTypes.OutQuint); - Text.FadeColour(Color4.White, transition_length, EasingTypes.OutQuint); + box.FadeIn(transition_length, Easing.OutQuint); + Text.FadeColour(Color4.White, transition_length, Easing.OutQuint); } private void fadeInactive() { - box.FadeOut(transition_length, EasingTypes.OutQuint); - Text.FadeColour(AccentColour, transition_length, EasingTypes.OutQuint); + box.FadeOut(transition_length, Easing.OutQuint); + Text.FadeColour(AccentColour, transition_length, Easing.OutQuint); } protected override bool OnHover(InputState state) diff --git a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs index 940d9b4943..57a87dc74b 100644 --- a/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTabControlCheckbox.cs @@ -49,14 +49,14 @@ namespace osu.Game.Graphics.UserInterface private void fadeIn() { - box.FadeIn(transition_length, EasingTypes.OutQuint); - text.FadeColour(Color4.White, transition_length, EasingTypes.OutQuint); + box.FadeIn(transition_length, Easing.OutQuint); + text.FadeColour(Color4.White, transition_length, Easing.OutQuint); } private void fadeOut() { - box.FadeOut(transition_length, EasingTypes.OutQuint); - text.FadeColour(AccentColour, transition_length, EasingTypes.OutQuint); + box.FadeOut(transition_length, Easing.OutQuint); + text.FadeColour(AccentColour, transition_length, Easing.OutQuint); } protected override bool OnHover(InputState state) diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index b51dd2287b..0a402f9045 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -1,9 +1,6 @@ // 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.Transforms; -using osu.Framework.MathUtils; using System; namespace osu.Game.Graphics.UserInterface @@ -13,8 +10,6 @@ namespace osu.Game.Graphics.UserInterface /// public class PercentageCounter : RollingCounter { - protected override Type TransformType => typeof(TransformAccuracy); - protected override double RollingDuration => 750; private float epsilon => 1e-10f; @@ -44,23 +39,5 @@ namespace osu.Game.Graphics.UserInterface { Current.Value = Current + amount; } - - protected class TransformAccuracy : Transform - { - public virtual double CurrentValue - { - get - { - double time = Time?.Current ?? 0; - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return Interpolation.ValueAt(time, (float)StartValue, (float)EndValue, StartTime, EndTime, Easing); - } - } - - public override void Apply(Drawable d) => ((PercentageCounter)d).DisplayedCount = CurrentValue; - public override void ReadIntoStartValue(Drawable d) => StartValue = ((PercentageCounter)d).DisplayedCount; - } } } diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs index db6e6ff44f..ce8d190dc0 100644 --- a/osu.Game/Graphics/UserInterface/RollingCounter.cs +++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs @@ -5,30 +5,21 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Transforms; using osu.Game.Graphics.Sprites; using System; using System.Collections.Generic; -using System.Diagnostics; using OpenTK.Graphics; namespace osu.Game.Graphics.UserInterface { public abstract class RollingCounter : Container, IHasAccentColour + where T : struct, IEquatable { /// /// The current value. /// public Bindable Current = new Bindable(); - /// - /// Type of the Transform to use. - /// - /// - /// Must be a subclass of Transform(T) - /// - protected virtual Type TransformType => typeof(Transform); - protected SpriteText DisplayedCountSpriteText; /// @@ -45,7 +36,7 @@ namespace osu.Game.Graphics.UserInterface /// /// Easing for the counter rollover animation. /// - protected virtual EasingTypes RollingEasing => EasingTypes.OutQuint; + protected virtual Easing RollingEasing => Easing.OutQuint; private T displayedCount; @@ -58,7 +49,8 @@ namespace osu.Game.Graphics.UserInterface { return displayedCount; } - protected set + + set { if (EqualityComparer.Default.Equals(displayedCount, value)) return; @@ -133,7 +125,7 @@ namespace osu.Game.Graphics.UserInterface /// public virtual void StopRolling() { - Flush(false, TransformType); + FinishTransforms(false, nameof(DisplayedCount)); DisplayedCount = Current; } @@ -176,44 +168,15 @@ namespace osu.Game.Graphics.UserInterface /// implement the rollover animation). /// /// Count value before modification. - /// Expected count value after modification- - /// + /// Expected count value after modification. protected virtual void TransformCount(T currentValue, T newValue) { - Debug.Assert( - typeof(Transform).IsAssignableFrom(TransformType), - @"transformType should be a subclass of Transform." - ); - - TransformCount((Transform)Activator.CreateInstance(TransformType), currentValue, newValue); - } - - /// - /// Intended to be used by TransformCount(T currentValue, T newValue). - /// - protected void TransformCount(Transform transform, T currentValue, T newValue) - { - Type type = transform.GetType(); - - Flush(false, type); - - if (RollingDuration < 1) - { - DisplayedCount = Current; - return; - } - double rollingTotalDuration = IsRollingProportional ? GetProportionalDuration(currentValue, newValue) : RollingDuration; - transform.StartTime = TransformStartTime; - transform.EndTime = TransformStartTime + rollingTotalDuration; - transform.EndValue = newValue; - transform.Easing = RollingEasing; - - Transforms.Add(transform); + this.TransformTo(nameof(DisplayedCount), newValue, rollingTotalDuration, RollingEasing); } } } diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs index 6fe43e1fcc..ee4fc912f3 100644 --- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs +++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs @@ -2,18 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; -using osu.Framework.Graphics.Transforms; -using osu.Framework.MathUtils; -using System; namespace osu.Game.Graphics.UserInterface { public class ScoreCounter : RollingCounter { - protected override Type TransformType => typeof(TransformScore); - protected override double RollingDuration => 1000; - protected override EasingTypes RollingEasing => EasingTypes.Out; + protected override Easing RollingEasing => Easing.Out; public bool UseCommaSeparator; @@ -55,23 +50,5 @@ namespace osu.Game.Graphics.UserInterface { Current.Value = Current + amount; } - - protected class TransformScore : Transform - { - public virtual double CurrentValue - { - get - { - double time = Time?.Current ?? 0; - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return Interpolation.ValueAt(time, (float)StartValue, (float)EndValue, StartTime, EndTime, Easing); - } - } - - public override void Apply(Drawable d) => ((ScoreCounter)d).DisplayedCount = CurrentValue; - public override void ReadIntoStartValue(Drawable d) => StartValue = ((ScoreCounter)d).DisplayedCount; - } } } diff --git a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs index 7664eeee40..211de72efc 100644 --- a/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs +++ b/osu.Game/Graphics/UserInterface/SimpleComboCounter.cs @@ -2,9 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Transforms; -using osu.Framework.MathUtils; namespace osu.Game.Graphics.UserInterface { @@ -13,8 +10,6 @@ namespace osu.Game.Graphics.UserInterface /// public class SimpleComboCounter : RollingCounter { - protected override Type TransformType => typeof(TransformCounterCount); - protected override double RollingDuration => 750; public SimpleComboCounter() @@ -36,23 +31,5 @@ namespace osu.Game.Graphics.UserInterface { Current.Value = Current + amount; } - - private class TransformCounterCount : Transform - { - public int CurrentValue - { - get - { - double time = Time?.Current ?? 0; - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return (int)Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - } - - public override void Apply(Drawable d) => ((SimpleComboCounter)d).DisplayedCount = CurrentValue; - public override void ReadIntoStartValue(Drawable d) => StartValue = ((SimpleComboCounter)d).DisplayedCount; - } } } \ No newline at end of file diff --git a/osu.Game/Graphics/UserInterface/StarCounter.cs b/osu.Game/Graphics/UserInterface/StarCounter.cs index 490ea6e64a..6c5204fed4 100644 --- a/osu.Game/Graphics/UserInterface/StarCounter.cs +++ b/osu.Game/Graphics/UserInterface/StarCounter.cs @@ -24,7 +24,7 @@ namespace osu.Game.Graphics.UserInterface private double animationDelay => 80; private double scalingDuration => 1000; - private EasingTypes scalingEasing => EasingTypes.OutElasticHalf; + private Easing scalingEasing => Easing.OutElasticHalf; private float minStarScale => 0.4f; private double fadingDuration => 100; @@ -122,7 +122,7 @@ namespace osu.Game.Graphics.UserInterface if (value <= i) return minStarScale; - return i + 1 <= value ? 1.0f : (float)Interpolation.ValueAt(value, minStarScale, 1.0f, i, i + 1); + return i + 1 <= value ? 1.0f : Interpolation.ValueAt(value, minStarScale, 1.0f, i, i + 1); } private void transformCount(float newValue) @@ -133,12 +133,8 @@ namespace osu.Game.Graphics.UserInterface star.ClearTransforms(true); var delay = (countStars <= newValue ? Math.Max(i - countStars, 0) : Math.Max(countStars - 1 - i, 0)) * animationDelay; - - using (BeginDelayedSequence(delay, true)) - { - star.FadeTo(i < newValue ? 1.0f : minStarAlpha, fadingDuration); - star.Icon.ScaleTo(getStarScale(i, newValue), scalingDuration, scalingEasing); - } + star.Delay(delay).FadeTo(i < newValue ? 1.0f : minStarAlpha, fadingDuration); + star.Icon.Delay(delay).ScaleTo(getStarScale(i, newValue), scalingDuration, scalingEasing); i++; } diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs index 7f2bbb8f9f..f290f4fadd 100644 --- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs +++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs @@ -173,20 +173,20 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(InputState state) { - ResizeTo(SIZE_EXTENDED, transform_time, EasingTypes.OutElastic); - IconLayer.FadeColour(HoverColour, transform_time, EasingTypes.OutElastic); + this.ResizeTo(SIZE_EXTENDED, transform_time, Easing.OutElastic); + IconLayer.FadeColour(HoverColour, transform_time, Easing.OutElastic); - bouncingIcon.ScaleTo(1.1f, transform_time, EasingTypes.OutElastic); + bouncingIcon.ScaleTo(1.1f, transform_time, Easing.OutElastic); return true; } protected override void OnHoverLost(InputState state) { - ResizeTo(SIZE_RETRACTED, transform_time, EasingTypes.OutElastic); - IconLayer.FadeColour(TextLayer.Colour, transform_time, EasingTypes.OutElastic); + this.ResizeTo(SIZE_RETRACTED, transform_time, Easing.OutElastic); + IconLayer.FadeColour(TextLayer.Colour, transform_time, Easing.OutElastic); - bouncingIcon.ScaleTo(1, transform_time, EasingTypes.OutElastic); + bouncingIcon.ScaleTo(1, transform_time, Easing.OutElastic); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) @@ -205,7 +205,7 @@ namespace osu.Game.Graphics.UserInterface Add(flash); flash.Alpha = 1; - flash.FadeOut(500, EasingTypes.OutQuint); + flash.FadeOut(500, Easing.OutQuint); flash.Expire(); return base.OnClick(state); @@ -245,9 +245,9 @@ namespace osu.Game.Graphics.UserInterface if (beatIndex < 0) return; - icon.ScaleTo(1 - 0.1f * amplitudeAdjust, beat_in_time, EasingTypes.Out); - using (icon.BeginDelayedSequence(beat_in_time)) - icon.ScaleTo(1, beatLength * 2, EasingTypes.OutQuint); + icon.ScaleTo(1 - 0.1f * amplitudeAdjust, beat_in_time, Easing.Out) + .Then() + .ScaleTo(1, beatLength * 2, Easing.OutQuint); } } } diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs index a758d5fdef..fa192b0825 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeControl.cs @@ -93,21 +93,20 @@ namespace osu.Game.Graphics.UserInterface.Volume protected override void PopIn() { ClearTransforms(); - FadeIn(100); + this.FadeIn(100); schedulePopOut(); } protected override void PopOut() { - FadeOut(100); + this.FadeOut(100); } private void schedulePopOut() { popOutDelegate?.Cancel(); - Delay(1000); - popOutDelegate = Schedule(Hide); + this.Delay(1000).Schedule(Hide, out popOutDelegate); } } } \ No newline at end of file diff --git a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs index 57eea71086..41fa60bec2 100644 --- a/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs +++ b/osu.Game/Graphics/UserInterface/Volume/VolumeMeter.cs @@ -82,6 +82,6 @@ namespace osu.Game.Graphics.UserInterface.Volume return true; } - private void updateFill() => meterFill.ScaleTo(new Vector2(1, (float)Volume), 300, EasingTypes.OutQuint); + private void updateFill() => meterFill.ScaleTo(new Vector2(1, (float)Volume), 300, Easing.OutQuint); } } \ No newline at end of file diff --git a/osu.Game/IO/FileInfo.cs b/osu.Game/IO/FileInfo.cs new file mode 100644 index 0000000000..367fd68f7b --- /dev/null +++ b/osu.Game/IO/FileInfo.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 System.IO; +using SQLite.Net.Attributes; + +namespace osu.Game.IO +{ + public class FileInfo + { + [PrimaryKey, AutoIncrement] + public int ID { get; set; } + + [Indexed(Unique = true)] + public string Hash { get; set; } + + public string StoragePath => Path.Combine(Hash.Remove(1), Hash.Remove(2), Hash); + + [Indexed] + public int ReferenceCount { get; set; } + } +} diff --git a/osu.Game/IO/FileStore.cs b/osu.Game/IO/FileStore.cs new file mode 100644 index 0000000000..e55af2e23a --- /dev/null +++ b/osu.Game/IO/FileStore.cs @@ -0,0 +1,159 @@ +// 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 osu.Framework.Extensions; +using osu.Framework.IO.Stores; +using osu.Framework.Logging; +using osu.Framework.Platform; +using osu.Game.Database; +using SQLite.Net; + +namespace osu.Game.IO +{ + /// + /// Handles the Store and retrieval of Files/FileSets to the database backing + /// + public class FileStore : DatabaseBackedStore + { + private const string prefix = "files"; + + public readonly ResourceStore Store; + + protected override int StoreVersion => 2; + + public FileStore(SQLiteConnection connection, Storage storage) : base(connection, storage) + { + Store = new NamespacedResourceStore(new StorageBackedResourceStore(storage), prefix); + } + + protected override Type[] ValidTypes => new[] { + typeof(FileInfo), + }; + + protected override void Prepare(bool reset = false) + { + if (reset) + { + // in earlier versions we stored beatmaps as solid archives, but not any more. + if (Storage.ExistsDirectory("beatmaps")) + Storage.DeleteDirectory("beatmaps"); + + if (Storage.ExistsDirectory(prefix)) + Storage.DeleteDirectory(prefix); + + Connection.DropTable(); + } + + Connection.CreateTable(); + } + + protected override void StartupTasks() + { + base.StartupTasks(); + deletePending(); + } + + /// + /// Perform migrations between two store versions. + /// + /// The current store version. This will be zero on a fresh database initialisation. + /// The target version which we are migrating to (equal to the current ). + protected override void PerformMigration(int currentVersion, int targetVersion) + { + base.PerformMigration(currentVersion, targetVersion); + + while (currentVersion++ < targetVersion) + { + switch (currentVersion) + { + case 1: + case 2: + // cannot migrate; breaking underlying changes. + Reset(); + break; + } + } + } + + public FileInfo Add(Stream data) + { + string hash = data.ComputeSHA2Hash(); + + var info = new FileInfo { Hash = hash }; + + var existing = Connection.Table().FirstOrDefault(f => f.Hash == info.Hash); + + if (existing != null) + { + info = existing; + } + else + { + string path = Path.Combine(prefix, info.StoragePath); + + data.Seek(0, SeekOrigin.Begin); + + if (!Storage.Exists(path)) + using (var output = Storage.GetStream(path, FileAccess.Write)) + data.CopyTo(output); + + data.Seek(0, SeekOrigin.Begin); + + Connection.Insert(info); + } + + Reference(new[] { info }); + return info; + } + + public void Reference(IEnumerable files) + { + Connection.RunInTransaction(() => + { + var incrementedFiles = files.GroupBy(f => f.ID).Select(f => + { + var accurateRefCount = Connection.Get(f.First().ID); + accurateRefCount.ReferenceCount += f.Count(); + return accurateRefCount; + }); + + Connection.UpdateAll(incrementedFiles); + }); + } + + public void Dereference(IEnumerable files) + { + Connection.RunInTransaction(() => + { + var incrementedFiles = files.GroupBy(f => f.ID).Select(f => + { + var accurateRefCount = Connection.Get(f.First().ID); + accurateRefCount.ReferenceCount -= f.Count(); + return accurateRefCount; + }); + + Connection.UpdateAll(incrementedFiles); + }); + } + + private void deletePending() + { + foreach (var f in QueryAndPopulate(f => f.ReferenceCount < 1)) + { + try + { + Connection.Delete(f); + Storage.Delete(Path.Combine(prefix, f.StoragePath)); + } + catch (Exception e) + { + Logger.Error(e, $@"Could not delete beatmap {f}"); + } + } + } + } +} \ No newline at end of file diff --git a/osu.Game/IPC/BeatmapIPCChannel.cs b/osu.Game/IPC/BeatmapIPCChannel.cs index 61e6cc76cc..6a9019251c 100644 --- a/osu.Game/IPC/BeatmapIPCChannel.cs +++ b/osu.Game/IPC/BeatmapIPCChannel.cs @@ -4,15 +4,15 @@ using System.Diagnostics; using System.Threading.Tasks; using osu.Framework.Platform; -using osu.Game.Database; +using osu.Game.Beatmaps; namespace osu.Game.IPC { public class BeatmapIPCChannel : IpcChannel { - private readonly BeatmapDatabase beatmaps; + private readonly BeatmapManager beatmaps; - public BeatmapIPCChannel(IIpcHost host, BeatmapDatabase beatmaps = null) + public BeatmapIPCChannel(IIpcHost host, BeatmapManager beatmaps = null) : base(host) { this.beatmaps = beatmaps; diff --git a/osu.Game/IPC/ScoreIPCChannel.cs b/osu.Game/IPC/ScoreIPCChannel.cs index 7a509ee0e8..ae44250e8d 100644 --- a/osu.Game/IPC/ScoreIPCChannel.cs +++ b/osu.Game/IPC/ScoreIPCChannel.cs @@ -4,15 +4,15 @@ using System.Diagnostics; using System.Threading.Tasks; using osu.Framework.Platform; -using osu.Game.Database; +using osu.Game.Rulesets.Scoring; namespace osu.Game.IPC { public class ScoreIPCChannel : IpcChannel { - private readonly ScoreDatabase scores; + private readonly ScoreStore scores; - public ScoreIPCChannel(IIpcHost host, ScoreDatabase scores = null) + public ScoreIPCChannel(IIpcHost host, ScoreStore scores = null) : base(host) { this.scores = scores; diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 7e3bb44465..57f5c54a18 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -117,7 +117,7 @@ namespace osu.Game.Online.API if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(Username, Password)) { //todo: this fails even on network-related issues. we should probably handle those differently. - //NotificationManager.ShowMessage("Login failed!"); + //NotificationOverlay.ShowMessage("Login failed!"); log.Add(@"Login failed!"); Password = null; continue; @@ -254,7 +254,7 @@ namespace osu.Game.Online.API { //OsuGame.Scheduler.Add(delegate { - //NotificationManager.ShowMessage($@"We just went {newState}!", newState == APIState.Online ? Color4.YellowGreen : Color4.OrangeRed, 5000); + //NotificationOverlay.ShowMessage($@"We just went {newState}!", newState == APIState.Online ? Color4.YellowGreen : Color4.OrangeRed, 5000); log.Add($@"We just went {newState}!"); Scheduler.Add(delegate { diff --git a/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs index a529dde592..15e20a3d55 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapDetailsRequest.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Newtonsoft.Json; -using osu.Game.Database; +using osu.Game.Beatmaps; namespace osu.Game.Online.API.Requests { diff --git a/osu.Game/Online/API/Requests/GetBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapSetsRequest.cs index f6f9bf69fd..ca984d3511 100644 --- a/osu.Game/Online/API/Requests/GetBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/GetBeatmapSetsRequest.cs @@ -4,9 +4,10 @@ using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; -using osu.Game.Database; +using osu.Game.Beatmaps; using osu.Game.Overlays; using osu.Game.Overlays.Direct; +using osu.Game.Rulesets; namespace osu.Game.Online.API.Requests { @@ -48,7 +49,7 @@ namespace osu.Game.Online.API.Requests [JsonProperty(@"beatmaps")] private IEnumerable beatmaps { get; set; } - public BeatmapSetInfo ToBeatmapSet(RulesetDatabase rulesets) + public BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) { return new BeatmapSetInfo { @@ -78,7 +79,7 @@ namespace osu.Game.Online.API.Requests [JsonProperty(@"difficulty_rating")] private double starDifficulty { get; set; } - public BeatmapInfo ToBeatmap(RulesetDatabase rulesets) + public BeatmapInfo ToBeatmap(RulesetStore rulesets) { return new BeatmapInfo { diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 5e6bf1ea9f..966049429e 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using Newtonsoft.Json; using osu.Framework.IO.Network; -using osu.Game.Database; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Scoring; namespace osu.Game.Online.API.Requests diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs index 26b9dbc88a..e808f2c3ad 100644 --- a/osu.Game/Online/Multiplayer/Room.cs +++ b/osu.Game/Online/Multiplayer/Room.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Configuration; -using osu.Game.Database; +using osu.Game.Beatmaps; using osu.Game.Users; namespace osu.Game.Online.Multiplayer diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 6bec2cb184..a70a7b7d97 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -21,10 +21,10 @@ using OpenTK; using System.Linq; using System.Threading.Tasks; using osu.Framework.Threading; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Rulesets.Scoring; using osu.Game.Overlays.Notifications; +using osu.Game.Rulesets; using osu.Game.Screens.Play; namespace osu.Game @@ -37,7 +37,7 @@ namespace osu.Game private MusicController musicController; - private NotificationManager notificationManager; + private NotificationOverlay notificationOverlay; private DialogOverlay dialogOverlay; @@ -80,6 +80,11 @@ namespace osu.Game public void ToggleDirect() => direct.ToggleVisibility(); + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) => + dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + [BackgroundDependencyLoader] private void load(FrameworkConfigManager frameworkConfig) { @@ -94,13 +99,13 @@ namespace osu.Game if (args?.Length > 0) { var paths = args.Where(a => !a.StartsWith(@"-")); - Task.Run(() => BeatmapDatabase.Import(paths.ToArray())); + Task.Run(() => BeatmapManager.Import(paths.ToArray())); } - Dependencies.Cache(this); + dependencies.Cache(this); configRuleset = LocalConfig.GetBindable(OsuSetting.Ruleset); - Ruleset.Value = RulesetDatabase.GetRuleset(configRuleset.Value); + Ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value); Ruleset.ValueChanged += r => configRuleset.Value = r.ID ?? 0; } @@ -121,14 +126,13 @@ namespace osu.Game if (!menu.IsCurrentScreen) { menu.MakeCurrent(); - Delay(500); - scoreLoad = Schedule(() => LoadScore(s)); + this.Delay(500).Schedule(() => LoadScore(s), out scoreLoad); return; } if (s.Beatmap == null) { - notificationManager.Post(new SimpleNotification + notificationOverlay.Post(new SimpleNotification { Text = @"Tried to load a score for a beatmap we don't have!", Icon = FontAwesome.fa_life_saver, @@ -136,7 +140,7 @@ namespace osu.Game return; } - Beatmap.Value = BeatmapDatabase.GetWorkingBeatmap(s.Beatmap); + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(s.Beatmap); menu.Push(new PlayerLoader(new ReplayPlayer(s.Replay))); } @@ -145,6 +149,9 @@ namespace osu.Game { base.LoadComplete(); + // hook up notifications to components. + BeatmapManager.PostNotification = n => notificationOverlay?.Post(n); + AddRange(new Drawable[] { new VolumeControlReceptor { @@ -175,45 +182,45 @@ namespace osu.Game LoadComponentAsync(direct = new DirectOverlay { Depth = -1 }, mainContent.Add); LoadComponentAsync(social = new SocialOverlay { Depth = -1 }, mainContent.Add); LoadComponentAsync(chat = new ChatOverlay { Depth = -1 }, mainContent.Add); - LoadComponentAsync(userProfile = new UserProfileOverlay { Depth = -1 }, mainContent.Add); LoadComponentAsync(settings = new SettingsOverlay { Depth = -1 }, overlayContent.Add); + LoadComponentAsync(userProfile = new UserProfileOverlay { Depth = -2 }, mainContent.Add); LoadComponentAsync(musicController = new MusicController { - Depth = -2, + Depth = -3, Position = new Vector2(0, Toolbar.HEIGHT), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, overlayContent.Add); - LoadComponentAsync(notificationManager = new NotificationManager + LoadComponentAsync(notificationOverlay = new NotificationOverlay { - Depth = -2, + Depth = -3, Anchor = Anchor.TopRight, Origin = Anchor.TopRight, }, overlayContent.Add); LoadComponentAsync(dialogOverlay = new DialogOverlay { - Depth = -4, + Depth = -5, }, overlayContent.Add); Logger.NewEntry += entry => { if (entry.Level < LogLevel.Important) return; - notificationManager.Post(new SimpleNotification + notificationOverlay.Post(new SimpleNotification { Text = $@"{entry.Level}: {entry.Message}" }); }; - Dependencies.Cache(settings); - Dependencies.Cache(social); - Dependencies.Cache(chat); - Dependencies.Cache(userProfile); - Dependencies.Cache(musicController); - Dependencies.Cache(notificationManager); - Dependencies.Cache(dialogOverlay); + dependencies.Cache(settings); + dependencies.Cache(social); + dependencies.Cache(chat); + dependencies.Cache(userProfile); + dependencies.Cache(musicController); + dependencies.Cache(notificationOverlay); + dependencies.Cache(dialogOverlay); // ensure both overlays aren't presented at the same time chat.StateChanged += (container, state) => social.State = state == Visibility.Visible ? Visibility.Hidden : social.State; @@ -221,7 +228,7 @@ namespace osu.Game LoadComponentAsync(Toolbar = new Toolbar { - Depth = -3, + Depth = -4, OnHome = delegate { intro?.ChildScreen?.MakeCurrent(); }, }, overlayContent.Add); @@ -230,10 +237,10 @@ namespace osu.Game switch (settings.State) { case Visibility.Hidden: - intro.MoveToX(0, SettingsOverlay.TRANSITION_LENGTH, EasingTypes.OutQuint); + intro.MoveToX(0, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint); break; case Visibility.Visible: - intro.MoveToX(SettingsOverlay.SIDEBAR_WIDTH / 2, SettingsOverlay.TRANSITION_LENGTH, EasingTypes.OutQuint); + intro.MoveToX(SettingsOverlay.SIDEBAR_WIDTH / 2, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint); break; } }; @@ -327,6 +334,7 @@ namespace osu.Game direct.State = Visibility.Hidden; social.State = Visibility.Hidden; userProfile.State = Visibility.Hidden; + notificationOverlay.State = Visibility.Hidden; } else { diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index 939c4a4915..0dec4228de 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -11,15 +11,17 @@ using osu.Framework.Graphics.Containers; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.IO; using osu.Game.Configuration; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Processing; using osu.Game.Online.API; using SQLite.Net; using osu.Framework.Graphics.Performance; +using osu.Game.Database; +using osu.Game.IO; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Scoring; namespace osu.Game { @@ -27,11 +29,13 @@ namespace osu.Game { protected OsuConfigManager LocalConfig; - protected BeatmapDatabase BeatmapDatabase; + protected BeatmapManager BeatmapManager; - protected RulesetDatabase RulesetDatabase; + protected RulesetStore RulesetStore; - protected ScoreDatabase ScoreDatabase; + protected FileStore FileStore; + + protected ScoreStore ScoreStore; protected override string MainResourceFile => @"osu.Game.Resources.dll"; @@ -81,21 +85,29 @@ namespace osu.Game Name = @"osu!lazer"; } + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) => + dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + [BackgroundDependencyLoader] private void load() { - Dependencies.Cache(this); - Dependencies.Cache(LocalConfig); + dependencies.Cache(this); + dependencies.Cache(LocalConfig); 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()); + connection.CreateTable(); + + dependencies.Cache(RulesetStore = new RulesetStore(connection)); + dependencies.Cache(FileStore = new FileStore(connection, Host.Storage)); + dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, FileStore, connection, RulesetStore, Host)); + dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, connection, Host, BeatmapManager)); + dependencies.Cache(new OsuColour()); //this completely overrides the framework default. will need to change once we make a proper FontStore. - Dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 }, true); + dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 }, true); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome")); Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont")); @@ -123,19 +135,35 @@ namespace osu.Game var defaultBeatmap = new DummyWorkingBeatmap(this); Beatmap = new NonNullableBindable(defaultBeatmap); - BeatmapDatabase.DefaultBeatmap = defaultBeatmap; + BeatmapManager.DefaultBeatmap = defaultBeatmap; - OszArchiveReader.Register(); - - Dependencies.Cache(API = new APIAccess + dependencies.Cache(API = new APIAccess { Username = LocalConfig.Get(OsuSetting.Username), Token = LocalConfig.Get(OsuSetting.Token) }); + Beatmap.ValueChanged += b => + { + // compare to last baetmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) + if (lastBeatmap?.Track != b.Track) + { + // this disposal is done to stop the audio track. + // it may not be exactly what we want for cases beatmaps are reused, as it will + // trigger a fresh load of contained resources. + lastBeatmap?.Dispose(); + + Audio.Track.AddItem(b.Track); + } + + lastBeatmap = b; + }; + API.Register(this); } + private WorkingBeatmap lastBeatmap; + public void APIStateChanged(APIAccess api, APIState state) { switch (state) diff --git a/osu.Game/Overlays/Chat/ChannelListItem.cs b/osu.Game/Overlays/Chat/ChannelListItem.cs index aca65bbc17..791377187b 100644 --- a/osu.Game/Overlays/Chat/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/ChannelListItem.cs @@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Chat { set { - FadeTo(value ? 1f : 0f, 100); + this.FadeTo(value ? 1f : 0f, 100); } } @@ -156,7 +156,7 @@ namespace osu.Game.Overlays.Chat protected override bool OnHover(InputState state) { if (!channel.Joined.Value) - name.FadeColour(hoverColour, 50, EasingTypes.OutQuint); + name.FadeColour(hoverColour, 50, Easing.OutQuint); return base.OnHover(state); } @@ -175,14 +175,14 @@ namespace osu.Game.Overlays.Chat joinedCheckmark.FadeTo(1f, transition_duration); topic.FadeTo(0.8f, transition_duration); topic.FadeColour(Color4.White, transition_duration); - FadeColour(joinedColour, transition_duration); + this.FadeColour(joinedColour, transition_duration); } else { joinedCheckmark.FadeTo(0f, transition_duration); topic.FadeTo(1f, transition_duration); topic.FadeColour(topicColour, transition_duration); - FadeColour(Color4.White, transition_duration); + this.FadeColour(Color4.White, transition_duration); } } } diff --git a/osu.Game/Overlays/Chat/ChannelSection.cs b/osu.Game/Overlays/Chat/ChannelSection.cs index cafb88b6ac..1f046aff2a 100644 --- a/osu.Game/Overlays/Chat/ChannelSection.cs +++ b/osu.Game/Overlays/Chat/ChannelSection.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Chat { set { - FadeTo(value ? 1f : 0f, 100); + this.FadeTo(value ? 1f : 0f, 100); } } diff --git a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs index 135f8f43b9..368d3cc5ef 100644 --- a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs +++ b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.Chat AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, LayoutDuration = 200, - LayoutEasing = EasingTypes.OutQuint, + LayoutEasing = Easing.OutQuint, Spacing = new Vector2(0f, 20f), Padding = new MarginPadding { Vertical = 20, Left = WIDTH_PADDING }, }, @@ -158,10 +158,10 @@ namespace osu.Game.Overlays.Chat protected override void PopIn() { - if (Alpha == 0) MoveToY(DrawHeight); + if (Alpha == 0) this.MoveToY(DrawHeight); - FadeIn(transition_duration, EasingTypes.OutQuint); - MoveToY(0, transition_duration, EasingTypes.OutQuint); + this.FadeIn(transition_duration, Easing.OutQuint); + this.MoveToY(0, transition_duration, Easing.OutQuint); search.HoldFocus = true; base.PopIn(); @@ -169,8 +169,8 @@ namespace osu.Game.Overlays.Chat protected override void PopOut() { - FadeOut(transition_duration, EasingTypes.InSine); - MoveToY(DrawHeight, transition_duration, EasingTypes.InSine); + this.FadeOut(transition_duration, Easing.InSine); + this.MoveToY(DrawHeight, transition_duration, Easing.InSine); search.HoldFocus = false; base.PopOut(); diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 198a2a9419..fcebca6fe3 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -11,6 +12,8 @@ using OpenTK.Graphics; using osu.Framework.Graphics.Effects; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Allocation; +using osu.Game.Users; +using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Chat { @@ -62,6 +65,8 @@ namespace osu.Game.Overlays.Chat private const float message_padding = 200; private const float text_size = 20; + private Action loadProfile; + private Color4 customUsernameColour; public ChatLine(Message message) @@ -74,10 +79,11 @@ namespace osu.Game.Overlays.Chat Padding = new MarginPadding { Left = padding, Right = padding }; } - [BackgroundDependencyLoader] - private void load(OsuColour colours) + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, UserProfileOverlay profile) { customUsernameColour = colours.ChatBlue; + loadProfile = u => profile?.ShowUser(u); } protected override void LoadComplete() @@ -87,8 +93,6 @@ namespace osu.Game.Overlays.Chat bool hasBackground = !string.IsNullOrEmpty(Message.Sender.Colour); Drawable username = new OsuSpriteText { - Origin = Anchor.TopRight, - Anchor = Anchor.TopRight, Font = @"Exo2.0-BoldItalic", Text = $@"{Message.Sender.Username}" + (hasBackground ? "" : ":"), Colour = hasBackground ? customUsernameColour : username_colours[Message.UserId % username_colours.Length], @@ -132,7 +136,7 @@ namespace osu.Game.Overlays.Chat new Container { Size = new Vector2(message_padding, text_size), - Children = new[] + Children = new Drawable[] { new OsuSpriteText { @@ -144,7 +148,14 @@ namespace osu.Game.Overlays.Chat TextSize = text_size * 0.75f, Alpha = 0.4f, }, - username + new ClickableContainer + { + AutoSizeAxes = Axes.Both, + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + Child = username, + Action = () => loadProfile(Message.Sender), + }, } }, new Container @@ -154,10 +165,12 @@ namespace osu.Game.Overlays.Chat Padding = new MarginPadding { Left = message_padding + padding }, Children = new Drawable[] { - new OsuSpriteText + new OsuTextFlowContainer(t => + { + t.TextSize = text_size; + }) { Text = Message.Content, - TextSize = text_size, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, } diff --git a/osu.Game/Overlays/Chat/ChatTabControl.cs b/osu.Game/Overlays/Chat/ChatTabControl.cs index 92147db57f..c3c930eba0 100644 --- a/osu.Game/Overlays/Chat/ChatTabControl.cs +++ b/osu.Game/Overlays/Chat/ChatTabControl.cs @@ -86,30 +86,30 @@ namespace osu.Game.Overlays.Chat private void fadeActive() { - ResizeTo(new Vector2(Width, 1.1f), transition_length, EasingTypes.OutQuint); + this.ResizeTo(new Vector2(Width, 1.1f), transition_length, Easing.OutQuint); - box.FadeColour(backgroundActive, transition_length, EasingTypes.OutQuint); - highlightBox.FadeIn(transition_length, EasingTypes.OutQuint); + box.FadeColour(backgroundActive, transition_length, Easing.OutQuint); + highlightBox.FadeIn(transition_length, Easing.OutQuint); - text.FadeOut(transition_length, EasingTypes.OutQuint); - textBold.FadeIn(transition_length, EasingTypes.OutQuint); + text.FadeOut(transition_length, Easing.OutQuint); + textBold.FadeIn(transition_length, Easing.OutQuint); } private void fadeInactive() { - ResizeTo(new Vector2(Width, 1), transition_length, EasingTypes.OutQuint); + this.ResizeTo(new Vector2(Width, 1), transition_length, Easing.OutQuint); - box.FadeColour(backgroundInactive, transition_length, EasingTypes.OutQuint); - highlightBox.FadeOut(transition_length, EasingTypes.OutQuint); + box.FadeColour(backgroundInactive, transition_length, Easing.OutQuint); + highlightBox.FadeOut(transition_length, Easing.OutQuint); - text.FadeIn(transition_length, EasingTypes.OutQuint); - textBold.FadeOut(transition_length, EasingTypes.OutQuint); + text.FadeIn(transition_length, Easing.OutQuint); + textBold.FadeOut(transition_length, Easing.OutQuint); } protected override bool OnHover(InputState state) { if (!Active) - box.FadeColour(backgroundHover, transition_length, EasingTypes.OutQuint); + box.FadeColour(backgroundHover, transition_length, Easing.OutQuint); return true; } diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index 1f9f7e57ca..29b7548ada 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -52,6 +52,7 @@ namespace osu.Game.Overlays private readonly ChatTabControl channelTabs; private readonly Container chatContainer; + private readonly Container tabsArea; private readonly Box chatBackground; private readonly Box tabBackground; @@ -144,7 +145,7 @@ namespace osu.Game.Overlays loading = new LoadingAnimation(), } }, - new Container + tabsArea = new Container { Name = @"tabs area", RelativeSizeAxes = Axes.X, @@ -177,8 +178,8 @@ namespace osu.Game.Overlays inputTextBox.HoldFocus = false; if (1f - chatHeight.Value < channel_selection_min_height) { - chatContainer.ResizeHeightTo(1f - channel_selection_min_height, 800, EasingTypes.OutQuint); - channelSelectionContainer.ResizeHeightTo(channel_selection_min_height, 800, EasingTypes.OutQuint); + chatContainer.ResizeHeightTo(1f - channel_selection_min_height, 800, Easing.OutQuint); + channelSelectionContainer.ResizeHeightTo(channel_selection_min_height, 800, Easing.OutQuint); channelSelection.Show(); chatHeight.Value = 1f - channel_selection_min_height; } @@ -191,10 +192,13 @@ namespace osu.Game.Overlays } private double startDragChatHeight; + private bool isDragging; protected override bool OnDragStart(InputState state) { - if (!channelTabs.IsHovered) + isDragging = tabsArea.IsHovered; + + if (!isDragging) return base.OnDragStart(state); startDragChatHeight = chatHeight.Value; @@ -203,10 +207,20 @@ namespace osu.Game.Overlays protected override bool OnDrag(InputState state) { - Trace.Assert(state.Mouse.PositionMouseDown != null); + if (isDragging) + { + Trace.Assert(state.Mouse.PositionMouseDown != null); - chatHeight.Value = startDragChatHeight - (state.Mouse.Position.Y - state.Mouse.PositionMouseDown.Value.Y) / Parent.DrawSize.Y; - return base.OnDrag(state); + chatHeight.Value = startDragChatHeight - (state.Mouse.Position.Y - state.Mouse.PositionMouseDown.Value.Y) / Parent.DrawSize.Y; + } + + return true; + } + + protected override bool OnDragEnd(InputState state) + { + isDragging = false; + return base.OnDragEnd(state); } public void APIStateChanged(APIAccess api, APIState state) @@ -235,8 +249,8 @@ namespace osu.Game.Overlays protected override void PopIn() { - MoveToY(0, transition_length, EasingTypes.OutQuint); - FadeIn(transition_length, EasingTypes.OutQuint); + this.MoveToY(0, transition_length, Easing.OutQuint); + this.FadeIn(transition_length, Easing.OutQuint); inputTextBox.HoldFocus = true; base.PopIn(); @@ -244,8 +258,8 @@ namespace osu.Game.Overlays protected override void PopOut() { - MoveToY(Height, transition_length, EasingTypes.InSine); - FadeOut(transition_length, EasingTypes.InSine); + this.MoveToY(Height, transition_length, Easing.InSine); + this.FadeOut(transition_length, Easing.InSine); inputTextBox.HoldFocus = false; base.PopOut(); @@ -328,7 +342,7 @@ namespace osu.Game.Overlays var loaded = loadedChannels.Find(d => d.Channel == value); if (loaded == null) { - currentChannelContainer.FadeOut(500, EasingTypes.OutQuint); + currentChannelContainer.FadeOut(500, Easing.OutQuint); loading.Show(); loaded = new DrawableChannel(currentChannel); @@ -340,7 +354,7 @@ namespace osu.Game.Overlays currentChannelContainer.Clear(false); currentChannelContainer.Add(loaded); - currentChannelContainer.FadeIn(500, EasingTypes.OutQuint); + currentChannelContainer.FadeIn(500, Easing.OutQuint); }); } else diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 39338ba3e1..97aae2f49c 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -115,17 +115,17 @@ namespace osu.Game.Overlays.Dialog ring.ResizeTo(ringMinifiedSize); } - content.FadeIn(ENTER_DURATION, EasingTypes.OutQuint); - ring.ResizeTo(ringSize, ENTER_DURATION, EasingTypes.OutQuint); - buttonsContainer.TransformSpacingTo(Vector2.Zero, ENTER_DURATION, EasingTypes.OutQuint); - buttonsContainer.MoveToY(0, ENTER_DURATION, EasingTypes.OutQuint); + content.FadeIn(ENTER_DURATION, Easing.OutQuint); + ring.ResizeTo(ringSize, ENTER_DURATION, Easing.OutQuint); + buttonsContainer.TransformSpacingTo(Vector2.Zero, ENTER_DURATION, Easing.OutQuint); + buttonsContainer.MoveToY(0, ENTER_DURATION, Easing.OutQuint); } protected override void PopOut() { base.PopOut(); - content.FadeOut(EXIT_DURATION, EasingTypes.InSine); + content.FadeOut(EXIT_DURATION, Easing.InSine); } public PopupDialog() diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index f1a6bc1681..012e93f10d 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -35,8 +35,7 @@ namespace osu.Game.Overlays if (v != Visibility.Hidden) return; //handle the dialog being dismissed. - dialog.Delay(PopupDialog.EXIT_DURATION); - dialog.Expire(); + dialog.Delay(PopupDialog.EXIT_DURATION).Expire(); if (dialog == currentDialog) State = Visibility.Hidden; @@ -45,13 +44,13 @@ namespace osu.Game.Overlays protected override void PopIn() { base.PopIn(); - FadeIn(PopupDialog.ENTER_DURATION, EasingTypes.OutQuint); + this.FadeIn(PopupDialog.ENTER_DURATION, Easing.OutQuint); } protected override void PopOut() { base.PopOut(); - FadeOut(PopupDialog.EXIT_DURATION, EasingTypes.InSine); + this.FadeOut(PopupDialog.EXIT_DURATION, Easing.InSine); } public DialogOverlay() diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index 3c464af05d..98ab5e88f8 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -8,10 +8,10 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; namespace osu.Game.Overlays.Direct { @@ -41,9 +41,9 @@ namespace osu.Game.Overlays.Direct { base.LoadComplete(); - FadeInFromZero(200, EasingTypes.Out); + this.FadeInFromZero(200, Easing.Out); bottomPanel.LayoutDuration = 200; - bottomPanel.LayoutEasing = EasingTypes.Out; + bottomPanel.LayoutEasing = Easing.Out; bottomPanel.Origin = Anchor.BottomLeft; } diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index f693998563..b9063a5c82 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -9,11 +9,11 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Colour; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Database; using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Framework.Input; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Direct @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.Direct { base.LoadComplete(); - FadeInFromZero(200, EasingTypes.Out); + this.FadeInFromZero(200, Easing.Out); } [BackgroundDependencyLoader] @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.Direct new Box { RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.25f), Color4.Black.Opacity(0.75f)), + Colour = ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.25f), Color4.Black.Opacity(0.75f)), }, new Container { @@ -171,25 +171,25 @@ namespace osu.Game.Overlays.Direct protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - icon.ScaleTo(0.9f, 1000, EasingTypes.Out); + icon.ScaleTo(0.9f, 1000, Easing.Out); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - icon.ScaleTo(1f, 500, EasingTypes.OutElastic); + icon.ScaleTo(1f, 500, Easing.OutElastic); return base.OnMouseUp(state, args); } protected override bool OnHover(InputState state) { - icon.ScaleTo(1.1f, 500, EasingTypes.OutElastic); + icon.ScaleTo(1.1f, 500, Easing.OutElastic); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - icon.ScaleTo(1f, 500, EasingTypes.OutElastic); + icon.ScaleTo(1f, 500, Easing.OutElastic); } } } diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 4fc9a922a8..75619d9ba4 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -6,8 +6,8 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Direct Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(400, EasingTypes.Out), + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), }) { RelativeSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs index e947895fc2..4f815f220c 100644 --- a/osu.Game/Overlays/Direct/FilterControl.cs +++ b/osu.Game/Overlays/Direct/FilterControl.cs @@ -7,10 +7,11 @@ using osu.Framework.Allocation; using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Database; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Overlays.SearchableList; +using osu.Game.Rulesets; namespace osu.Game.Overlays.Direct { @@ -33,7 +34,7 @@ namespace osu.Game.Overlays.Direct } [BackgroundDependencyLoader(true)] - private void load(OsuGame game, RulesetDatabase rulesets, OsuColour colours) + private void load(OsuGame game, RulesetStore rulesets, OsuColour colours) { DisplayStyleControl.Dropdown.AccentColour = colours.BlueDark; diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index 5fa90ab1d6..b1c7dab778 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -9,13 +9,14 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Threading; -using osu.Game.Database; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Direct; using osu.Game.Overlays.SearchableList; +using osu.Game.Rulesets; using OpenTK.Graphics; namespace osu.Game.Overlays @@ -25,7 +26,7 @@ namespace osu.Game.Overlays private const float panel_padding = 10f; private APIAccess api; - private RulesetDatabase rulesets; + private RulesetStore rulesets; private readonly FillFlowContainer resultCountsContainer; private readonly OsuSpriteText resultCountsText; @@ -160,7 +161,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuColour colours, APIAccess api, RulesetDatabase rulesets) + private void load(OsuColour colours, APIAccess api, RulesetStore rulesets) { this.api = api; this.rulesets = rulesets; @@ -169,7 +170,7 @@ namespace osu.Game.Overlays private void updateResultCounts() { - resultCountsContainer.FadeTo(ResultAmounts == null ? 0f : 1f, 200, EasingTypes.OutQuint); + resultCountsContainer.FadeTo(ResultAmounts == null ? 0f : 1f, 200, Easing.OutQuint); if (ResultAmounts == null) return; resultCountsText.Text = pluralize("Artist", ResultAmounts.Artists) + ", " + diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index d9d5a44fd5..95e0fef9aa 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -40,7 +40,7 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.Y, Masking = true, AutoSizeDuration = transition_time, - AutoSizeEasing = EasingTypes.OutQuint, + AutoSizeEasing = Easing.OutQuint, Children = new Drawable[] { settingsSection = new LoginSettings @@ -67,7 +67,7 @@ namespace osu.Game.Overlays base.PopIn(); settingsSection.Bounding = true; - FadeIn(transition_time, EasingTypes.OutQuint); + this.FadeIn(transition_time, Easing.OutQuint); InputManager.ChangeFocus(settingsSection); } @@ -77,7 +77,7 @@ namespace osu.Game.Overlays base.PopOut(); settingsSection.Bounding = false; - FadeOut(transition_time); + this.FadeOut(transition_time); } } } diff --git a/osu.Game/Overlays/MedalOverlay.cs b/osu.Game/Overlays/MedalOverlay.cs index 5f85474ede..880b607e78 100644 --- a/osu.Game/Overlays/MedalOverlay.cs +++ b/osu.Game/Overlays/MedalOverlay.cs @@ -194,38 +194,43 @@ namespace osu.Game.Overlays { base.PopIn(); - FadeIn(200); + this.FadeIn(200); background.FlashColour(Color4.White.Opacity(0.25f), 400); getSample.Play(); - using (innerSpin.BeginLoopedSequence()) - innerSpin.RotateTo(360, 20000); - - using (outerSpin.BeginLoopedSequence()) - outerSpin.RotateTo(360, 40000); + innerSpin.Spin(20000, RotationDirection.Clockwise); + outerSpin.Spin(40000, RotationDirection.Clockwise); using (BeginDelayedSequence(200, true)) { - disc.FadeIn(initial_duration); + disc.FadeIn(initial_duration) + .ScaleTo(1f, initial_duration * 2, Easing.OutElastic); + particleContainer.FadeIn(initial_duration); outerSpin.FadeTo(0.1f, initial_duration * 2); - disc.ScaleTo(1f, initial_duration * 2, EasingTypes.OutElastic); using (BeginDelayedSequence(initial_duration + 200, true)) { backgroundStrip.FadeIn(step_duration); - leftStrip.ResizeWidthTo(1f, step_duration, EasingTypes.OutQuint); - rightStrip.ResizeWidthTo(1f, step_duration, EasingTypes.OutQuint); - Schedule(() => { if (drawableMedal.State != DisplayState.Full) drawableMedal.State = DisplayState.Icon; }); + leftStrip.ResizeWidthTo(1f, step_duration, Easing.OutQuint); + rightStrip.ResizeWidthTo(1f, step_duration, Easing.OutQuint); - using (BeginDelayedSequence(step_duration, true)) + this.Animate().Schedule(() => { - Schedule(() => { if (drawableMedal.State != DisplayState.Full) drawableMedal.State = DisplayState.MedalUnlocked; }); - - using (BeginDelayedSequence(step_duration, true)) - Schedule(() => { if (drawableMedal.State != DisplayState.Full) drawableMedal.State = DisplayState.Full; }); - } + if (drawableMedal.State != DisplayState.Full) + drawableMedal.State = DisplayState.Icon; + }) + .Delay(step_duration).Schedule(() => + { + if (drawableMedal.State != DisplayState.Full) + drawableMedal.State = DisplayState.MedalUnlocked; + }) + .Delay(step_duration).Schedule(() => + { + if (drawableMedal.State != DisplayState.Full) + drawableMedal.State = DisplayState.Full; + }); } } } @@ -233,7 +238,7 @@ namespace osu.Game.Overlays protected override void PopOut() { base.PopOut(); - FadeOut(200); + this.FadeOut(200); } private void dismiss() @@ -242,7 +247,7 @@ namespace osu.Game.Overlays { // if we haven't yet, play out the animation fully drawableMedal.State = DisplayState.Full; - Flush(true); + FinishTransforms(true); return; } @@ -256,7 +261,7 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.Both; Width = 0f; - ColourInfo = ColourInfo.GradientHorizontal(Color4.White.Opacity(start), Color4.White.Opacity(end)); + Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(start), Color4.White.Opacity(end)); Masking = true; Children = new[] @@ -295,8 +300,8 @@ namespace osu.Game.Overlays Radius = 5, }; - MoveTo(positionForOffset(DISC_SIZE / 2 + 200), 500); - FadeOut(500); + this.MoveTo(positionForOffset(DISC_SIZE / 2 + 200), 500); + this.FadeOut(500); Expire(); } } diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs index 7d7ffbd12a..56b26e7176 100644 --- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs +++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs @@ -147,23 +147,26 @@ namespace osu.Game.Overlays.MedalSplash medalContainer.ScaleTo(0); break; case DisplayState.Icon: - medalContainer.ScaleTo(1, duration, EasingTypes.OutElastic); - medalContainer.FadeIn(duration); + medalContainer + .FadeIn(duration) + .ScaleTo(1, duration, Easing.OutElastic); break; case DisplayState.MedalUnlocked: - medalContainer.ScaleTo(1); - medalContainer.Show(); + medalContainer + .FadeTo(1) + .ScaleTo(1); - ScaleTo(scale_when_unlocked, duration, EasingTypes.OutExpo); - MoveToY(MedalOverlay.DISC_SIZE / 2 - 30, duration, EasingTypes.OutExpo); + this.ScaleTo(scale_when_unlocked, duration, Easing.OutExpo); + this.MoveToY(MedalOverlay.DISC_SIZE / 2 - 30, duration, Easing.OutExpo); unlocked.FadeInFromZero(duration); break; case DisplayState.Full: - medalContainer.ScaleTo(1); - medalContainer.Show(); + medalContainer + .FadeTo(1) + .ScaleTo(1); - ScaleTo(scale_when_full, duration, EasingTypes.OutExpo); - MoveToY(MedalOverlay.DISC_SIZE / 2 - 60, duration, EasingTypes.OutExpo); + this.ScaleTo(scale_when_full, duration, Easing.OutExpo); + this.MoveToY(MedalOverlay.DISC_SIZE / 2 - 60, duration, Easing.OutExpo); name.FadeInFromZero(duration + 100); description.FadeInFromZero(duration * 2); break; diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs index aca73d2828..3ca4a204a5 100644 --- a/osu.Game/Overlays/Mods/ModButton.cs +++ b/osu.Game/Overlays/Mods/ModButton.cs @@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Mods public string TooltipText => (SelectedMod?.Description ?? Mods.FirstOrDefault()?.Description) ?? string.Empty; - private const EasingTypes mod_switch_easing = EasingTypes.InOutSine; + private const Easing mod_switch_easing = Easing.InOutSine; private const double mod_switch_duration = 120; // A selected index of -1 means not selected. @@ -67,8 +67,8 @@ namespace osu.Game.Overlays.Mods if (beforeSelected != Selected) { - iconsContainer.RotateTo(Selected ? 5f : 0f, 300, EasingTypes.OutElastic); - iconsContainer.ScaleTo(Selected ? 1.1f : 1f, 300, EasingTypes.OutElastic); + iconsContainer.RotateTo(Selected ? 5f : 0f, 300, Easing.OutElastic); + iconsContainer.ScaleTo(Selected ? 1.1f : 1f, 300, Easing.OutElastic); } if (modBefore != modAfter) @@ -81,11 +81,13 @@ namespace osu.Game.Overlays.Mods backgroundIcon.Icon = modAfter.Icon; using (BeginDelayedSequence(mod_switch_duration, true)) { - foregroundIcon.RotateTo(-rotate_angle * direction); - foregroundIcon.RotateTo(0f, mod_switch_duration, mod_switch_easing); + foregroundIcon + .RotateTo(-rotate_angle * direction) + .RotateTo(0f, mod_switch_duration, mod_switch_easing); - backgroundIcon.RotateTo(rotate_angle * direction); - backgroundIcon.RotateTo(0f, mod_switch_duration, mod_switch_easing); + backgroundIcon + .RotateTo(rotate_angle * direction) + .RotateTo(0f, mod_switch_duration, mod_switch_easing); Schedule(() => displayMod(modAfter)); } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index ca74189c86..eb643f390f 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -15,8 +15,8 @@ using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; using System.Linq; -using osu.Game.Database; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets; namespace osu.Game.Overlays.Mods { @@ -48,7 +48,7 @@ namespace osu.Game.Overlays.Mods } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, OsuGame osu, RulesetDatabase rulesets) + private void load(OsuColour colours, OsuGame osu, RulesetStore rulesets) { lowMultiplierColour = colours.Red; highMultiplierColour = colours.Green; @@ -66,14 +66,14 @@ namespace osu.Game.Overlays.Mods { base.PopOut(); - rankedMultiplerContainer.MoveToX(rankedMultiplerContainer.DrawSize.X, APPEAR_DURATION, EasingTypes.InSine); - rankedMultiplerContainer.FadeOut(APPEAR_DURATION, EasingTypes.InSine); + rankedMultiplerContainer.MoveToX(rankedMultiplerContainer.DrawSize.X, APPEAR_DURATION, Easing.InSine); + rankedMultiplerContainer.FadeOut(APPEAR_DURATION, Easing.InSine); foreach (ModSection section in modSectionsContainer.Children) { - section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), APPEAR_DURATION, EasingTypes.InSine); - section.ButtonsContainer.MoveToX(100f, APPEAR_DURATION, EasingTypes.InSine); - section.ButtonsContainer.FadeOut(APPEAR_DURATION, EasingTypes.InSine); + section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), APPEAR_DURATION, Easing.InSine); + section.ButtonsContainer.MoveToX(100f, APPEAR_DURATION, Easing.InSine); + section.ButtonsContainer.FadeOut(APPEAR_DURATION, Easing.InSine); } } @@ -81,14 +81,14 @@ namespace osu.Game.Overlays.Mods { base.PopIn(); - rankedMultiplerContainer.MoveToX(0, ranked_multiplier_duration, EasingTypes.OutQuint); - rankedMultiplerContainer.FadeIn(ranked_multiplier_duration, EasingTypes.OutQuint); + rankedMultiplerContainer.MoveToX(0, ranked_multiplier_duration, Easing.OutQuint); + rankedMultiplerContainer.FadeIn(ranked_multiplier_duration, Easing.OutQuint); foreach (ModSection section in modSectionsContainer.Children) { - section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), button_duration, EasingTypes.OutQuint); - section.ButtonsContainer.MoveToX(0, button_duration, EasingTypes.OutQuint); - section.ButtonsContainer.FadeIn(button_duration, EasingTypes.OutQuint); + section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), button_duration, Easing.OutQuint); + section.ButtonsContainer.MoveToX(0, button_duration, Easing.OutQuint); + section.ButtonsContainer.FadeIn(button_duration, Easing.OutQuint); } } diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 0a095327b0..1e3e48b17a 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -9,7 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; -using osu.Game.Database; +using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Music if (value == selected) return; selected = value; - Flush(true); + FinishTransforms(true); foreach (SpriteText s in titleSprites) s.FadeColour(Selected ? hoverColour : Color4.White, fade_duration); } @@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Music matching = value; - FadeTo(matching ? 1 : 0, 200); + this.FadeTo(matching ? 1 : 0, 200); } } } diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index ca46bdea95..3dd514edeb 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Database; +using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Music @@ -73,6 +73,17 @@ namespace osu.Game.Overlays.Music }; } + public void AddBeatmapSet(BeatmapSetInfo beatmapSet) + { + items.Add(new PlaylistItem(beatmapSet) { OnSelect = itemSelected }); + } + + public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) + { + PlaylistItem itemToRemove = items.Children.FirstOrDefault(item => item.BeatmapSetInfo.ID == beatmapSet.ID); + if (itemToRemove != null) items.Remove(itemToRemove); + } + private class ItemSearchContainer : FillFlowContainer, IHasFilterableChildren { public string[] FilterTerms => new string[] { }; @@ -90,7 +101,7 @@ namespace osu.Game.Overlays.Music public ItemSearchContainer() { LayoutDuration = 200; - LayoutEasing = EasingTypes.OutQuint; + LayoutEasing = Easing.OutQuint; } } } diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index a9fd77a52c..5bbaa1b1ae 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -3,9 +3,7 @@ using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Audio.Track; using osu.Framework.Configuration; using osu.Framework.Extensions; using osu.Framework.Extensions.Color4Extensions; @@ -14,10 +12,11 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Graphics; using OpenTK; using OpenTK.Graphics; +using osu.Framework.Input; +using osu.Framework.Graphics.Shapes; namespace osu.Game.Overlays.Music { @@ -30,8 +29,7 @@ namespace osu.Game.Overlays.Music private FilterControl filter; private PlaylistList list; - private TrackManager trackManager; - private BeatmapDatabase beatmaps; + private BeatmapManager beatmaps; private readonly Bindable beatmapBacking = new Bindable(); @@ -39,11 +37,10 @@ namespace osu.Game.Overlays.Music private InputManager inputManager; [BackgroundDependencyLoader] - private void load(OsuGameBase game, BeatmapDatabase beatmaps, OsuColour colours, UserInputManager inputManager) + private void load(OsuGameBase game, BeatmapManager beatmaps, OsuColour colours, UserInputManager inputManager) { this.inputManager = inputManager; this.beatmaps = beatmaps; - trackManager = game.Audio.Track; Children = new Drawable[] { @@ -83,7 +80,11 @@ namespace osu.Game.Overlays.Music }, }; - list.BeatmapSets = BeatmapSets = beatmaps.GetAllWithChildren(b => !b.DeletePending).ToList(); + beatmaps.BeatmapSetAdded += s => Schedule(() => list.AddBeatmapSet(s)); + beatmaps.BeatmapSetRemoved += s => Schedule(() => list.RemoveBeatmapSet(s)); + + list.BeatmapSets = BeatmapSets = beatmaps.GetAllUsableBeatmapSets(); + beatmapBacking.BindTo(game.Beatmap); @@ -106,16 +107,16 @@ namespace osu.Game.Overlays.Music filter.Search.HoldFocus = true; Schedule(() => inputManager.ChangeFocus(filter.Search)); - ResizeTo(new Vector2(1, playlist_height), transition_duration, EasingTypes.OutQuint); - FadeIn(transition_duration, EasingTypes.OutQuint); + this.ResizeTo(new Vector2(1, playlist_height), transition_duration, Easing.OutQuint); + this.FadeIn(transition_duration, Easing.OutQuint); } protected override void PopOut() { filter.Search.HoldFocus = false; - ResizeTo(new Vector2(1, 0), transition_duration, EasingTypes.OutQuint); - FadeOut(transition_duration); + this.ResizeTo(new Vector2(1, 0), transition_duration, Easing.OutQuint); + this.FadeOut(transition_duration); } private void itemSelected(BeatmapSetInfo set) @@ -154,13 +155,7 @@ namespace osu.Game.Overlays.Music private void playSpecified(BeatmapInfo info) { beatmapBacking.Value = beatmaps.GetWorkingBeatmap(info, beatmapBacking); - - Task.Run(() => - { - var track = beatmapBacking.Value.Track; - trackManager.SetExclusive(track); - track.Start(); - }).ContinueWith(task => Schedule(task.ThrowIfFaulted), TaskContinuationOptions.OnlyOnFaulted); + beatmapBacking.Value.Track.Start(); } } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 00592792b3..d53641ec78 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -19,7 +19,6 @@ using osu.Framework.Input; using osu.Framework.Localisation; using osu.Framework.Threading; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Music; @@ -84,7 +83,7 @@ namespace osu.Game.Overlays protected override bool OnDragEnd(InputState state) { - dragContainer.MoveTo(Vector2.Zero, 800, EasingTypes.OutElastic); + dragContainer.MoveTo(Vector2.Zero, 800, Easing.OutElastic); return base.OnDragEnd(state); } @@ -206,7 +205,7 @@ namespace osu.Game.Overlays beatmapBacking.BindTo(game.Beatmap); - playlist.StateChanged += (c, s) => playlistButton.FadeColour(s == Visibility.Visible ? colours.Yellow : Color4.White, 200, EasingTypes.OutQuint); + playlist.StateChanged += (c, s) => playlistButton.FadeColour(s == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); } protected override void LoadComplete() @@ -356,13 +355,13 @@ namespace osu.Game.Overlays { case TransformDirection.Next: d.Position = new Vector2(400, 0); - d.MoveToX(0, 500, EasingTypes.OutCubic); - currentBackground.MoveToX(-400, 500, EasingTypes.OutCubic); + d.MoveToX(0, 500, Easing.OutCubic); + currentBackground.MoveToX(-400, 500, Easing.OutCubic); break; case TransformDirection.Prev: d.Position = new Vector2(-400, 0); - d.MoveToX(0, 500, EasingTypes.OutCubic); - currentBackground.MoveToX(400, 500, EasingTypes.OutCubic); + d.MoveToX(0, 500, Easing.OutCubic); + currentBackground.MoveToX(400, 500, Easing.OutCubic); break; } currentBackground.Expire(); @@ -379,16 +378,16 @@ namespace osu.Game.Overlays { base.PopIn(); - FadeIn(transition_length, EasingTypes.OutQuint); - dragContainer.ScaleTo(1, transition_length, EasingTypes.OutElastic); + this.FadeIn(transition_length, Easing.OutQuint); + dragContainer.ScaleTo(1, transition_length, Easing.OutElastic); } protected override void PopOut() { base.PopOut(); - FadeOut(transition_length, EasingTypes.OutQuint); - dragContainer.ScaleTo(0.9f, transition_length, EasingTypes.OutQuint); + this.FadeOut(transition_length, Easing.OutQuint); + dragContainer.ScaleTo(0.9f, transition_length, Easing.OutQuint); } private enum TransformDirection diff --git a/osu.Game/Overlays/NotificationManager.cs b/osu.Game/Overlays/NotificationOverlay.cs similarity index 73% rename from osu.Game/Overlays/NotificationManager.cs rename to osu.Game/Overlays/NotificationOverlay.cs index 18cb49f335..7eabb592c6 100644 --- a/osu.Game/Overlays/NotificationManager.cs +++ b/osu.Game/Overlays/NotificationOverlay.cs @@ -13,7 +13,7 @@ using osu.Game.Graphics.Containers; namespace osu.Game.Overlays { - public class NotificationManager : OsuFocusedOverlayContainer + public class NotificationOverlay : OsuFocusedOverlayContainer { private const float width = 320; @@ -28,6 +28,8 @@ namespace osu.Game.Overlays Width = width; RelativeSizeAxes = Axes.Y; + AlwaysPresent = true; + Children = new Drawable[] { new Box @@ -72,26 +74,29 @@ namespace osu.Game.Overlays public void Post(Notification notification) { - State = Visibility.Visible; + Schedule(() => + { + State = Visibility.Visible; - ++runningDepth; - notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth; + ++runningDepth; + notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth; - var hasCompletionTarget = notification as IHasCompletionTarget; - if (hasCompletionTarget != null) - hasCompletionTarget.CompletionTarget = Post; + var hasCompletionTarget = notification as IHasCompletionTarget; + if (hasCompletionTarget != null) + hasCompletionTarget.CompletionTarget = Post; - var ourType = notification.GetType(); - sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)))?.Add(notification); + var ourType = notification.GetType(); + sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)))?.Add(notification); + }); } protected override void PopIn() { base.PopIn(); - scrollContainer.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); - MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); - FadeTo(1, TRANSITION_LENGTH / 2); + scrollContainer.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); + this.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); + this.FadeTo(1, TRANSITION_LENGTH / 2); } private void markAllRead() @@ -105,8 +110,8 @@ namespace osu.Game.Overlays markAllRead(); - MoveToX(width, TRANSITION_LENGTH, EasingTypes.OutQuint); - FadeTo(0, TRANSITION_LENGTH / 2); + this.MoveToX(width, TRANSITION_LENGTH, Easing.OutQuint); + this.FadeTo(0, TRANSITION_LENGTH / 2); } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs index f5613d6656..49b2823531 100644 --- a/osu.Game/Overlays/Notifications/Notification.cs +++ b/osu.Game/Overlays/Notifications/Notification.cs @@ -63,6 +63,8 @@ namespace osu.Game.Overlays.Notifications Masking = true, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + AutoSizeDuration = 400, + AutoSizeEasing = Easing.OutQuint, Children = new Drawable[] { new Box @@ -74,7 +76,7 @@ namespace osu.Game.Overlays.Notifications { RelativeSizeAxes = Axes.X, Padding = new MarginPadding(5), - Height = 60, + AutoSizeAxes = Axes.Y, Children = new Drawable[] { IconContent = new Container @@ -135,9 +137,9 @@ namespace osu.Game.Overlays.Notifications protected override void LoadComplete() { base.LoadComplete(); - FadeInFromZero(200); + this.FadeInFromZero(200); NotificationContent.MoveToX(DrawSize.X); - NotificationContent.MoveToX(0, 500, EasingTypes.OutQuint); + NotificationContent.MoveToX(0, 500, Easing.OutQuint); } private bool wasClosed; @@ -148,7 +150,7 @@ namespace osu.Game.Overlays.Notifications wasClosed = true; Closed?.Invoke(); - FadeOut(100); + this.FadeOut(100); Expire(); } @@ -181,13 +183,13 @@ namespace osu.Game.Overlays.Notifications protected override bool OnHover(InputState state) { - FadeColour(hoverColour, 200); + this.FadeColour(hoverColour, 200); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - FadeColour(OsuColour.Gray(0.2f), 200); + this.FadeColour(OsuColour.Gray(0.2f), 200); base.OnHoverLost(state); } } @@ -212,12 +214,9 @@ namespace osu.Game.Overlays.Notifications if (pulsate) { const float length = 1000; - using (pulsateLayer.BeginLoopedSequence(length / 2)) - { - pulsateLayer.FadeTo(0.4f, length, EasingTypes.In); - using (pulsateLayer.BeginDelayedSequence(length)) - pulsateLayer.FadeTo(1, length, EasingTypes.Out); - } + pulsateLayer.Loop(length / 2, + p => p.FadeTo(0.4f, length, Easing.In).Then().FadeTo(1, length, Easing.Out) + ); } } } diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs index 831b09e7e9..efd3b39ee2 100644 --- a/osu.Game/Overlays/Notifications/NotificationSection.cs +++ b/osu.Game/Overlays/Notifications/NotificationSection.cs @@ -114,7 +114,7 @@ namespace osu.Game.Overlays.Notifications AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, LayoutDuration = 150, - LayoutEasing = EasingTypes.OutQuart, + LayoutEasing = Easing.OutQuart, Spacing = new Vector2(3), } }); diff --git a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs index cd1ce56011..d70868046b 100644 --- a/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressCompletionNotification.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Notifications [BackgroundDependencyLoader] private void load(OsuColour colours) { - IconBackgound.ColourInfo = ColourInfo.GradientVertical(colours.GreenDark, colours.GreenLight); + IconBackgound.Colour = ColourInfo.GradientVertical(colours.GreenDark, colours.GreenLight); } } } \ No newline at end of file diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index f0fa7e6da1..f42b4b6cb3 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -6,9 +6,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; using OpenTK; using OpenTK.Graphics; @@ -18,10 +16,9 @@ namespace osu.Game.Overlays.Notifications { public string Text { - get { return textDrawable.Text; } set { - textDrawable.Text = value; + Schedule(() => textDrawable.Text = value); } } @@ -77,11 +74,8 @@ namespace osu.Game.Overlays.Notifications switch (state) { case ProgressNotificationState.Completed: - NotificationContent.MoveToY(-DrawSize.Y / 2, 200, EasingTypes.OutQuint); - FadeTo(0.01f, 200); //don't completely fade out or our scheduled task won't run. - - Delay(100); - Schedule(Completed); + NotificationContent.MoveToY(-DrawSize.Y / 2, 200, Easing.OutQuint); + this.FadeOut(200).Finally(d => Completed()); break; } } @@ -93,7 +87,7 @@ namespace osu.Game.Overlays.Notifications protected virtual Notification CreateCompletionNotification() => new ProgressCompletionNotification { Activated = CompletionClickAction, - Text = $"Task \"{Text}\" has completed!" + Text = "Task has completed!" }; protected virtual void Completed() @@ -109,7 +103,7 @@ namespace osu.Game.Overlays.Notifications private Color4 colourActive; private Color4 colourCancelled; - private readonly SpriteText textDrawable; + private readonly TextFlowContainer textDrawable; public ProgressNotification() { @@ -118,9 +112,11 @@ namespace osu.Game.Overlays.Notifications RelativeSizeAxes = Axes.Both, }); - Content.Add(textDrawable = new OsuSpriteText + Content.Add(textDrawable = new TextFlowContainer(t => + { + t.TextSize = 16; + }) { - TextSize = 16, Colour = OsuColour.Gray(128), AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, @@ -134,6 +130,9 @@ namespace osu.Game.Overlays.Notifications }); State = ProgressNotificationState.Queued; + + // don't close on click by default. + Activated = () => false; } [BackgroundDependencyLoader] @@ -170,7 +169,7 @@ namespace osu.Game.Overlays.Notifications private class ProgressBar : Container { - private Box box; + private readonly Box box; private Color4 colourActive; private Color4 colourInactive; @@ -184,7 +183,7 @@ namespace osu.Game.Overlays.Notifications if (progress == value) return; progress = value; - box.ResizeTo(new Vector2(progress, 1), 100, EasingTypes.OutQuad); + box.ResizeTo(new Vector2(progress, 1), 100, Easing.OutQuad); } } @@ -196,19 +195,12 @@ namespace osu.Game.Overlays.Notifications set { active = value; - FadeColour(active ? colourActive : colourInactive, 100); + this.FadeColour(active ? colourActive : colourInactive, 100); } } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) + public ProgressBar() { - colourActive = colours.Blue; - Colour = colourInactive = OsuColour.Gray(0.5f); - - Height = 5; - Children = new[] { box = new Box @@ -218,6 +210,15 @@ namespace osu.Game.Overlays.Notifications } }; } + + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + colourActive = colours.Blue; + Colour = colourInactive = OsuColour.Gray(0.5f); + Height = 5; + } } } diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index 42604658de..44e6d92aef 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays.Notifications IconBackgound = new Box { RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientVertical(OsuColour.Gray(0.2f), OsuColour.Gray(0.6f)) + Colour = ColourInfo.GradientVertical(OsuColour.Gray(0.2f), OsuColour.Gray(0.6f)) }, iconDrawable = new TextAwesome { diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs index 464c9893d1..746b6dd50f 100644 --- a/osu.Game/Overlays/OnScreenDisplay.cs +++ b/osu.Game/Overlays/OnScreenDisplay.cs @@ -154,14 +154,13 @@ namespace osu.Game.Overlays textLine2.Text = settingValue; textLine3.Text = shortcut.ToUpper(); - box.FadeIn(500, EasingTypes.OutQuint); - box.ResizeHeightTo(height, 500, EasingTypes.OutQuint); - - using (box.BeginDelayedSequence(500)) - { - box.FadeOutFromOne(1500, EasingTypes.InQuint); - box.ResizeHeightTo(height_contracted, 1500, EasingTypes.InQuint); - } + box.Animate( + b => b.FadeIn(500, Easing.OutQuint), + b => b.ResizeHeightTo(height, 500, Easing.OutQuint) + ).Then( + b => b.FadeOutFromOne(1500, Easing.InQuint), + b => b.ResizeHeightTo(height_contracted, 1500, Easing.InQuint) + ); int optionCount = 0; int selectedOption = -1; @@ -232,13 +231,13 @@ namespace osu.Game.Overlays { if (glowing) { - fill.FadeColour(glowingColour, transition_speed, EasingTypes.OutQuint); - FadeEdgeEffectTo(glow_strength, transition_speed, EasingTypes.OutQuint); + fill.FadeColour(glowingColour, transition_speed, Easing.OutQuint); + FadeEdgeEffectTo(glow_strength, transition_speed, Easing.OutQuint); } else { - FadeEdgeEffectTo(0, transition_speed, EasingTypes.OutQuint); - fill.FadeColour(idleColour, transition_speed, EasingTypes.OutQuint); + FadeEdgeEffectTo(0, transition_speed, Easing.OutQuint); + fill.FadeColour(idleColour, transition_speed, Easing.OutQuint); } } @@ -261,7 +260,7 @@ namespace osu.Game.Overlays }; updateGlow(); - Flush(true); + FinishTransforms(true); } } } diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 17493d5078..93044315cc 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -12,16 +12,20 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Users; +using System.Diagnostics; +using System.Globalization; namespace osu.Game.Overlays.Profile { public class ProfileHeader : Container { - private readonly OsuTextFlowContainer infoTextLeft, infoTextRight; + private readonly OsuTextFlowContainer infoTextLeft; + private readonly LinkFlowContainer infoTextRight; private readonly FillFlowContainer scoreText, scoreNumberText; private readonly Container coverContainer, chartContainer, supporterTag; @@ -29,6 +33,7 @@ namespace osu.Game.Overlays.Profile private readonly SpriteText levelText; private readonly GradeBadge gradeSSPlus, gradeSS, gradeSPlus, gradeS, gradeA; private readonly Box colourBar; + private readonly DrawableFlag countryFlag; private const float cover_height = 350; private const float info_height = 150; @@ -53,7 +58,7 @@ namespace osu.Game.Overlays.Profile new Box { RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.75f)) + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.1f), Color4.Black.Opacity(0.75f)) }, new Container { @@ -114,16 +119,17 @@ namespace osu.Game.Overlays.Profile } } }, - new OsuSpriteText + new LinkFlowContainer.LinkText { Text = user.Username, + Url = $@"https://osu.ppy.sh/users/{user.Id}", TextSize = 30, Font = @"Exo2.0-RegularItalic", Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, Y = -48 }, - new DrawableFlag(user.Country?.FlagName ?? "__") + countryFlag = new DrawableFlag(user.Country?.FlagName) { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -158,7 +164,7 @@ namespace osu.Game.Overlays.Profile ParagraphSpacing = 0.8f, LineSpacing = 0.2f }, - infoTextRight = new OsuTextFlowContainer(t => + infoTextRight = new LinkFlowContainer(t => { t.TextSize = 14; t.Font = @"Exo2.0-RegularItalic"; @@ -350,6 +356,7 @@ namespace osu.Game.Overlays.Profile { infoTextLeft.AddText("from "); infoTextLeft.AddText(user.Country.FullName, boldItalic); + countryFlag.FlagName = user.Country.FlagName; } infoTextLeft.NewParagraph(); @@ -373,14 +380,22 @@ namespace osu.Game.Overlays.Profile infoTextLeft.AddText(string.Join(", ", user.PlayStyle), boldItalic); } + string websiteWithoutProtcol = user.Website; + if (!string.IsNullOrEmpty(websiteWithoutProtcol)) + { + int protocolIndex = websiteWithoutProtcol.IndexOf("//", StringComparison.Ordinal); + if (protocolIndex >= 0) + websiteWithoutProtcol = websiteWithoutProtcol.Substring(protocolIndex + 2); + } + tryAddInfoRightLine(FontAwesome.fa_map_marker, user.Location); tryAddInfoRightLine(FontAwesome.fa_heart_o, user.Intrerests); tryAddInfoRightLine(FontAwesome.fa_suitcase, user.Occupation); infoTextRight.NewParagraph(); if (!string.IsNullOrEmpty(user.Twitter)) - tryAddInfoRightLine(FontAwesome.fa_twitter, "@" + user.Twitter); - tryAddInfoRightLine(FontAwesome.fa_globe, user.Website); - tryAddInfoRightLine(FontAwesome.fa_skype, user.Skype); + tryAddInfoRightLine(FontAwesome.fa_twitter, "@" + user.Twitter, $@"https://twitter.com/{user.Twitter}"); + tryAddInfoRightLine(FontAwesome.fa_globe, websiteWithoutProtcol, user.Website); + tryAddInfoRightLine(FontAwesome.fa_skype, user.Skype, @"skype:" + user.Skype + @"?chat"); if (user.Statistics != null) { @@ -390,7 +405,7 @@ namespace osu.Game.Overlays.Profile scoreText.Add(createScoreText("Ranked Score")); scoreNumberText.Add(createScoreNumberText(user.Statistics.RankedScore.ToString(@"#,0"))); scoreText.Add(createScoreText("Accuracy")); - scoreNumberText.Add(createScoreNumberText($"{user.Statistics.Accuracy}%")); + scoreNumberText.Add(createScoreNumberText($"{user.Statistics.Accuracy.ToString("0.##", CultureInfo.CurrentCulture)}%")); scoreText.Add(createScoreText("Play Count")); scoreNumberText.Add(createScoreNumberText(user.Statistics.PlayCount.ToString(@"#,0"))); scoreText.Add(createScoreText("Total Score")); @@ -433,12 +448,12 @@ namespace osu.Game.Overlays.Profile Text = text }; - private void tryAddInfoRightLine(FontAwesome icon, string str) + private void tryAddInfoRightLine(FontAwesome icon, string str, string url = null) { if (string.IsNullOrEmpty(str)) return; infoTextRight.AddIcon(icon); - infoTextRight.AddText(" " + str); + infoTextRight.AddLink(" " + str, url); infoTextRight.NewLine(); } @@ -479,5 +494,51 @@ namespace osu.Game.Overlays.Profile badge.Texture = textures.Get($"Grades/{grade}"); } } + + private class LinkFlowContainer : OsuTextFlowContainer + { + public override bool HandleInput => true; + + public LinkFlowContainer(Action defaultCreationParameters = null) : base(defaultCreationParameters) + { + } + + protected override SpriteText CreateSpriteText() => new LinkText(); + + public void AddLink(string text, string url) => AddText(text, link => ((LinkText)link).Url = url); + + public class LinkText : OsuSpriteText + { + public override bool HandleInput => Url != null; + + public string Url; + + private Color4 hoverColour; + + protected override bool OnHover(InputState state) + { + this.FadeColour(hoverColour, 500, Easing.OutQuint); + return base.OnHover(state); + } + + protected override void OnHoverLost(InputState state) + { + this.FadeColour(Color4.White, 500, Easing.OutQuint); + base.OnHoverLost(state); + } + + protected override bool OnClick(InputState state) + { + Process.Start(Url); + return true; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + hoverColour = colours.Yellow; + } + } + } } } diff --git a/osu.Game/Overlays/Profile/RankChart.cs b/osu.Game/Overlays/Profile/RankChart.cs index dfd2219e1f..416bcedfea 100644 --- a/osu.Game/Overlays/Profile/RankChart.cs +++ b/osu.Game/Overlays/Profile/RankChart.cs @@ -138,7 +138,7 @@ namespace osu.Game.Overlays.Profile public void ResetBall() { - ball.MoveTo(new Vector2(1, GetYPosition(Values.Last())), ballShown ? transform_duration : 0, EasingTypes.OutQuint); + ball.MoveTo(new Vector2(1, GetYPosition(Values.Last())), ballShown ? transform_duration : 0, Easing.OutQuint); ball.Show(); BallRelease(); ballShown = true; @@ -158,7 +158,7 @@ namespace osu.Game.Overlays.Profile float y = GetYPosition(values[i]); if (Math.Abs(y * DrawHeight - position.Y) <= 8f) { - ball.MoveTo(new Vector2(index / (float)(count - 1), y), transform_duration, EasingTypes.OutQuint); + ball.MoveTo(new Vector2(index / (float)(count - 1), y), transform_duration, Easing.OutQuint); BallMove(i); } } diff --git a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs index c20519a9b5..326cb582e2 100644 --- a/osu.Game/Overlays/Settings/Sections/GameplaySection.cs +++ b/osu.Game/Overlays/Settings/Sections/GameplaySection.cs @@ -3,7 +3,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Overlays.Settings.Sections.Gameplay; using osu.Game.Rulesets; @@ -26,7 +25,7 @@ namespace osu.Game.Overlays.Settings.Sections } [BackgroundDependencyLoader] - private void load(RulesetDatabase rulesets) + private void load(RulesetStore rulesets) { foreach(Ruleset ruleset in rulesets.AllRulesets.Select(info => info.CreateInstance())) { diff --git a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs index bbecdff29a..6268a9753a 100644 --- a/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/LoginSettings.cs @@ -291,7 +291,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { set { - statusIcon.FadeColour(value, 500, EasingTypes.OutQuint); + statusIcon.FadeColour(value, 500, Easing.OutQuint); } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs index 5f8900449a..c4ce742153 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/LayoutSettings.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, AutoSizeDuration = transition_duration, - AutoSizeEasing = EasingTypes.OutQuint, + AutoSizeEasing = Easing.OutQuint, Masking = true, Children = new Drawable[] @@ -66,7 +66,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics letterboxSettings.AutoSizeAxes = isVisible ? Axes.Y : Axes.None; if (!isVisible) - letterboxSettings.ResizeHeightTo(0, transition_duration, EasingTypes.OutQuint); + letterboxSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint); }; letterboxing.TriggerChange(); } diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs new file mode 100644 index 0000000000..9d13a2ae2f --- /dev/null +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Threading.Tasks; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.Settings.Sections.Maintenance +{ + public class GeneralSettings : SettingsSubsection + { + private OsuButton importButton; + private OsuButton deleteButton; + + protected override string Header => "General"; + + [BackgroundDependencyLoader] + private void load(BeatmapManager beatmaps) + { + Children = new Drawable[] + { + importButton = new OsuButton + { + RelativeSizeAxes = Axes.X, + Text = "Import beatmaps from stable", + Action = () => + { + importButton.Enabled.Value = false; + Task.Run(() => beatmaps.ImportFromStable()).ContinueWith(t => Schedule(() => importButton.Enabled.Value = true)); + } + }, + deleteButton = new OsuButton + { + RelativeSizeAxes = Axes.X, + Text = "Delete ALL beatmaps", + Action = () => + { + deleteButton.Enabled.Value = false; + Task.Run(() => beatmaps.DeleteAll()).ContinueWith(t => Schedule(() => deleteButton.Enabled.Value = true)); + } + }, + }; + } + } +} diff --git a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs index 529cec79c1..b42c64d324 100644 --- a/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs +++ b/osu.Game/Overlays/Settings/Sections/MaintenanceSection.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Game.Graphics; +using osu.Game.Overlays.Settings.Sections.Maintenance; using OpenTK; namespace osu.Game.Overlays.Settings.Sections @@ -17,6 +18,7 @@ namespace osu.Game.Overlays.Settings.Sections FlowContent.Spacing = new Vector2(0, 5); Children = new Drawable[] { + new GeneralSettings() }; } } diff --git a/osu.Game/Overlays/Settings/SettingsFooter.cs b/osu.Game/Overlays/Settings/SettingsFooter.cs index be08e61c1a..6c25b146a1 100644 --- a/osu.Game/Overlays/Settings/SettingsFooter.cs +++ b/osu.Game/Overlays/Settings/SettingsFooter.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Rulesets; using OpenTK; using OpenTK.Graphics; @@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Settings public class SettingsFooter : FillFlowContainer { [BackgroundDependencyLoader] - private void load(OsuGameBase game, OsuColour colours, RulesetDatabase rulesets) + private void load(OsuGameBase game, OsuColour colours, RulesetStore rulesets) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index f80fef4a99..c74f4070e7 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -60,7 +60,7 @@ namespace osu.Game.Overlays.Settings set { // probably needs a better transition. - FadeTo(value ? 1 : 0); + this.FadeTo(value ? 1 : 0); } } diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index 77bf87f718..68ebde6b28 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Settings { set { - FadeTo(value ? 1 : 0); + this.FadeTo(value ? 1 : 0); } } diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 0a9f7ba5d0..ac6d2fa239 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings { set { - FadeTo(value ? 1 : 0); + this.FadeTo(value ? 1 : 0); } } diff --git a/osu.Game/Overlays/Settings/Sidebar.cs b/osu.Game/Overlays/Settings/Sidebar.cs index 44d296a079..6eafc65d12 100644 --- a/osu.Game/Overlays/Settings/Sidebar.cs +++ b/osu.Game/Overlays/Settings/Sidebar.cs @@ -94,10 +94,10 @@ namespace osu.Game.Overlays.Settings switch (state) { default: - ResizeTo(new Vector2(DEFAULT_WIDTH, Height), 500, EasingTypes.OutQuint); + this.ResizeTo(new Vector2(DEFAULT_WIDTH, Height), 500, Easing.OutQuint); break; case ExpandedState.Expanded: - ResizeTo(new Vector2(EXPANDED_WIDTH, Height), 500, EasingTypes.OutQuint); + this.ResizeTo(new Vector2(EXPANDED_WIDTH, Height), 500, Easing.OutQuint); break; } } diff --git a/osu.Game/Overlays/SettingsOverlay.cs b/osu.Game/Overlays/SettingsOverlay.cs index 86e1c1069c..1dcabbfa15 100644 --- a/osu.Game/Overlays/SettingsOverlay.cs +++ b/osu.Game/Overlays/SettingsOverlay.cs @@ -125,9 +125,9 @@ namespace osu.Game.Overlays { base.PopIn(); - sectionsContainer.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); - sidebar.MoveToX(0, TRANSITION_LENGTH, EasingTypes.OutQuint); - FadeTo(1, TRANSITION_LENGTH / 2); + sectionsContainer.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); + sidebar.MoveToX(0, TRANSITION_LENGTH, Easing.OutQuint); + this.FadeTo(1, TRANSITION_LENGTH / 2); searchTextBox.HoldFocus = true; } @@ -136,9 +136,9 @@ namespace osu.Game.Overlays { base.PopOut(); - sectionsContainer.MoveToX(-width, TRANSITION_LENGTH, EasingTypes.OutQuint); - sidebar.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, EasingTypes.OutQuint); - FadeTo(0, TRANSITION_LENGTH / 2); + sectionsContainer.MoveToX(-width, TRANSITION_LENGTH, Easing.OutQuint); + sidebar.MoveToX(-SIDEBAR_WIDTH, TRANSITION_LENGTH, Easing.OutQuint); + this.FadeTo(0, TRANSITION_LENGTH / 2); searchTextBox.HoldFocus = false; if (searchTextBox.HasFocus) diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index a7e5f8dcc4..1ecfe90aa1 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -99,7 +99,7 @@ namespace osu.Game.Overlays.Toolbar Anchor = Anchor.BottomLeft, Alpha = 0, Height = 90, - ColourInfo = ColourInfo.GradientVertical( + Colour = ColourInfo.GradientVertical( OsuColour.Gray(0.1f).Opacity(0.5f), OsuColour.Gray(0.1f).Opacity(0)), }, }; @@ -107,30 +107,30 @@ namespace osu.Game.Overlays.Toolbar protected override bool OnHover(InputState state) { - solidBackground.FadeTo(alpha_hovering, transition_time, EasingTypes.OutQuint); - gradientBackground.FadeIn(transition_time, EasingTypes.OutQuint); + solidBackground.FadeTo(alpha_hovering, transition_time, Easing.OutQuint); + gradientBackground.FadeIn(transition_time, Easing.OutQuint); return true; } protected override void OnHoverLost(InputState state) { - solidBackground.FadeTo(alpha_normal, transition_time, EasingTypes.OutQuint); - gradientBackground.FadeOut(transition_time, EasingTypes.OutQuint); + solidBackground.FadeTo(alpha_normal, transition_time, Easing.OutQuint); + gradientBackground.FadeOut(transition_time, Easing.OutQuint); } } protected override void PopIn() { - MoveToY(0, transition_time, EasingTypes.OutQuint); - FadeIn(transition_time / 2, EasingTypes.OutQuint); + this.MoveToY(0, transition_time, Easing.OutQuint); + this.FadeIn(transition_time / 2, Easing.OutQuint); } protected override void PopOut() { userArea?.LoginOverlay.Hide(); - MoveToY(-DrawSize.Y, transition_time, EasingTypes.OutQuint); - FadeOut(transition_time); + this.MoveToY(-DrawSize.Y, transition_time, Easing.OutQuint); + this.FadeOut(transition_time); } } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs index 38fd954fe3..b5e832d381 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs @@ -135,7 +135,7 @@ namespace osu.Game.Overlays.Toolbar protected override bool OnClick(InputState state) { - HoverBackground.FlashColour(Color4.White.Opacity(100), 500, EasingTypes.OutQuint); + HoverBackground.FlashColour(Color4.White.Opacity(100), 500, Easing.OutQuint); return base.OnClick(state); } diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs index 6a11f68572..2c50897e1f 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs @@ -2,7 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; -using osu.Game.Database; +using osu.Game.Rulesets; using OpenTK.Graphics; namespace osu.Game.Overlays.Toolbar diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 95906464ec..60c1261190 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -6,11 +6,11 @@ using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Database; using OpenTK; using OpenTK.Graphics; using osu.Framework.Configuration; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets; namespace osu.Game.Overlays.Toolbar { @@ -65,7 +65,7 @@ namespace osu.Game.Overlays.Toolbar } [BackgroundDependencyLoader] - private void load(RulesetDatabase rulesets, OsuGame game) + private void load(RulesetStore rulesets, OsuGame game) { foreach (var r in rulesets.AllRulesets) { @@ -86,7 +86,7 @@ namespace osu.Game.Overlays.Toolbar public override bool HandleInput => !ruleset.Disabled; - private void disabledChanged(bool isDisabled) => FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); + private void disabledChanged(bool isDisabled) => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300); protected override void Update() { @@ -115,7 +115,7 @@ namespace osu.Game.Overlays.Toolbar if (!activeMode.IsValid) { - modeButtonLine.MoveToX(activeButton.DrawPosition.X, 200, EasingTypes.OutQuint); + modeButtonLine.MoveToX(activeButton.DrawPosition.X, 200, Easing.OutQuint); activeMode.Validate(); } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs index 5126f6a2a4..dcadc4bf56 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs @@ -19,9 +19,9 @@ namespace osu.Game.Overlays.Toolbar } [BackgroundDependencyLoader] - private void load(NotificationManager notificationManager) + private void load(NotificationOverlay notificationOverlay) { - StateContainer = notificationManager; + StateContainer = notificationOverlay; } } } \ No newline at end of file diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index f26b143088..f604eb5cd2 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -73,13 +73,13 @@ namespace osu.Game.Overlays protected override void PopIn() { base.PopIn(); - FadeEdgeEffectTo(0.5f, APPEAR_DURATION, EasingTypes.In); + FadeEdgeEffectTo(0.5f, APPEAR_DURATION, Easing.In); } protected override void PopOut() { base.PopOut(); - FadeEdgeEffectTo(0, DISAPPEAR_DURATION, EasingTypes.Out); + FadeEdgeEffectTo(0, DISAPPEAR_DURATION, Easing.Out); } public void ShowUser(User user, bool fetchOnline = true) diff --git a/osu.Game/Overlays/WaveOverlayContainer.cs b/osu.Game/Overlays/WaveOverlayContainer.cs index 1bb7813d90..fd89dcfbc4 100644 --- a/osu.Game/Overlays/WaveOverlayContainer.cs +++ b/osu.Game/Overlays/WaveOverlayContainer.cs @@ -17,8 +17,8 @@ namespace osu.Game.Overlays protected const float APPEAR_DURATION = 800; protected const float DISAPPEAR_DURATION = 500; - private const EasingTypes easing_show = EasingTypes.OutSine; - private const EasingTypes easing_hide = EasingTypes.InSine; + private const Easing easing_show = Easing.OutSine; + private const Easing easing_hide = Easing.InSine; private readonly Wave firstWave; private readonly Wave secondWave; @@ -137,23 +137,23 @@ namespace osu.Game.Overlays foreach (var w in wavesContainer.Children) w.State = Visibility.Visible; - FadeIn(100, EasingTypes.OutQuint); - contentContainer.MoveToY(0, APPEAR_DURATION, EasingTypes.OutQuint); + this.FadeIn(100, Easing.OutQuint); + contentContainer.MoveToY(0, APPEAR_DURATION, Easing.OutQuint); - FadeIn(100, EasingTypes.OutQuint); + this.FadeIn(100, Easing.OutQuint); } protected override void PopOut() { base.PopOut(); - FadeOut(DISAPPEAR_DURATION, EasingTypes.InQuint); - contentContainer.MoveToY(DrawHeight * 2f, DISAPPEAR_DURATION, EasingTypes.In); + this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint); + contentContainer.MoveToY(DrawHeight * 2f, DISAPPEAR_DURATION, Easing.In); foreach (var w in wavesContainer.Children) w.State = Visibility.Hidden; - FadeOut(DISAPPEAR_DURATION, EasingTypes.InQuint); + this.FadeOut(DISAPPEAR_DURATION, Easing.InQuint); } protected override void UpdateAfterChildren() @@ -210,10 +210,10 @@ namespace osu.Game.Overlays switch (value) { case Visibility.Hidden: - MoveToY(Parent.Parent.DrawSize.Y, DISAPPEAR_DURATION, easing_hide); + this.MoveToY(Parent.Parent.DrawSize.Y, DISAPPEAR_DURATION, easing_hide); break; case Visibility.Visible: - MoveToY(FinalPosition, APPEAR_DURATION, easing_show); + this.MoveToY(FinalPosition, APPEAR_DURATION, easing_show); break; } } diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 3a82827497..f0a53d677b 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -64,26 +64,24 @@ namespace osu.Game.Rulesets.Judgements { base.LoadComplete(); - FadeInFromZero(100, EasingTypes.OutQuint); + this.FadeInFromZero(100, Easing.OutQuint); switch (Judgement.Result) { case HitResult.Miss: - ScaleTo(1.6f); - ScaleTo(1, 100, EasingTypes.In); + this.ScaleTo(1.6f); + this.ScaleTo(1, 100, Easing.In); - MoveToOffset(new Vector2(0, 100), 800, EasingTypes.InQuint); - RotateTo(40, 800, EasingTypes.InQuint); + this.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint); + this.RotateTo(40, 800, Easing.InQuint); - Delay(600); - FadeOut(200); + this.Delay(600).FadeOut(200); break; case HitResult.Hit: - ScaleTo(0.9f); - ScaleTo(1, 500, EasingTypes.OutElastic); + this.ScaleTo(0.9f); + this.ScaleTo(1, 500, Easing.OutElastic); - Delay(100); - FadeOut(400); + this.Delay(100).FadeOut(400); break; } diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index b282965db8..c343cdaf33 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -2,8 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Audio; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Database; using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Objects diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index 8c2aead5ff..ffe40e4f2e 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -6,8 +6,8 @@ using System; using System.Collections.Generic; using OpenTK; using osu.Game.Audio; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Database; namespace osu.Game.Rulesets.Objects.Legacy { diff --git a/osu.Game/Database/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs similarity index 89% rename from osu.Game/Database/RulesetInfo.cs rename to osu.Game/Rulesets/RulesetInfo.cs index 3990f9e8ae..84ecb7718e 100644 --- a/osu.Game/Database/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -2,10 +2,9 @@ // 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 +namespace osu.Game.Rulesets { public class RulesetInfo { diff --git a/osu.Game/Database/RulesetDatabase.cs b/osu.Game/Rulesets/RulesetStore.cs similarity index 87% rename from osu.Game/Database/RulesetDatabase.cs rename to osu.Game/Rulesets/RulesetStore.cs index b78ca5ffc6..88aee2bffc 100644 --- a/osu.Game/Database/RulesetDatabase.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -6,21 +6,19 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using osu.Framework.Platform; -using osu.Game.Rulesets; +using osu.Game.Database; using SQLite.Net; -namespace osu.Game.Database +namespace osu.Game.Rulesets { /// - /// Todo: All of this needs to be moved to a RulesetDatabase. + /// Todo: All of this needs to be moved to a RulesetStore. /// - public class RulesetDatabase : Database + public class RulesetStore : DatabaseBackedStore { public IEnumerable AllRulesets => Query().Where(r => r.Available); - public RulesetDatabase(Storage storage, SQLiteConnection connection) - : base(storage, connection) + public RulesetStore(SQLiteConnection connection) : base(connection) { } diff --git a/osu.Game/Rulesets/Scoring/Score.cs b/osu.Game/Rulesets/Scoring/Score.cs index 2cca0f54af..6169bb7380 100644 --- a/osu.Game/Rulesets/Scoring/Score.cs +++ b/osu.Game/Rulesets/Scoring/Score.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using Newtonsoft.Json; -using osu.Game.Database; +using osu.Game.Beatmaps; using osu.Game.Rulesets.Mods; using osu.Game.Users; using osu.Game.Rulesets.Replays; diff --git a/osu.Game/Database/ScoreDatabase.cs b/osu.Game/Rulesets/Scoring/ScoreStore.cs similarity index 87% rename from osu.Game/Database/ScoreDatabase.cs rename to osu.Game/Rulesets/Scoring/ScoreStore.cs index adca76d2ac..e69fec4b54 100644 --- a/osu.Game/Database/ScoreDatabase.cs +++ b/osu.Game/Rulesets/Scoring/ScoreStore.cs @@ -4,30 +4,30 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using osu.Framework.Platform; +using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.IO.Legacy; using osu.Game.IPC; using osu.Game.Rulesets.Replays; -using osu.Game.Rulesets.Scoring; using SharpCompress.Compressors.LZMA; using SQLite.Net; -namespace osu.Game.Database +namespace osu.Game.Rulesets.Scoring { - public class ScoreDatabase : Database + public class ScoreStore : DatabaseBackedStore { private readonly Storage storage; - private readonly BeatmapDatabase beatmaps; - private readonly RulesetDatabase rulesets; + private readonly BeatmapManager beatmaps; + private readonly RulesetStore 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, SQLiteConnection connection, IIpcHost importHost = null, BeatmapDatabase beatmaps = null, RulesetDatabase rulesets = null) : base(storage, connection) + public ScoreStore(Storage storage, SQLiteConnection connection, IIpcHost importHost = null, BeatmapManager beatmaps = null, RulesetStore rulesets = null) : base(connection) { this.storage = storage; this.beatmaps = beatmaps; @@ -53,7 +53,7 @@ namespace osu.Game.Database var version = sr.ReadInt32(); /* score.FileChecksum = */ var beatmapHash = sr.ReadString(); - score.Beatmap = beatmaps.Query().FirstOrDefault(b => b.Hash == beatmapHash); + score.Beatmap = beatmaps.QueryBeatmap(b => b.Hash == beatmapHash); /* score.PlayerName = */ sr.ReadString(); /* var localScoreChecksum = */ diff --git a/osu.Game/Screens/BackgroundScreen.cs b/osu.Game/Screens/BackgroundScreen.cs index a9cb93876c..c5bbf04075 100644 --- a/osu.Game/Screens/BackgroundScreen.cs +++ b/osu.Game/Screens/BackgroundScreen.cs @@ -56,29 +56,29 @@ namespace osu.Game.Screens Content.FadeOut(); Content.MoveToX(x_movement_amount); - Content.FadeIn(transition_length, EasingTypes.InOutQuart); - Content.MoveToX(0, transition_length, EasingTypes.InOutQuart); + Content.FadeIn(transition_length, Easing.InOutQuart); + Content.MoveToX(0, transition_length, Easing.InOutQuart); base.OnEntering(last); } protected override void OnSuspending(Screen next) { - Content.MoveToX(-x_movement_amount, transition_length, EasingTypes.InOutQuart); + Content.MoveToX(-x_movement_amount, transition_length, Easing.InOutQuart); base.OnSuspending(next); } protected override bool OnExiting(Screen next) { - Content.FadeOut(transition_length, EasingTypes.OutExpo); - Content.MoveToX(x_movement_amount, transition_length, EasingTypes.OutExpo); + Content.FadeOut(transition_length, Easing.OutExpo); + Content.MoveToX(x_movement_amount, transition_length, Easing.OutExpo); return base.OnExiting(next); } protected override void OnResuming(Screen last) { - Content.MoveToX(0, transition_length, EasingTypes.OutExpo); + Content.MoveToX(0, transition_length, Easing.OutExpo); base.OnResuming(last); } } diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 7e2c0305a9..29a422892f 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -40,7 +40,7 @@ namespace osu.Game.Screens.Backgrounds if (background != null) { newDepth = background.Depth + 1; - background.Flush(); + background.FinishTransforms(); background.FadeOut(250); background.Expire(); } @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Backgrounds Beatmap = beatmap; } - public void BlurTo(Vector2 sigma, double duration, EasingTypes easing = EasingTypes.None) + public void BlurTo(Vector2 sigma, double duration, Easing easing = Easing.None) { background?.BlurTo(sigma, duration, easing); blurTarget = sigma; diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs index bab267a24a..de84e90baf 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs @@ -24,7 +24,7 @@ namespace osu.Game.Screens.Backgrounds private void display(Background newBackground) { - current?.FadeOut(800, EasingTypes.OutQuint); + current?.FadeOut(800, Easing.OutQuint); current?.Expire(); Add(current = newBackground); diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 7ec8347a8f..9f33d624e2 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -7,6 +7,7 @@ using OpenTK.Graphics; using osu.Framework.Screens; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Select; +using osu.Framework.Graphics; namespace osu.Game.Screens.Edit { diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs index 8dad83bd0e..e55c4ef4fe 100644 --- a/osu.Game/Screens/Menu/Button.cs +++ b/osu.Game/Screens/Menu/Button.cs @@ -128,16 +128,15 @@ namespace osu.Game.Screens.Menu bool rightward = beatIndex % 2 == 1; double duration = timingPoint.BeatLength / 2; - icon.RotateTo(rightward ? 10 : -10, duration * 2, EasingTypes.InOutSine); + icon.RotateTo(rightward ? 10 : -10, duration * 2, Easing.InOutSine); - icon.MoveToY(-10, duration, EasingTypes.Out); - icon.ScaleTo(Vector2.One, duration, EasingTypes.Out); - - using (icon.BeginDelayedSequence(duration)) - { - icon.MoveToY(0, duration, EasingTypes.In); - icon.ScaleTo(new Vector2(1, 0.9f), duration, EasingTypes.In); - } + icon.Animate( + i => i.MoveToY(-10, duration, Easing.Out), + i => i.ScaleTo(1, duration, Easing.Out) + ).Then( + i => i.MoveToY(0, duration, Easing.In), + i => i.ScaleTo(new Vector2(1, 0.9f), duration, Easing.In) + ); } protected override bool OnHover(InputState state) @@ -146,25 +145,25 @@ namespace osu.Game.Screens.Menu sampleHover?.Play(); - box.ScaleTo(new Vector2(1.5f, 1), 500, EasingTypes.OutElastic); + box.ScaleTo(new Vector2(1.5f, 1), 500, Easing.OutElastic); double duration = TimeUntilNextBeat; icon.ClearTransforms(); - icon.RotateTo(10, duration, EasingTypes.InOutSine); - icon.ScaleTo(new Vector2(1, 0.9f), duration, EasingTypes.Out); + icon.RotateTo(10, duration, Easing.InOutSine); + icon.ScaleTo(new Vector2(1, 0.9f), duration, Easing.Out); return true; } protected override void OnHoverLost(InputState state) { icon.ClearTransforms(); - icon.RotateTo(0, 500, EasingTypes.Out); - icon.MoveTo(Vector2.Zero, 500, EasingTypes.Out); - icon.ScaleTo(Vector2.One, 200, EasingTypes.Out); + icon.RotateTo(0, 500, Easing.Out); + icon.MoveTo(Vector2.Zero, 500, Easing.Out); + icon.ScaleTo(Vector2.One, 200, Easing.Out); if (State == ButtonState.Expanded) - box.ScaleTo(new Vector2(1, 1), 500, EasingTypes.OutElastic); + box.ScaleTo(new Vector2(1, 1), 500, Easing.OutElastic); } [BackgroundDependencyLoader] @@ -177,13 +176,13 @@ namespace osu.Game.Screens.Menu protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - boxHoverLayer.FadeTo(0.1f, 1000, EasingTypes.OutQuint); + boxHoverLayer.FadeTo(0.1f, 1000, Easing.OutQuint); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - boxHoverLayer.FadeTo(0, 1000, EasingTypes.OutQuint); + boxHoverLayer.FadeTo(0, 1000, Easing.OutQuint); return base.OnMouseUp(state, args); } @@ -215,7 +214,7 @@ namespace osu.Game.Screens.Menu boxHoverLayer.ClearTransforms(); boxHoverLayer.Alpha = 0.9f; - boxHoverLayer.FadeOut(800, EasingTypes.OutExpo); + boxHoverLayer.FadeOut(800, Easing.OutExpo); } public override bool HandleInput => state != ButtonState.Exploded && box.Scale.X >= 0.8f; @@ -247,24 +246,24 @@ namespace osu.Game.Screens.Menu switch (ContractStyle) { default: - box.ScaleTo(new Vector2(0, 1), 500, EasingTypes.OutExpo); - FadeOut(500); + box.ScaleTo(new Vector2(0, 1), 500, Easing.OutExpo); + this.FadeOut(500); break; case 1: - box.ScaleTo(new Vector2(0, 1), 400, EasingTypes.InSine); - FadeOut(800); + box.ScaleTo(new Vector2(0, 1), 400, Easing.InSine); + this.FadeOut(800); break; } break; case ButtonState.Expanded: const int expand_duration = 500; - box.ScaleTo(new Vector2(1, 1), expand_duration, EasingTypes.OutExpo); - FadeIn(expand_duration / 6f); + box.ScaleTo(new Vector2(1, 1), expand_duration, Easing.OutExpo); + this.FadeIn(expand_duration / 6f); break; case ButtonState.Exploded: const int explode_duration = 200; - box.ScaleTo(new Vector2(2, 1), explode_duration, EasingTypes.OutExpo); - FadeOut(explode_duration / 4f * 3); + box.ScaleTo(new Vector2(2, 1), explode_duration, Easing.OutExpo); + this.FadeOut(explode_duration / 4f * 3); break; } } diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index 24fee10195..71f2a16c09 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -216,7 +216,7 @@ namespace osu.Game.Screens.Menu bool fromInitial = lastState == MenuState.Initial; if (state == MenuState.TopLevel) - buttonArea.Flush(true); + buttonArea.FinishTransforms(true); using (buttonArea.BeginDelayedSequence(fromInitial ? 150 : 0, true)) { @@ -224,16 +224,13 @@ namespace osu.Game.Screens.Menu { case MenuState.Exit: case MenuState.Initial: - toolbar?.Hide(); - - buttonAreaBackground.ScaleTo(Vector2.One, 500, EasingTypes.Out); + buttonAreaBackground.ScaleTo(Vector2.One, 500, Easing.Out); buttonArea.FadeOut(300); - using (osuLogo.BeginDelayedSequence(150)) - { - osuLogo.MoveTo(Vector2.Zero, 800, EasingTypes.OutExpo); - osuLogo.ScaleTo(1, 800, EasingTypes.OutExpo); - } + osuLogo.Delay(150) + .Schedule(() => toolbar?.Hide()) + .ScaleTo(1, 800, Easing.OutExpo) + .MoveTo(Vector2.Zero, 800, Easing.OutExpo); foreach (Button b in buttonsTopLevel) b.State = ButtonState.Contracted; @@ -250,19 +247,20 @@ namespace osu.Game.Screens.Menu sampleBack?.Play(); break; case MenuState.TopLevel: - buttonAreaBackground.ScaleTo(Vector2.One, 200, EasingTypes.Out); + buttonAreaBackground.ScaleTo(Vector2.One, 200, Easing.Out); - osuLogo.ClearTransforms(); - osuLogo.MoveTo(buttonFlow.DrawPosition, 200, EasingTypes.In); - osuLogo.ScaleTo(0.5f, 200, EasingTypes.In); - - buttonArea.FadeIn(300); + var sequence = osuLogo + .ScaleTo(0.5f, 200, Easing.In) + .MoveTo(buttonFlow.DrawPosition, 200, Easing.In); if (fromInitial && osuLogo.Scale.X > 0.5f) - using (osuLogo.BeginDelayedSequence(200, true)) - osuLogo.Impact(); + sequence.OnComplete(o => + { + o.Impact(); + toolbar?.Show(); + }); - Scheduler.AddDelayed(() => toolbar?.Show(), 150); + buttonArea.FadeIn(300); foreach (Button b in buttonsTopLevel) b.State = ButtonState.Expanded; @@ -278,7 +276,7 @@ namespace osu.Game.Screens.Menu b.State = ButtonState.Expanded; break; case MenuState.EnteringMode: - buttonAreaBackground.ScaleTo(new Vector2(2, 0), 300, EasingTypes.InSine); + buttonAreaBackground.ScaleTo(new Vector2(2, 0), 300, Easing.InSine); buttonsTopLevel.ForEach(b => b.ContractStyle = 1); buttonsPlay.ForEach(b => b.ContractStyle = 1); diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index beaaa373b6..6a176898a2 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -98,18 +98,13 @@ namespace osu.Game.Screens.Menu { base.OnEntering(last); - Content.FadeInFromZero(500); + icon.Delay(1500).FadeColour(iconColour, 200); - icon.Delay(1500); - icon.FadeColour(iconColour, 200); - - Delay(6000, true); - - Content.FadeOut(250); - - Delay(250); - - Schedule(() => Push(intro)); + Content + .FadeInFromZero(500) + .Then(5500) + .FadeOut(250) + .Finally(d => Push(intro)); } } } diff --git a/osu.Game/Screens/Menu/Intro.cs b/osu.Game/Screens/Menu/Intro.cs index 4ab157db05..a0cf6eec66 100644 --- a/osu.Game/Screens/Menu/Intro.cs +++ b/osu.Game/Screens/Menu/Intro.cs @@ -9,9 +9,9 @@ using osu.Framework.Configuration; using osu.Framework.Screens; using osu.Framework.Graphics; using osu.Framework.MathUtils; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.IO; using osu.Game.Configuration; -using osu.Game.Database; using osu.Game.Graphics.Containers; using osu.Game.Screens.Backgrounds; using OpenTK.Graphics; @@ -22,7 +22,7 @@ namespace osu.Game.Screens.Menu { private readonly OsuLogo logo; - public const string MENU_MUSIC_BEATMAP_HASH = "21c1271b91234385978b5418881fdd88"; + private const string menu_music_beatmap_hash = "715a09144f885d746644c1983e285044"; /// /// Whether we have loaded the menu previously. @@ -67,46 +67,37 @@ namespace osu.Game.Screens.Menu private Track track; [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuConfigManager config, BeatmapDatabase beatmaps, Framework.Game game) + private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game) { menuVoice = config.GetBindable(OsuSetting.MenuVoice); menuMusic = config.GetBindable(OsuSetting.MenuMusic); - var trackManager = audio.Track; - BeatmapSetInfo setInfo = null; if (!menuMusic) { - var query = beatmaps.Query().Where(b => !b.DeletePending); - int count = query.Count(); - if (count > 0) - setInfo = query.ElementAt(RNG.Next(0, count - 1)); + var sets = beatmaps.GetAllUsableBeatmapSets(false); + if (sets.Count > 0) + setInfo = beatmaps.QueryBeatmapSet(s => s.ID == sets[RNG.Next(0, sets.Count - 1)].ID); } if (setInfo == null) { - var query = beatmaps.Query().Where(b => b.Hash == MENU_MUSIC_BEATMAP_HASH); - - setInfo = query.FirstOrDefault(); + setInfo = beatmaps.QueryBeatmapSet(b => b.Hash == menu_music_beatmap_hash); if (setInfo == null) { // we need to import the default menu background beatmap - beatmaps.Import(new OszArchiveReader(game.Resources.GetStream(@"Tracks/circles.osz"))); + setInfo = beatmaps.Import(new OszArchiveReader(game.Resources.GetStream(@"Tracks/circles.osz"))); - setInfo = query.First(); - - setInfo.DeletePending = true; - beatmaps.Update(setInfo, false); + setInfo.Protected = true; + beatmaps.Delete(setInfo); } } - beatmaps.GetChildren(setInfo); Beatmap.Value = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]); track = Beatmap.Value.Track; - trackManager.SetExclusive(track); welcome = audio.Sample.Get(@"welcome"); seeya = audio.Sample.Get(@"seeya"); @@ -121,7 +112,9 @@ namespace osu.Game.Screens.Menu Scheduler.AddDelayed(delegate { - track.Start(); + // Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu. + if (menuMusic) + track.Start(); LoadComponentAsync(mainMenu = new MainMenu()); @@ -135,8 +128,8 @@ namespace osu.Game.Screens.Menu logo.ScaleTo(0.4f); logo.FadeOut(); - logo.ScaleTo(1, 4400, EasingTypes.OutQuint); - logo.FadeIn(20000, EasingTypes.OutQuint); + logo.ScaleTo(1, 4400, Easing.OutQuint); + logo.FadeIn(20000, Easing.OutQuint); } protected override void OnSuspending(Screen next) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index df9b304a47..2544cc2837 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -94,9 +94,7 @@ namespace osu.Game.Screens.Menu { if (!track.IsRunning) { - track.Seek(metadata.PreviewTime); - if (metadata.PreviewTime == -1) - track.Seek(track.Length * 0.4f); + track.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * track.Length); track.Start(); } } @@ -120,10 +118,10 @@ namespace osu.Game.Screens.Menu buttons.State = MenuState.EnteringMode; - Content.FadeOut(length, EasingTypes.InSine); - Content.MoveTo(new Vector2(-800, 0), length, EasingTypes.InSine); + Content.FadeOut(length, Easing.InSine); + Content.MoveTo(new Vector2(-800, 0), length, Easing.InSine); - sideFlashes.FadeOut(length / 4, EasingTypes.OutQuint); + sideFlashes.FadeOut(length / 4, Easing.OutQuint); } protected override void OnResuming(Screen last) @@ -139,10 +137,10 @@ namespace osu.Game.Screens.Menu buttons.State = MenuState.TopLevel; - Content.FadeIn(length, EasingTypes.OutQuint); - Content.MoveTo(new Vector2(0, 0), length, EasingTypes.OutQuint); + Content.FadeIn(length, Easing.OutQuint); + Content.MoveTo(new Vector2(0, 0), length, Easing.OutQuint); - sideFlashes.FadeIn(length / 4, EasingTypes.InQuint); + sideFlashes.FadeIn(length / 4, Easing.InQuint); } protected override bool OnExiting(Screen next) diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index 065c7c5be0..49c777f09a 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -73,8 +73,8 @@ namespace osu.Game.Screens.Menu Color4 gradientDark = colours.Blue.Opacity(0).ToLinear(); Color4 gradientLight = colours.Blue.Opacity(0.3f).ToLinear(); - leftBox.ColourInfo = ColourInfo.GradientHorizontal(gradientLight, gradientDark); - rightBox.ColourInfo = ColourInfo.GradientHorizontal(gradientDark, gradientLight); + leftBox.Colour = ColourInfo.GradientHorizontal(gradientLight, gradientDark); + rightBox.Colour = ColourInfo.GradientHorizontal(gradientDark, gradientLight); } protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) @@ -90,9 +90,9 @@ namespace osu.Game.Screens.Menu private void flash(Drawable d, double beatLength, bool kiai, TrackAmplitudes amplitudes) { - d.FadeTo(Math.Max(0, ((d.Equals(leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time); - using (d.BeginDelayedSequence(box_fade_in_time)) - d.FadeOut(beatLength, EasingTypes.In); + d.FadeTo(Math.Max(0, ((d.Equals(leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time) + .Then() + .FadeOut(beatLength, Easing.In); } } } diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs index ecfd98688e..64c28816d8 100644 --- a/osu.Game/Screens/Menu/OsuLogo.cs +++ b/osu.Game/Screens/Menu/OsuLogo.cs @@ -237,34 +237,32 @@ namespace osu.Game.Screens.Menu if (beatIndex < 0) return; if (IsHovered) - { - using (BeginDelayedSequence(early_activation)) - Schedule(() => sampleBeat.Play()); - } + this.Delay(early_activation).Schedule(() => sampleBeat.Play()); - logoBeatContainer.ScaleTo(1 - 0.02f * amplitudeAdjust, early_activation, EasingTypes.Out); - using (logoBeatContainer.BeginDelayedSequence(early_activation)) - logoBeatContainer.ScaleTo(1, beatLength * 2, EasingTypes.OutQuint); + logoBeatContainer + .ScaleTo(1 - 0.02f * amplitudeAdjust, early_activation, Easing.Out) + .Then() + .ScaleTo(1, beatLength * 2, Easing.OutQuint); ripple.ClearTransforms(); - - ripple.ScaleTo(logoAmplitudeContainer.Scale); - ripple.Alpha = 0.15f * amplitudeAdjust; - - ripple.ScaleTo(logoAmplitudeContainer.Scale * (1 + 0.04f * amplitudeAdjust), beatLength, EasingTypes.OutQuint); - ripple.FadeOut(beatLength, EasingTypes.OutQuint); + ripple + .ScaleTo(logoAmplitudeContainer.Scale) + .ScaleTo(logoAmplitudeContainer.Scale * (1 + 0.04f * amplitudeAdjust), beatLength, Easing.OutQuint) + .FadeTo(0.15f * amplitudeAdjust).FadeOut(beatLength, Easing.OutQuint); if (effectPoint.KiaiMode && flashLayer.Alpha < 0.4f) { flashLayer.ClearTransforms(); - visualizer.ClearTransforms(); + flashLayer + .FadeTo(0.2f * amplitudeAdjust, early_activation, Easing.Out) + .Then() + .FadeOut(beatLength); - flashLayer.FadeTo(0.2f * amplitudeAdjust, early_activation, EasingTypes.Out); - visualizer.FadeTo(0.9f * amplitudeAdjust, early_activation, EasingTypes.Out); - using (flashLayer.BeginDelayedSequence(early_activation)) - flashLayer.FadeOut(beatLength); - using (visualizer.BeginDelayedSequence(early_activation)) - visualizer.FadeTo(0.5f, beatLength); + visualizer.ClearTransforms(); + visualizer + .FadeTo(0.9f * amplitudeAdjust, early_activation, Easing.Out) + .Then() + .FadeTo(0.5f, beatLength); } } @@ -276,7 +274,7 @@ namespace osu.Game.Screens.Menu const float velocity_adjust_cutoff = 0.98f; var maxAmplitude = lastBeatIndex >= 0 ? Beatmap.Value.Track?.CurrentAmplitudes.Maximum ?? 0 : 0; - logoAmplitudeContainer.ScaleTo(1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 75, EasingTypes.OutQuint); + logoAmplitudeContainer.ScaleTo(1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 75, Easing.OutQuint); if (maxAmplitude > velocity_adjust_cutoff) triangles.Velocity = 1 + Math.Max(0, maxAmplitude - velocity_adjust_cutoff) * 50; @@ -288,13 +286,13 @@ namespace osu.Game.Screens.Menu { if (!Interactive) return false; - logoBounceContainer.ScaleTo(0.9f, 1000, EasingTypes.Out); + logoBounceContainer.ScaleTo(0.9f, 1000, Easing.Out); return true; } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - logoBounceContainer.ScaleTo(1f, 500, EasingTypes.OutElastic); + logoBounceContainer.ScaleTo(1f, 500, Easing.OutElastic); return true; } @@ -306,7 +304,7 @@ namespace osu.Game.Screens.Menu flashLayer.ClearTransforms(); flashLayer.Alpha = 0.4f; - flashLayer.FadeOut(1500, EasingTypes.OutExpo); + flashLayer.FadeOut(1500, Easing.OutExpo); Action?.Invoke(); return true; @@ -316,18 +314,18 @@ namespace osu.Game.Screens.Menu { if (!Interactive) return false; - logoHoverContainer.ScaleTo(1.1f, 500, EasingTypes.OutElastic); + logoHoverContainer.ScaleTo(1.1f, 500, Easing.OutElastic); return true; } protected override void OnHoverLost(InputState state) { - logoHoverContainer.ScaleTo(1, 500, EasingTypes.OutElastic); + logoHoverContainer.ScaleTo(1, 500, Easing.OutElastic); } public void Impact() { - impactContainer.FadeOutFromOne(250, EasingTypes.In); + impactContainer.FadeOutFromOne(250, Easing.In); impactContainer.ScaleTo(0.96f); impactContainer.ScaleTo(1.12f, 250); } diff --git a/osu.Game/Screens/Multiplayer/DrawableRoom.cs b/osu.Game/Screens/Multiplayer/DrawableRoom.cs index d8963be116..d2f88224c2 100644 --- a/osu.Game/Screens/Multiplayer/DrawableRoom.cs +++ b/osu.Game/Screens/Multiplayer/DrawableRoom.cs @@ -10,8 +10,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -235,7 +235,7 @@ namespace osu.Game.Screens.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(400, EasingTypes.Out), + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), }) { RelativeSizeAxes = Axes.Both }, }; diff --git a/osu.Game/Screens/Multiplayer/Match.cs b/osu.Game/Screens/Multiplayer/Match.cs index ec6a66062d..a0843bfcae 100644 --- a/osu.Game/Screens/Multiplayer/Match.cs +++ b/osu.Game/Screens/Multiplayer/Match.cs @@ -8,6 +8,7 @@ using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Play; using OpenTK.Graphics; using osu.Game.Screens.Select; +using osu.Framework.Graphics; namespace osu.Game.Screens.Multiplayer { diff --git a/osu.Game/Screens/Multiplayer/ModeTypeInfo.cs b/osu.Game/Screens/Multiplayer/ModeTypeInfo.cs index fff40aeed5..40d385418a 100644 --- a/osu.Game/Screens/Multiplayer/ModeTypeInfo.cs +++ b/osu.Game/Screens/Multiplayer/ModeTypeInfo.cs @@ -4,8 +4,8 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; -using osu.Game.Database; using osu.Game.Online.Multiplayer; namespace osu.Game.Screens.Multiplayer diff --git a/osu.Game/Screens/Multiplayer/ParticipantInfo.cs b/osu.Game/Screens/Multiplayer/ParticipantInfo.cs index 639f29567f..fa48287ce1 100644 --- a/osu.Game/Screens/Multiplayer/ParticipantInfo.cs +++ b/osu.Game/Screens/Multiplayer/ParticipantInfo.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.Multiplayer set { host.Text = value.Username; - flagContainer.Children = new[] { new DrawableFlag(value.Country?.FlagName ?? @"__") { RelativeSizeAxes = Axes.Both } }; + flagContainer.Children = new[] { new DrawableFlag(value.Country?.FlagName) { RelativeSizeAxes = Axes.Both } }; } } diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs index 83950b4387..66ce51b428 100644 --- a/osu.Game/Screens/Multiplayer/RoomInspector.cs +++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs @@ -13,8 +13,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Localisation; +using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -112,7 +112,7 @@ namespace osu.Game.Screens.Multiplayer new Box { RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientVertical(Color4.Black.Opacity(0.5f), Color4.Black.Opacity(0)), + Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.5f), Color4.Black.Opacity(0)), }, new Container { @@ -337,7 +337,7 @@ namespace osu.Game.Screens.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(400, EasingTypes.Out), + OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out), }) { RelativeSizeAxes = Axes.Both }, }; diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index d916614abd..d215385ece 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -6,11 +6,11 @@ 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; using OpenTK; using osu.Framework.Audio.Sample; using osu.Framework.Audio; +using osu.Game.Rulesets; namespace osu.Game.Screens { diff --git a/osu.Game/Screens/Play/HUD/ComboCounter.cs b/osu.Game/Screens/Play/HUD/ComboCounter.cs index f527eaacaf..47099f96e9 100644 --- a/osu.Game/Screens/Play/HUD/ComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboCounter.cs @@ -5,8 +5,6 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.Transforms; -using osu.Framework.MathUtils; using osu.Game.Graphics.Sprites; namespace osu.Game.Screens.Play.HUD @@ -24,7 +22,7 @@ namespace osu.Game.Screens.Play.HUD protected virtual double PopOutDuration => 150; protected virtual float PopOutScale => 2.0f; - protected virtual EasingTypes PopOutEasing => EasingTypes.None; + protected virtual Easing PopOutEasing => Easing.None; protected virtual float PopOutInitialAlpha => 0.75f; protected virtual double FadeOutDuration => 100; @@ -37,7 +35,7 @@ namespace osu.Game.Screens.Play.HUD /// /// Easing for the counter rollover animation. /// - protected EasingTypes RollingEasing => EasingTypes.None; + protected Easing RollingEasing => Easing.None; protected SpriteText DisplayedCountSpriteText; @@ -130,7 +128,7 @@ namespace osu.Game.Screens.Play.HUD protected virtual void OnCountRolling(int currentValue, int newValue) { - transformRoll(new TransformComboRoll(), currentValue, newValue); + transformRoll(currentValue, newValue); } protected virtual void OnCountIncrement(int currentValue, int newValue) @@ -170,7 +168,7 @@ namespace osu.Game.Screens.Play.HUD if (!rolling) { - Flush(false, typeof(TransformComboRoll)); + FinishTransforms(false, nameof(DisplayedCount)); IsRolling = false; DisplayedCount = prev; @@ -186,40 +184,9 @@ namespace osu.Game.Screens.Play.HUD } } - private void transformRoll(TransformComboRoll transform, int currentValue, int newValue) + private void transformRoll(int currentValue, int newValue) { - Flush(false, typeof(TransformComboRoll)); - - if (RollingDuration < 1) - { - DisplayedCount = Current; - return; - } - - transform.StartTime = Time.Current; - transform.EndTime = Time.Current + getProportionalDuration(currentValue, newValue); - transform.EndValue = newValue; - transform.Easing = RollingEasing; - - Transforms.Add(transform); - } - - protected class TransformComboRoll : Transform - { - public virtual int CurrentValue - { - get - { - double time = Time?.Current ?? 0; - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return (int)Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - } - - public override void Apply(Drawable d) => ((ComboCounter)d).DisplayedCount = CurrentValue; - public override void ReadIntoStartValue(Drawable d) => StartValue = ((ComboCounter)d).DisplayedCount; + this.TransformTo(nameof(DisplayedCount), newValue, getProportionalDuration(currentValue, newValue), RollingEasing); } protected abstract void OnDisplayedCountRolling(int currentValue, int newValue); diff --git a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs index c280702390..a4732f6796 100644 --- a/osu.Game/Screens/Play/HUD/ComboResultCounter.cs +++ b/osu.Game/Screens/Play/HUD/ComboResultCounter.cs @@ -1,10 +1,7 @@ // 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.Graphics; -using osu.Framework.Graphics.Transforms; -using osu.Framework.MathUtils; using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Play.HUD @@ -12,44 +9,24 @@ namespace osu.Game.Screens.Play.HUD /// /// Used to display combo with a roll-up animation in results screen. /// - public class ComboResultCounter : RollingCounter + public class ComboResultCounter : RollingCounter { - protected override Type TransformType => typeof(TransformComboResult); - protected override double RollingDuration => 500; - protected override EasingTypes RollingEasing => EasingTypes.Out; + protected override Easing RollingEasing => Easing.Out; - protected override double GetProportionalDuration(ulong currentValue, ulong newValue) + protected override double GetProportionalDuration(long currentValue, long newValue) { return currentValue > newValue ? currentValue - newValue : newValue - currentValue; } - protected override string FormatCount(ulong count) + protected override string FormatCount(long count) { return $@"{count}x"; } - public override void Increment(ulong amount) + public override void Increment(long amount) { Current.Value = Current + amount; } - - protected class TransformComboResult : Transform - { - public virtual ulong CurrentValue - { - get - { - double time = Time?.Current ?? 0; - if (time < StartTime) return StartValue; - if (time >= EndTime) return EndValue; - - return (ulong)Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); - } - } - - public override void Apply(Drawable d) => ((ComboResultCounter)d).DisplayedCount = CurrentValue; - public override void ReadIntoStartValue(Drawable d) => StartValue = ((ComboResultCounter)d).DisplayedCount; - } } } diff --git a/osu.Game/Screens/Play/HUD/ModDisplay.cs b/osu.Game/Screens/Play/HUD/ModDisplay.cs index f8235e5bcf..18a3096d7c 100644 --- a/osu.Game/Screens/Play/HUD/ModDisplay.cs +++ b/osu.Game/Screens/Play/HUD/ModDisplay.cs @@ -76,20 +76,20 @@ namespace osu.Game.Screens.Play.HUD private void appearTransform() { if (mods.Value.Any(m => !m.Ranked)) - unrankedText.FadeInFromZero(fade_duration, EasingTypes.OutQuint); + unrankedText.FadeInFromZero(fade_duration, Easing.OutQuint); else unrankedText.Hide(); - iconsContainer.Flush(); - iconsContainer.FadeInFromZero(fade_duration, EasingTypes.OutQuint); + iconsContainer.FinishTransforms(); + iconsContainer.FadeInFromZero(fade_duration, Easing.OutQuint); expand(); using (iconsContainer.BeginDelayedSequence(1200)) contract(); } - private void expand() => iconsContainer.TransformSpacingTo(new Vector2(5, 0), 500, EasingTypes.OutQuint); + private void expand() => iconsContainer.TransformSpacingTo(new Vector2(5, 0), 500, Easing.OutQuint); - private void contract() => iconsContainer.TransformSpacingTo(new Vector2(-25, 0), 500, EasingTypes.OutQuint); + private void contract() => iconsContainer.TransformSpacingTo(new Vector2(-25, 0), 500, Easing.OutQuint); protected override bool OnHover(InputState state) { diff --git a/osu.Game/Screens/Play/HUD/StandardComboCounter.cs b/osu.Game/Screens/Play/HUD/StandardComboCounter.cs index 525e52d207..04fe78116e 100644 --- a/osu.Game/Screens/Play/HUD/StandardComboCounter.cs +++ b/osu.Game/Screens/Play/HUD/StandardComboCounter.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; +using osu.Framework.Graphics; namespace osu.Game.Screens.Play.HUD { diff --git a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs index cac1f1a71b..06ef87276a 100644 --- a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs +++ b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs @@ -97,11 +97,11 @@ namespace osu.Game.Screens.Play.HUD 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); + fill.FadeEdgeEffectTo(Math.Min(1, fill.EdgeEffect.Colour.Linear.A + (1f - base_glow_opacity) / glow_max_hits), 50, Easing.OutQuint) + .Delay(glow_fade_delay) + .FadeEdgeEffectTo(base_glow_opacity, glow_fade_time, Easing.OutQuint); } - protected override void SetHealth(float value) => fill.ResizeTo(new Vector2(value, 1), 200, EasingTypes.OutQuint); + protected override void SetHealth(float value) => fill.ResizeTo(new Vector2(value, 1), 200, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index 3248495b61..ea75c140db 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -61,7 +61,7 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader(true)] - private void load(OsuConfigManager config, NotificationManager notificationManager, OsuColour colours) + private void load(OsuConfigManager config, NotificationOverlay notificationOverlay, OsuColour colours) { showHud = config.GetBindable(OsuSetting.ShowInterface); showHud.ValueChanged += hudVisibility => content.FadeTo(hudVisibility ? 1 : 0, duration); @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Play { hasShownNotificationOnce = true; - notificationManager?.Post(new SimpleNotification + notificationOverlay?.Post(new SimpleNotification { Text = @"The score overlay is currently disabled. You can toggle this by pressing Shift+Tab." }); @@ -98,10 +98,7 @@ namespace osu.Game.Screens.Play // in the case a replay isn't loaded, we want some elements to only appear briefly. if (!replayLoaded) - { - using (ModDisplay.BeginDelayedSequence(2000)) - ModDisplay.FadeOut(200); - } + ModDisplay.Delay(2000).FadeOut(200); } protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) diff --git a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs index c4d956ebce..11f9a484dd 100644 --- a/osu.Game/Screens/Play/HotkeyRetryOverlay.cs +++ b/osu.Game/Screens/Play/HotkeyRetryOverlay.cs @@ -46,7 +46,7 @@ namespace osu.Game.Screens.Play if (args.Key == Key.Tilde) { - overlay.FadeIn(activate_delay, EasingTypes.Out); + overlay.FadeIn(activate_delay, Easing.Out); return true; } @@ -57,7 +57,7 @@ namespace osu.Game.Screens.Play { if (args.Key == Key.Tilde && !fired) { - overlay.FadeOut(fadeout_delay, EasingTypes.Out); + overlay.FadeOut(fadeout_delay, Easing.Out); return true; } diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs index b4b2691390..01e20fdbd7 100644 --- a/osu.Game/Screens/Play/KeyCounterCollection.cs +++ b/osu.Game/Screens/Play/KeyCounterCollection.cs @@ -44,7 +44,7 @@ namespace osu.Game.Screens.Play private void load(OsuConfigManager config) { showKeyCounter = config.GetBindable(OsuSetting.KeyOverlay); - showKeyCounter.ValueChanged += keyCounterVisibility => FadeTo(keyCounterVisibility ? 1 : 0, duration); + showKeyCounter.ValueChanged += keyCounterVisibility => this.FadeTo(keyCounterVisibility ? 1 : 0, duration); showKeyCounter.TriggerChange(); } diff --git a/osu.Game/Screens/Play/MenuOverlay.cs b/osu.Game/Screens/Play/MenuOverlay.cs index aedbffbab9..a0f867d248 100644 --- a/osu.Game/Screens/Play/MenuOverlay.cs +++ b/osu.Game/Screens/Play/MenuOverlay.cs @@ -76,8 +76,8 @@ namespace osu.Game.Screens.Play public override bool HandleInput => State == Visibility.Visible; - protected override void PopIn() => FadeIn(transition_duration, EasingTypes.In); - protected override void PopOut() => FadeOut(transition_duration, EasingTypes.In); + protected override void PopIn() => this.FadeIn(transition_duration, Easing.In); + protected override void PopOut() => this.FadeOut(transition_duration, Easing.In); // Don't let mouse down events through the overlay or people can click circles while paused. protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; diff --git a/osu.Game/Screens/Play/PauseContainer.cs b/osu.Game/Screens/Play/PauseContainer.cs index f052bafd63..eed5cd1c20 100644 --- a/osu.Game/Screens/Play/PauseContainer.cs +++ b/osu.Game/Screens/Play/PauseContainer.cs @@ -56,11 +56,7 @@ namespace osu.Game.Screens.Play AddInternal(pauseOverlay = new PauseOverlay { - OnResume = delegate - { - Delay(400); - Schedule(Resume); - }, + OnResume = () => this.Delay(400).Schedule(Resume), OnRetry = () => OnRetry(), OnQuit = () => OnQuit(), }); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7bd310e168..84261d509e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -13,7 +13,6 @@ using osu.Framework.Logging; using osu.Framework.Screens; using osu.Framework.Timing; using osu.Game.Configuration; -using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.UI; using osu.Game.Screens.Backgrounds; @@ -35,8 +34,6 @@ namespace osu.Game.Screens.Play internal override bool HasLocalCursorDisplayed => !pauseContainer.IsPaused && !HasFailed && HitRenderer.ProvidingUserCursor; - public BeatmapInfo BeatmapInfo; - public Action RestartRequested; internal override bool AllowBeatmapRulesetChange => false; @@ -72,7 +69,7 @@ namespace osu.Game.Screens.Play private bool loadedSuccessfully => HitRenderer?.Objects.Any() == true; [BackgroundDependencyLoader(permitNulls: true)] - private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager config, OsuGame osu) + private void load(AudioManager audio, OsuConfigManager config, OsuGame osu) { dimLevel = config.GetBindable(OsuSetting.DimLevel); mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel); @@ -83,10 +80,6 @@ namespace osu.Game.Screens.Play try { - if (!Beatmap.Value.WithStoryboard) - // we need to ensure the storyboard is loaded. - Beatmap.Value = beatmaps.GetWorkingBeatmap(BeatmapInfo, withStoryboard: true); - if (Beatmap.Value.Beatmap == null) throw new InvalidOperationException("Beatmap was not loaded"); @@ -121,10 +114,7 @@ namespace osu.Game.Screens.Play Track track = Beatmap.Value.Track; if (track != null) - { - audio.Track.SetExclusive(track); adjustableSourceClock = track; - } adjustableSourceClock = (IAdjustableClock)track ?? new StopwatchClock(); @@ -271,29 +261,27 @@ namespace osu.Game.Screens.Play if (!loadedSuccessfully) return; - (Background as BackgroundScreenBeatmap)?.BlurTo(Vector2.Zero, 1500, EasingTypes.OutQuint); - Background?.FadeTo(1 - (float)dimLevel, 1500, EasingTypes.OutQuint); + (Background as BackgroundScreenBeatmap)?.BlurTo(Vector2.Zero, 1500, Easing.OutQuint); + Background?.FadeTo(1 - (float)dimLevel, 1500, Easing.OutQuint); Content.Alpha = 0; dimLevel.ValueChanged += newDim => Background?.FadeTo(1 - (float)newDim, 800); - Content.ScaleTo(0.7f); + Content + .ScaleTo(0.7f) + .ScaleTo(1, 750, Easing.OutQuint) + .Delay(250) + .FadeIn(250); - using (Content.BeginDelayedSequence(250)) - Content.FadeIn(250); - - Content.ScaleTo(1, 750, EasingTypes.OutQuint); - - using (BeginDelayedSequence(750)) - Schedule(() => - { - if (!pauseContainer.IsPaused) - decoupledClock.Start(); - }); + this.Delay(750).Schedule(() => + { + if (!pauseContainer.IsPaused) + decoupledClock.Start(); + }); pauseContainer.Alpha = 0; - pauseContainer.FadeIn(750, EasingTypes.OutQuint); + pauseContainer.FadeIn(750, Easing.OutQuint); } protected override void OnSuspending(Screen next) @@ -325,7 +313,7 @@ namespace osu.Game.Screens.Play HitRenderer?.FadeOut(fade_out_duration); Content.FadeOut(fade_out_duration); - hudOverlay?.ScaleTo(0.7f, fade_out_duration * 3, EasingTypes.In); + hudOverlay?.ScaleTo(0.7f, fade_out_duration * 3, Easing.In); Background?.FadeTo(1f, fade_out_duration); } diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index cdb608e74d..1cac1bd2ad 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Screens; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Screens.Backgrounds; @@ -77,20 +76,18 @@ namespace osu.Game.Screens.Play RestartRequested = player.RestartRequested, }); - Delay(400); - - Schedule(pushWhenLoaded); + this.Delay(400).Schedule(pushWhenLoaded); } private void contentIn() { - Content.ScaleTo(1, 650, EasingTypes.OutQuint); + Content.ScaleTo(1, 650, Easing.OutQuint); Content.FadeInFromZero(400); } private void contentOut() { - Content.ScaleTo(0.7f, 300, EasingTypes.InQuint); + Content.ScaleTo(0.7f, 300, Easing.InQuint); Content.FadeOut(250); } @@ -104,16 +101,9 @@ namespace osu.Game.Screens.Play contentIn(); - Delay(500, true); - - logo.MoveToOffset(new Vector2(0, -180), 500, EasingTypes.InOutExpo); - Delay(250, true); - - info.FadeIn(500); - - Delay(1400, true); - - Schedule(pushWhenLoaded); + logo.Delay(500).MoveToOffset(new Vector2(0, -180), 500, Easing.InOutExpo); + info.Delay(750).FadeIn(500); + this.Delay(2150).Schedule(pushWhenLoaded); } private void pushWhenLoaded() @@ -123,9 +113,7 @@ namespace osu.Game.Screens.Play contentOut(); - Delay(250); - - Schedule(() => + this.Delay(250).Schedule(() => { if (!IsCurrentScreen) return; @@ -142,8 +130,8 @@ namespace osu.Game.Screens.Play protected override bool OnExiting(Screen next) { - Content.ScaleTo(0.7f, 150, EasingTypes.InQuint); - FadeOut(150); + Content.ScaleTo(0.7f, 150, Easing.InQuint); + this.FadeOut(150); return base.OnExiting(next); } diff --git a/osu.Game/Screens/Play/ReplaySettings/ReplayGroup.cs b/osu.Game/Screens/Play/ReplaySettings/ReplayGroup.cs index a2494d3a69..06cd783cae 100644 --- a/osu.Game/Screens/Play/ReplaySettings/ReplayGroup.cs +++ b/osu.Game/Screens/Play/ReplaySettings/ReplayGroup.cs @@ -94,7 +94,7 @@ namespace osu.Game.Screens.Play.ReplaySettings Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.X, AutoSizeDuration = transition_duration, - AutoSizeEasing = EasingTypes.OutQuint, + AutoSizeEasing = Easing.OutQuint, AutoSizeAxes = Axes.Y, Padding = new MarginPadding(15), Spacing = new Vector2(0, 15), @@ -123,10 +123,10 @@ namespace osu.Game.Screens.Play.ReplaySettings else { content.AutoSizeAxes = Axes.None; - content.ResizeHeightTo(0, transition_duration, EasingTypes.OutQuint); + content.ResizeHeightTo(0, transition_duration, Easing.OutQuint); } - button.FadeColour(expanded ? buttonActiveColour : Color4.White, 200, EasingTypes.OutQuint); + button.FadeColour(expanded ? buttonActiveColour : Color4.White, 200, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Play/SkipButton.cs b/osu.Game/Screens/Play/SkipButton.cs index b0e3de0ea4..b2d5abe71a 100644 --- a/osu.Game/Screens/Play/SkipButton.cs +++ b/osu.Game/Screens/Play/SkipButton.cs @@ -100,9 +100,9 @@ namespace osu.Game.Screens.Play return; } - FadeInFromZero(fade_time); + this.FadeInFromZero(fade_time); using (BeginAbsoluteSequence(beginFadeTime)) - FadeOut(fade_time); + this.FadeOut(fade_time); button.Action = () => AudioClock?.Seek(startTime - skip_required_cutoff - fade_time); @@ -114,7 +114,7 @@ namespace osu.Game.Screens.Play protected override void Update() { base.Update(); - remainingTimeBox.ResizeWidthTo((float)Math.Max(0, 1 - (Time.Current - displayTime) / (beginFadeTime - displayTime)), 120, EasingTypes.OutQuint); + remainingTimeBox.ResizeWidthTo((float)Math.Max(0, 1 - (Time.Current - displayTime) / (beginFadeTime - displayTime)), 120, Easing.OutQuint); } protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) @@ -154,14 +154,14 @@ namespace osu.Game.Screens.Play { case Visibility.Visible: if (lastState == Visibility.Hidden) - FadeIn(500, EasingTypes.OutExpo); + this.FadeIn(500, Easing.OutExpo); if (!IsHovered) using (BeginDelayedSequence(1000)) scheduledHide = Schedule(() => State = Visibility.Hidden); break; case Visibility.Hidden: - FadeOut(1000, EasingTypes.OutExpo); + this.FadeOut(1000, Easing.OutExpo); break; } } @@ -249,29 +249,29 @@ namespace osu.Game.Screens.Play protected override bool OnHover(InputState state) { - flow.TransformSpacingTo(new Vector2(5), 500, EasingTypes.OutQuint); - box.FadeColour(colourHover, 500, EasingTypes.OutQuint); - background.FadeTo(0.4f, 500, EasingTypes.OutQuint); + flow.TransformSpacingTo(new Vector2(5), 500, Easing.OutQuint); + box.FadeColour(colourHover, 500, Easing.OutQuint); + background.FadeTo(0.4f, 500, Easing.OutQuint); return base.OnHover(state); } protected override void OnHoverLost(InputState state) { - flow.TransformSpacingTo(new Vector2(0), 500, EasingTypes.OutQuint); - box.FadeColour(colourNormal, 500, EasingTypes.OutQuint); - background.FadeTo(0.2f, 500, EasingTypes.OutQuint); + flow.TransformSpacingTo(new Vector2(0), 500, Easing.OutQuint); + box.FadeColour(colourNormal, 500, Easing.OutQuint); + background.FadeTo(0.2f, 500, Easing.OutQuint); base.OnHoverLost(state); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - aspect.ScaleTo(0.75f, 2000, EasingTypes.OutQuint); + aspect.ScaleTo(0.75f, 2000, Easing.OutQuint); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - aspect.ScaleTo(1, 1000, EasingTypes.OutElastic); + aspect.ScaleTo(1, 1000, Easing.OutElastic); return base.OnMouseUp(state, args); } @@ -280,8 +280,8 @@ namespace osu.Game.Screens.Play if (!Enabled) return false; - box.FlashColour(Color4.White, 500, EasingTypes.OutQuint); - aspect.ScaleTo(1.2f, 2000, EasingTypes.OutQuint); + box.FlashColour(Color4.White, 500, Easing.OutQuint); + aspect.ScaleTo(1.2f, 2000, Easing.OutQuint); bool result = base.OnClick(state); diff --git a/osu.Game/Screens/Play/SongProgress.cs b/osu.Game/Screens/Play/SongProgress.cs index ea91089aa4..c513daf3d9 100644 --- a/osu.Game/Screens/Play/SongProgress.cs +++ b/osu.Game/Screens/Play/SongProgress.cs @@ -121,19 +121,19 @@ namespace osu.Game.Screens.Play private void updateBarVisibility() { - bar.FadeTo(allowSeeking ? 1 : 0, transition_duration, EasingTypes.In); - MoveTo(new Vector2(0, allowSeeking ? 0 : bottom_bar_height), transition_duration, EasingTypes.In); + bar.FadeTo(allowSeeking ? 1 : 0, transition_duration, Easing.In); + this.MoveTo(new Vector2(0, allowSeeking ? 0 : bottom_bar_height), transition_duration, Easing.In); } protected override void PopIn() { updateBarVisibility(); - FadeIn(500, EasingTypes.OutQuint); + this.FadeIn(500, Easing.OutQuint); } protected override void PopOut() { - FadeOut(100); + this.FadeOut(100); } protected override void Update() diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index 9251ca33a4..541065e532 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -25,7 +25,7 @@ namespace osu.Game.Screens.Play return; var firstHit = objects.First().StartTime; - var lastHit = (objects.Last() as IHasEndTime)?.EndTime ?? 0; + var lastHit = objects.Max(o => (o as IHasEndTime)?.EndTime ?? o.StartTime); if (lastHit == 0) lastHit = objects.Last().StartTime; diff --git a/osu.Game/Screens/Ranking/ResultModeButton.cs b/osu.Game/Screens/Ranking/ResultModeButton.cs index 4789a5abb7..50be5c8d00 100644 --- a/osu.Game/Screens/Ranking/ResultModeButton.cs +++ b/osu.Game/Screens/Ranking/ResultModeButton.cs @@ -92,8 +92,8 @@ namespace osu.Game.Screens.Ranking }; } - protected override void OnActivated() => colouredPart.FadeColour(activeColour, 200, EasingTypes.OutQuint); + protected override void OnActivated() => colouredPart.FadeColour(activeColour, 200, Easing.OutQuint); - protected override void OnDeactivated() => colouredPart.FadeColour(inactiveColour, 200, EasingTypes.OutQuint); + protected override void OnDeactivated() => colouredPart.FadeColour(inactiveColour, 200, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs index 93f6fec862..60ad484673 100644 --- a/osu.Game/Screens/Ranking/Results.cs +++ b/osu.Game/Screens/Ranking/Results.cs @@ -55,7 +55,7 @@ namespace osu.Game.Screens.Ranking protected override void OnEntering(Screen last) { base.OnEntering(last); - (Background as BackgroundScreenBeatmap)?.BlurTo(background_blur, 2500, EasingTypes.OutQuint); + (Background as BackgroundScreenBeatmap)?.BlurTo(background_blur, 2500, Easing.OutQuint); allCircles.ForEach(c => { @@ -67,25 +67,28 @@ namespace osu.Game.Screens.Ranking modeChangeButtons.FadeOut(); currentPage.FadeOut(); - circleOuterBackground.ScaleTo(1, transition_time, EasingTypes.OutQuint); - circleOuterBackground.FadeTo(1, transition_time, EasingTypes.OutQuint); + circleOuterBackground + .FadeIn(transition_time, Easing.OutQuint) + .ScaleTo(1, transition_time, Easing.OutQuint); using (BeginDelayedSequence(transition_time * 0.25f, true)) { - circleOuter.ScaleTo(1, transition_time, EasingTypes.OutQuint); - circleOuter.FadeTo(1, transition_time, EasingTypes.OutQuint); + circleOuter + .FadeIn(transition_time, Easing.OutQuint) + .ScaleTo(1, transition_time, Easing.OutQuint); using (BeginDelayedSequence(transition_time * 0.3f, true)) { - backgroundParallax.FadeIn(transition_time, EasingTypes.OutQuint); + backgroundParallax.FadeIn(transition_time, Easing.OutQuint); - circleInner.ScaleTo(1, transition_time, EasingTypes.OutQuint); - circleInner.FadeTo(1, transition_time, EasingTypes.OutQuint); + circleInner + .FadeIn(transition_time, Easing.OutQuint) + .ScaleTo(1, transition_time, Easing.OutQuint); using (BeginDelayedSequence(transition_time * 0.4f, true)) { - modeChangeButtons.FadeIn(transition_time, EasingTypes.OutQuint); - currentPage.FadeIn(transition_time, EasingTypes.OutQuint); + modeChangeButtons.FadeIn(transition_time, Easing.OutQuint); + currentPage.FadeIn(transition_time, Easing.OutQuint); } } } @@ -95,7 +98,7 @@ namespace osu.Game.Screens.Ranking { allCircles.ForEach(c => { - c.ScaleTo(0, transition_time, EasingTypes.OutSine); + c.ScaleTo(0, transition_time, Easing.OutSine); }); Content.FadeOut(transition_time / 4); diff --git a/osu.Game/Screens/Ranking/ResultsPage.cs b/osu.Game/Screens/Ranking/ResultsPage.cs index 59173748ed..7f381ebf99 100644 --- a/osu.Game/Screens/Ranking/ResultsPage.cs +++ b/osu.Game/Screens/Ranking/ResultsPage.cs @@ -33,8 +33,7 @@ namespace osu.Game.Screens.Ranking protected override void LoadComplete() { base.LoadComplete(); - fill.Delay(400); - fill.FadeInFromZero(600); + fill.Delay(400).FadeInFromZero(600); } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs index 96e63585bf..bf406ff912 100644 --- a/osu.Game/Screens/Ranking/ResultsPageScore.cs +++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs @@ -15,7 +15,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Localisation; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -133,7 +132,7 @@ namespace osu.Game.Screens.Ranking { new Box { - ColourInfo = ColourInfo.GradientHorizontal( + Colour = ColourInfo.GradientHorizontal( colours.GrayC.Opacity(0), colours.GrayC.Opacity(0.9f)), RelativeSizeAxes = Axes.Both, @@ -143,7 +142,7 @@ namespace osu.Game.Screens.Ranking { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - ColourInfo = ColourInfo.GradientHorizontal( + Colour = ColourInfo.GradientHorizontal( colours.GrayC.Opacity(0.9f), colours.GrayC.Opacity(0)), RelativeSizeAxes = Axes.Both, @@ -158,7 +157,7 @@ namespace osu.Game.Screens.Ranking Origin = Anchor.TopCentre, Direction = FillDirection.Horizontal, LayoutDuration = 200, - LayoutEasing = EasingTypes.OutQuint + LayoutEasing = Easing.OutQuint } } } @@ -178,9 +177,9 @@ namespace osu.Game.Screens.Ranking int delay = 0; foreach (var s in statisticsContainer.Children) { - s.FadeOut(); - s.Delay(delay += 200); - s.FadeIn(300 + delay, EasingTypes.Out); + s.FadeOut() + .Then(delay += 200) + .FadeIn(300 + delay, Easing.Out); } }); } @@ -372,7 +371,7 @@ namespace osu.Game.Screens.Ranking { protected override double RollingDuration => 3000; - protected override EasingTypes RollingEasing => EasingTypes.OutPow10; + protected override Easing RollingEasing => Easing.OutPow10; public SlowScoreCounter(uint leading = 0) : base(leading) { diff --git a/osu.Game/Screens/ScreenWhiteBox.cs b/osu.Game/Screens/ScreenWhiteBox.cs index 21239e8030..5596f345d5 100644 --- a/osu.Game/Screens/ScreenWhiteBox.cs +++ b/osu.Game/Screens/ScreenWhiteBox.cs @@ -44,19 +44,20 @@ namespace osu.Game.Screens boxContainer.ScaleTo(0.2f); boxContainer.RotateTo(-20); - Content.Delay(300, true); + using (Content.BeginDelayedSequence(300, true)) + { + boxContainer.ScaleTo(1, transition_time, Easing.OutElastic); + boxContainer.RotateTo(0, transition_time / 2, Easing.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); + textContainer.MoveTo(Vector2.Zero, transition_time, Easing.OutExpo); + Content.FadeIn(transition_time, Easing.OutExpo); + } } protected override bool OnExiting(Screen next) { - textContainer.MoveTo(new Vector2(DrawSize.X / 16, 0), transition_time, EasingTypes.OutExpo); - Content.FadeOut(transition_time, EasingTypes.OutExpo); + textContainer.MoveTo(new Vector2(DrawSize.X / 16, 0), transition_time, Easing.OutExpo); + Content.FadeOut(transition_time, Easing.OutExpo); return base.OnExiting(next); } @@ -65,16 +66,16 @@ namespace osu.Game.Screens { base.OnSuspending(next); - textContainer.MoveTo(new Vector2(-(DrawSize.X / 16), 0), transition_time, EasingTypes.OutExpo); - Content.FadeOut(transition_time, EasingTypes.OutExpo); + textContainer.MoveTo(new Vector2(-(DrawSize.X / 16), 0), transition_time, Easing.OutExpo); + Content.FadeOut(transition_time, Easing.OutExpo); } protected override void OnResuming(Screen last) { base.OnResuming(last); - textContainer.MoveTo(Vector2.Zero, transition_time, EasingTypes.OutExpo); - Content.FadeIn(transition_time, EasingTypes.OutExpo); + textContainer.MoveTo(Vector2.Zero, transition_time, Easing.OutExpo); + Content.FadeIn(transition_time, Easing.OutExpo); } public ScreenWhiteBox() diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index e135fefc6d..264636b258 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -4,7 +4,6 @@ using OpenTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Database; using System; using System.Collections.Generic; using System.Linq; @@ -18,13 +17,17 @@ using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Threading; using osu.Framework.Configuration; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Select { - internal class BeatmapCarousel : ScrollContainer + internal class BeatmapCarousel : OsuScrollContainer { public BeatmapInfo SelectedBeatmap => selectedPanel?.Beatmap; + public override bool HandleInput => AllowSelection; + public Action BeatmapsChanged; public IEnumerable Beatmaps @@ -65,7 +68,7 @@ namespace osu.Game.Screens.Select /// /// Required for now unfortunately. /// - private BeatmapDatabase database; + private BeatmapManager manager; private readonly Container scrollableContent; @@ -104,6 +107,14 @@ namespace osu.Game.Screens.Select }); } + public void RemoveBeatmap(BeatmapSetInfo beatmapSet) + { + Schedule(delegate + { + removeGroup(groups.Find(b => b.BeatmapSet.ID == beatmapSet.ID)); + }); + } + public void SelectBeatmap(BeatmapInfo beatmap, bool animated = true) { if (beatmap == null) @@ -125,15 +136,13 @@ namespace osu.Game.Screens.Select } } - public void RemoveBeatmap(BeatmapSetInfo info) => removeGroup(groups.Find(b => b.BeatmapSet.ID == info.ID)); - public Action SelectionChanged; public Action StartRequested; public void SelectNext(int direction = 1, bool skipDifficulties = true) { - if (groups.Count == 0) + if (groups.All(g => g.State == BeatmapGroupState.Hidden)) { selectedGroup = null; selectedPanel = null; @@ -175,12 +184,15 @@ namespace osu.Game.Screens.Select public void SelectNextRandom() { - randomSelectedBeatmaps.Push(new KeyValuePair(selectedGroup, selectedGroup.SelectedPanel)); + if (groups.Count == 0) + return; var visibleGroups = getVisibleGroups(); if (!visibleGroups.Any()) return; + randomSelectedBeatmaps.Push(new KeyValuePair(selectedGroup, selectedGroup.SelectedPanel)); + BeatmapGroup group; if (randomType == SelectionRandomType.RandomPermutation) @@ -228,6 +240,14 @@ namespace osu.Game.Screens.Select private ScheduledDelegate filterTask; + public bool AllowSelection = true; + + public void FlushPendingFilters() + { + if (filterTask?.Completed == false) + Filter(null, false); + } + public void Filter(FilterCriteria newCriteria = null, bool debounce = true) { if (newCriteria != null) @@ -259,12 +279,20 @@ namespace osu.Game.Screens.Select }; filterTask?.Cancel(); + filterTask = null; + if (debounce) filterTask = Scheduler.AddDelayed(perform, 250); else perform(); } + public void ScrollToSelected(bool animated = true) + { + float selectedY = computeYPositions(animated); + ScrollTo(selectedY, animated); + } + private BeatmapGroup createGroup(BeatmapSetInfo beatmapSet) { foreach (var b in beatmapSet.Beatmaps) @@ -273,7 +301,7 @@ namespace osu.Game.Screens.Select b.Metadata = beatmapSet.Metadata; } - return new BeatmapGroup(beatmapSet, database) + return new BeatmapGroup(beatmapSet, manager) { SelectionChanged = (g, p) => selectGroup(g, p), StartRequested = b => StartRequested?.Invoke(), @@ -282,9 +310,9 @@ namespace osu.Game.Screens.Select } [BackgroundDependencyLoader(permitNulls: true)] - private void load(BeatmapDatabase database, OsuConfigManager config) + private void load(BeatmapManager manager, OsuConfigManager config) { - this.database = database; + this.manager = manager; randomType = config.GetBindable(OsuSetting.SelectionRandomType); } @@ -298,6 +326,9 @@ namespace osu.Game.Screens.Select private void removeGroup(BeatmapGroup group) { + if (group == null) + return; + groups.Remove(group); panels.Remove(group.Header); foreach (var p in group.BeatmapPanels) @@ -329,7 +360,7 @@ namespace osu.Game.Screens.Select if (group.State == BeatmapGroupState.Expanded) { - group.Header.MoveToX(-100, 500, EasingTypes.OutExpo); + group.Header.MoveToX(-100, 500, Easing.OutExpo); var headerY = group.Header.Position.Y; foreach (BeatmapPanel panel in group.BeatmapPanels) @@ -337,7 +368,7 @@ namespace osu.Game.Screens.Select if (panel == selectedPanel) selectedY = currentY + panel.DrawHeight / 2 - DrawHeight / 2; - panel.MoveToX(-50, 500, EasingTypes.OutExpo); + panel.MoveToX(-50, 500, Easing.OutExpo); //on first display we want to begin hidden under our group's header. if (panel.Alpha == 0) @@ -348,11 +379,11 @@ namespace osu.Game.Screens.Select } else { - group.Header.MoveToX(0, 500, EasingTypes.OutExpo); + group.Header.MoveToX(0, 500, Easing.OutExpo); foreach (BeatmapPanel panel in group.BeatmapPanels) { - panel.MoveToX(0, 500, EasingTypes.OutExpo); + panel.MoveToX(0, 500, Easing.OutExpo); movePanel(panel, false, animated, ref currentY); } } @@ -367,7 +398,7 @@ namespace osu.Game.Screens.Select private void movePanel(Panel panel, bool advance, bool animated, ref float currentY) { yPositions.Add(currentY); - panel.MoveToY(currentY, animated ? 750 : 0, EasingTypes.OutExpo); + panel.MoveToY(currentY, animated ? 750 : 0, Easing.OutExpo); if (advance) currentY += panel.DrawHeight + 5; @@ -401,8 +432,7 @@ namespace osu.Game.Screens.Select } finally { - float selectedY = computeYPositions(animated); - ScrollTo(selectedY, animated); + ScrollToSelected(animated); } } diff --git a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs index 0890625eb9..96caf2f236 100644 --- a/osu.Game/Screens/Select/BeatmapDeleteDialog.cs +++ b/osu.Game/Screens/Select/BeatmapDeleteDialog.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Allocation; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Overlays.Dialog; @@ -12,12 +11,12 @@ namespace osu.Game.Screens.Select { public class BeatmapDeleteDialog : PopupDialog { - private BeatmapDatabase database; + private BeatmapManager manager; [BackgroundDependencyLoader] - private void load(BeatmapDatabase beatmapDatabase) + private void load(BeatmapManager beatmapManager) { - database = beatmapDatabase; + manager = beatmapManager; } public BeatmapDeleteDialog(WorkingBeatmap beatmap) @@ -35,7 +34,7 @@ namespace osu.Game.Screens.Select Action = () => { beatmap.Dispose(); - database.Delete(beatmap.BeatmapSetInfo); + manager.Delete(beatmap.BeatmapSetInfo); }, }, new PopupDialogCancelButton diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 9ad932ff26..a5486efa96 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -6,7 +6,6 @@ using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -16,6 +15,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Framework.Threading; using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; namespace osu.Game.Screens.Select { @@ -86,7 +86,7 @@ namespace osu.Game.Screens.Select requestedBeatmap.Metrics = res; Schedule(() => updateMetrics(res)); }; - lookup.Failure += e => updateMetrics(null); + lookup.Failure += e => Schedule(() => updateMetrics(null)); api.Queue(lookup); loading.Show(); @@ -119,12 +119,12 @@ namespace osu.Game.Screens.Select ratingsGraph.Values = ratings.Select(rating => (float)rating); - ratingsContainer.FadeColour(Color4.White, 500, EasingTypes.Out); + ratingsContainer.FadeColour(Color4.White, 500, Easing.Out); } else if (failOnMissing) ratingsGraph.Values = new float[10]; else - ratingsContainer.FadeColour(Color4.Gray, 500, EasingTypes.Out); + ratingsContainer.FadeColour(Color4.Gray, 500, Easing.Out); if (hasRetriesFails) { @@ -139,7 +139,7 @@ namespace osu.Game.Screens.Select failGraph.Values = fails.Select(fail => (float)fail); retryGraph.Values = retries.Zip(fails, (retry, fail) => retry + MathHelper.Clamp(fail, 0, maxValue)); - retryFailContainer.FadeColour(Color4.White, 500, EasingTypes.Out); + retryFailContainer.FadeColour(Color4.White, 500, Easing.Out); } else if (failOnMissing) { @@ -147,7 +147,7 @@ namespace osu.Game.Screens.Select retryGraph.Values = new float[100]; } else - retryFailContainer.FadeColour(Color4.Gray, 500, EasingTypes.Out); + retryFailContainer.FadeColour(Color4.Gray, 500, Easing.Out); } public BeatmapDetails() @@ -169,7 +169,7 @@ namespace osu.Game.Screens.Select Width = 0.4f, Direction = FillDirection.Vertical, LayoutDuration = 200, - LayoutEasing = EasingTypes.OutQuint, + LayoutEasing = Easing.OutQuint, Children = new[] { description = new MetadataSegment("Description"), diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 8ba450720b..385492980f 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -14,7 +14,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.MathUtils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; @@ -57,14 +56,14 @@ namespace osu.Game.Screens.Select protected override void PopIn() { - MoveToX(0, 800, EasingTypes.OutQuint); - RotateTo(0, 800, EasingTypes.OutQuint); + this.MoveToX(0, 800, Easing.OutQuint); + this.RotateTo(0, 800, Easing.OutQuint); } protected override void PopOut() { - MoveToX(-100, 800, EasingTypes.InQuint); - RotateTo(10, 800, EasingTypes.InQuint); + this.MoveToX(-100, 800, Easing.InQuint); + this.RotateTo(10, 800, Easing.InQuint); } public void UpdateBeatmap(WorkingBeatmap beatmap) @@ -78,7 +77,7 @@ namespace osu.Game.Screens.Select Shear = -Shear, OnLoadComplete = d => { - FadeIn(250); + this.FadeIn(250); lastContainer?.FadeOut(250); lastContainer?.Expire(); @@ -140,7 +139,7 @@ namespace osu.Game.Screens.Select new Container { RelativeSizeAxes = Axes.Both, - ColourInfo = ColourInfo.GradientVertical(Color4.White, Color4.White.Opacity(0.3f)), + Colour = ColourInfo.GradientVertical(Color4.White, Color4.White.Opacity(0.3f)), Children = new[] { // Zoomed-in and cropped beatmap background diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 35fee9e32d..c406e7c44d 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -14,8 +14,8 @@ 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.Database; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets; namespace osu.Game.Screens.Select { diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 3634e739cf..a1fea4a41d 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.Database; +using osu.Game.Rulesets; using osu.Game.Screens.Select.Filter; namespace osu.Game.Screens.Select diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs index ddb808c5e4..bb6d16da0f 100644 --- a/osu.Game/Screens/Select/Footer.cs +++ b/osu.Game/Screens/Select/Footer.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using OpenTK; using OpenTK.Graphics; using OpenTK.Input; @@ -31,7 +32,7 @@ namespace osu.Game.Screens.Select public Action OnBack; public Action OnStart; - private readonly FillFlowContainer buttons; + private readonly FillFlowContainer buttons; public OsuLogo StartButton; @@ -43,29 +44,21 @@ namespace osu.Game.Screens.Select /// Higher depth to be put on the left, and lower to be put on the right. /// Notice this is different to ! /// - public void AddButton(string text, Color4 colour, Action action, Key? hotkey = null, float depth = 0) + public void AddButton(string text, Color4 colour, Action action, Key? hotkey = null, float depth = 0) => buttons.Add(new FooterButton { - var button = new FooterButton - { - Text = text, - Height = play_song_select_button_height, - Width = play_song_select_button_width, - Depth = depth, - SelectedColour = colour, - DeselectedColour = colour.Opacity(0.5f), - Hotkey = hotkey, - }; + Text = text, + Height = play_song_select_button_height, + Width = play_song_select_button_width, + Depth = depth, + SelectedColour = colour, + DeselectedColour = colour.Opacity(0.5f), + Hotkey = hotkey, + Hovered = updateModeLight, + HoverLost = updateModeLight, + Action = action, + }); - button.Hovered = () => updateModeLight(button); - button.HoverLost = () => updateModeLight(); - button.Action = action; - buttons.Add(button); - } - - private void updateModeLight(FooterButton button = null) - { - modeLight.FadeColour(button?.SelectedColour ?? Color4.Transparent, TRANSITION_LENGTH, EasingTypes.OutQuint); - } + private void updateModeLight() => modeLight.FadeColour(buttons.FirstOrDefault(b => b.IsHovered)?.SelectedColour ?? Color4.Transparent, TRANSITION_LENGTH, Easing.OutQuint); public Footer() { @@ -111,7 +104,7 @@ namespace osu.Game.Screens.Select Spacing = new Vector2(padding, 0), Children = new Drawable[] { - buttons = new FillFlowContainer + buttons = new FillFlowContainer { Direction = FillDirection.Horizontal, Spacing = new Vector2(0.2f, 0), diff --git a/osu.Game/Screens/Select/FooterButton.cs b/osu.Game/Screens/Select/FooterButton.cs index 536bf3971a..ae6c7d3c1e 100644 --- a/osu.Game/Screens/Select/FooterButton.cs +++ b/osu.Game/Screens/Select/FooterButton.cs @@ -89,27 +89,27 @@ namespace osu.Game.Screens.Select protected override bool OnHover(InputState state) { Hovered?.Invoke(); - light.ScaleTo(new Vector2(1, 2), Footer.TRANSITION_LENGTH, EasingTypes.OutQuint); - light.FadeColour(SelectedColour, Footer.TRANSITION_LENGTH, EasingTypes.OutQuint); + light.ScaleTo(new Vector2(1, 2), Footer.TRANSITION_LENGTH, Easing.OutQuint); + light.FadeColour(SelectedColour, Footer.TRANSITION_LENGTH, Easing.OutQuint); return true; } protected override void OnHoverLost(InputState state) { HoverLost?.Invoke(); - light.ScaleTo(new Vector2(1, 1), Footer.TRANSITION_LENGTH, EasingTypes.OutQuint); - light.FadeColour(DeselectedColour, Footer.TRANSITION_LENGTH, EasingTypes.OutQuint); + light.ScaleTo(new Vector2(1, 1), Footer.TRANSITION_LENGTH, Easing.OutQuint); + light.FadeColour(DeselectedColour, Footer.TRANSITION_LENGTH, Easing.OutQuint); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - box.FadeTo(0.3f, Footer.TRANSITION_LENGTH * 2, EasingTypes.OutQuint); + box.FadeTo(0.3f, Footer.TRANSITION_LENGTH * 2, Easing.OutQuint); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - box.FadeOut(Footer.TRANSITION_LENGTH, EasingTypes.OutQuint); + box.FadeOut(Footer.TRANSITION_LENGTH, Easing.OutQuint); return base.OnMouseUp(state, args); } @@ -117,7 +117,7 @@ namespace osu.Game.Screens.Select { box.ClearTransforms(); box.Alpha = 1; - box.FadeOut(Footer.TRANSITION_LENGTH * 3, EasingTypes.OutQuint); + box.FadeOut(Footer.TRANSITION_LENGTH * 3, Easing.OutQuint); return base.OnClick(state); } diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index 2a8e4ca5fb..5a375e55d4 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -11,7 +11,7 @@ using osu.Framework.Graphics.Containers; using System; using osu.Framework.Allocation; using osu.Framework.Threading; -using osu.Game.Database; +using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Scoring; @@ -63,8 +63,8 @@ namespace osu.Game.Screens.Select.Leaderboards }; scrollFlow.Add(ls); - ls.Delay(i++ * 50, true); - ls.Show(); + using (BeginDelayedSequence(i++ * 50, true)) + ls.Show(); } scrollContainer.ScrollTo(0f, false); @@ -163,7 +163,7 @@ namespace osu.Game.Screens.Select.Leaderboards c.Colour = Color4.Transparent; else { - c.ColourInfo = ColourInfo.GradientVertical( + c.Colour = ColourInfo.GradientVertical( Color4.White.Opacity(Math.Min(1 - (topY - fadeStart) / LeaderboardScore.HEIGHT, 1)), Color4.White.Opacity(Math.Min(1 - (bottomY - fadeStart) / LeaderboardScore.HEIGHT, 1))); } diff --git a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs index 48de4c2d3a..39c948f8d3 100644 --- a/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs @@ -61,26 +61,29 @@ namespace osu.Game.Screens.Select.Leaderboards nameLabel.MoveToX(150); break; case Visibility.Visible: - FadeIn(200); - content.MoveToY(0, 800, EasingTypes.OutQuint); + this.FadeIn(200); + content.MoveToY(0, 800, Easing.OutQuint); - Delay(100, true); - avatar.FadeIn(300, EasingTypes.OutQuint); - nameLabel.FadeIn(350, EasingTypes.OutQuint); - - avatar.MoveToX(0, 300, EasingTypes.OutQuint); - nameLabel.MoveToX(0, 350, EasingTypes.OutQuint); - - Delay(250, true); - scoreLabel.FadeIn(200); - scoreRank.FadeIn(200); - - Delay(50, true); - var drawables = new Drawable[] { flagBadgeContainer, maxCombo, accuracy, modsContainer, }; - - for (int i = 0; i < drawables.Length; i++) + using (BeginDelayedSequence(100, true)) { - drawables[i].FadeIn(100 + i * 50); + avatar.FadeIn(300, Easing.OutQuint); + nameLabel.FadeIn(350, Easing.OutQuint); + + avatar.MoveToX(0, 300, Easing.OutQuint); + nameLabel.MoveToX(0, 350, Easing.OutQuint); + + using (BeginDelayedSequence(250, true)) + { + scoreLabel.FadeIn(200); + scoreRank.FadeIn(200); + + using (BeginDelayedSequence(50, true)) + { + var drawables = new Drawable[] { flagBadgeContainer, maxCombo, accuracy, modsContainer, }; + for (int i = 0; i < drawables.Length; i++) + drawables[i].FadeIn(100 + i * 50); + } + } } break; @@ -188,7 +191,7 @@ namespace osu.Game.Screens.Select.Leaderboards Masking = true, Children = new Drawable[] { - new DrawableFlag(Score.User?.Country?.FlagName ?? "__") + new DrawableFlag(Score.User?.Country?.FlagName) { Width = 30, RelativeSizeAxes = Axes.Y, @@ -266,13 +269,13 @@ namespace osu.Game.Screens.Select.Leaderboards protected override bool OnHover(Framework.Input.InputState state) { - background.FadeTo(0.5f, 300, EasingTypes.OutQuint); + background.FadeTo(0.5f, 300, Easing.OutQuint); return base.OnHover(state); } protected override void OnHoverLost(Framework.Input.InputState state) { - background.FadeTo(background_alpha, 200, EasingTypes.OutQuint); + background.FadeTo(background_alpha, 200, Easing.OutQuint); base.OnHoverLost(state); } diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs index 58ce5ac564..ab02e8678f 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs @@ -54,13 +54,13 @@ namespace osu.Game.Screens.Select.Options protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) { - flash.FadeTo(0.1f, 1000, EasingTypes.OutQuint); + flash.FadeTo(0.1f, 1000, Easing.OutQuint); return base.OnMouseDown(state, args); } protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) { - flash.FadeTo(0, 1000, EasingTypes.OutQuint); + flash.FadeTo(0, 1000, Easing.OutQuint); return base.OnMouseUp(state, args); } @@ -68,7 +68,7 @@ namespace osu.Game.Screens.Select.Options { flash.ClearTransforms(); flash.Alpha = 0.9f; - flash.FadeOut(800, EasingTypes.OutExpo); + flash.FadeOut(800, Easing.OutExpo); return base.OnClick(state); } diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs index 6345807ea3..0a410f0e0f 100644 --- a/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs +++ b/osu.Game/Screens/Select/Options/BeatmapOptionsOverlay.cs @@ -29,27 +29,27 @@ namespace osu.Game.Screens.Select.Options { base.PopIn(); - FadeIn(transition_duration, EasingTypes.OutQuint); + this.FadeIn(transition_duration, Easing.OutQuint); if (buttonsContainer.Position.X == 1 || Alpha == 0) buttonsContainer.MoveToX(x_position - x_movement); - holder.ScaleTo(new Vector2(1, 1), transition_duration / 2, EasingTypes.OutQuint); + holder.ScaleTo(new Vector2(1, 1), transition_duration / 2, Easing.OutQuint); - buttonsContainer.MoveToX(x_position, transition_duration, EasingTypes.OutQuint); - buttonsContainer.TransformSpacingTo(Vector2.Zero, transition_duration, EasingTypes.OutQuint); + buttonsContainer.MoveToX(x_position, transition_duration, Easing.OutQuint); + buttonsContainer.TransformSpacingTo(Vector2.Zero, transition_duration, Easing.OutQuint); } protected override void PopOut() { base.PopOut(); - holder.ScaleTo(new Vector2(1, 0), transition_duration / 2, EasingTypes.InSine); + holder.ScaleTo(new Vector2(1, 0), transition_duration / 2, Easing.InSine); - buttonsContainer.MoveToX(x_position + x_movement, transition_duration, EasingTypes.InSine); - buttonsContainer.TransformSpacingTo(new Vector2(200f, 0f), transition_duration, EasingTypes.InSine); + buttonsContainer.MoveToX(x_position + x_movement, transition_duration, Easing.InSine); + buttonsContainer.TransformSpacingTo(new Vector2(200f, 0f), transition_duration, Easing.InSine); - FadeOut(transition_duration, EasingTypes.InQuint); + this.FadeOut(transition_duration, Easing.InQuint); } public BeatmapOptionsOverlay() diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 51f570e901..e393caf931 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -105,6 +105,7 @@ namespace osu.Game.Screens.Select if (player != null) return; Beatmap.Value.Track.Looping = false; + Beatmap.Disabled = true; LoadComponentAsync(player = new PlayerLoader(new Player()), l => Push(player)); } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index d28a84217b..217baccf58 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -16,10 +16,10 @@ using osu.Framework.Input; using osu.Framework.Screens; using osu.Framework.Threading; using osu.Game.Beatmaps; -using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Overlays; +using osu.Game.Rulesets; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Select.Options; @@ -28,11 +28,10 @@ namespace osu.Game.Screens.Select public abstract class SongSelect : OsuScreen { private readonly Bindable ruleset = new Bindable(); - private BeatmapDatabase database; + private BeatmapManager manager; protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(); private readonly BeatmapCarousel carousel; - private TrackManager trackManager; private DialogOverlay dialogOverlay; private static readonly Vector2 wedged_container_size = new Vector2(0.5f, 245); @@ -110,7 +109,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.CentreRight, SelectionChanged = carouselSelectionChanged, BeatmapsChanged = carouselBeatmapsLoaded, - StartRequested = carouselRaisedStart + StartRequested = carouselRaisedStart, }); Add(FilterControl = new FilterControl { @@ -130,6 +129,11 @@ namespace osu.Game.Screens.Select Right = left_area_padding, }, }); + Add(new ResetScrollContainer(() => carousel.ScrollToSelected()) + { + RelativeSizeAxes = Axes.Y, + Width = 250, + }); if (ShowFooter) { @@ -155,7 +159,7 @@ namespace osu.Game.Screens.Select } [BackgroundDependencyLoader(permitNulls: true)] - private void load(BeatmapDatabase beatmaps, AudioManager audio, DialogOverlay dialog, OsuGame osu, OsuColour colours, UserInputManager input) + private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuGame osu, OsuColour colours, UserInputManager input) { if (Footer != null) { @@ -165,16 +169,15 @@ namespace osu.Game.Screens.Select BeatmapOptions.AddButton(@"Delete", @"Beatmap", FontAwesome.fa_trash, colours.Pink, promptDelete, Key.Number4, float.MaxValue); } - if (database == null) - database = beatmaps; + if (manager == null) + manager = beatmaps; if (osu != null) ruleset.BindTo(osu.Ruleset); - database.BeatmapSetAdded += onBeatmapSetAdded; - database.BeatmapSetRemoved += onBeatmapSetRemoved; + manager.BeatmapSetAdded += onBeatmapSetAdded; + manager.BeatmapSetRemoved += onBeatmapSetRemoved; - trackManager = audio.Track; dialogOverlay = dialog; sampleChangeDifficulty = audio.Sample.Get(@"SongSelect/select-difficulty"); @@ -182,14 +185,17 @@ namespace osu.Game.Screens.Select initialAddSetsTask = new CancellationTokenSource(); - carousel.Beatmaps = database.GetAllWithChildren(b => !b.DeletePending); + carousel.Beatmaps = manager.GetAllUsableBeatmapSets(); Beatmap.ValueChanged += beatmap_ValueChanged; + + Beatmap.DisabledChanged += disabled => carousel.AllowSelection = !disabled; + carousel.AllowSelection = !Beatmap.Disabled; } private void carouselBeatmapsLoaded() { - if (Beatmap.Value != null && !Beatmap.Value.BeatmapSetInfo.DeletePending) + if (Beatmap.Value.BeatmapSetInfo?.DeletePending == false) carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo, false); else carousel.SelectNext(); @@ -197,13 +203,15 @@ namespace osu.Game.Screens.Select private void carouselRaisedStart() { - var pendingSelection = selectionChangedDebounce; - selectionChangedDebounce = null; + // if we have a pending filter operation, we want to run it now. + // it could change selection (ie. if the ruleset has been changed). + carousel.FlushPendingFilters(); - if (pendingSelection?.Completed == false) + if (selectionChangedDebounce?.Completed == false) { - pendingSelection.RunTask(); - pendingSelection.Cancel(); // cancel the already scheduled task. + selectionChangedDebounce.RunTask(); + selectionChangedDebounce.Cancel(); // cancel the already scheduled task. + selectionChangedDebounce = null; } OnSelected(); @@ -221,14 +229,26 @@ namespace osu.Game.Screens.Select { Action performLoad = delegate { - bool preview = beatmap?.BeatmapSetInfoID != Beatmap.Value.BeatmapInfo.BeatmapSetInfoID; + // We may be arriving here due to another component changing the bindable Beatmap. + // In these cases, the other component has already loaded the beatmap, so we don't need to do so again. + if (beatmap?.Equals(Beatmap.Value.BeatmapInfo) != true) + { + bool preview = beatmap?.BeatmapSetInfoID != Beatmap.Value.BeatmapInfo.BeatmapSetInfoID; - Beatmap.Value = database.GetWorkingBeatmap(beatmap, Beatmap); + Beatmap.Value = manager.GetWorkingBeatmap(beatmap, Beatmap); + ensurePlayingSelected(preview); + } - ensurePlayingSelected(preview); changeBackground(Beatmap.Value); }; + selectionChangedDebounce?.Cancel(); + + if (beatmap?.Equals(beatmapNoDebounce) == true) + return; + + beatmapNoDebounce = beatmap; + if (beatmap == null) { if (!Beatmap.IsDefault) @@ -236,18 +256,13 @@ namespace osu.Game.Screens.Select } else { - selectionChangedDebounce?.Cancel(); - - if (beatmap.Equals(beatmapNoDebounce)) - return; + ruleset.Value = beatmap.Ruleset; if (beatmap.BeatmapSetInfoID == beatmapNoDebounce?.BeatmapSetInfoID) sampleChangeDifficulty.Play(); else sampleChangeBeatmap.Play(); - beatmapNoDebounce = beatmap; - if (beatmap == Beatmap.Value.BeatmapInfo) performLoad(); else @@ -270,7 +285,7 @@ namespace osu.Game.Screens.Select carousel.Filter(criteria, debounce); } - private void onBeatmapSetAdded(BeatmapSetInfo s) => carousel.AddBeatmap(s); + private void onBeatmapSetAdded(BeatmapSetInfo s) => Schedule(() => addBeatmapSet(s)); private void onBeatmapSetRemoved(BeatmapSetInfo s) => Schedule(() => removeBeatmapSet(s)); @@ -302,14 +317,14 @@ namespace osu.Game.Screens.Select Content.FadeIn(250); - Content.ScaleTo(1, 250, EasingTypes.OutSine); + Content.ScaleTo(1, 250, Easing.OutSine); FilterControl.Activate(); } protected override void OnSuspending(Screen next) { - Content.ScaleTo(1.1f, 250, EasingTypes.InSine); + Content.ScaleTo(1.1f, 250, Easing.InSine); Content.FadeOut(250); @@ -331,10 +346,10 @@ namespace osu.Game.Screens.Select { base.Dispose(isDisposing); - if (database != null) + if (manager != null) { - database.BeatmapSetAdded -= onBeatmapSetAdded; - database.BeatmapSetRemoved -= onBeatmapSetRemoved; + manager.BeatmapSetAdded -= onBeatmapSetAdded; + manager.BeatmapSetRemoved -= onBeatmapSetRemoved; } initialAddSetsTask?.Cancel(); @@ -358,10 +373,16 @@ namespace osu.Game.Screens.Select { Track track = Beatmap.Value.Track; - trackManager.SetExclusive(track); + if (!track.IsRunning) + { + if (preview) track.Seek(Beatmap.Value.Metadata.PreviewTime); + track.Start(); + } + } - if (preview) track.Seek(Beatmap.Value.Metadata.PreviewTime); - track.Start(); + private void addBeatmapSet(BeatmapSetInfo beatmapSet) + { + carousel.AddBeatmap(beatmapSet); } private void removeBeatmapSet(BeatmapSetInfo beatmapSet) @@ -373,7 +394,7 @@ namespace osu.Game.Screens.Select private void promptDelete() { - if (Beatmap != null) + if (Beatmap != null && !Beatmap.IsDefault) dialogOverlay?.Push(new BeatmapDeleteDialog(Beatmap)); } @@ -398,5 +419,21 @@ namespace osu.Game.Screens.Select return base.OnKeyDown(state, args); } + + private class ResetScrollContainer : Container + { + private readonly Action onHoverAction; + + public ResetScrollContainer(Action onHoverAction) + { + this.onHoverAction = onHoverAction; + } + + protected override bool OnHover(InputState state) + { + onHoverAction?.Invoke(); + return base.OnHover(state); + } + } } } diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 246fa17e85..7cd81a924d 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -47,10 +47,13 @@ namespace osu.Game.Screens.Tournament public ITeamList TeamList; - protected override DependencyContainer CreateLocalDependencies(DependencyContainer parent) => new DependencyContainer(parent); + private DependencyContainer dependencies; + + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) => + dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); [BackgroundDependencyLoader] - private void load(TextureStore textures, Storage storage, DependencyContainer dependencies) + private void load(TextureStore textures, Storage storage) { this.storage = storage; diff --git a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs index 30f109e598..2eb0dacec3 100644 --- a/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs +++ b/osu.Game/Screens/Tournament/ScrollingTeamContainer.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Graphics.Transforms; using osu.Framework.Threading; using OpenTK; using OpenTK.Graphics; @@ -29,7 +28,11 @@ namespace osu.Game.Screens.Tournament private readonly Container tracker; +#pragma warning disable 649 + // set via reflection. private float speed; +#pragma warning restore 649 + private int expiredCount; private float offset; @@ -65,7 +68,7 @@ namespace osu.Game.Screens.Tournament Origin = Anchor.BottomCentre, Size = new Vector2(2, 55), - ColourInfo = ColourInfo.GradientVertical(Color4.Transparent, Color4.White) + Colour = ColourInfo.GradientVertical(Color4.Transparent, Color4.White) }, new Box { @@ -73,7 +76,7 @@ namespace osu.Game.Screens.Tournament Origin = Anchor.TopCentre, Size = new Vector2(2, 55), - ColourInfo = ColourInfo.GradientVertical(Color4.White, Color4.Transparent) + Colour = ColourInfo.GradientVertical(Color4.White, Color4.Transparent) } } } @@ -297,7 +300,8 @@ namespace osu.Game.Screens.Tournament } } - private void speedTo(float value, double duration = 0, EasingTypes easing = EasingTypes.None) => TransformTo(value, duration, easing, new TransformScrollSpeed()); + private void speedTo(float value, double duration = 0, Easing easing = Easing.None) => + this.TransformTo(nameof(speed), value, duration, easing); private enum ScrollState { @@ -308,12 +312,6 @@ namespace osu.Game.Screens.Tournament Scrolling } - public class TransformScrollSpeed : TransformFloat - { - public override void Apply(Drawable d) => ((ScrollingTeamContainer)d).speed = CurrentValue; - public override void ReadIntoStartValue(Drawable d) => StartValue = ((ScrollingTeamContainer)d).speed; - } - public class ScrollingTeam : Container { public const float WIDTH = 58; diff --git a/osu.Game/Users/Country.cs b/osu.Game/Users/Country.cs index ac95d22329..bf06d9f8bc 100644 --- a/osu.Game/Users/Country.cs +++ b/osu.Game/Users/Country.cs @@ -49,9 +49,9 @@ namespace osu.Game.Users sprite.Texture = textures.Get($@"Flags/{flagName}"); } - public DrawableFlag(string name = @"__") + public DrawableFlag(string name = null) { - flagName = name; + flagName = name ?? @"__"; Children = new Drawable[] { diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index 0780c2ffd0..cd9ca582fc 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -102,7 +102,7 @@ namespace osu.Game.Users Spacing = new Vector2(5f, 0f), Children = new Drawable[] { - new DrawableFlag(user.Country?.FlagName ?? @"__") + new DrawableFlag(user.Country?.FlagName) { Width = 30f, RelativeSizeAxes = Axes.Y, @@ -169,7 +169,7 @@ namespace osu.Game.Users private void load(OsuColour colours, UserProfileOverlay profile) { Status.ValueChanged += displayStatus; - Status.ValueChanged += status => statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, EasingTypes.OutQuint); + Status.ValueChanged += status => statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint); base.Action = () => { @@ -190,15 +190,15 @@ namespace osu.Game.Users if (status == null) { - statusBar.ResizeHeightTo(0f, transition_duration, EasingTypes.OutQuint); - statusBar.FadeOut(transition_duration, EasingTypes.OutQuint); - ResizeHeightTo(height - status_height, transition_duration, EasingTypes.OutQuint); + statusBar.ResizeHeightTo(0f, transition_duration, Easing.OutQuint); + statusBar.FadeOut(transition_duration, Easing.OutQuint); + this.ResizeHeightTo(height - status_height, transition_duration, Easing.OutQuint); } else { - statusBar.ResizeHeightTo(status_height, transition_duration, EasingTypes.OutQuint); - statusBar.FadeIn(transition_duration, EasingTypes.OutQuint); - ResizeHeightTo(height, transition_duration, EasingTypes.OutQuint); + statusBar.ResizeHeightTo(status_height, transition_duration, Easing.OutQuint); + statusBar.FadeIn(transition_duration, Easing.OutQuint); + this.ResizeHeightTo(height, transition_duration, Easing.OutQuint); statusMessage.Text = status.Message; } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 95b339afb5..8b462b5287 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -74,9 +74,13 @@ + + + + @@ -88,6 +92,8 @@ + + @@ -98,6 +104,7 @@ + @@ -125,16 +132,15 @@ - - - - + + + + - @@ -216,7 +222,7 @@ - + @@ -245,7 +251,7 @@ - + @@ -385,17 +391,16 @@ - + - - - - - + + + + @@ -489,10 +494,10 @@ - + - - + + diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index f6a6e4bf9b..e3eae96ca8 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -189,7 +189,9 @@ IP IPC LTRB + MD5 RNG + SHA SRGB TK SS