1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 21:03:08 +08:00

Remove generic editor beatmap (#7398)

Remove generic editor beatmap

Co-authored-by: Dean Herbert <pe@ppy.sh>
This commit is contained in:
Dean Herbert 2020-01-01 22:40:07 +09:00
commit 6a992b340d
10 changed files with 61 additions and 70 deletions

View File

@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Osu.Tests
}; };
[Cached(typeof(IEditorBeatmap))] [Cached(typeof(IEditorBeatmap))]
private readonly EditorBeatmap<OsuHitObject> editorBeatmap; private readonly EditorBeatmap editorBeatmap;
[Cached] [Cached]
private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor();
@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Tests
public TestSceneOsuDistanceSnapGrid() public TestSceneOsuDistanceSnapGrid()
{ {
editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap()); editorBeatmap = new EditorBeatmap(new OsuBeatmap());
} }
[SetUp] [SetUp]

View File

@ -91,10 +91,10 @@ namespace osu.Game.Rulesets.Osu.Edit
if (sourceIndex == -1) if (sourceIndex == -1)
return null; return null;
OsuHitObject sourceObject = EditorBeatmap.HitObjects[sourceIndex]; HitObject sourceObject = EditorBeatmap.HitObjects[sourceIndex];
int targetIndex = sourceIndex + targetOffset; int targetIndex = sourceIndex + targetOffset;
OsuHitObject targetObject = null; HitObject targetObject = null;
// Keep advancing the target object while its start time falls before the end time of the source object // Keep advancing the target object while its start time falls before the end time of the source object
while (true) while (true)
@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu.Edit
targetIndex++; targetIndex++;
} }
return new OsuDistanceSnapGrid(sourceObject, targetObject); return new OsuDistanceSnapGrid((OsuHitObject)sourceObject, (OsuHitObject)targetObject);
} }
} }
} }

View File

@ -20,7 +20,7 @@ namespace osu.Game.Tests.Beatmaps
[Test] [Test]
public void TestHitObjectAddEvent() public void TestHitObjectAddEvent()
{ {
var editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap()); var editorBeatmap = new EditorBeatmap(new OsuBeatmap());
HitObject addedObject = null; HitObject addedObject = null;
editorBeatmap.HitObjectAdded += h => addedObject = h; editorBeatmap.HitObjectAdded += h => addedObject = h;
@ -38,7 +38,7 @@ namespace osu.Game.Tests.Beatmaps
public void HitObjectRemoveEvent() public void HitObjectRemoveEvent()
{ {
var hitCircle = new HitCircle(); var hitCircle = new HitCircle();
var editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap { HitObjects = { hitCircle } }); var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } });
HitObject removedObject = null; HitObject removedObject = null;
editorBeatmap.HitObjectRemoved += h => removedObject = h; editorBeatmap.HitObjectRemoved += h => removedObject = h;
@ -55,7 +55,7 @@ namespace osu.Game.Tests.Beatmaps
public void TestInitialHitObjectStartTimeChangeEvent() public void TestInitialHitObjectStartTimeChangeEvent()
{ {
var hitCircle = new HitCircle(); var hitCircle = new HitCircle();
var editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap { HitObjects = { hitCircle } }); var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } });
HitObject changedObject = null; HitObject changedObject = null;
editorBeatmap.StartTimeChanged += h => changedObject = h; editorBeatmap.StartTimeChanged += h => changedObject = h;
@ -71,7 +71,7 @@ namespace osu.Game.Tests.Beatmaps
[Test] [Test]
public void TestAddedHitObjectStartTimeChangeEvent() public void TestAddedHitObjectStartTimeChangeEvent()
{ {
var editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap()); var editorBeatmap = new EditorBeatmap(new OsuBeatmap());
HitObject changedObject = null; HitObject changedObject = null;
editorBeatmap.StartTimeChanged += h => changedObject = h; editorBeatmap.StartTimeChanged += h => changedObject = h;
@ -92,7 +92,7 @@ namespace osu.Game.Tests.Beatmaps
public void TestRemovedHitObjectStartTimeChangeEvent() public void TestRemovedHitObjectStartTimeChangeEvent()
{ {
var hitCircle = new HitCircle(); var hitCircle = new HitCircle();
var editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap { HitObjects = { hitCircle } }); var editorBeatmap = new EditorBeatmap(new OsuBeatmap { HitObjects = { hitCircle } });
HitObject changedObject = null; HitObject changedObject = null;
editorBeatmap.StartTimeChanged += h => changedObject = h; editorBeatmap.StartTimeChanged += h => changedObject = h;
@ -110,7 +110,7 @@ namespace osu.Game.Tests.Beatmaps
[Test] [Test]
public void TestAddHitObjectInMiddle() public void TestAddHitObjectInMiddle()
{ {
var editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap var editorBeatmap = new EditorBeatmap(new OsuBeatmap
{ {
HitObjects = HitObjects =
{ {
@ -134,7 +134,7 @@ namespace osu.Game.Tests.Beatmaps
public void TestResortWhenStartTimeChanged() public void TestResortWhenStartTimeChanged()
{ {
var hitCircle = new HitCircle { StartTime = 1000 }; var hitCircle = new HitCircle { StartTime = 1000 };
var editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap var editorBeatmap = new EditorBeatmap(new OsuBeatmap
{ {
HitObjects = HitObjects =
{ {

View File

@ -6,7 +6,6 @@ using osu.Framework.Testing;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Edit;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Edit; using osu.Game.Screens.Edit;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
@ -183,7 +182,7 @@ namespace osu.Game.Tests.Editor
private class TestHitObjectComposer : OsuHitObjectComposer private class TestHitObjectComposer : OsuHitObjectComposer
{ {
public new EditorBeatmap<OsuHitObject> EditorBeatmap => base.EditorBeatmap; public new EditorBeatmap EditorBeatmap => base.EditorBeatmap;
public TestHitObjectComposer() public TestHitObjectComposer()
: base(new OsuRuleset()) : base(new OsuRuleset())

View File

@ -8,7 +8,6 @@ using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.Edit; using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose.Components; using osu.Game.Screens.Edit.Compose.Components;
using osuTK; using osuTK;
@ -22,14 +21,14 @@ namespace osu.Game.Tests.Visual.Editor
private static readonly Vector2 grid_position = new Vector2(512, 384); private static readonly Vector2 grid_position = new Vector2(512, 384);
[Cached(typeof(IEditorBeatmap))] [Cached(typeof(IEditorBeatmap))]
private readonly EditorBeatmap<OsuHitObject> editorBeatmap; private readonly EditorBeatmap editorBeatmap;
[Cached(typeof(IDistanceSnapProvider))] [Cached(typeof(IDistanceSnapProvider))]
private readonly SnapProvider snapProvider = new SnapProvider(); private readonly SnapProvider snapProvider = new SnapProvider();
public TestSceneDistanceSnapGrid() public TestSceneDistanceSnapGrid()
{ {
editorBeatmap = new EditorBeatmap<OsuHitObject>(new OsuBeatmap()); editorBeatmap = new EditorBeatmap(new OsuBeatmap());
editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length }); editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = beat_length });
} }

View File

@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Editor
{ {
Beatmap.Value = new WaveformTestBeatmap(audio); Beatmap.Value = new WaveformTestBeatmap(audio);
var editorBeatmap = new EditorBeatmap<HitObject>((Beatmap<HitObject>)Beatmap.Value.Beatmap); var editorBeatmap = new EditorBeatmap((Beatmap<HitObject>)Beatmap.Value.Beatmap);
Children = new Drawable[] Children = new Drawable[]
{ {

View File

@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Edit
private readonly DrawableRuleset<TObject> drawableRuleset; private readonly DrawableRuleset<TObject> drawableRuleset;
[Resolved] [Resolved]
private IEditorBeatmap<TObject> beatmap { get; set; } private IEditorBeatmap beatmap { get; set; }
public DrawableEditRulesetWrapper(DrawableRuleset<TObject> drawableRuleset) public DrawableEditRulesetWrapper(DrawableRuleset<TObject> drawableRuleset)
{ {

View File

@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Edit
{ {
protected IRulesetConfigManager Config { get; private set; } protected IRulesetConfigManager Config { get; private set; }
protected new EditorBeatmap<TObject> EditorBeatmap { get; private set; } protected new EditorBeatmap EditorBeatmap { get; private set; }
protected readonly Ruleset Ruleset; protected readonly Ruleset Ruleset;
@ -148,14 +148,13 @@ namespace osu.Game.Rulesets.Edit
beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap); beatmapProcessor = Ruleset.CreateBeatmapProcessor(playableBeatmap);
base.EditorBeatmap = EditorBeatmap = new EditorBeatmap<TObject>(playableBeatmap); base.EditorBeatmap = EditorBeatmap = new EditorBeatmap(playableBeatmap);
EditorBeatmap.HitObjectAdded += addHitObject; EditorBeatmap.HitObjectAdded += addHitObject;
EditorBeatmap.HitObjectRemoved += removeHitObject; EditorBeatmap.HitObjectRemoved += removeHitObject;
EditorBeatmap.StartTimeChanged += UpdateHitObject; EditorBeatmap.StartTimeChanged += UpdateHitObject;
var dependencies = new DependencyContainer(parent); var dependencies = new DependencyContainer(parent);
dependencies.CacheAs<IEditorBeatmap>(EditorBeatmap); dependencies.CacheAs<IEditorBeatmap>(EditorBeatmap);
dependencies.CacheAs<IEditorBeatmap<TObject>>(EditorBeatmap);
Config = dependencies.Get<RulesetConfigCache>().GetConfigFor(Ruleset); Config = dependencies.Get<RulesetConfigCache>().GetConfigFor(Ruleset);

View File

@ -2,6 +2,7 @@
// 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; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -11,28 +12,27 @@ using osu.Game.Rulesets.Objects;
namespace osu.Game.Screens.Edit namespace osu.Game.Screens.Edit
{ {
public class EditorBeatmap<T> : IEditorBeatmap<T> public class EditorBeatmap : IEditorBeatmap
where T : HitObject
{ {
/// <summary> /// <summary>
/// Invoked when a <see cref="HitObject"/> is added to this <see cref="EditorBeatmap{T}"/>. /// Invoked when a <see cref="HitObject"/> is added to this <see cref="EditorBeatmap"/>.
/// </summary> /// </summary>
public event Action<HitObject> HitObjectAdded; public event Action<HitObject> HitObjectAdded;
/// <summary> /// <summary>
/// Invoked when a <see cref="HitObject"/> is removed from this <see cref="EditorBeatmap{T}"/>. /// Invoked when a <see cref="HitObject"/> is removed from this <see cref="EditorBeatmap"/>.
/// </summary> /// </summary>
public event Action<HitObject> HitObjectRemoved; public event Action<HitObject> HitObjectRemoved;
/// <summary> /// <summary>
/// Invoked when the start time of a <see cref="HitObject"/> in this <see cref="EditorBeatmap{T}"/> was changed. /// Invoked when the start time of a <see cref="HitObject"/> in this <see cref="EditorBeatmap"/> was changed.
/// </summary> /// </summary>
public event Action<HitObject> StartTimeChanged; public event Action<HitObject> StartTimeChanged;
private readonly Dictionary<T, Bindable<double>> startTimeBindables = new Dictionary<T, Bindable<double>>(); private readonly Dictionary<HitObject, Bindable<double>> startTimeBindables = new Dictionary<HitObject, Bindable<double>>();
private readonly Beatmap<T> beatmap; private readonly IBeatmap beatmap;
public EditorBeatmap(Beatmap<T> beatmap) public EditorBeatmap(IBeatmap beatmap)
{ {
this.beatmap = beatmap; this.beatmap = beatmap;
@ -54,70 +54,73 @@ namespace osu.Game.Screens.Edit
public double TotalBreakTime => beatmap.TotalBreakTime; public double TotalBreakTime => beatmap.TotalBreakTime;
public IReadOnlyList<T> HitObjects => beatmap.HitObjects; public IReadOnlyList<HitObject> HitObjects => beatmap.HitObjects;
IReadOnlyList<HitObject> IBeatmap.HitObjects => beatmap.HitObjects; IReadOnlyList<HitObject> IBeatmap.HitObjects => beatmap.HitObjects;
public IEnumerable<BeatmapStatistic> GetStatistics() => beatmap.GetStatistics(); public IEnumerable<BeatmapStatistic> GetStatistics() => beatmap.GetStatistics();
public IBeatmap Clone() => (EditorBeatmap<T>)MemberwiseClone(); public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone();
private IList mutableHitObjects => (IList)beatmap.HitObjects;
/// <summary> /// <summary>
/// Adds a <see cref="HitObject"/> to this <see cref="EditorBeatmap{T}"/>. /// Adds a <see cref="HitObject"/> to this <see cref="EditorBeatmap"/>.
/// </summary> /// </summary>
/// <param name="hitObject">The <see cref="HitObject"/> to add.</param> /// <param name="hitObject">The <see cref="HitObject"/> to add.</param>
public void Add(T hitObject) public void Add(HitObject hitObject)
{ {
trackStartTime(hitObject); trackStartTime(hitObject);
// Preserve existing sorting order in the beatmap // Preserve existing sorting order in the beatmap
var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); var insertionIndex = findInsertionIndex(beatmap.HitObjects, hitObject.StartTime);
beatmap.HitObjects.Insert(insertionIndex + 1, hitObject); mutableHitObjects.Insert(insertionIndex + 1, hitObject);
HitObjectAdded?.Invoke(hitObject); HitObjectAdded?.Invoke(hitObject);
} }
/// <summary> /// <summary>
/// Removes a <see cref="HitObject"/> from this <see cref="EditorBeatmap{T}"/>. /// Removes a <see cref="HitObject"/> from this <see cref="EditorBeatmap"/>.
/// </summary> /// </summary>
/// <param name="hitObject">The <see cref="HitObject"/> to add.</param> /// <param name="hitObject">The <see cref="HitObject"/> to add.</param>
public void Remove(T hitObject) public void Remove(HitObject hitObject)
{
if (beatmap.HitObjects.Remove(hitObject))
{ {
if (!mutableHitObjects.Contains(hitObject))
return;
mutableHitObjects.Remove(hitObject);
var bindable = startTimeBindables[hitObject]; var bindable = startTimeBindables[hitObject];
bindable.UnbindAll(); bindable.UnbindAll();
startTimeBindables.Remove(hitObject); startTimeBindables.Remove(hitObject);
HitObjectRemoved?.Invoke(hitObject); HitObjectRemoved?.Invoke(hitObject);
} }
}
private void trackStartTime(T hitObject) private void trackStartTime(HitObject hitObject)
{ {
startTimeBindables[hitObject] = hitObject.StartTimeBindable.GetBoundCopy(); startTimeBindables[hitObject] = hitObject.StartTimeBindable.GetBoundCopy();
startTimeBindables[hitObject].ValueChanged += _ => startTimeBindables[hitObject].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.
beatmap.HitObjects.Remove(hitObject); mutableHitObjects.Remove(hitObject);
var insertionIndex = beatmap.HitObjects.FindLastIndex(h => h.StartTime <= hitObject.StartTime); var insertionIndex = findInsertionIndex(beatmap.HitObjects, hitObject.StartTime);
beatmap.HitObjects.Insert(insertionIndex + 1, hitObject); mutableHitObjects.Insert(insertionIndex + 1, hitObject);
StartTimeChanged?.Invoke(hitObject); StartTimeChanged?.Invoke(hitObject);
}; };
} }
/// <summary> private int findInsertionIndex(IReadOnlyList<HitObject> list, double startTime)
/// Adds a <see cref="HitObject"/> to this <see cref="EditorBeatmap{T}"/>. {
/// </summary> for (int i = 0; i < list.Count; i++)
/// <param name="hitObject">The <see cref="HitObject"/> to add.</param> {
public void Add(HitObject hitObject) => Add((T)hitObject); if (list[i].StartTime > startTime)
return i - 1;
}
/// <summary> return list.Count - 1;
/// Removes a <see cref="HitObject"/> from this <see cref="EditorBeatmap{T}"/>. }
/// </summary>
/// <param name="hitObject">The <see cref="HitObject"/> to add.</param>
public void Remove(HitObject hitObject) => Remove((T)hitObject);
} }
} }

View File

@ -10,7 +10,7 @@ namespace osu.Game.Screens.Edit
{ {
/// <summary> /// <summary>
/// Interface for the <see cref="IBeatmap"/> contained by the see <see cref="HitObjectComposer"/>. /// Interface for the <see cref="IBeatmap"/> contained by the see <see cref="HitObjectComposer"/>.
/// Children of <see cref="HitObjectComposer"/> may resolve the beatmap via <see cref="IEditorBeatmap"/> or <see cref="IEditorBeatmap{T}"/>. /// Children of <see cref="HitObjectComposer"/> may resolve the beatmap via <see cref="IEditorBeatmap"/>.
/// </summary> /// </summary>
public interface IEditorBeatmap : IBeatmap public interface IEditorBeatmap : IBeatmap
{ {
@ -25,17 +25,8 @@ namespace osu.Game.Screens.Edit
event Action<HitObject> HitObjectRemoved; event Action<HitObject> HitObjectRemoved;
/// <summary> /// <summary>
/// Invoked when the start time of a <see cref="HitObject"/> in this <see cref="EditorBeatmap{T}"/> was changed. /// Invoked when the start time of a <see cref="HitObject"/> in this <see cref="EditorBeatmap"/> was changed.
/// </summary> /// </summary>
event Action<HitObject> StartTimeChanged; event Action<HitObject> StartTimeChanged;
} }
/// <summary>
/// Interface for the <see cref="IBeatmap"/> contained by the see <see cref="HitObjectComposer"/>.
/// Children of <see cref="HitObjectComposer"/> may resolve the beatmap via <see cref="IEditorBeatmap"/> or <see cref="IEditorBeatmap{T}"/>.
/// </summary>
public interface IEditorBeatmap<out T> : IEditorBeatmap, IBeatmap<T>
where T : HitObject
{
}
} }