mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 09:27:29 +08:00
Merge pull request #14737 from bdach/editor-difficulty-switch-shared-state
Preserve current time and clipboard contents when switching between difficulties
This commit is contained in:
commit
1ba716d9f1
@ -55,6 +55,59 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
AddAssert("stack empty", () => Stack.CurrentScreen == null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClockPositionPreservedBetweenSwitches()
|
||||
{
|
||||
BeatmapInfo targetDifficulty = null;
|
||||
AddStep("seek editor to 00:05:00", () => EditorClock.Seek(5000));
|
||||
|
||||
AddStep("set target difficulty", () => targetDifficulty = importedBeatmapSet.Beatmaps.Last(beatmap => !beatmap.Equals(Beatmap.Value.BeatmapInfo)));
|
||||
switchToDifficulty(() => targetDifficulty);
|
||||
confirmEditingBeatmap(() => targetDifficulty);
|
||||
AddAssert("editor clock at 00:05:00", () => EditorClock.CurrentTime == 5000);
|
||||
|
||||
AddStep("exit editor", () => Stack.Exit());
|
||||
// ensure editor loader didn't resume.
|
||||
AddAssert("stack empty", () => Stack.CurrentScreen == null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestClipboardPreservedAfterSwitch([Values] bool sameRuleset)
|
||||
{
|
||||
BeatmapInfo targetDifficulty = null;
|
||||
|
||||
AddStep("select first object", () => EditorBeatmap.SelectedHitObjects.Add(EditorBeatmap.HitObjects.First()));
|
||||
AddStep("copy object", () => Editor.Copy());
|
||||
|
||||
AddStep("set target difficulty", () =>
|
||||
{
|
||||
targetDifficulty = sameRuleset
|
||||
? importedBeatmapSet.Beatmaps.Last(beatmap => !beatmap.Equals(Beatmap.Value.BeatmapInfo) && beatmap.RulesetID == Beatmap.Value.BeatmapInfo.RulesetID)
|
||||
: importedBeatmapSet.Beatmaps.Last(beatmap => !beatmap.Equals(Beatmap.Value.BeatmapInfo) && beatmap.RulesetID != Beatmap.Value.BeatmapInfo.RulesetID);
|
||||
});
|
||||
switchToDifficulty(() => targetDifficulty);
|
||||
confirmEditingBeatmap(() => targetDifficulty);
|
||||
|
||||
AddAssert("no objects selected", () => !EditorBeatmap.SelectedHitObjects.Any());
|
||||
AddStep("paste object", () => Editor.Paste());
|
||||
|
||||
if (sameRuleset)
|
||||
AddAssert("object was pasted", () => EditorBeatmap.SelectedHitObjects.Any());
|
||||
else
|
||||
AddAssert("object was not pasted", () => !EditorBeatmap.SelectedHitObjects.Any());
|
||||
|
||||
AddStep("exit editor", () => Stack.Exit());
|
||||
|
||||
if (sameRuleset)
|
||||
{
|
||||
AddUntilStep("prompt for save dialog shown", () => DialogOverlay.CurrentDialog is PromptForSaveDialog);
|
||||
AddStep("discard changes", () => ((PromptForSaveDialog)DialogOverlay.CurrentDialog).PerformOkAction());
|
||||
}
|
||||
|
||||
// ensure editor loader didn't resume.
|
||||
AddAssert("stack empty", () => Stack.CurrentScreen == null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPreventSwitchDueToUnsavedChanges()
|
||||
{
|
||||
@ -118,7 +171,7 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
private void confirmEditingBeatmap(Func<BeatmapInfo> targetDifficulty)
|
||||
{
|
||||
AddUntilStep("current beatmap is correct", () => Beatmap.Value.BeatmapInfo.Equals(targetDifficulty.Invoke()));
|
||||
AddUntilStep("current screen is editor", () => Stack.CurrentScreen is Editor);
|
||||
AddUntilStep("current screen is editor", () => Stack.CurrentScreen == Editor && Editor?.IsLoaded == true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ namespace osu.Game.Screens.Edit.Compose
|
||||
public bool OnPressed(PlatformAction action)
|
||||
{
|
||||
if (action == PlatformAction.Copy)
|
||||
host.GetClipboard().SetText(formatSelectionAsString());
|
||||
host.GetClipboard()?.SetText(formatSelectionAsString());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -317,6 +317,16 @@ namespace osu.Game.Screens.Edit
|
||||
/// </summary>
|
||||
public void UpdateClockSource() => clock.ChangeSource(Beatmap.Value.Track);
|
||||
|
||||
/// <summary>
|
||||
/// Restore the editor to a provided state.
|
||||
/// </summary>
|
||||
/// <param name="state">The state to restore.</param>
|
||||
public void RestoreState([NotNull] EditorState state) => Schedule(() =>
|
||||
{
|
||||
clock.Seek(state.Time);
|
||||
clipboard.Value = state.ClipboardContent;
|
||||
});
|
||||
|
||||
protected void Save()
|
||||
{
|
||||
// no longer new after first user-triggered save.
|
||||
@ -740,7 +750,11 @@ namespace osu.Game.Screens.Edit
|
||||
return new DifficultyMenuItem(beatmapInfo, isCurrentDifficulty, SwitchToDifficulty);
|
||||
}
|
||||
|
||||
protected void SwitchToDifficulty(BeatmapInfo beatmapInfo) => loader?.ScheduleDifficultySwitch(beatmapInfo);
|
||||
protected void SwitchToDifficulty(BeatmapInfo nextBeatmap) => loader?.ScheduleDifficultySwitch(nextBeatmap, new EditorState
|
||||
{
|
||||
Time = clock.CurrentTimeAccurate,
|
||||
ClipboardContent = editorBeatmap.BeatmapInfo.RulesetID == nextBeatmap.RulesetID ? clipboard.Value : string.Empty
|
||||
});
|
||||
|
||||
private void cancelExit() => loader?.CancelPendingDifficultySwitch();
|
||||
|
||||
|
@ -20,6 +20,13 @@ namespace osu.Game.Screens.Edit
|
||||
/// </summary>
|
||||
public class EditorLoader : ScreenWithBeatmapBackground
|
||||
{
|
||||
/// <summary>
|
||||
/// The stored state from the last editor opened.
|
||||
/// This will be read by the next editor instance to be opened to restore any relevant previous state.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
private EditorState state;
|
||||
|
||||
public override float BackgroundParallaxAmount => 0.1f;
|
||||
|
||||
public override bool AllowBackButton => false;
|
||||
@ -61,7 +68,7 @@ namespace osu.Game.Screens.Edit
|
||||
}
|
||||
}
|
||||
|
||||
public void ScheduleDifficultySwitch(BeatmapInfo beatmapInfo)
|
||||
public void ScheduleDifficultySwitch(BeatmapInfo nextBeatmap, EditorState editorState)
|
||||
{
|
||||
scheduledDifficultySwitch?.Cancel();
|
||||
ValidForResume = true;
|
||||
@ -70,7 +77,8 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
scheduledDifficultySwitch = Schedule(() =>
|
||||
{
|
||||
Beatmap.Value = beatmapManager.GetWorkingBeatmap(beatmapInfo);
|
||||
Beatmap.Value = beatmapManager.GetWorkingBeatmap(nextBeatmap);
|
||||
state = editorState;
|
||||
|
||||
// This screen is a weird exception to the rule that nothing after song select changes the global beatmap.
|
||||
// Because of this, we need to update the background stack's beatmap to match.
|
||||
@ -83,7 +91,13 @@ namespace osu.Game.Screens.Edit
|
||||
|
||||
private void pushEditor()
|
||||
{
|
||||
this.Push(CreateEditor());
|
||||
var editor = CreateEditor();
|
||||
|
||||
this.Push(editor);
|
||||
|
||||
if (state != null)
|
||||
editor.RestoreState(state);
|
||||
|
||||
ValidForResume = false;
|
||||
}
|
||||
|
||||
|
23
osu.Game/Screens/Edit/EditorState.cs
Normal file
23
osu.Game/Screens/Edit/EditorState.cs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace osu.Game.Screens.Edit
|
||||
{
|
||||
/// <summary>
|
||||
/// Structure used to convey the general state of an <see cref="Editor"/> instance.
|
||||
/// </summary>
|
||||
public class EditorState
|
||||
{
|
||||
/// <summary>
|
||||
/// The current audio time.
|
||||
/// </summary>
|
||||
public double Time { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The editor clipboard content.
|
||||
/// </summary>
|
||||
public string ClipboardContent { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user