Make EditorBeatmap implement TransactionalCommitComponent

This commit is contained in:
Dean Herbert 2020-10-08 17:18:20 +09:00
parent a9bca671d0
commit 0781fbd443
2 changed files with 24 additions and 39 deletions

View File

@ -8,7 +8,6 @@ using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps.Timing; using osu.Game.Beatmaps.Timing;
@ -18,7 +17,7 @@ using osu.Game.Skinning;
namespace osu.Game.Screens.Edit namespace osu.Game.Screens.Edit
{ {
public class EditorBeatmap : Component, IBeatmap, IBeatSnapProvider public class EditorBeatmap : TransactionalCommitComponent, IBeatmap, IBeatSnapProvider
{ {
/// <summary> /// <summary>
/// Invoked when a <see cref="HitObject"/> is added to this <see cref="EditorBeatmap"/>. /// Invoked when a <see cref="HitObject"/> is added to this <see cref="EditorBeatmap"/>.
@ -89,19 +88,16 @@ namespace osu.Game.Screens.Edit
private IList mutableHitObjects => (IList)PlayableBeatmap.HitObjects; private IList mutableHitObjects => (IList)PlayableBeatmap.HitObjects;
private bool isBatchApplying;
/// <summary> /// <summary>
/// Adds a collection of <see cref="HitObject"/>s to this <see cref="EditorBeatmap"/>. /// Adds a collection of <see cref="HitObject"/>s to this <see cref="EditorBeatmap"/>.
/// </summary> /// </summary>
/// <param name="hitObjects">The <see cref="HitObject"/>s to add.</param> /// <param name="hitObjects">The <see cref="HitObject"/>s to add.</param>
public void AddRange(IEnumerable<HitObject> hitObjects) public void AddRange(IEnumerable<HitObject> hitObjects)
{ {
ApplyBatchChanges(_ => BeginChange();
{
foreach (var h in hitObjects) foreach (var h in hitObjects)
Add(h); Add(h);
}); EndChange();
} }
/// <summary> /// <summary>
@ -129,7 +125,7 @@ namespace osu.Game.Screens.Edit
mutableHitObjects.Insert(index, hitObject); mutableHitObjects.Insert(index, hitObject);
if (isBatchApplying) if (TransactionActive)
batchPendingInserts.Add(hitObject); batchPendingInserts.Add(hitObject);
else else
{ {
@ -148,16 +144,8 @@ namespace osu.Game.Screens.Edit
/// <param name="hitObject">The <see cref="HitObject"/> to update.</param> /// <param name="hitObject">The <see cref="HitObject"/> to update.</param>
public void UpdateHitObject([NotNull] HitObject hitObject) public void UpdateHitObject([NotNull] HitObject hitObject)
{ {
if (isBatchApplying) // updates are debounced regardless of whether a batch is active.
batchPendingUpdates.Add(hitObject); batchPendingUpdates.Add(hitObject);
else
{
beatmapProcessor?.PreProcess();
processHitObject(hitObject);
beatmapProcessor?.PostProcess();
HitObjectUpdated?.Invoke(hitObject);
}
} }
/// <summary> /// <summary>
@ -182,11 +170,10 @@ namespace osu.Game.Screens.Edit
/// <param name="hitObjects">The <see cref="HitObject"/>s to remove.</param> /// <param name="hitObjects">The <see cref="HitObject"/>s to remove.</param>
public void RemoveRange(IEnumerable<HitObject> hitObjects) public void RemoveRange(IEnumerable<HitObject> hitObjects)
{ {
ApplyBatchChanges(_ => BeginChange();
{
foreach (var h in hitObjects) foreach (var h in hitObjects)
Remove(h); Remove(h);
}); EndChange();
} }
/// <summary> /// <summary>
@ -210,7 +197,7 @@ namespace osu.Game.Screens.Edit
bindable.UnbindAll(); bindable.UnbindAll();
startTimeBindables.Remove(hitObject); startTimeBindables.Remove(hitObject);
if (isBatchApplying) if (TransactionActive)
batchPendingDeletes.Add(hitObject); batchPendingDeletes.Add(hitObject);
else else
{ {
@ -229,18 +216,18 @@ namespace osu.Game.Screens.Edit
private readonly HashSet<HitObject> batchPendingUpdates = new HashSet<HitObject>(); private readonly HashSet<HitObject> batchPendingUpdates = new HashSet<HitObject>();
/// <summary> protected override void Update()
/// Apply a batch of operations in one go, without performing Pre/Postprocessing each time.
/// </summary>
/// <param name="applyFunction">The function which will apply the batch changes.</param>
public void ApplyBatchChanges(Action<EditorBeatmap> applyFunction)
{ {
if (isBatchApplying) base.Update();
throw new InvalidOperationException("Attempting to perform a batch application from within an existing batch");
isBatchApplying = true; if (batchPendingUpdates.Count > 0)
UpdateState();
}
applyFunction(this); protected override void UpdateState()
{
if (batchPendingUpdates.Count == 0 && batchPendingDeletes.Count == 0 && batchPendingInserts.Count == 0)
return;
beatmapProcessor?.PreProcess(); beatmapProcessor?.PreProcess();
@ -257,8 +244,6 @@ namespace osu.Game.Screens.Edit
batchPendingDeletes.Clear(); batchPendingDeletes.Clear();
batchPendingInserts.Clear(); batchPendingInserts.Clear();
batchPendingUpdates.Clear(); batchPendingUpdates.Clear();
isBatchApplying = false;
} }
/// <summary> /// <summary>
@ -309,7 +294,7 @@ namespace osu.Game.Screens.Edit
/// <summary> /// <summary>
/// Update all hit objects with potentially changed difficulty or control point data. /// Update all hit objects with potentially changed difficulty or control point data.
/// </summary> /// </summary>
public void UpdateBeatmap() public void UpdateAllHitObjects()
{ {
foreach (var h in HitObjects) foreach (var h in HitObjects)
batchPendingUpdates.Add(h); batchPendingUpdates.Add(h);

View File

@ -93,7 +93,7 @@ namespace osu.Game.Screens.Edit.Setup
Beatmap.Value.BeatmapInfo.BaseDifficulty.ApproachRate = approachRateSlider.Current.Value; Beatmap.Value.BeatmapInfo.BaseDifficulty.ApproachRate = approachRateSlider.Current.Value;
Beatmap.Value.BeatmapInfo.BaseDifficulty.OverallDifficulty = overallDifficultySlider.Current.Value; Beatmap.Value.BeatmapInfo.BaseDifficulty.OverallDifficulty = overallDifficultySlider.Current.Value;
editorBeatmap.UpdateBeatmap(); editorBeatmap.UpdateAllHitObjects();
} }
} }
} }