mirror of
https://github.com/ppy/osu.git
synced 2025-03-28 09:37:23 +08:00
Merge pull request #2334 from peppy/async-screens
Make screens always load async (fixes stutter when entering editor)
This commit is contained in:
commit
a9ddb46ade
@ -1 +1 @@
|
|||||||
Subproject commit f1751c27ffe2c5febece74129368596b5ad3a4e2
|
Subproject commit 61e676094d25436bb9e8858946f65c43d15d8e01
|
@ -110,11 +110,13 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
private void selectBeatmap(string name)
|
private void selectBeatmap(string name)
|
||||||
{
|
{
|
||||||
var infoBefore = infoWedge.Info;
|
BeatmapInfoWedge.BufferedWedgeInfo infoBefore = null;
|
||||||
|
|
||||||
AddStep($"select {name} beatmap", () =>
|
AddStep($"select {name} beatmap", () =>
|
||||||
{
|
{
|
||||||
beatmap.Value = new TestWorkingBeatmap(beatmaps.First(b => b.BeatmapInfo.Ruleset.ShortName == name));
|
infoBefore = infoWedge.Info;
|
||||||
|
WorkingBeatmap bm = new TestWorkingBeatmap(beatmaps.First(b => b.BeatmapInfo.Ruleset.ShortName == name));
|
||||||
|
beatmap.Value = bm;
|
||||||
infoWedge.UpdateBeatmap(beatmap);
|
infoWedge.UpdateBeatmap(beatmap);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
24
osu.Game.Tests/Visual/TestCasePlayerLoader.cs
Normal file
24
osu.Game.Tests/Visual/TestCasePlayerLoader.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
public class TestCasePlayerLoader : OsuTestCase
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuGameBase game)
|
||||||
|
{
|
||||||
|
AddStep("load dummy beatmap", () => Add(new PlayerLoader(new Player
|
||||||
|
{
|
||||||
|
InitialBeatmap = new DummyWorkingBeatmap(game),
|
||||||
|
AllowPause = false,
|
||||||
|
AllowLeadIn = false,
|
||||||
|
AllowResults = false,
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,9 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.Profile;
|
using osu.Game.Overlays.Profile;
|
||||||
using osu.Game.Overlays.Profile.Header;
|
using osu.Game.Overlays.Profile.Header;
|
||||||
@ -17,6 +19,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
public class TestCaseUserProfile : OsuTestCase
|
public class TestCaseUserProfile : OsuTestCase
|
||||||
{
|
{
|
||||||
private readonly TestUserProfileOverlay profile;
|
private readonly TestUserProfileOverlay profile;
|
||||||
|
private APIAccess api;
|
||||||
|
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
@ -32,6 +35,12 @@ namespace osu.Game.Tests.Visual
|
|||||||
Add(profile = new TestUserProfileOverlay());
|
Add(profile = new TestUserProfileOverlay());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(APIAccess api)
|
||||||
|
{
|
||||||
|
this.api = api;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
@ -79,9 +88,10 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
Username = @"peppy",
|
Username = @"peppy",
|
||||||
Id = 2,
|
Id = 2,
|
||||||
|
IsSupporter = true,
|
||||||
Country = new Country { FullName = @"Australia", FlagName = @"AU" },
|
Country = new Country { FullName = @"Australia", FlagName = @"AU" },
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg"
|
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg"
|
||||||
}));
|
}, api.IsLoggedIn));
|
||||||
|
|
||||||
checkSupporterTag(true);
|
checkSupporterTag(true);
|
||||||
|
|
||||||
@ -91,7 +101,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
Id = 3103765,
|
Id = 3103765,
|
||||||
Country = new Country { FullName = @"Japan", FlagName = @"JP" },
|
Country = new Country { FullName = @"Japan", FlagName = @"JP" },
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
|
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
|
||||||
}));
|
}, api.IsLoggedIn));
|
||||||
|
|
||||||
AddStep("Hide", profile.Hide);
|
AddStep("Hide", profile.Hide);
|
||||||
AddStep("Show without reload", profile.Show);
|
AddStep("Show without reload", profile.Show);
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
|
|
||||||
namespace osu.Game.IO.Archives
|
namespace osu.Game.IO.Archives
|
||||||
{
|
{
|
||||||
public abstract class ArchiveReader : IDisposable, IResourceStore<byte[]>
|
public abstract class ArchiveReader : IResourceStore<byte[]>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens a stream for reading a specific file from this archive.
|
/// Opens a stream for reading a specific file from this archive.
|
||||||
|
@ -188,6 +188,20 @@ namespace osu.Game
|
|||||||
FileStore.Cleanup();
|
FileStore.Cleanup();
|
||||||
|
|
||||||
AddInternal(api);
|
AddInternal(api);
|
||||||
|
|
||||||
|
GlobalActionContainer globalBinding;
|
||||||
|
|
||||||
|
CursorOverrideContainer = new CursorOverrideContainer { RelativeSizeAxes = Axes.Both };
|
||||||
|
CursorOverrideContainer.Child = globalBinding = new GlobalActionContainer(this)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Child = content = new OsuTooltipContainer(CursorOverrideContainer.Cursor) { RelativeSizeAxes = Axes.Both }
|
||||||
|
};
|
||||||
|
|
||||||
|
base.Content.Add(new DrawSizePreservingFillContainer { Child = CursorOverrideContainer });
|
||||||
|
|
||||||
|
KeyBindingStore.Register(globalBinding);
|
||||||
|
dependencies.Cache(globalBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runMigrations()
|
private void runMigrations()
|
||||||
@ -217,20 +231,6 @@ namespace osu.Game
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
GlobalActionContainer globalBinding;
|
|
||||||
|
|
||||||
CursorOverrideContainer = new CursorOverrideContainer { RelativeSizeAxes = Axes.Both };
|
|
||||||
CursorOverrideContainer.Child = globalBinding = new GlobalActionContainer(this)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Child = content = new OsuTooltipContainer(CursorOverrideContainer.Cursor) { RelativeSizeAxes = Axes.Both }
|
|
||||||
};
|
|
||||||
|
|
||||||
base.Content.Add(new DrawSizePreservingFillContainer { Child = CursorOverrideContainer });
|
|
||||||
|
|
||||||
KeyBindingStore.Register(globalBinding);
|
|
||||||
dependencies.Cache(globalBinding);
|
|
||||||
|
|
||||||
// TODO: This is temporary until we reimplement the local FPS display.
|
// TODO: This is temporary until we reimplement the local FPS display.
|
||||||
// It's just to allow end-users to access the framework FPS display without knowing the shortcut key.
|
// It's just to allow end-users to access the framework FPS display without knowing the shortcut key.
|
||||||
fpsDisplayVisible = LocalConfig.GetBindable<bool>(OsuSetting.ShowFpsDisplay);
|
fpsDisplayVisible = LocalConfig.GetBindable<bool>(OsuSetting.ShowFpsDisplay);
|
||||||
|
@ -26,14 +26,14 @@ namespace osu.Game.Screens
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Push(Screen screen)
|
public override void Push(Screen screen)
|
||||||
{
|
{
|
||||||
// When trying to push a non-loaded screen, load it asynchronously and re-invoke Push
|
// When trying to push a non-loaded screen, load it asynchronously and re-invoke Push
|
||||||
// once it's done.
|
// once it's done.
|
||||||
if (screen.LoadState == LoadState.NotLoaded)
|
if (screen.LoadState == LoadState.NotLoaded)
|
||||||
{
|
{
|
||||||
LoadComponentAsync(screen, d => Push((BackgroundScreen)d));
|
LoadComponentAsync(screen, d => Push((BackgroundScreen)d));
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the in-progress loading is complete before pushing the screen.
|
// Make sure the in-progress loading is complete before pushing the screen.
|
||||||
@ -41,8 +41,6 @@ namespace osu.Game.Screens
|
|||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
|
|
||||||
base.Push(screen);
|
base.Push(screen);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
|
@ -178,7 +178,7 @@ namespace osu.Game.Screens.Edit
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentScreen.Beatmap.BindTo(Beatmap);
|
currentScreen.Beatmap.BindTo(Beatmap);
|
||||||
screenContainer.Add(currentScreen);
|
LoadComponentAsync(currentScreen, screenContainer.Add);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnWheel(InputState state)
|
protected override bool OnWheel(InputState state)
|
||||||
|
@ -77,7 +77,7 @@ namespace osu.Game.Screens.Play
|
|||||||
private DrawableStoryboard storyboard;
|
private DrawableStoryboard storyboard;
|
||||||
private Container storyboardContainer;
|
private Container storyboardContainer;
|
||||||
|
|
||||||
private bool loadedSuccessfully => RulesetContainer?.Objects.Any() == true;
|
public bool LoadedBeatmapSuccessfully => RulesetContainer?.Objects.Any() == true;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(AudioManager audio, APIAccess api, OsuConfigManager config)
|
private void load(AudioManager audio, APIAccess api, OsuConfigManager config)
|
||||||
@ -86,10 +86,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
WorkingBeatmap working = Beatmap.Value;
|
WorkingBeatmap working = Beatmap.Value;
|
||||||
if (working is DummyWorkingBeatmap)
|
if (working is DummyWorkingBeatmap)
|
||||||
{
|
|
||||||
Exit();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
sampleRestart = audio.Sample.Get(@"Gameplay/restart");
|
sampleRestart = audio.Sample.Get(@"Gameplay/restart");
|
||||||
|
|
||||||
@ -122,14 +119,15 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!RulesetContainer.Objects.Any())
|
if (!RulesetContainer.Objects.Any())
|
||||||
throw new InvalidOperationException("Beatmap contains no hit objects!");
|
{
|
||||||
|
Logger.Error(new InvalidOperationException("Beatmap contains no hit objects!"), "Beatmap contains no hit objects!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Error(e, "Could not load beatmap sucessfully!");
|
Logger.Error(e, "Could not load beatmap sucessfully!");
|
||||||
|
|
||||||
//couldn't load, hard abort!
|
//couldn't load, hard abort!
|
||||||
Exit();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +291,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
base.OnEntering(last);
|
base.OnEntering(last);
|
||||||
|
|
||||||
if (!loadedSuccessfully)
|
if (!LoadedBeatmapSuccessfully)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Content.Alpha = 0;
|
Content.Alpha = 0;
|
||||||
@ -343,7 +341,7 @@ namespace osu.Game.Screens.Play
|
|||||||
return base.OnExiting(next);
|
return base.OnExiting(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadedSuccessfully)
|
if (LoadedBeatmapSuccessfully)
|
||||||
pauseContainer?.Pause();
|
pauseContainer?.Pause();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -159,14 +159,14 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
loadTask = null;
|
loadTask = null;
|
||||||
|
|
||||||
if (!Push(player))
|
//By default, we want to load the player and never be returned to.
|
||||||
Exit();
|
//Note that this may change if the player we load requested a re-run.
|
||||||
|
ValidForResume = false;
|
||||||
|
|
||||||
|
if (player.LoadedBeatmapSuccessfully)
|
||||||
|
Push(player);
|
||||||
else
|
else
|
||||||
{
|
Exit();
|
||||||
//By default, we want to load the player and never be returned to.
|
|
||||||
//Note that this may change if the player we load requested a re-run.
|
|
||||||
ValidForResume = false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,12 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
|
|
||||||
protected List<CarouselItem> InternalChildren = new List<CarouselItem>();
|
protected List<CarouselItem> InternalChildren = new List<CarouselItem>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to assign a monotonically increasing ID to children as they are added. This member is
|
||||||
|
/// incremented whenever a child is added.
|
||||||
|
/// </summary>
|
||||||
|
private ulong currentChildID;
|
||||||
|
|
||||||
public override List<DrawableCarouselItem> Drawables
|
public override List<DrawableCarouselItem> Drawables
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -39,6 +45,7 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
public virtual void AddChild(CarouselItem i)
|
public virtual void AddChild(CarouselItem i)
|
||||||
{
|
{
|
||||||
i.State.ValueChanged += v => ChildItemStateChanged(i, v);
|
i.State.ValueChanged += v => ChildItemStateChanged(i, v);
|
||||||
|
i.ChildID = ++currentChildID;
|
||||||
InternalChildren.Add(i);
|
InternalChildren.Add(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int creationOrder;
|
||||||
|
|
||||||
protected CarouselItem()
|
protected CarouselItem()
|
||||||
{
|
{
|
||||||
drawableRepresentation = new Lazy<DrawableCarouselItem>(CreateDrawableRepresentation);
|
drawableRepresentation = new Lazy<DrawableCarouselItem>(CreateDrawableRepresentation);
|
||||||
@ -44,13 +46,18 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
|
|
||||||
private readonly Lazy<DrawableCarouselItem> drawableRepresentation;
|
private readonly Lazy<DrawableCarouselItem> drawableRepresentation;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used as a default sort method for <see cref="CarouselItem"/>s of differing types.
|
||||||
|
/// </summary>
|
||||||
|
internal ulong ChildID;
|
||||||
|
|
||||||
protected abstract DrawableCarouselItem CreateDrawableRepresentation();
|
protected abstract DrawableCarouselItem CreateDrawableRepresentation();
|
||||||
|
|
||||||
public virtual void Filter(FilterCriteria criteria)
|
public virtual void Filter(FilterCriteria criteria)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual int CompareTo(FilterCriteria criteria, CarouselItem other) => GetHashCode().CompareTo(other.GetHashCode());
|
public virtual int CompareTo(FilterCriteria criteria, CarouselItem other) => ChildID.CompareTo(other.ChildID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum CarouselItemState
|
public enum CarouselItemState
|
||||||
|
@ -113,6 +113,31 @@ namespace osu.Game.Skinning
|
|||||||
string path = getPathForFile(name);
|
string path = getPathForFile(name);
|
||||||
return path == null ? null : underlyingStore.Get(path);
|
return path == null ? null : underlyingStore.Get(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region IDisposable Support
|
||||||
|
|
||||||
|
private bool isDisposed;
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!isDisposed)
|
||||||
|
{
|
||||||
|
isDisposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~LegacySkinResourceStore()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,14 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
protected override string MainResourceFile => File.Exists(base.MainResourceFile) ? base.MainResourceFile : Assembly.GetExecutingAssembly().Location;
|
protected override string MainResourceFile => File.Exists(base.MainResourceFile) ? base.MainResourceFile : Assembly.GetExecutingAssembly().Location;
|
||||||
|
|
||||||
private readonly TestCaseTestRunner.TestRunner runner;
|
private TestCaseTestRunner.TestRunner runner;
|
||||||
|
|
||||||
public OsuTestCaseTestRunner()
|
protected override void LoadAsyncComplete()
|
||||||
{
|
{
|
||||||
runner = new TestCaseTestRunner.TestRunner();
|
// this has to be run here rather than LoadComplete because
|
||||||
}
|
// TestCase.cs is checking the IsLoaded state (on another thread) and expects
|
||||||
|
// the runner to be loaded at that point.
|
||||||
protected override void LoadComplete()
|
Add(runner = new TestCaseTestRunner.TestRunner());
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
Add(runner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RunTestBlocking(TestCase test) => runner.RunTestBlocking(test);
|
public void RunTestBlocking(TestCase test) => runner.RunTestBlocking(test);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user