mirror of
https://github.com/ppy/osu.git
synced 2025-02-06 02:23:21 +08:00
invoking hitobject updated before invoking removed
This commit is contained in:
parent
f48a743890
commit
8400de4b2e
@ -1,10 +1,12 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests.Editor
|
namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||||
{
|
{
|
||||||
@ -16,13 +18,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
public void TestSingleDeleteAtSameTime()
|
public void TestSingleDeleteAtSameTime()
|
||||||
{
|
{
|
||||||
HitCircle? circle1 = null;
|
HitCircle? circle1 = null;
|
||||||
HitCircle? circle2 = null;
|
|
||||||
|
|
||||||
AddStep("add two circles at the same time", () =>
|
AddStep("add two circles at the same time", () =>
|
||||||
{
|
{
|
||||||
circle1 = new HitCircle();
|
|
||||||
circle2 = new HitCircle();
|
|
||||||
EditorClock.Seek(0);
|
EditorClock.Seek(0);
|
||||||
|
circle1 = new HitCircle();
|
||||||
|
var circle2 = new HitCircle();
|
||||||
EditorBeatmap.Add(circle1);
|
EditorBeatmap.Add(circle1);
|
||||||
EditorBeatmap.Add(circle2);
|
EditorBeatmap.Add(circle2);
|
||||||
EditorBeatmap.SelectedHitObjects.Add(circle1);
|
EditorBeatmap.SelectedHitObjects.Add(circle1);
|
||||||
@ -31,5 +32,33 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
|
|
||||||
AddStep("delete the first circle", () => EditorBeatmap.Remove(circle1));
|
AddStep("delete the first circle", () => EditorBeatmap.Remove(circle1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestBigStackDeleteAtSameTime()
|
||||||
|
{
|
||||||
|
AddStep("add 20 circles at the same time", () =>
|
||||||
|
{
|
||||||
|
EditorClock.Seek(0);
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
EditorBeatmap.Add(new HitCircle());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("select half of the circles", () =>
|
||||||
|
{
|
||||||
|
foreach (var hitObject in EditorBeatmap.HitObjects.SkipLast(10).Reverse())
|
||||||
|
{
|
||||||
|
EditorBeatmap.SelectedHitObjects.Add(hitObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("delete all selected circles", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.Delete);
|
||||||
|
InputManager.ReleaseKey(Key.Delete);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ using osu.Game.Beatmaps.Legacy;
|
|||||||
using osu.Game.Beatmaps.Timing;
|
using osu.Game.Beatmaps.Timing;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit
|
namespace osu.Game.Screens.Edit
|
||||||
@ -79,7 +80,7 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
private readonly IBeatmapProcessor beatmapProcessor;
|
private readonly IBeatmapProcessor beatmapProcessor;
|
||||||
|
|
||||||
private readonly Dictionary<HitObject, Bindable<double>> startTimeBindables = new Dictionary<HitObject, Bindable<double>>();
|
private readonly Dictionary<HitObject, List<IUnbindable>> hitObjectBindables = new Dictionary<HitObject, List<IUnbindable>>();
|
||||||
|
|
||||||
public EditorBeatmap(IBeatmap playableBeatmap, ISkin beatmapSkin = null, BeatmapInfo beatmapInfo = null)
|
public EditorBeatmap(IBeatmap playableBeatmap, ISkin beatmapSkin = null, BeatmapInfo beatmapInfo = null)
|
||||||
{
|
{
|
||||||
@ -97,7 +98,7 @@ namespace osu.Game.Screens.Edit
|
|||||||
beatmapProcessor = playableBeatmap.BeatmapInfo.Ruleset.CreateInstance().CreateBeatmapProcessor(PlayableBeatmap);
|
beatmapProcessor = playableBeatmap.BeatmapInfo.Ruleset.CreateInstance().CreateBeatmapProcessor(PlayableBeatmap);
|
||||||
|
|
||||||
foreach (var obj in HitObjects)
|
foreach (var obj in HitObjects)
|
||||||
trackStartTime(obj);
|
trackBindables(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -222,7 +223,7 @@ namespace osu.Game.Screens.Edit
|
|||||||
/// <param name="hitObject">The <see cref="HitObject"/> to insert.</param>
|
/// <param name="hitObject">The <see cref="HitObject"/> to insert.</param>
|
||||||
public void Insert(int index, HitObject hitObject)
|
public void Insert(int index, HitObject hitObject)
|
||||||
{
|
{
|
||||||
trackStartTime(hitObject);
|
trackBindables(hitObject);
|
||||||
|
|
||||||
mutableHitObjects.Insert(index, hitObject);
|
mutableHitObjects.Insert(index, hitObject);
|
||||||
|
|
||||||
@ -299,9 +300,9 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
mutableHitObjects.RemoveAt(index);
|
mutableHitObjects.RemoveAt(index);
|
||||||
|
|
||||||
var bindable = startTimeBindables[hitObject];
|
var bindables = hitObjectBindables[hitObject];
|
||||||
bindable.UnbindAll();
|
bindables.ForEach(b => b.UnbindAll());
|
||||||
startTimeBindables.Remove(hitObject);
|
hitObjectBindables.Remove(hitObject);
|
||||||
|
|
||||||
BeginChange();
|
BeginChange();
|
||||||
batchPendingDeletes.Add(hitObject);
|
batchPendingDeletes.Add(hitObject);
|
||||||
@ -325,25 +326,25 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
beatmapProcessor?.PreProcess();
|
beatmapProcessor?.PreProcess();
|
||||||
|
|
||||||
|
foreach (var h in batchPendingUpdates) processHitObject(h);
|
||||||
foreach (var h in batchPendingDeletes) processHitObject(h);
|
foreach (var h in batchPendingDeletes) processHitObject(h);
|
||||||
foreach (var h in batchPendingInserts) processHitObject(h);
|
foreach (var h in batchPendingInserts) processHitObject(h);
|
||||||
foreach (var h in batchPendingUpdates) processHitObject(h);
|
|
||||||
|
|
||||||
beatmapProcessor?.PostProcess();
|
beatmapProcessor?.PostProcess();
|
||||||
|
|
||||||
// callbacks may modify the lists so let's be safe about it
|
// callbacks may modify the lists so let's be safe about it
|
||||||
|
var updates = batchPendingUpdates.ToArray();
|
||||||
|
batchPendingUpdates.Clear();
|
||||||
|
|
||||||
var deletes = batchPendingDeletes.ToArray();
|
var deletes = batchPendingDeletes.ToArray();
|
||||||
batchPendingDeletes.Clear();
|
batchPendingDeletes.Clear();
|
||||||
|
|
||||||
var inserts = batchPendingInserts.ToArray();
|
var inserts = batchPendingInserts.ToArray();
|
||||||
batchPendingInserts.Clear();
|
batchPendingInserts.Clear();
|
||||||
|
|
||||||
var updates = batchPendingUpdates.ToArray();
|
foreach (var h in updates) HitObjectUpdated?.Invoke(h);
|
||||||
batchPendingUpdates.Clear();
|
|
||||||
|
|
||||||
foreach (var h in deletes) HitObjectRemoved?.Invoke(h);
|
foreach (var h in deletes) HitObjectRemoved?.Invoke(h);
|
||||||
foreach (var h in inserts) HitObjectAdded?.Invoke(h);
|
foreach (var h in inserts) HitObjectAdded?.Invoke(h);
|
||||||
foreach (var h in updates) HitObjectUpdated?.Invoke(h);
|
|
||||||
|
|
||||||
updateInProgress.Value = false;
|
updateInProgress.Value = false;
|
||||||
}
|
}
|
||||||
@ -355,10 +356,12 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
private void processHitObject(HitObject hitObject) => hitObject.ApplyDefaults(ControlPointInfo, PlayableBeatmap.Difficulty);
|
private void processHitObject(HitObject hitObject) => hitObject.ApplyDefaults(ControlPointInfo, PlayableBeatmap.Difficulty);
|
||||||
|
|
||||||
private void trackStartTime(HitObject hitObject)
|
private void trackBindables(HitObject hitObject)
|
||||||
{
|
{
|
||||||
startTimeBindables[hitObject] = hitObject.StartTimeBindable.GetBoundCopy();
|
var bindables = new List<IUnbindable>(3);
|
||||||
startTimeBindables[hitObject].ValueChanged += _ =>
|
|
||||||
|
var startTimeBindable = hitObject.StartTimeBindable.GetBoundCopy();
|
||||||
|
startTimeBindable.ValueChanged += _ =>
|
||||||
{
|
{
|
||||||
// For now we'll remove and re-add the hitobject. This is not optimal and can be improved if required.
|
// For now we'll remove and re-add the hitobject. This is not optimal and can be improved if required.
|
||||||
mutableHitObjects.Remove(hitObject);
|
mutableHitObjects.Remove(hitObject);
|
||||||
@ -368,6 +371,20 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
Update(hitObject);
|
Update(hitObject);
|
||||||
};
|
};
|
||||||
|
bindables.Add(startTimeBindable);
|
||||||
|
|
||||||
|
if (hitObject is IHasComboInformation hasCombo)
|
||||||
|
{
|
||||||
|
var comboIndexBindable = hasCombo.ComboIndexBindable.GetBoundCopy();
|
||||||
|
comboIndexBindable.ValueChanged += _ => Update(hitObject);
|
||||||
|
bindables.Add(comboIndexBindable);
|
||||||
|
|
||||||
|
var indexInCurrentComboBindable = hasCombo.IndexInCurrentComboBindable.GetBoundCopy();
|
||||||
|
indexInCurrentComboBindable.ValueChanged += _ => Update(hitObject);
|
||||||
|
bindables.Add(indexInCurrentComboBindable);
|
||||||
|
}
|
||||||
|
|
||||||
|
hitObjectBindables[hitObject] = bindables;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int findInsertionIndex(IReadOnlyList<HitObject> list, double startTime)
|
private int findInsertionIndex(IReadOnlyList<HitObject> list, double startTime)
|
||||||
|
Loading…
Reference in New Issue
Block a user