diff --git a/README.md b/README.md index ad56178132..856536d22d 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ This is still heavily under development and is not intended for end-user use. Th We welcome all contributions, but keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention on having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time, to ensure no effort is wasted. -Contributions can be made via pull requests to this repository. We hope to credit and reward larger contributions via a [bounty system](https://www.bountysource.com/teams/ppy). If you're unsure of what you can help with, check out the [list of open issues](https://github.com/ppy/osu-framework/issues). +Please make sure you are familiar with the [development and testing](https://github.com/ppy/osu-framework/wiki/Development-and-Testing) procedure we have set up. New component development, and where possible, bug fixing and debugging existing components **should always be done under VisualTests**. + +Contributions can be made via pull requests to this repository. We hope to credit and reward larger contributions via a [bounty system](https://www.bountysource.com/teams/ppy). If you're unsure of what you can help with, check out the [list of open issues](https://github.com/ppy/osu/issues). Note that while we already have certain standards in place, nothing is set in stone. If you have an issue with the way code is structured; with any libraries we are using; with any processes involved with contributing, *please* bring it up. I welcome all feedback so we can make contributing to this project as pain-free as possible. diff --git a/osu-framework b/osu-framework index 83925a8407..c6fd291492 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 83925a84072ec9da0d008c82256294b765321c0b +Subproject commit c6fd2914926f2a6df23eda536c0310f072581b1b diff --git a/osu.Game.Tests/Visual/TestCasePlaybackControl.cs b/osu.Game.Tests/Visual/TestCasePlaybackControl.cs new file mode 100644 index 0000000000..ff59bb7bfd --- /dev/null +++ b/osu.Game.Tests/Visual/TestCasePlaybackControl.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.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Screens.Edit.Components; +using osu.Game.Tests.Beatmaps; +using OpenTK; + +namespace osu.Game.Tests.Visual +{ + public class TestCasePlaybackControl : OsuTestCase + { + public TestCasePlaybackControl() + { + var playback = new PlaybackControl + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(200,100) + }; + playback.Beatmap.Value = new TestWorkingBeatmap(new Beatmap()); + + Add(playback); + } + } +} diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 974bde9319..9bba09b1a7 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -124,6 +124,7 @@ + diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 006269f186..0641cabcd8 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -18,6 +18,7 @@ using osu.Framework.Platform; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.IO; using osu.Game.Database; +using osu.Game.Graphics; using osu.Game.IO; using osu.Game.IPC; using osu.Game.Online.API; @@ -52,6 +53,11 @@ namespace osu.Game.Beatmaps /// public event Action BeatmapRestored; + /// + /// Fired when a beatmap download begins. + /// + public event Action BeatmapDownloadBegan; + /// /// A default representation of a WorkingBeatmap to use when no beatmap is available. /// @@ -165,7 +171,7 @@ namespace osu.Game.Beatmaps catch (Exception e) { e = e.InnerException ?? e; - Logger.Error(e, @"Could not import beatmap set"); + Logger.Error(e, $@"Could not import beatmap set ({Path.GetFileName(path)})"); } } @@ -221,21 +227,29 @@ namespace osu.Game.Beatmaps /// Downloads a beatmap. /// /// The to be downloaded. - /// A new , or an existing one if a download is already in progress. - public DownloadBeatmapSetRequest Download(BeatmapSetInfo beatmapSetInfo) + /// Whether the beatmap should be downloaded without video. Defaults to false. + public void Download(BeatmapSetInfo beatmapSetInfo, bool noVideo = false) { var existing = GetExistingDownload(beatmapSetInfo); - if (existing != null) return existing; + if (existing != null || api == null) return; - if (api == null) return null; + if (!api.LocalUser.Value.IsSupporter) + { + PostNotification?.Invoke(new SimpleNotification + { + Icon = FontAwesome.fa_superpowers, + Text = "You gotta be a supporter to download for now 'yo" + }); + return; + } ProgressNotification downloadNotification = new ProgressNotification { Text = $"Downloading {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}", }; - var request = new DownloadBeatmapSetRequest(beatmapSetInfo); + var request = new DownloadBeatmapSetRequest(beatmapSetInfo, noVideo); request.DownloadProgressed += progress => { @@ -280,8 +294,7 @@ namespace osu.Game.Beatmaps // don't run in the main api queue as this is a long-running task. Task.Factory.StartNew(() => request.Perform(api), TaskCreationOptions.LongRunning); - - return request; + BeatmapDownloadBegan?.Invoke(request); } /// diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs index 5b84fa7c6e..85daefea57 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; -using osu.Framework.Graphics.Sprites; using osu.Framework.Localisation; using osu.Game.Graphics.Sprites; using osu.Framework.Graphics.Shapes; @@ -28,10 +27,8 @@ namespace osu.Game.Beatmaps.Drawables public Action RestoreHiddenRequested; - private readonly SpriteText title; - private readonly SpriteText artist; - private readonly WorkingBeatmap beatmap; + private readonly FillFlowContainer difficultyIcons; public BeatmapSetHeader(WorkingBeatmap beatmap) @@ -41,6 +38,25 @@ namespace osu.Game.Beatmaps.Drawables this.beatmap = beatmap; + difficultyIcons = new FillFlowContainer + { + Margin = new MarginPadding { Top = 5 }, + AutoSizeAxes = Axes.Both, + }; + } + + protected override void Selected() + { + base.Selected(); + GainedSelection?.Invoke(this); + } + + [BackgroundDependencyLoader] + private void load(LocalisationEngine localisation) + { + if (localisation == null) + throw new ArgumentNullException(nameof(localisation)); + Children = new Drawable[] { new DelayedLoadWrapper( @@ -56,44 +72,26 @@ namespace osu.Game.Beatmaps.Drawables AutoSizeAxes = Axes.Both, Children = new Drawable[] { - title = new OsuSpriteText + new OsuSpriteText { Font = @"Exo2.0-BoldItalic", + Current = localisation.GetUnicodePreference(beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title), TextSize = 22, Shadow = true, }, - artist = new OsuSpriteText + new OsuSpriteText { Font = @"Exo2.0-SemiBoldItalic", + Current = localisation.GetUnicodePreference(beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist), TextSize = 17, Shadow = true, }, - difficultyIcons = new FillFlowContainer - { - Margin = new MarginPadding { Top = 5 }, - AutoSizeAxes = Axes.Both, - } + difficultyIcons } } }; } - protected override void Selected() - { - base.Selected(); - GainedSelection?.Invoke(this); - } - - [BackgroundDependencyLoader] - private void load(LocalisationEngine localisation) - { - if (localisation == null) - throw new ArgumentNullException(nameof(localisation)); - - title.Current = localisation.GetUnicodePreference(beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title); - artist.Current = localisation.GetUnicodePreference(beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist); - } - private class PanelBackground : BufferedContainer { public PanelBackground(WorkingBeatmap working) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 1d4ed75688..2a8178882e 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -8,6 +8,7 @@ using osu.Game.Rulesets.Mods; using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace osu.Game.Beatmaps { @@ -29,10 +30,10 @@ namespace osu.Game.Beatmaps Mods.ValueChanged += mods => applyRateAdjustments(); - beatmap = new Lazy(populateBeatmap); - background = new Lazy(populateBackground); - track = new Lazy(populateTrack); - waveform = new Lazy(populateWaveform); + beatmap = new AsyncLazy(populateBeatmap); + background = new AsyncLazy(populateBackground); + track = new AsyncLazy(populateTrack); + waveform = new AsyncLazy(populateWaveform); } protected abstract Beatmap GetBeatmap(); @@ -41,8 +42,10 @@ namespace osu.Game.Beatmaps protected virtual Waveform GetWaveform() => new Waveform(); public bool BeatmapLoaded => beatmap.IsValueCreated; - public Beatmap Beatmap => beatmap.Value; - private readonly Lazy beatmap; + public Beatmap Beatmap => beatmap.Value.Result; + public async Task GetBeatmapAsync() => await beatmap.Value; + + private readonly AsyncLazy beatmap; private Beatmap populateBeatmap() { @@ -55,14 +58,16 @@ namespace osu.Game.Beatmaps } public bool BackgroundLoaded => background.IsValueCreated; - public Texture Background => background.Value; - private Lazy background; + public Texture Background => background.Value.Result; + public async Task GetBackgroundAsync() => await background.Value; + private AsyncLazy background; private Texture populateBackground() => GetBackground(); public bool TrackLoaded => track.IsValueCreated; - public Track Track => track.Value; - private Lazy track; + public Track Track => track.Value.Result; + public async Task GetTrackAsync() => await track.Value; + private AsyncLazy track; private Track populateTrack() { @@ -73,8 +78,9 @@ namespace osu.Game.Beatmaps } public bool WaveformLoaded => waveform.IsValueCreated; - public Waveform Waveform => waveform.Value; - private readonly Lazy waveform; + public Waveform Waveform => waveform.Value.Result; + public async Task GetWaveformAsync() => await waveform.Value; + private readonly AsyncLazy waveform; private Waveform populateWaveform() => GetWaveform(); @@ -107,5 +113,13 @@ namespace osu.Game.Beatmaps foreach (var mod in Mods.Value.OfType()) mod.ApplyToClock(t); } + + public class AsyncLazy : Lazy> + { + public AsyncLazy(Func valueFactory) + : base(() => Task.Run(valueFactory)) + { + } + } } } diff --git a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs index 5a9f609bca..cdcc06a65c 100644 --- a/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs +++ b/osu.Game/Online/API/Requests/DownloadBeatmapSetRequest.cs @@ -12,13 +12,16 @@ namespace osu.Game.Online.API.Requests public Action DownloadProgressed; - public DownloadBeatmapSetRequest(BeatmapSetInfo set) + private readonly bool noVideo; + + public DownloadBeatmapSetRequest(BeatmapSetInfo set, bool noVideo) { + this.noVideo = noVideo; BeatmapSet = set; Progress += (current, total) => DownloadProgressed?.Invoke((float) current / total); } - protected override string Target => $@"beatmapsets/{BeatmapSet.OnlineBeatmapSetID}/download"; + protected override string Target => $@"beatmapsets/{BeatmapSet.OnlineBeatmapSetID}/download{(noVideo ? "?noVideo=1" : "")}"; } } diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 195ff63ca5..fbe4585d5f 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -29,8 +29,11 @@ namespace osu.Game.Overlays.BeatmapSet private readonly Container noVideoButtons; private readonly FillFlowContainer videoButtons; private readonly AuthorInfo author; + private readonly Container downloadButtonsContainer; public Details Details; + private BeatmapManager beatmaps; + private DelayedLoadWrapper cover; public readonly BeatmapPicker Picker; @@ -48,6 +51,7 @@ namespace osu.Game.Overlays.BeatmapSet title.Text = BeatmapSet.Metadata.Title; artist.Text = BeatmapSet.Metadata.Artist; + downloadButtonsContainer.FadeIn(); noVideoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 0 : 1, transition_duration); videoButtons.FadeTo(BeatmapSet.OnlineInfo.HasVideo ? 1 : 0, transition_duration); @@ -161,7 +165,7 @@ namespace osu.Game.Overlays.BeatmapSet Children = new Drawable[] { new FavouriteButton(), - new Container + downloadButtonsContainer = new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = buttons_height + buttons_spacing }, @@ -171,7 +175,10 @@ namespace osu.Game.Overlays.BeatmapSet { RelativeSizeAxes = Axes.Both, Alpha = 0f, - Child = new DownloadButton("Download", @""), + Child = new DownloadButton("Download", @"") + { + Action = () => download(false), + }, }, videoButtons = new FillFlowContainer { @@ -180,8 +187,14 @@ namespace osu.Game.Overlays.BeatmapSet Alpha = 0f, Children = new[] { - new DownloadButton("Download", "with Video"), - new DownloadButton("Download", "without Video"), + new DownloadButton("Download", "with Video") + { + Action = () => download(false), + }, + new DownloadButton("Download", "without Video") + { + Action = () => download(true), + }, }, }, }, @@ -205,9 +218,39 @@ namespace osu.Game.Overlays.BeatmapSet } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, BeatmapManager beatmaps) { tabsBg.Colour = colours.Gray3; + this.beatmaps = beatmaps; + + beatmaps.BeatmapSetAdded += handleBeatmapAdd; + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + beatmaps.BeatmapSetAdded -= handleBeatmapAdd; + } + + private void handleBeatmapAdd(BeatmapSetInfo beatmap) + { + if (beatmap.OnlineBeatmapSetID == BeatmapSet.OnlineBeatmapSetID) + downloadButtonsContainer.FadeOut(transition_duration); + } + + private void download(bool noVideo) + { + if (beatmaps.GetExistingDownload(BeatmapSet) != null) + { + downloadButtonsContainer.MoveToX(-5, 50, Easing.OutSine).Then() + .MoveToX(5, 100, Easing.InOutSine).Then() + .MoveToX(-5, 100, Easing.InOutSine).Then() + .MoveToX(0, 50, Easing.InSine).Then(); + + return; + } + + beatmaps.Download(BeatmapSet, noVideo); } } } diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 2e842af614..a55de951f1 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -16,9 +16,7 @@ using osu.Game.Graphics.Sprites; using OpenTK.Graphics; using osu.Framework.Input; using osu.Game.Graphics.UserInterface; -using osu.Game.Online.API; using osu.Framework.Logging; -using osu.Game.Overlays.Notifications; using osu.Game.Online.API.Requests; using osu.Framework.Configuration; using osu.Framework.Audio.Track; @@ -35,10 +33,8 @@ namespace osu.Game.Overlays.Direct private Container content; - private APIAccess api; private ProgressBar progressBar; private BeatmapManager beatmaps; - private NotificationOverlay notifications; private BeatmapSetOverlay beatmapSetOverlay; public Track Preview => PlayButton.Preview; @@ -71,11 +67,9 @@ namespace osu.Game.Overlays.Direct [BackgroundDependencyLoader(permitNulls: true)] - private void load(APIAccess api, BeatmapManager beatmaps, OsuColour colours, NotificationOverlay notifications, BeatmapSetOverlay beatmapSetOverlay) + private void load(BeatmapManager beatmaps, OsuColour colours, BeatmapSetOverlay beatmapSetOverlay) { - this.api = api; this.beatmaps = beatmaps; - this.notifications = notifications; this.beatmapSetOverlay = beatmapSetOverlay; AddInternal(content = new Container @@ -109,6 +103,14 @@ namespace osu.Game.Overlays.Direct if (downloadRequest != null) attachDownload(downloadRequest); + + beatmaps.BeatmapDownloadBegan += attachDownload; + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + beatmaps.BeatmapDownloadBegan -= attachDownload; } protected override void Update() @@ -151,16 +153,6 @@ namespace osu.Game.Overlays.Direct protected void StartDownload() { - if (!api.LocalUser.Value.IsSupporter) - { - notifications.Post(new SimpleNotification - { - Icon = FontAwesome.fa_superpowers, - Text = "You gotta be a supporter to download for now 'yo" - }); - return; - } - if (beatmaps.GetExistingDownload(SetInfo) != null) { // we already have an active download running. @@ -172,13 +164,14 @@ namespace osu.Game.Overlays.Direct return; } - var request = beatmaps.Download(SetInfo); - - attachDownload(request); + beatmaps.Download(SetInfo); } private void attachDownload(DownloadBeatmapSetRequest request) { + if (request.BeatmapSet.OnlineBeatmapSetID != SetInfo.OnlineBeatmapSetID) + return; + progressBar.FadeIn(400, Easing.OutQuint); progressBar.ResizeHeightTo(4, 400, Easing.OutQuint); diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs new file mode 100644 index 0000000000..8a835634b8 --- /dev/null +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs @@ -0,0 +1,134 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Configuration; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Input; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Users; + +namespace osu.Game.Overlays.Profile.Sections.Kudosu +{ + public class KudosuInfo : Container + { + private readonly Bindable user = new Bindable(); + + public KudosuInfo(Bindable user) + { + this.user.BindTo(user); + + CountSection total; + CountSection avaliable; + + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Masking = true; + CornerRadius = 3; + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0f, 1f), + Radius = 3f, + Colour = Color4.Black.Opacity(0.2f), + }; + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.Gray(0.2f) + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new[] + { + total = new CountSection( + "Total Kudosu Earned", + "Based on how much of a contribution the user has made to beatmap moderation. See this link for more information." + ), + avaliable = new CountSection( + "Kudosu Avaliable", + "Kudosu can be traded for kudosu stars, which will help your beatmap get more attention. This is the number of kudosu you haven't traded in yet." + ), + } + } + }; + + this.user.ValueChanged += newUser => + { + total.Count = newUser?.Kudosu.Total ?? 0; + avaliable.Count = newUser?.Kudosu.Available ?? 0; + }; + } + + protected override bool OnClick(InputState state) => true; + + private class CountSection : Container + { + private readonly OsuSpriteText valueText; + + public int Count + { + set { valueText.Text = value.ToString(); } + } + + public CountSection(string header, string description) + { + RelativeSizeAxes = Axes.X; + Width = 0.5f; + AutoSizeAxes = Axes.Y; + Padding = new MarginPadding { Horizontal = 10, Top = 10, Bottom = 20 }; + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 5), + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Text = header + ":", + TextSize = 20, + Font = @"Exo2.0-RegularItalic", + }, + valueText = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Text = "0", + TextSize = 40, + UseFullGlyphHeight = false, + Font = @"Exo2.0-RegularItalic" + } + } + }, + new TextFlowContainer(t => { t.TextSize = 19; }) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Text = description + } + } + }; + } + } + } +} diff --git a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs index 3c36368fd7..907c26e5e8 100644 --- a/osu.Game/Overlays/Profile/Sections/KudosuSection.cs +++ b/osu.Game/Overlays/Profile/Sections/KudosuSection.cs @@ -1,6 +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.Overlays.Profile.Sections.Kudosu; + namespace osu.Game.Overlays.Profile.Sections { public class KudosuSection : ProfileSection @@ -8,5 +10,13 @@ namespace osu.Game.Overlays.Profile.Sections public override string Title => "Kudosu!"; public override string Identifier => "kudosu"; + + public KudosuSection() + { + Children = new[] + { + new KudosuInfo(User), + }; + } } } diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index dd31a43290..7374a9aa44 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -97,7 +97,7 @@ namespace osu.Game.Overlays //new MedalsSection(), new HistoricalSection(), new BeatmapsSection(), - //new KudosuSection() + new KudosuSection() }; tabs = new ProfileTabControl { diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 7b26e50dd8..e129a81116 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -224,8 +224,8 @@ namespace osu.Game.Rulesets.Scoring OnNewJudgement(judgement); updateScore(); - NotifyNewJudgement(judgement); UpdateFailed(); + NotifyNewJudgement(judgement); } protected void RemoveJudgement(Judgement judgement) diff --git a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs index d65355b5f4..0e57407928 100644 --- a/osu.Game/Screens/Edit/Components/BottomBarContainer.cs +++ b/osu.Game/Screens/Edit/Components/BottomBarContainer.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Edit.Components private const float corner_radius = 5; private const float contents_padding = 15; - public Bindable Beatmap = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); protected Track Track => Beatmap.Value.Track; private readonly Drawable background; diff --git a/osu.Game/Screens/Edit/Components/PlaybackContainer.cs b/osu.Game/Screens/Edit/Components/PlaybackControl.cs similarity index 70% rename from osu.Game/Screens/Edit/Components/PlaybackContainer.cs rename to osu.Game/Screens/Edit/Components/PlaybackControl.cs index a7d1db4802..5ffa66c43e 100644 --- a/osu.Game/Screens/Edit/Components/PlaybackContainer.cs +++ b/osu.Game/Screens/Edit/Components/PlaybackControl.cs @@ -2,7 +2,9 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; +using OpenTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; @@ -13,11 +15,11 @@ using osu.Game.Graphics.UserInterface; namespace osu.Game.Screens.Edit.Components { - public class PlaybackContainer : BottomBarContainer + public class PlaybackControl : BottomBarContainer { private readonly IconButton playButton; - public PlaybackContainer() + public PlaybackControl() { PlaybackTabControl tabs; @@ -30,7 +32,7 @@ namespace osu.Game.Screens.Edit.Components Scale = new Vector2(1.4f), IconScale = new Vector2(1.4f), Icon = FontAwesome.fa_play_circle_o, - Action = playPause, + Action = togglePause, Padding = new MarginPadding { Left = 20 } }, new OsuSpriteText @@ -52,14 +54,10 @@ namespace osu.Game.Screens.Edit.Components } }; - tabs.AddItem(0.25); - tabs.AddItem(0.75); - tabs.AddItem(1); - tabs.Current.ValueChanged += newValue => Track.Tempo.Value = newValue; } - private void playPause() + private void togglePause() { if (Track.IsRunning) Track.Stop(); @@ -76,6 +74,8 @@ namespace osu.Game.Screens.Edit.Components private class PlaybackTabControl : OsuTabControl { + private static readonly double[] tempo_values = { 0.5, 0.75, 1 }; + protected override TabItem CreateTabItem(double value) => new PlaybackTabItem(value); protected override Dropdown CreateDropdown() => null; @@ -83,20 +83,23 @@ namespace osu.Game.Screens.Edit.Components public PlaybackTabControl() { RelativeSizeAxes = Axes.Both; - TabContainer.Spacing = new Vector2(20, 0); + TabContainer.Spacing = Vector2.Zero; + + tempo_values.ForEach(AddItem); } public class PlaybackTabItem : TabItem { - private const float fade_duration = 100; + private const float fade_duration = 200; private readonly OsuSpriteText text; private readonly OsuSpriteText textBold; public PlaybackTabItem(double value) : base(value) { - AutoSizeAxes = Axes.X; - RelativeSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.Both; + + Width = 1f / tempo_values.Length; Children = new Drawable[] { @@ -104,56 +107,47 @@ namespace osu.Game.Screens.Edit.Components { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - Text = $"{value:P0}", + Text = $"{value:0%}", TextSize = 14, }, textBold = new OsuSpriteText { Origin = Anchor.TopCentre, Anchor = Anchor.TopCentre, - Text = $"{value:P0}", + Text = $"{value:0%}", TextSize = 14, Font = @"Exo2.0-Bold", Alpha = 0, - AlwaysPresent = true, }, }; } + private Color4 hoveredColour; + private Color4 normalColour; + [BackgroundDependencyLoader] private void load(OsuColour colours) { - text.Colour = colours.Gray5; + text.Colour = normalColour = colours.YellowDarker; + textBold.Colour = hoveredColour = colours.Yellow; } protected override bool OnHover(InputState state) { - if (!Active) - toBold(); + updateState(); return true; } - protected override void OnHoverLost(InputState state) + protected override void OnHoverLost(InputState state) => updateState(); + protected override void OnActivated() => updateState(); + protected override void OnDeactivated() => updateState(); + + private void updateState() { - if (!Active) - toNormal(); + text.FadeColour(Active || IsHovered ? hoveredColour : normalColour, fade_duration, Easing.OutQuint); + text.FadeTo(Active ? 0 : 1, fade_duration, Easing.OutQuint); + textBold.FadeTo(Active ? 1 : 0, fade_duration, Easing.OutQuint); } - - private void toBold() - { - text.FadeOut(fade_duration); - textBold.FadeIn(fade_duration); - } - - private void toNormal() - { - text.FadeIn(fade_duration); - textBold.FadeOut(fade_duration); - } - - protected override void OnActivated() => toBold(); - - protected override void OnDeactivated() => toNormal(); } } } diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index e2971deb75..607ff792d8 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Edit EditorMenuBar menuBar; TimeInfoContainer timeInfo; SummaryTimeline timeline; - PlaybackContainer playback; + PlaybackControl playback; Children = new[] { @@ -114,7 +114,7 @@ namespace osu.Game.Screens.Edit { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Left = 10 }, - Child = playback = new PlaybackContainer { RelativeSizeAxes = Axes.Both }, + Child = playback = new PlaybackControl { RelativeSizeAxes = Axes.Both }, } }, } diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 452f8c484c..b0a636dfb3 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -572,7 +572,18 @@ namespace osu.Game.Screens.Select // Makes sure headers are always _below_ panels, // and depth flows downward. panel.Depth = i + (panel is BeatmapSetHeader ? panels.Count : 0); - scrollableContent.Add(panel); + + switch (panel.LoadState) + { + case LoadState.NotLoaded: + LoadComponentAsync(panel); + break; + case LoadState.Loading: + break; + default: + scrollableContent.Add(panel); + break; + } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 048735358e..87c8275512 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -292,6 +292,7 @@ + @@ -299,7 +300,7 @@ - +