diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 89f9aec5ee1d..a7cbe1f1ad6b 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -24,6 +24,7 @@ using osu.Framework.Platform; using osu.Framework.Screens; using osu.Framework.Testing; +using osu.Framework.Threading; using osu.Framework.Timing; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -233,6 +234,8 @@ private void load(OsuConfigManager config) AddInternal(editorBeatmap = new EditorBeatmap(playableBeatmap, loadableBeatmap.GetSkin(), loadableBeatmap.BeatmapInfo)); dependencies.CacheAs(editorBeatmap); + editorBeatmap.UpdateInProgress.BindValueChanged(updateInProgress); + canSave = editorBeatmap.BeatmapInfo.Ruleset.CreateInstance() is ILegacyRuleset; if (canSave) @@ -714,6 +717,27 @@ private void confirmExit() this.Exit(); } + #region Mute from update application + + private ScheduledDelegate temporaryMuteRestorationDelegate; + private bool temporaryMuteFromUpdateInProgress; + + private void updateInProgress(ValueChangedEvent obj) + { + temporaryMuteFromUpdateInProgress = true; + updateSampleDisabledState(); + + // Debounce is arbitrarily high enough to avoid flip-flopping the value each other frame. + temporaryMuteRestorationDelegate?.Cancel(); + temporaryMuteRestorationDelegate = Scheduler.AddDelayed(() => + { + temporaryMuteFromUpdateInProgress = false; + updateSampleDisabledState(); + }, 50); + } + + #endregion + #region Clipboard support private EditorMenuItem cutMenuItem; @@ -829,7 +853,9 @@ private void onModeChanged(ValueChangedEvent e) private void updateSampleDisabledState() { - samplePlaybackDisabled.Value = clock.SeekingOrStopped.Value || !(currentScreen is ComposeScreen); + samplePlaybackDisabled.Value = clock.SeekingOrStopped.Value + || currentScreen is not ComposeScreen + || temporaryMuteFromUpdateInProgress; } private void seek(UIEvent e, int direction) diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index 96425e8bc8cb..6154485bc24d 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -22,6 +22,17 @@ namespace osu.Game.Screens.Edit { public class EditorBeatmap : TransactionalCommitComponent, IBeatmap, IBeatSnapProvider { + /// + /// Will become true when a new update is queued, and false when all updates have been applied. + /// + /// + /// This is intended to be used to avoid performing operations (like playback of samples) + /// while mutating hitobjects. + /// + public IBindable UpdateInProgress => updateInProgress; + + private readonly BindableBool updateInProgress = new BindableBool(); + /// /// Invoked when a is added to this . /// @@ -225,6 +236,8 @@ public void Update([NotNull] HitObject hitObject) { // updates are debounced regardless of whether a batch is active. batchPendingUpdates.Add(hitObject); + + updateInProgress.Value = true; } /// @@ -234,6 +247,8 @@ public void UpdateAllHitObjects() { foreach (var h in HitObjects) batchPendingUpdates.Add(h); + + updateInProgress.Value = true; } /// @@ -326,6 +341,8 @@ protected override void UpdateState() foreach (var h in deletes) HitObjectRemoved?.Invoke(h); foreach (var h in inserts) HitObjectAdded?.Invoke(h); foreach (var h in updates) HitObjectUpdated?.Invoke(h); + + updateInProgress.Value = false; } ///