mirror of
https://github.com/ppy/osu.git
synced 2025-01-18 11:02:57 +08:00
Merge pull request #30960 from bdach/bookmarks
Implement basic bookmark support in editor
This commit is contained in:
commit
48bf2fa001
@ -109,9 +109,9 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
95901, 106450, 116999, 119637, 130186, 140735, 151285,
|
95901, 106450, 116999, 119637, 130186, 140735, 151285,
|
||||||
161834, 164471, 175020, 185570, 196119, 206669, 209306
|
161834, 164471, 175020, 185570, 196119, 206669, 209306
|
||||||
};
|
};
|
||||||
Assert.AreEqual(expectedBookmarks.Length, beatmap.BeatmapInfo.Bookmarks.Length);
|
Assert.AreEqual(expectedBookmarks.Length, beatmap.Bookmarks.Length);
|
||||||
for (int i = 0; i < expectedBookmarks.Length; i++)
|
for (int i = 0; i < expectedBookmarks.Length; i++)
|
||||||
Assert.AreEqual(expectedBookmarks[i], beatmap.BeatmapInfo.Bookmarks[i]);
|
Assert.AreEqual(expectedBookmarks[i], beatmap.Bookmarks[i]);
|
||||||
Assert.AreEqual(1.8, beatmap.DistanceSpacing);
|
Assert.AreEqual(1.8, beatmap.DistanceSpacing);
|
||||||
Assert.AreEqual(4, beatmap.BeatmapInfo.BeatDivisor);
|
Assert.AreEqual(4, beatmap.BeatmapInfo.BeatDivisor);
|
||||||
Assert.AreEqual(4, beatmap.GridSize);
|
Assert.AreEqual(4, beatmap.GridSize);
|
||||||
|
@ -73,9 +73,9 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
95901, 106450, 116999, 119637, 130186, 140735, 151285,
|
95901, 106450, 116999, 119637, 130186, 140735, 151285,
|
||||||
161834, 164471, 175020, 185570, 196119, 206669, 209306
|
161834, 164471, 175020, 185570, 196119, 206669, 209306
|
||||||
};
|
};
|
||||||
Assert.AreEqual(expectedBookmarks.Length, beatmapInfo.Bookmarks.Length);
|
Assert.AreEqual(expectedBookmarks.Length, beatmap.Bookmarks.Length);
|
||||||
for (int i = 0; i < expectedBookmarks.Length; i++)
|
for (int i = 0; i < expectedBookmarks.Length; i++)
|
||||||
Assert.AreEqual(expectedBookmarks[i], beatmapInfo.Bookmarks[i]);
|
Assert.AreEqual(expectedBookmarks[i], beatmap.Bookmarks[i]);
|
||||||
Assert.AreEqual(1.8, beatmap.DistanceSpacing);
|
Assert.AreEqual(1.8, beatmap.DistanceSpacing);
|
||||||
Assert.AreEqual(4, beatmapInfo.BeatDivisor);
|
Assert.AreEqual(4, beatmapInfo.BeatDivisor);
|
||||||
Assert.AreEqual(4, beatmap.GridSize);
|
Assert.AreEqual(4, beatmap.GridSize);
|
||||||
|
@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
beatmap.ControlPointInfo.Add(50000, new DifficultyControlPoint { SliderVelocity = 2 });
|
beatmap.ControlPointInfo.Add(50000, new DifficultyControlPoint { SliderVelocity = 2 });
|
||||||
beatmap.ControlPointInfo.Add(80000, new EffectControlPoint { KiaiMode = true });
|
beatmap.ControlPointInfo.Add(80000, new EffectControlPoint { KiaiMode = true });
|
||||||
beatmap.ControlPointInfo.Add(110000, new EffectControlPoint { KiaiMode = false });
|
beatmap.ControlPointInfo.Add(110000, new EffectControlPoint { KiaiMode = false });
|
||||||
beatmap.BeatmapInfo.Bookmarks = new[] { 75000, 125000 };
|
beatmap.Bookmarks = new[] { 75000, 125000 };
|
||||||
beatmap.Breaks.Add(new ManualBreakPeriod(90000, 120000));
|
beatmap.Breaks.Add(new ManualBreakPeriod(90000, 120000));
|
||||||
|
|
||||||
editorBeatmap = new EditorBeatmap(beatmap);
|
editorBeatmap = new EditorBeatmap(beatmap);
|
||||||
|
@ -139,6 +139,8 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public int CountdownOffset { get; set; }
|
public int CountdownOffset { get; set; }
|
||||||
|
|
||||||
|
public int[] Bookmarks { get; set; } = Array.Empty<int>();
|
||||||
|
|
||||||
IBeatmap IBeatmap.Clone() => Clone();
|
IBeatmap IBeatmap.Clone() => Clone();
|
||||||
|
|
||||||
public Beatmap<T> Clone() => (Beatmap<T>)MemberwiseClone();
|
public Beatmap<T> Clone() => (Beatmap<T>)MemberwiseClone();
|
||||||
|
@ -85,6 +85,7 @@ namespace osu.Game.Beatmaps
|
|||||||
beatmap.TimelineZoom = original.TimelineZoom;
|
beatmap.TimelineZoom = original.TimelineZoom;
|
||||||
beatmap.Countdown = original.Countdown;
|
beatmap.Countdown = original.Countdown;
|
||||||
beatmap.CountdownOffset = original.CountdownOffset;
|
beatmap.CountdownOffset = original.CountdownOffset;
|
||||||
|
beatmap.Bookmarks = original.Bookmarks;
|
||||||
|
|
||||||
return beatmap;
|
return beatmap;
|
||||||
}
|
}
|
||||||
|
@ -231,9 +231,6 @@ namespace osu.Game.Beatmaps
|
|||||||
[Obsolete("Use ScoreManager.GetMaximumAchievableComboAsync instead.")]
|
[Obsolete("Use ScoreManager.GetMaximumAchievableComboAsync instead.")]
|
||||||
public int? MaxCombo { get; set; }
|
public int? MaxCombo { get; set; }
|
||||||
|
|
||||||
[Ignored]
|
|
||||||
public int[] Bookmarks { get; set; } = Array.Empty<int>();
|
|
||||||
|
|
||||||
public int BeatmapVersion;
|
public int BeatmapVersion;
|
||||||
|
|
||||||
public BeatmapInfo Clone() => (BeatmapInfo)this.Detach().MemberwiseClone();
|
public BeatmapInfo Clone() => (BeatmapInfo)this.Detach().MemberwiseClone();
|
||||||
|
@ -305,7 +305,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
switch (pair.Key)
|
switch (pair.Key)
|
||||||
{
|
{
|
||||||
case @"Bookmarks":
|
case @"Bookmarks":
|
||||||
beatmap.BeatmapInfo.Bookmarks = pair.Value.Split(',').Select(v =>
|
beatmap.Bookmarks = pair.Value.Split(',').Select(v =>
|
||||||
{
|
{
|
||||||
bool result = int.TryParse(v, out int val);
|
bool result = int.TryParse(v, out int val);
|
||||||
return new { result, val };
|
return new { result, val };
|
||||||
|
@ -110,8 +110,8 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
{
|
{
|
||||||
writer.WriteLine("[Editor]");
|
writer.WriteLine("[Editor]");
|
||||||
|
|
||||||
if (beatmap.BeatmapInfo.Bookmarks.Length > 0)
|
if (beatmap.Bookmarks.Length > 0)
|
||||||
writer.WriteLine(FormattableString.Invariant($"Bookmarks: {string.Join(',', beatmap.BeatmapInfo.Bookmarks)}"));
|
writer.WriteLine(FormattableString.Invariant($"Bookmarks: {string.Join(',', beatmap.Bookmarks)}"));
|
||||||
writer.WriteLine(FormattableString.Invariant($"DistanceSpacing: {beatmap.DistanceSpacing}"));
|
writer.WriteLine(FormattableString.Invariant($"DistanceSpacing: {beatmap.DistanceSpacing}"));
|
||||||
writer.WriteLine(FormattableString.Invariant($"BeatDivisor: {beatmap.BeatmapInfo.BeatDivisor}"));
|
writer.WriteLine(FormattableString.Invariant($"BeatDivisor: {beatmap.BeatmapInfo.BeatDivisor}"));
|
||||||
writer.WriteLine(FormattableString.Invariant($"GridSize: {beatmap.GridSize}"));
|
writer.WriteLine(FormattableString.Invariant($"GridSize: {beatmap.GridSize}"));
|
||||||
|
@ -107,6 +107,8 @@ namespace osu.Game.Beatmaps
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
int CountdownOffset { get; internal set; }
|
int CountdownOffset { get; internal set; }
|
||||||
|
|
||||||
|
int[] Bookmarks { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a shallow-clone of this beatmap and returns it.
|
/// Creates a shallow-clone of this beatmap and returns it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -152,6 +152,10 @@ namespace osu.Game.Input.Bindings
|
|||||||
new KeyBinding(new[] { InputKey.Control, InputKey.Right }, GlobalAction.EditorSeekToNextHitObject),
|
new KeyBinding(new[] { InputKey.Control, InputKey.Right }, GlobalAction.EditorSeekToNextHitObject),
|
||||||
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.Left }, GlobalAction.EditorSeekToPreviousSamplePoint),
|
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.Left }, GlobalAction.EditorSeekToPreviousSamplePoint),
|
||||||
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.Right }, GlobalAction.EditorSeekToNextSamplePoint),
|
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.Right }, GlobalAction.EditorSeekToNextSamplePoint),
|
||||||
|
new KeyBinding(new[] { InputKey.Control, InputKey.B }, GlobalAction.EditorAddBookmark),
|
||||||
|
new KeyBinding(new[] { InputKey.Control, InputKey.Shift, InputKey.B }, GlobalAction.EditorRemoveClosestBookmark),
|
||||||
|
new KeyBinding(new[] { InputKey.Alt, InputKey.Left }, GlobalAction.EditorSeekToPreviousBookmark),
|
||||||
|
new KeyBinding(new[] { InputKey.Alt, InputKey.Right }, GlobalAction.EditorSeekToNextBookmark),
|
||||||
};
|
};
|
||||||
|
|
||||||
private static IEnumerable<KeyBinding> editorTestPlayKeyBindings => new[]
|
private static IEnumerable<KeyBinding> editorTestPlayKeyBindings => new[]
|
||||||
@ -476,6 +480,18 @@ namespace osu.Game.Input.Bindings
|
|||||||
|
|
||||||
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorCycleGridType))]
|
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorCycleGridType))]
|
||||||
EditorCycleGridType,
|
EditorCycleGridType,
|
||||||
|
|
||||||
|
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorAddBookmark))]
|
||||||
|
EditorAddBookmark,
|
||||||
|
|
||||||
|
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorRemoveClosestBookmark))]
|
||||||
|
EditorRemoveClosestBookmark,
|
||||||
|
|
||||||
|
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorSeekToPreviousBookmark))]
|
||||||
|
EditorSeekToPreviousBookmark,
|
||||||
|
|
||||||
|
[LocalisableDescription(typeof(GlobalActionKeyBindingStrings), nameof(GlobalActionKeyBindingStrings.EditorSeekToNextBookmark))]
|
||||||
|
EditorSeekToNextBookmark,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum GlobalActionCategory
|
public enum GlobalActionCategory
|
||||||
|
@ -154,6 +154,36 @@ namespace osu.Game.Localisation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString TimelineShowTicks => new TranslatableString(getKey(@"timeline_show_ticks"), @"Show ticks");
|
public static LocalisableString TimelineShowTicks => new TranslatableString(getKey(@"timeline_show_ticks"), @"Show ticks");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Bookmarks"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString Bookmarks => new TranslatableString(getKey(@"bookmarks"), @"Bookmarks");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Add bookmark"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString AddBookmark => new TranslatableString(getKey(@"add_bookmark"), @"Add bookmark");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Remove closest bookmark"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString RemoveClosestBookmark => new TranslatableString(getKey(@"remove_closest_bookmark"), @"Remove closest bookmark");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Seek to previous bookmark"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString SeekToPreviousBookmark => new TranslatableString(getKey(@"seek_to_previous_bookmark"), @"Seek to previous bookmark");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Seek to next bookmark"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString SeekToNextBookmark => new TranslatableString(getKey(@"seek_to_next_bookmark"), @"Seek to next bookmark");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Reset bookmarks"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString ResetBookmarks => new TranslatableString(getKey(@"reset_bookmarks"), @"Reset bookmarks");
|
||||||
|
|
||||||
private static string getKey(string key) => $@"{prefix}:{key}";
|
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -429,6 +429,26 @@ namespace osu.Game.Localisation
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static LocalisableString EditorSeekToNextSamplePoint => new TranslatableString(getKey(@"editor_seek_to_next_sample_point"), @"Seek to next sample point");
|
public static LocalisableString EditorSeekToNextSamplePoint => new TranslatableString(getKey(@"editor_seek_to_next_sample_point"), @"Seek to next sample point");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Add bookmark"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString EditorAddBookmark => new TranslatableString(getKey(@"editor_add_bookmark"), @"Add bookmark");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Remove closest bookmark"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString EditorRemoveClosestBookmark => new TranslatableString(getKey(@"editor_remove_closest_bookmark"), @"Remove closest bookmark");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Seek to previous bookmark"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString EditorSeekToPreviousBookmark => new TranslatableString(getKey(@"editor_seek_to_previous_bookmark"), @"Seek to previous bookmark");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Seek to next bookmark"
|
||||||
|
/// </summary>
|
||||||
|
public static LocalisableString EditorSeekToNextBookmark => new TranslatableString(getKey(@"editor_seek_to_next_bookmark"), @"Seek to next bookmark");
|
||||||
|
|
||||||
private static string getKey(string key) => $@"{prefix}:{key}";
|
private static string getKey(string key) => $@"{prefix}:{key}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,6 +413,12 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
set => baseBeatmap.CountdownOffset = value;
|
set => baseBeatmap.CountdownOffset = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int[] Bookmarks
|
||||||
|
{
|
||||||
|
get => baseBeatmap.Bookmarks;
|
||||||
|
set => baseBeatmap.Bookmarks = value;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
// 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 osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
using osu.Framework.Graphics.Pooling;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Extensions;
|
using osu.Game.Extensions;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
@ -15,24 +19,69 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class BookmarkPart : TimelinePart
|
public partial class BookmarkPart : TimelinePart
|
||||||
{
|
{
|
||||||
|
private readonly BindableList<int> bookmarks = new BindableList<int>();
|
||||||
|
|
||||||
|
private DrawablePool<BookmarkVisualisation> pool = null!;
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
AddInternal(pool = new DrawablePool<BookmarkVisualisation>(10));
|
||||||
|
}
|
||||||
|
|
||||||
protected override void LoadBeatmap(EditorBeatmap beatmap)
|
protected override void LoadBeatmap(EditorBeatmap beatmap)
|
||||||
{
|
{
|
||||||
base.LoadBeatmap(beatmap);
|
base.LoadBeatmap(beatmap);
|
||||||
foreach (int bookmark in beatmap.BeatmapInfo.Bookmarks)
|
|
||||||
Add(new BookmarkVisualisation(bookmark));
|
bookmarks.UnbindAll();
|
||||||
|
bookmarks.BindTo(beatmap.Bookmarks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private partial class BookmarkVisualisation : PointVisualisation, IHasTooltip
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
public BookmarkVisualisation(double startTime)
|
base.LoadComplete();
|
||||||
: base(startTime)
|
bookmarks.BindCollectionChanged((_, _) =>
|
||||||
{
|
{
|
||||||
|
Clear(disposeChildren: false);
|
||||||
|
foreach (int bookmark in bookmarks)
|
||||||
|
Add(pool.Get(v => v.StartTime = bookmark));
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class BookmarkVisualisation : PoolableDrawable, IHasTooltip
|
||||||
|
{
|
||||||
|
private int startTime;
|
||||||
|
|
||||||
|
public int StartTime
|
||||||
|
{
|
||||||
|
get => startTime;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (startTime == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
startTime = value;
|
||||||
|
X = startTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours) => Colour = colours.Blue;
|
private void load(OsuColour colours)
|
||||||
|
{
|
||||||
|
RelativePositionAxes = Axes.Both;
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
|
||||||
public LocalisableString TooltipText => $"{StartTime.ToEditorFormattedString()} bookmark";
|
Anchor = Anchor.CentreLeft;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
Width = PointVisualisation.MAX_WIDTH;
|
||||||
|
Height = 0.4f;
|
||||||
|
|
||||||
|
Colour = colours.Blue;
|
||||||
|
InternalChild = new FastCircle { RelativeSizeAxes = Axes.Both };
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalisableString TooltipText => $"{((double)StartTime).ToEditorFormattedString()} bookmark";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -422,6 +422,29 @@ namespace osu.Game.Screens.Edit
|
|||||||
Items = new MenuItem[]
|
Items = new MenuItem[]
|
||||||
{
|
{
|
||||||
new EditorMenuItem(EditorStrings.SetPreviewPointToCurrent, MenuItemType.Standard, SetPreviewPointToCurrentTime),
|
new EditorMenuItem(EditorStrings.SetPreviewPointToCurrent, MenuItemType.Standard, SetPreviewPointToCurrentTime),
|
||||||
|
new EditorMenuItem(EditorStrings.Bookmarks)
|
||||||
|
{
|
||||||
|
Items = new MenuItem[]
|
||||||
|
{
|
||||||
|
new EditorMenuItem(EditorStrings.AddBookmark, MenuItemType.Standard, addBookmarkAtCurrentTime)
|
||||||
|
{
|
||||||
|
Hotkey = new Hotkey(GlobalAction.EditorAddBookmark),
|
||||||
|
},
|
||||||
|
new EditorMenuItem(EditorStrings.RemoveClosestBookmark, MenuItemType.Destructive, removeBookmarksInProximityToCurrentTime)
|
||||||
|
{
|
||||||
|
Hotkey = new Hotkey(GlobalAction.EditorRemoveClosestBookmark)
|
||||||
|
},
|
||||||
|
new EditorMenuItem(EditorStrings.SeekToPreviousBookmark, MenuItemType.Standard, () => seekBookmark(-1))
|
||||||
|
{
|
||||||
|
Hotkey = new Hotkey(GlobalAction.EditorSeekToPreviousBookmark)
|
||||||
|
},
|
||||||
|
new EditorMenuItem(EditorStrings.SeekToNextBookmark, MenuItemType.Standard, () => seekBookmark(1))
|
||||||
|
{
|
||||||
|
Hotkey = new Hotkey(GlobalAction.EditorSeekToNextBookmark)
|
||||||
|
},
|
||||||
|
new EditorMenuItem(EditorStrings.ResetBookmarks, MenuItemType.Destructive, () => editorBeatmap.Bookmarks.Clear())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -753,6 +776,14 @@ namespace osu.Game.Screens.Edit
|
|||||||
case GlobalAction.EditorSeekToNextSamplePoint:
|
case GlobalAction.EditorSeekToNextSamplePoint:
|
||||||
seekSamplePoint(1);
|
seekSamplePoint(1);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case GlobalAction.EditorSeekToPreviousBookmark:
|
||||||
|
seekBookmark(-1);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case GlobalAction.EditorSeekToNextBookmark:
|
||||||
|
seekBookmark(1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.Repeat)
|
if (e.Repeat)
|
||||||
@ -760,6 +791,14 @@ namespace osu.Game.Screens.Edit
|
|||||||
|
|
||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
|
case GlobalAction.EditorAddBookmark:
|
||||||
|
addBookmarkAtCurrentTime();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case GlobalAction.EditorRemoveClosestBookmark:
|
||||||
|
removeBookmarksInProximityToCurrentTime();
|
||||||
|
return true;
|
||||||
|
|
||||||
case GlobalAction.EditorCloneSelection:
|
case GlobalAction.EditorCloneSelection:
|
||||||
Clone();
|
Clone();
|
||||||
return true;
|
return true;
|
||||||
@ -792,6 +831,19 @@ namespace osu.Game.Screens.Edit
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addBookmarkAtCurrentTime()
|
||||||
|
{
|
||||||
|
int bookmark = (int)clock.CurrentTimeAccurate;
|
||||||
|
int idx = editorBeatmap.Bookmarks.BinarySearch(bookmark);
|
||||||
|
if (idx < 0)
|
||||||
|
editorBeatmap.Bookmarks.Insert(~idx, bookmark);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeBookmarksInProximityToCurrentTime()
|
||||||
|
{
|
||||||
|
editorBeatmap.Bookmarks.RemoveAll(b => Math.Abs(b - clock.CurrentTimeAccurate) < 2000);
|
||||||
|
}
|
||||||
|
|
||||||
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -1127,6 +1179,16 @@ namespace osu.Game.Screens.Edit
|
|||||||
clock.SeekSmoothlyTo(found.StartTime);
|
clock.SeekSmoothlyTo(found.StartTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void seekBookmark(int direction)
|
||||||
|
{
|
||||||
|
int? targetBookmark = direction < 1
|
||||||
|
? editorBeatmap.Bookmarks.Cast<int?>().LastOrDefault(b => b < clock.CurrentTimeAccurate)
|
||||||
|
: editorBeatmap.Bookmarks.Cast<int?>().FirstOrDefault(b => b > clock.CurrentTimeAccurate);
|
||||||
|
|
||||||
|
if (targetBookmark != null)
|
||||||
|
clock.SeekSmoothlyTo(targetBookmark.Value);
|
||||||
|
}
|
||||||
|
|
||||||
private void seekSamplePoint(int direction)
|
private void seekSamplePoint(int direction)
|
||||||
{
|
{
|
||||||
double currentTime = clock.CurrentTimeAccurate;
|
double currentTime = clock.CurrentTimeAccurate;
|
||||||
|
@ -118,6 +118,14 @@ namespace osu.Game.Screens.Edit
|
|||||||
playableBeatmap.Breaks.AddRange(Breaks);
|
playableBeatmap.Breaks.AddRange(Breaks);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Bookmarks = new BindableList<int>(playableBeatmap.Bookmarks);
|
||||||
|
Bookmarks.BindCollectionChanged((_, _) =>
|
||||||
|
{
|
||||||
|
BeginChange();
|
||||||
|
playableBeatmap.Bookmarks = Bookmarks.OrderBy(x => x).Distinct().ToArray();
|
||||||
|
EndChange();
|
||||||
|
});
|
||||||
|
|
||||||
PreviewTime = new BindableInt(BeatmapInfo.Metadata.PreviewTime);
|
PreviewTime = new BindableInt(BeatmapInfo.Metadata.PreviewTime);
|
||||||
PreviewTime.BindValueChanged(s =>
|
PreviewTime.BindValueChanged(s =>
|
||||||
{
|
{
|
||||||
@ -270,6 +278,14 @@ namespace osu.Game.Screens.Edit
|
|||||||
set => PlayableBeatmap.CountdownOffset = value;
|
set => PlayableBeatmap.CountdownOffset = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly BindableList<int> Bookmarks;
|
||||||
|
|
||||||
|
int[] IBeatmap.Bookmarks
|
||||||
|
{
|
||||||
|
get => PlayableBeatmap.Bookmarks;
|
||||||
|
set => PlayableBeatmap.Bookmarks = value;
|
||||||
|
}
|
||||||
|
|
||||||
public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone();
|
public IBeatmap Clone() => (EditorBeatmap)MemberwiseClone();
|
||||||
|
|
||||||
private IList mutableHitObjects => (IList)PlayableBeatmap.HitObjects;
|
private IList mutableHitObjects => (IList)PlayableBeatmap.HitObjects;
|
||||||
|
@ -46,6 +46,7 @@ namespace osu.Game.Screens.Edit
|
|||||||
processHitObjects(result, () => newBeatmap ??= readBeatmap(newState));
|
processHitObjects(result, () => newBeatmap ??= readBeatmap(newState));
|
||||||
processTimingPoints(() => newBeatmap ??= readBeatmap(newState));
|
processTimingPoints(() => newBeatmap ??= readBeatmap(newState));
|
||||||
processBreaks(() => newBeatmap ??= readBeatmap(newState));
|
processBreaks(() => newBeatmap ??= readBeatmap(newState));
|
||||||
|
processBookmarks(() => newBeatmap ??= readBeatmap(newState));
|
||||||
processHitObjectLocalData(() => newBeatmap ??= readBeatmap(newState));
|
processHitObjectLocalData(() => newBeatmap ??= readBeatmap(newState));
|
||||||
editorBeatmap.EndChange();
|
editorBeatmap.EndChange();
|
||||||
}
|
}
|
||||||
@ -97,6 +98,27 @@ namespace osu.Game.Screens.Edit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processBookmarks(Func<IBeatmap> getNewBeatmap)
|
||||||
|
{
|
||||||
|
var newBookmarks = getNewBeatmap().Bookmarks.ToHashSet();
|
||||||
|
|
||||||
|
foreach (int oldBookmark in editorBeatmap.Bookmarks.ToArray())
|
||||||
|
{
|
||||||
|
if (newBookmarks.Contains(oldBookmark))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
editorBeatmap.Bookmarks.Remove(oldBookmark);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (int newBookmark in newBookmarks)
|
||||||
|
{
|
||||||
|
if (editorBeatmap.Bookmarks.Contains(newBookmark))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
editorBeatmap.Bookmarks.Add(newBookmark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void processHitObjects(DiffResult result, Func<IBeatmap> getNewBeatmap)
|
private void processHitObjects(DiffResult result, Func<IBeatmap> getNewBeatmap)
|
||||||
{
|
{
|
||||||
findChangedIndices(result, LegacyDecoder<Beatmap>.Section.HitObjects, out var removedIndices, out var addedIndices);
|
findChangedIndices(result, LegacyDecoder<Beatmap>.Section.HitObjects, out var removedIndices, out var addedIndices);
|
||||||
|
Loading…
Reference in New Issue
Block a user