diff --git a/osu-framework b/osu-framework index 500a791577..e8ae207769 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 500a791577979669e47eece699d5bd8b9068ee4b +Subproject commit e8ae207769ec26fb7ddd67a2433514fcda354ecd diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index beabeb0a19..4aeb76121a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods @@ -25,7 +26,10 @@ namespace osu.Game.Rulesets.Osu.Mods foreach (var d in drawables.OfType()) { d.ApplyCustomUpdateState += ApplyHiddenState; + d.HitObject.TimeFadein = d.HitObject.TimePreempt * fade_in_duration_multiplier; + foreach (var h in d.HitObject.NestedHitObjects.OfType()) + h.TimeFadein = h.TimePreempt * fade_in_duration_multiplier; } } @@ -34,17 +38,20 @@ namespace osu.Game.Rulesets.Osu.Mods if (!(drawable is DrawableOsuHitObject d)) return; - var fadeOutStartTime = d.HitObject.StartTime - d.HitObject.TimePreempt + d.HitObject.TimeFadein; - var fadeOutDuration = d.HitObject.TimePreempt * fade_out_duration_multiplier; + var h = d.HitObject; + + var fadeOutStartTime = h.StartTime - h.TimePreempt + h.TimeFadein; + var fadeOutDuration = h.TimePreempt * fade_out_duration_multiplier; // new duration from completed fade in to end (before fading out) - var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime; + var longFadeDuration = ((h as IHasEndTime)?.EndTime ?? h.StartTime) - fadeOutStartTime; switch (drawable) { case DrawableHitCircle circle: // we don't want to see the approach circle - circle.ApproachCircle.Hide(); + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + circle.ApproachCircle.Hide(); // fade out immediately after fade in. using (drawable.BeginAbsoluteSequence(fadeOutStartTime, true)) diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs index 901d24e531..e50dc4b8fc 100644 --- a/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/TestCaseBeatmapCarousel.cs @@ -207,6 +207,12 @@ namespace osu.Game.Tests.Visual checkVisibleItemCount(true, 0); AddAssert("Selection is null", () => currentSelection == null); + advanceSelection(true); + AddAssert("Selection is null", () => currentSelection == null); + + advanceSelection(false); + AddAssert("Selection is null", () => currentSelection == null); + AddStep("Un-filter", () => carousel.Filter(new FilterCriteria(), false)); AddAssert("Selection is non-null", () => currentSelection != null); diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs index 8ab264da8e..f4400b7df2 100644 --- a/osu.Game/Graphics/Containers/ParallaxContainer.cs +++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs @@ -14,7 +14,9 @@ namespace osu.Game.Graphics.Containers { public class ParallaxContainer : Container, IRequireHighFrequencyMousePosition { - public float ParallaxAmount = 0.02f; + public const float DEFAULT_PARALLAX_AMOUNT = 0.02f; + + public float ParallaxAmount = DEFAULT_PARALLAX_AMOUNT; private Bindable parallaxEnabled; diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index d7268fb186..d0a507be98 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -65,6 +65,14 @@ namespace osu.Game.Overlays.Mods Ruleset.TriggerChange(); } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + Ruleset.UnbindAll(); + SelectedMods.UnbindAll(); + } + private void selectedModsChanged(IEnumerable obj) { foreach (ModSection section in ModSectionsContainer.Children) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index a2d41dc206..8f4e08d4a2 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -52,6 +52,10 @@ namespace osu.Game.Screens protected readonly Bindable Beatmap = new Bindable(); + protected virtual float BackgroundParallaxAmount => 1; + + private ParallaxContainer backgroundParallaxContainer; + public WorkingBeatmap InitialBeatmap { set @@ -102,11 +106,10 @@ namespace osu.Game.Screens protected override void OnResuming(Screen last) { - base.OnResuming(last); - logo.AppendAnimatingAction(() => LogoArriving(logo, true), true); sampleExit?.Play(); + applyArrivingDefaults(true); - ShowOverlays.Value = ShowOverlaysOnEnter; + base.OnResuming(last); } protected override void OnSuspending(Screen next) @@ -123,6 +126,8 @@ namespace osu.Game.Screens if (lastOsu?.Background != null) { + backgroundParallaxContainer = lastOsu.backgroundParallaxContainer; + if (bg == null || lastOsu.Background.Equals(bg)) //we can keep the previous mode's background. Background = lastOsu.Background; @@ -136,7 +141,7 @@ namespace osu.Game.Screens // this makes up for the fact our padding changes when the global toolbar is visible. bg.Scale = new Vector2(1.06f); - AddInternal(new ParallaxContainer + AddInternal(backgroundParallaxContainer = new ParallaxContainer { Depth = float.MaxValue, Children = new[] @@ -149,11 +154,9 @@ namespace osu.Game.Screens if ((logo = lastOsu?.logo) == null) LoadComponentAsync(logo = new OsuLogo { Alpha = 0 }, AddInternal); - logo.AppendAnimatingAction(() => LogoArriving(logo, false), true); + applyArrivingDefaults(false); base.OnEntering(last); - - ShowOverlays.Value = ShowOverlaysOnEnter; } protected override bool OnExiting(Screen next) @@ -193,6 +196,16 @@ namespace osu.Game.Screens logo.Ripple = true; } + private void applyArrivingDefaults(bool isResuming) + { + logo.AppendAnimatingAction(() => LogoArriving(logo, isResuming), true); + + if (backgroundParallaxContainer != null) + backgroundParallaxContainer.ParallaxAmount = ParallaxContainer.DEFAULT_PARALLAX_AMOUNT * BackgroundParallaxAmount; + + ShowOverlays.Value = ShowOverlaysOnEnter; + } + private void onExitingLogo() { logo.AppendAnimatingAction(() => { LogoExiting(logo); }, false); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 4954618ef9..7a0c723ab5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -37,6 +37,8 @@ namespace osu.Game.Screens.Play { protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); + protected override float BackgroundParallaxAmount => 0.1f; + public override bool ShowOverlaysOnEnter => false; public Action RestartRequested; @@ -351,7 +353,7 @@ namespace osu.Game.Screens.Play protected override bool OnExiting(Screen next) { - if ((!AllowPause || HasFailed || !ValidForResume || pauseContainer?.IsPaused != false || RulesetContainer?.HasReplayLoaded != false) && (!pauseContainer?.IsResuming ?? false)) + if ((!AllowPause || HasFailed || !ValidForResume || pauseContainer?.IsPaused != false || RulesetContainer?.HasReplayLoaded != false) && (!pauseContainer?.IsResuming ?? true)) { // In the case of replays, we may have changed the playback rate. applyRateFromMods(); diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 6da6fe6b1e..9793440348 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -192,7 +192,9 @@ namespace osu.Game.Screens.Select /// Whether to skip individual difficulties and only increment over full groups. public void SelectNext(int direction = 1, bool skipDifficulties = true) { - if (!Items.Any()) + var visibleItems = Items.Where(s => !s.Item.Filtered).ToList(); + + if (!visibleItems.Any()) return; DrawableCarouselItem drawable = null; @@ -202,15 +204,15 @@ namespace osu.Game.Screens.Select // we can fix this by changing this method to not reference drawables / Items in the first place. return; - int originalIndex = Items.IndexOf(drawable); + int originalIndex = visibleItems.IndexOf(drawable); int currentIndex = originalIndex; // local function to increment the index in the required direction, wrapping over extremities. - int incrementIndex() => currentIndex = (currentIndex + direction + Items.Count) % Items.Count; + int incrementIndex() => currentIndex = (currentIndex + direction + visibleItems.Count) % visibleItems.Count; while (incrementIndex() != originalIndex) { - var item = Items[currentIndex].Item; + var item = visibleItems[currentIndex].Item; if (item.Filtered || item.State == CarouselItemState.Selected) continue; diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 739bc39269..c347bfe70f 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -1,11 +1,13 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using System.Linq; using OpenTK.Input; using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; @@ -47,13 +49,15 @@ namespace osu.Game.Screens.Select private SampleChannel sampleConfirm; - [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, OsuGame game) - { - sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); + public readonly Bindable> SelectedMods = new Bindable>(new List()); - if (game != null) - modSelect.SelectedMods.BindTo(game.SelectedMods); + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, OsuGame osu) + { + if (osu != null) SelectedMods.BindTo(osu.SelectedMods); + modSelect.SelectedMods.BindTo(SelectedMods); + + sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection"); Footer.AddButton(@"mods", colours.Yellow, modSelect, Key.F1, float.MaxValue); @@ -80,7 +84,7 @@ namespace osu.Game.Screens.Select { base.UpdateBeatmap(beatmap); - beatmap.Mods.BindTo(modSelect.SelectedMods); + beatmap.Mods.BindTo(SelectedMods); BeatmapDetails.Beatmap = beatmap; @@ -95,7 +99,7 @@ namespace osu.Game.Screens.Select if (removeAutoModOnResume) { var autoType = Ruleset.Value.CreateInstance().GetAutoplayMod().GetType(); - modSelect.SelectedMods.Value = modSelect.SelectedMods.Value.Where(m => m.GetType() != autoType).ToArray(); + SelectedMods.Value = SelectedMods.Value.Where(m => m.GetType() != autoType).ToArray(); removeAutoModOnResume = false; } @@ -125,7 +129,7 @@ namespace osu.Game.Screens.Select if (Beatmap.Value.Track != null) Beatmap.Value.Track.Looping = false; - Beatmap.Value.Mods.UnbindBindings(); + SelectedMods.UnbindAll(); Beatmap.Value.Mods.Value = new Mod[] { }; return false; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index de6847d866..43d7cb637a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -386,6 +386,8 @@ namespace osu.Game.Screens.Select protected override bool OnExiting(Screen next) { + FinaliseSelection(); + beatmapInfoWedge.State = Visibility.Hidden; Content.FadeOut(100);