1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 17:13:06 +08:00

Merge remote-tracking branch 'upstream/master' into game-handles-links

This commit is contained in:
Dean Herbert 2019-11-03 13:04:18 +09:00
commit 5127b52c25
10 changed files with 109 additions and 40 deletions

View File

@ -38,9 +38,10 @@ namespace osu.Game.Rulesets.Osu.UI
}); });
} }
public override void Show() protected override void PopIn()
{ {
base.Show(); base.PopIn();
GameplayCursor.ActiveCursor.Hide(); GameplayCursor.ActiveCursor.Hide();
cursorScaleContainer.MoveTo(GameplayCursor.ActiveCursor.Position); cursorScaleContainer.MoveTo(GameplayCursor.ActiveCursor.Position);
clickToResumeCursor.Appear(); clickToResumeCursor.Appear();
@ -55,13 +56,13 @@ namespace osu.Game.Rulesets.Osu.UI
} }
} }
public override void Hide() protected override void PopOut()
{ {
base.PopOut();
localCursorContainer?.Expire(); localCursorContainer?.Expire();
localCursorContainer = null; localCursorContainer = null;
GameplayCursor.ActiveCursor.Show(); GameplayCursor?.ActiveCursor?.Show();
base.Hide();
} }
protected override bool OnHover(HoverEvent e) => true; protected override bool OnHover(HoverEvent e) => true;

View File

@ -69,6 +69,24 @@ namespace osu.Game.Tests.Visual.Gameplay
confirmClockRunning(true); confirmClockRunning(true);
} }
[Test]
public void TestPauseWithResumeOverlay()
{
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
AddUntilStep("wait for hitobjects", () => Player.ScoreProcessor.Health.Value < 1);
pauseAndConfirm();
resume();
confirmClockRunning(false);
confirmPauseOverlayShown(false);
pauseAndConfirm();
AddUntilStep("resume overlay is not active", () => Player.DrawableRuleset.ResumeOverlay.State.Value == Visibility.Hidden);
confirmPaused();
}
[Test] [Test]
public void TestResumeWithResumeOverlaySkipped() public void TestResumeWithResumeOverlaySkipped()
{ {

View File

@ -392,9 +392,16 @@ namespace osu.Game.Beatmaps
req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); }; req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); };
try
{
// intentionally blocking to limit web request concurrency // intentionally blocking to limit web request concurrency
req.Perform(api); req.Perform(api);
} }
catch (Exception e)
{
LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})");
}
}
} }
} }
} }

View File

@ -86,16 +86,7 @@ namespace osu.Game.Database
}, TaskCreationOptions.LongRunning); }, TaskCreationOptions.LongRunning);
}; };
request.Failure += error => request.Failure += triggerFailure;
{
DownloadFailed?.Invoke(request);
if (error is OperationCanceledException) return;
notification.State = ProgressNotificationState.Cancelled;
Logger.Error(error, $"{HumanisedModelName.Titleize()} download failed!");
currentDownloads.Remove(request);
};
notification.CancelRequested += () => notification.CancelRequested += () =>
{ {
@ -108,11 +99,31 @@ namespace osu.Game.Database
currentDownloads.Add(request); currentDownloads.Add(request);
PostNotification?.Invoke(notification); PostNotification?.Invoke(notification);
Task.Factory.StartNew(() => request.Perform(api), TaskCreationOptions.LongRunning); Task.Factory.StartNew(() =>
{
try
{
request.Perform(api);
}
catch (Exception error)
{
triggerFailure(error);
}
}, TaskCreationOptions.LongRunning);
DownloadBegan?.Invoke(request); DownloadBegan?.Invoke(request);
return true; return true;
void triggerFailure(Exception error)
{
DownloadFailed?.Invoke(request);
if (error is OperationCanceledException) return;
notification.State = ProgressNotificationState.Cancelled;
Logger.Error(error, $"{HumanisedModelName.Titleize()} download failed!");
currentDownloads.Remove(request);
}
} }
public bool IsAvailableLocally(TModel model) => CheckLocalAvailability(model, modelStore.ConsumableItems.Where(m => !m.DeletePending)); public bool IsAvailableLocally(TModel model) => CheckLocalAvailability(model, modelStore.ConsumableItems.Where(m => !m.DeletePending));

View File

@ -44,7 +44,17 @@ namespace osu.Game.Overlays.Changelog
req.Failure += _ => complete = true; req.Failure += _ => complete = true;
// This is done on a separate thread to support cancellation below // This is done on a separate thread to support cancellation below
Task.Run(() => req.Perform(api)); Task.Run(() =>
{
try
{
req.Perform(api);
}
catch
{
complete = true;
}
});
while (!complete) while (!complete)
{ {

View File

@ -170,6 +170,7 @@ namespace osu.Game.Overlays
var tcs = new TaskCompletionSource<bool>(); var tcs = new TaskCompletionSource<bool>();
var req = new GetChangelogRequest(); var req = new GetChangelogRequest();
req.Success += res => Schedule(() => req.Success += res => Schedule(() =>
{ {
// remap streams to builds to ensure model equality // remap streams to builds to ensure model equality
@ -183,8 +184,22 @@ namespace osu.Game.Overlays
tcs.SetResult(true); tcs.SetResult(true);
}); });
req.Failure += _ => initialFetchTask = null;
req.Failure += _ =>
{
initialFetchTask = null;
tcs.SetResult(false);
};
try
{
req.Perform(API); req.Perform(API);
}
catch
{
initialFetchTask = null;
tcs.SetResult(false);
}
await tcs.Task; await tcs.Task;
}); });

View File

@ -239,6 +239,12 @@ namespace osu.Game.Rulesets.UI
continueResume(); continueResume();
} }
public override void CancelResume()
{
// called if the user pauses while the resume overlay is open
ResumeOverlay?.Hide();
}
/// <summary> /// <summary>
/// Creates and adds the visual representation of a <see cref="TObject"/> to this <see cref="DrawableRuleset{TObject}"/>. /// Creates and adds the visual representation of a <see cref="TObject"/> to this <see cref="DrawableRuleset{TObject}"/>.
/// </summary> /// </summary>
@ -453,6 +459,11 @@ namespace osu.Game.Rulesets.UI
/// <param name="continueResume">The action to run when resuming is to be completed.</param> /// <param name="continueResume">The action to run when resuming is to be completed.</param>
public abstract void RequestResume(Action continueResume); public abstract void RequestResume(Action continueResume);
/// <summary>
/// Invoked when the user requests to pause while the resume overlay is active.
/// </summary>
public abstract void CancelResume();
/// <summary> /// <summary>
/// Create a <see cref="ScoreProcessor"/> for the associated ruleset and link with this /// Create a <see cref="ScoreProcessor"/> for the associated ruleset and link with this
/// <see cref="DrawableRuleset"/>. /// <see cref="DrawableRuleset"/>.

View File

@ -13,12 +13,6 @@ namespace osu.Game.Rulesets.UI.Scrolling
{ {
public class ScrollingHitObjectContainer : HitObjectContainer public class ScrollingHitObjectContainer : HitObjectContainer
{ {
/// <summary>
/// A multiplier applied to the length of the scrolling area to determine a safe default lifetime end for hitobjects.
/// This is only used to limit the lifetime end within reason, as proper lifetime management should be implemented on hitobjects themselves.
/// </summary>
private const float safe_lifetime_end_multiplier = 2;
private readonly IBindable<double> timeRange = new BindableDouble(); private readonly IBindable<double> timeRange = new BindableDouble();
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>(); private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
@ -123,28 +117,22 @@ namespace osu.Game.Rulesets.UI.Scrolling
if (cached.IsValid) if (cached.IsValid)
return; return;
double endTime = hitObject.HitObject.StartTime;
if (hitObject.HitObject is IHasEndTime e) if (hitObject.HitObject is IHasEndTime e)
{ {
endTime = e.EndTime;
switch (direction.Value) switch (direction.Value)
{ {
case ScrollingDirection.Up: case ScrollingDirection.Up:
case ScrollingDirection.Down: case ScrollingDirection.Down:
hitObject.Height = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, endTime, timeRange.Value, scrollLength); hitObject.Height = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, e.EndTime, timeRange.Value, scrollLength);
break; break;
case ScrollingDirection.Left: case ScrollingDirection.Left:
case ScrollingDirection.Right: case ScrollingDirection.Right:
hitObject.Width = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, endTime, timeRange.Value, scrollLength); hitObject.Width = scrollingInfo.Algorithm.GetLength(hitObject.HitObject.StartTime, e.EndTime, timeRange.Value, scrollLength);
break; break;
} }
} }
hitObject.LifetimeEnd = scrollingInfo.Algorithm.TimeAt(scrollLength * safe_lifetime_end_multiplier, endTime, timeRange.Value, scrollLength);
foreach (var obj in hitObject.NestedHitObjects) foreach (var obj in hitObject.NestedHitObjects)
{ {
computeInitialStateRecursive(obj); computeInitialStateRecursive(obj);

View File

@ -167,14 +167,17 @@ namespace osu.Game.Screens.Multi
public void APIStateChanged(IAPIProvider api, APIState state) public void APIStateChanged(IAPIProvider api, APIState state)
{ {
if (state != APIState.Online) if (state != APIState.Online)
forcefullyExit(); Schedule(forcefullyExit);
} }
private void forcefullyExit() private void forcefullyExit()
{ {
// This is temporary since we don't currently have a way to force screens to be exited // This is temporary since we don't currently have a way to force screens to be exited
if (this.IsCurrentScreen()) if (this.IsCurrentScreen())
{
while (this.IsCurrentScreen())
this.Exit(); this.Exit();
}
else else
{ {
this.MakeCurrent(); this.MakeCurrent();

View File

@ -443,7 +443,12 @@ namespace osu.Game.Screens.Play
{ {
if (!canPause) return; if (!canPause) return;
if (IsResuming)
{
DrawableRuleset.CancelResume();
IsResuming = false; IsResuming = false;
}
GameplayClockContainer.Stop(); GameplayClockContainer.Stop();
PauseOverlay.Show(); PauseOverlay.Show();
lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime; lastPauseActionTime = GameplayClockContainer.GameplayClock.CurrentTime;