1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 16:12:57 +08:00

Merge branch 'master' into fix-quick-delete-crash

This commit is contained in:
Dean Herbert 2020-11-16 13:54:54 +09:00 committed by GitHub
commit 7b79b9b9c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 81 additions and 27 deletions

View File

@ -207,11 +207,17 @@ namespace osu.Game.Rulesets.Osu.Edit
Quad quad = getSurroundingQuad(hitObjects); Quad quad = getSurroundingQuad(hitObjects);
if (quad.TopLeft.X + delta.X < 0 || Vector2 newTopLeft = quad.TopLeft + delta;
quad.TopLeft.Y + delta.Y < 0 || if (newTopLeft.X < 0)
quad.BottomRight.X + delta.X > DrawWidth || delta.X -= newTopLeft.X;
quad.BottomRight.Y + delta.Y > DrawHeight) if (newTopLeft.Y < 0)
return false; delta.Y -= newTopLeft.Y;
Vector2 newBottomRight = quad.BottomRight + delta;
if (newBottomRight.X > DrawWidth)
delta.X -= newBottomRight.X - DrawWidth;
if (newBottomRight.Y > DrawHeight)
delta.Y -= newBottomRight.Y - DrawHeight;
foreach (var h in hitObjects) foreach (var h in hitObjects)
h.Position += delta; h.Position += delta;

View File

@ -167,6 +167,21 @@ namespace osu.Game.Tests.Visual.Components
AddAssert("game not muted", () => audio.Tracks.AggregateVolume.Value != 0); AddAssert("game not muted", () => audio.Tracks.AggregateVolume.Value != 0);
} }
[Test]
public void TestOwnerNotRegistered()
{
PreviewTrack track = null;
AddStep("get track", () => Add(new TestTrackOwner(track = getTrack(), registerAsOwner: false)));
AddUntilStep("wait for loaded", () => track.IsLoaded);
AddStep("start track", () => track.Start());
AddUntilStep("track is running", () => track.IsRunning);
AddStep("cancel from anyone", () => trackManager.StopAnyPlaying(this));
AddAssert("track stopped", () => !track.IsRunning);
}
private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null); private TestPreviewTrack getTrack() => (TestPreviewTrack)trackManager.Get(null);
private TestPreviewTrack getOwnedTrack() private TestPreviewTrack getOwnedTrack()
@ -181,10 +196,12 @@ namespace osu.Game.Tests.Visual.Components
private class TestTrackOwner : CompositeDrawable, IPreviewTrackOwner private class TestTrackOwner : CompositeDrawable, IPreviewTrackOwner
{ {
private readonly PreviewTrack track; private readonly PreviewTrack track;
private readonly bool registerAsOwner;
public TestTrackOwner(PreviewTrack track) public TestTrackOwner(PreviewTrack track, bool registerAsOwner = true)
{ {
this.track = track; this.track = track;
this.registerAsOwner = registerAsOwner;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -196,7 +213,8 @@ namespace osu.Game.Tests.Visual.Components
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{ {
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
dependencies.CacheAs<IPreviewTrackOwner>(this); if (registerAsOwner)
dependencies.CacheAs<IPreviewTrackOwner>(this);
return dependencies; return dependencies;
} }
} }

View File

@ -144,9 +144,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
if (selected) if (selected)
{ {
selectionBox.Show(); selectionBox.Show();
if (editor) if (editor && editorInfo != null)
editorInfo.Selected.Value = Match; editorInfo.Selected.Value = Match;
else else if (ladderInfo != null)
ladderInfo.CurrentMatch.Value = Match; ladderInfo.CurrentMatch.Value = Match;
} }
else else

View File

@ -11,6 +11,7 @@ using osu.Framework.Audio.Track;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.IO.Stores; using osu.Framework.IO.Stores;
using osu.Framework.Logging;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
namespace osu.Game.Audio namespace osu.Game.Audio
@ -76,7 +77,7 @@ namespace osu.Game.Audio
/// <param name="source">The <see cref="IPreviewTrackOwner"/> which may be the owner of the <see cref="PreviewTrack"/>.</param> /// <param name="source">The <see cref="IPreviewTrackOwner"/> which may be the owner of the <see cref="PreviewTrack"/>.</param>
public void StopAnyPlaying(IPreviewTrackOwner source) public void StopAnyPlaying(IPreviewTrackOwner source)
{ {
if (CurrentTrack == null || CurrentTrack.Owner != source) if (CurrentTrack == null || (CurrentTrack.Owner != null && CurrentTrack.Owner != source))
return; return;
CurrentTrack.Stop(); CurrentTrack.Stop();
@ -86,11 +87,12 @@ namespace osu.Game.Audio
/// <summary> /// <summary>
/// Creates the <see cref="TrackManagerPreviewTrack"/>. /// Creates the <see cref="TrackManagerPreviewTrack"/>.
/// </summary> /// </summary>
protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore); protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) =>
new TrackManagerPreviewTrack(beatmapSetInfo, trackStore);
public class TrackManagerPreviewTrack : PreviewTrack public class TrackManagerPreviewTrack : PreviewTrack
{ {
[Resolved] [Resolved(canBeNull: true)]
public IPreviewTrackOwner Owner { get; private set; } public IPreviewTrackOwner Owner { get; private set; }
private readonly BeatmapSetInfo beatmapSetInfo; private readonly BeatmapSetInfo beatmapSetInfo;
@ -102,6 +104,12 @@ namespace osu.Game.Audio
this.trackManager = trackManager; this.trackManager = trackManager;
} }
protected override void LoadComplete()
{
base.LoadComplete();
Logger.Log($"A {nameof(PreviewTrack)} was created without a containing {nameof(IPreviewTrackOwner)}. An owner should be added for correct behaviour.");
}
protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3"); protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3");
} }

View File

@ -46,12 +46,15 @@ namespace osu.Game.Online
{ {
if (modelInfo.NewValue == null) if (modelInfo.NewValue == null)
attachDownload(null); attachDownload(null);
else if (manager.IsAvailableLocally(modelInfo.NewValue)) else if (manager?.IsAvailableLocally(modelInfo.NewValue) == true)
State.Value = DownloadState.LocallyAvailable; State.Value = DownloadState.LocallyAvailable;
else else
attachDownload(manager.GetExistingDownload(modelInfo.NewValue)); attachDownload(manager?.GetExistingDownload(modelInfo.NewValue));
}, true); }, true);
if (manager == null)
return;
managerDownloadBegan = manager.DownloadBegan.GetBoundCopy(); managerDownloadBegan = manager.DownloadBegan.GetBoundCopy();
managerDownloadBegan.BindValueChanged(downloadBegan); managerDownloadBegan.BindValueChanged(downloadBegan);
managerDownloadFailed = manager.DownloadFailed.GetBoundCopy(); managerDownloadFailed = manager.DownloadFailed.GetBoundCopy();

View File

@ -248,7 +248,9 @@ namespace osu.Game.Online.Leaderboards
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
apiState.BindTo(api.State); if (api != null)
apiState.BindTo(api.State);
apiState.BindValueChanged(onlineStateChanged, true); apiState.BindValueChanged(onlineStateChanged, true);
} }
@ -303,7 +305,7 @@ namespace osu.Game.Online.Leaderboards
PlaceholderState = PlaceholderState.NetworkFailure; PlaceholderState = PlaceholderState.NetworkFailure;
}); });
api.Queue(getScoresRequest); api?.Queue(getScoresRequest);
}); });
} }

View File

@ -30,7 +30,7 @@ namespace osu.Game.Overlays.AccountCreation
public override void OnEntering(IScreen last) public override void OnEntering(IScreen last)
{ {
if (string.IsNullOrEmpty(api.ProvidedUsername)) if (string.IsNullOrEmpty(api?.ProvidedUsername))
{ {
this.FadeOut(); this.FadeOut();
this.Push(new ScreenEntry()); this.Push(new ScreenEntry());
@ -43,7 +43,7 @@ namespace osu.Game.Overlays.AccountCreation
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(OsuColour colours, OsuGame game, TextureStore textures) private void load(OsuColour colours, OsuGame game, TextureStore textures)
{ {
if (string.IsNullOrEmpty(api.ProvidedUsername)) if (string.IsNullOrEmpty(api?.ProvidedUsername))
return; return;
InternalChildren = new Drawable[] InternalChildren = new Drawable[]

View File

@ -217,7 +217,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
private void performLogin() private void performLogin()
{ {
if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text)) if (!string.IsNullOrEmpty(username.Text) && !string.IsNullOrEmpty(password.Text))
api.Login(username.Text, password.Text); api?.Login(username.Text, password.Text);
else else
shakeSignIn.Shake(); shakeSignIn.Shake();
} }

View File

@ -76,7 +76,7 @@ namespace osu.Game
// a dialog may be blocking the execution for now. // a dialog may be blocking the execution for now.
if (checkForDialog(current)) return; if (checkForDialog(current)) return;
game.CloseAllOverlays(false); game?.CloseAllOverlays(false);
// we may already be at the target screen type. // we may already be at the target screen type.
if (validScreens.Contains(getCurrentScreen().GetType()) && !beatmap.Disabled) if (validScreens.Contains(getCurrentScreen().GetType()) && !beatmap.Disabled)

View File

@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.UI
{ {
Debug.Assert(!drawableMap.ContainsKey(entry)); Debug.Assert(!drawableMap.ContainsKey(entry));
var drawable = pooledObjectProvider.GetPooledDrawableRepresentation(entry.HitObject); var drawable = pooledObjectProvider?.GetPooledDrawableRepresentation(entry.HitObject);
if (drawable == null) if (drawable == null)
throw new InvalidOperationException($"A drawable representation could not be retrieved for hitobject type: {entry.HitObject.GetType().ReadableName()}."); throw new InvalidOperationException($"A drawable representation could not be retrieved for hitobject type: {entry.HitObject.GetType().ReadableName()}.");

View File

@ -456,6 +456,9 @@ namespace osu.Game.Screens.Edit.Compose.Components
if (movementBlueprint == null) if (movementBlueprint == null)
return false; return false;
if (snapProvider == null)
return true;
Debug.Assert(movementBlueprintOriginalPosition != null); Debug.Assert(movementBlueprintOriginalPosition != null);
HitObject draggedObject = movementBlueprint.HitObject; HitObject draggedObject = movementBlueprint.HitObject;

View File

@ -110,7 +110,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// </summary> /// </summary>
protected virtual void OnOperationBegan() protected virtual void OnOperationBegan()
{ {
ChangeHandler.BeginChange(); ChangeHandler?.BeginChange();
} }
/// <summary> /// <summary>
@ -118,7 +118,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
/// </summary> /// </summary>
protected virtual void OnOperationEnded() protected virtual void OnOperationEnded()
{ {
ChangeHandler.EndChange(); ChangeHandler?.EndChange();
} }
#region User Input Handling #region User Input Handling

View File

@ -96,7 +96,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
if (lastDragEvent != null) if (lastDragEvent != null)
OnDrag(lastDragEvent); OnDrag(lastDragEvent);
if (Composer != null) if (Composer != null && timeline != null)
{ {
Composer.Playfield.PastLifetimeExtension = timeline.VisibleRange / 2; Composer.Playfield.PastLifetimeExtension = timeline.VisibleRange / 2;
Composer.Playfield.FutureLifetimeExtension = timeline.VisibleRange / 2; Composer.Playfield.FutureLifetimeExtension = timeline.VisibleRange / 2;

View File

@ -128,7 +128,7 @@ namespace osu.Game.Screens.Edit.Timing
controlPointGroups.BindCollectionChanged((sender, args) => controlPointGroups.BindCollectionChanged((sender, args) =>
{ {
table.ControlGroups = controlPointGroups; table.ControlGroups = controlPointGroups;
changeHandler.SaveState(); changeHandler?.SaveState();
}, true); }, true);
} }

View File

@ -59,6 +59,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components
{ {
scheduledFilterUpdate?.Cancel(); scheduledFilterUpdate?.Cancel();
if (filter == null)
return;
filter.Value = new FilterCriteria filter.Value = new FilterCriteria
{ {
SearchString = Search.Current.Value ?? string.Empty, SearchString = Search.Current.Value ?? string.Empty,

View File

@ -13,6 +13,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Audio;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics; using osu.Game.Graphics;
@ -35,7 +36,8 @@ using osuTK;
namespace osu.Game.Screens.Play namespace osu.Game.Screens.Play
{ {
public class Spectator : OsuScreen [Cached(typeof(IPreviewTrackOwner))]
public class Spectator : OsuScreen, IPreviewTrackOwner
{ {
private readonly User targetUser; private readonly User targetUser;
@ -62,6 +64,9 @@ namespace osu.Game.Screens.Play
[Resolved] [Resolved]
private RulesetStore rulesets { get; set; } private RulesetStore rulesets { get; set; }
[Resolved]
private PreviewTrackManager previewTrackManager { get; set; }
private Score score; private Score score;
private readonly object scoreLock = new object(); private readonly object scoreLock = new object();
@ -275,6 +280,7 @@ namespace osu.Game.Screens.Play
{ {
watchButton.Enabled.Value = false; watchButton.Enabled.Value = false;
beatmapPanelContainer.Clear(); beatmapPanelContainer.Clear();
previewTrackManager.StopAnyPlaying(this);
} }
private void attemptStart() private void attemptStart()
@ -326,7 +332,6 @@ namespace osu.Game.Screens.Play
{ {
if (state?.BeatmapID == null) if (state?.BeatmapID == null)
{ {
beatmapPanelContainer.Clear();
onlineBeatmap = null; onlineBeatmap = null;
return; return;
} }
@ -359,6 +364,12 @@ namespace osu.Game.Screens.Play
beatmaps.Download(onlineBeatmap); beatmaps.Download(onlineBeatmap);
} }
public override bool OnExiting(IScreen next)
{
previewTrackManager.StopAnyPlaying(this);
return base.OnExiting(next);
}
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);